classification
Title: argparse should preserve argument ordering in Namespace
Type: enhancement Stage: resolved
Components: Library (Lib) Versions: Python 3.9
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: eric.snow, paul.j3, rhettinger
Priority: normal Keywords: patch

Created on 2019-12-15 22:16 by rhettinger, last changed 2020-05-18 01:53 by rhettinger. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 17621 merged rhettinger, 2019-12-16 03:23
Messages (5)
msg358455 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2019-12-15 22:16
Currently, Namespace() objects sort the attributes in the __repr__.  This is annoying because argument order matters and because everywhere else in the module we preserve order (i.e. users see help in the order that arguments are added).

Note, the docs do not promise that Namespace is displayed with a sort.  This is likely just an artifact of older dictionaries having arbitrary or randomised ordering.


>>> from argparse import ArgumentParser
>>> parser = ArgumentParser()
>>> _ = parser.add_argument('source')
>>> _ = parser.add_argument('destination')

# Order matters to the user inputing the arguments 
# (source must go first and destination must go last
>>> args = parser.parse_args(['input.txt', 'output.txt'])

# Order is preserved internally
>>> vars(args)
{'source': 'input.txt', 'destination': 'output.txt'}

# Despite this, the Namespace() repr alphabetizes the output
>>> args
Namespace(destination='output.txt', source='input.txt')

# Order is preserved in help()
>>> parser.parse_args(['-h'])       
usage: [-h] source destination

positional arguments:
  source
  destination

optional arguments:
  -h, --help   show this help message and exit
msg358554 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2019-12-17 16:24
> Currently, Namespace() objects sort the attributes in the __repr__.  This is annoying because argument
> order matters and because everywhere else in the module we preserve order (i.e. users see help in the
> order that arguments are added).

Hmm, I was going to suggest switching to types.SimpleNamespace, but
realized we sort that repr too (likely for the same reason).  I've
opened issue #39075 to address that.

In writing up that issue, I considered that a sorted repr can be
useful in some cases.  However, I don't think any of those cases
really apply here.

Anyway, I agree with your conclusion. :)
msg358556 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2019-12-17 16:37
FWIW, I've also opened issue #39076 about subclassing types.SimpleNamespace.
msg358591 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2019-12-17 22:10
This patch changes the super class, _AttributeHolder.  ArgumentParser and Actions also inherit from this, though they have their own _get_kwargs methods, and so aren't affected by the sort and its removal.

I just had occasion on stackoverflow to discuss the order in which attributes are added.  A poster wanted to preserve the sys.argv order.

https://stackoverflow.com/questions/58904423/find-the-order-of-arguments-in-argparse-python3/58905067#58905067

Most attributes are added as defaults at the start of parsing - via a loop through parser._actions.  Predefining the namespace, SUPPRESS defaults, parser.set_defaults may alter this default order.

Anyways removing the sort makes sense, and the proposed change phrase "in the order attributes were added" is sufficiently general.
msg369160 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2020-05-18 01:53
New changeset 9681953c99b686cf23d1c476a2b26d2ddbec7694 by Raymond Hettinger in branch 'master':
bpo-39058:  Preserve attribute order in argparse Namespace reprs. (GH-17621)
https://github.com/python/cpython/commit/9681953c99b686cf23d1c476a2b26d2ddbec7694
History
Date User Action Args
2020-05-18 01:53:39rhettingersetstatus: open -> closed
resolution: fixed
stage: patch review -> resolved
2020-05-18 01:53:09rhettingersetmessages: + msg369160
2019-12-17 22:10:31paul.j3setnosy: + paul.j3
messages: + msg358591
2019-12-17 16:37:11eric.snowsetmessages: + msg358556
2019-12-17 16:24:41eric.snowsetnosy: + eric.snow
messages: + msg358554
2019-12-16 03:23:11rhettingersetkeywords: + patch
stage: patch review
pull_requests: + pull_request17091
2019-12-15 22:16:04rhettingercreate