Author paul.j3
Recipients docs@python, kop, paul.j3
Date 2015-03-31.22:20:23
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1427840423.94.0.661205419068.issue23814@psf.upfronthosting.co.za>
In-reply-to
Content
The handling of defaults is a bit complicated.

Note that `set_defaults` both sets a `_defaults` attribute, and any actions with a matching `dest`.  So it could change the `default` of 0, 1 or more actions.

    def set_defaults(self, **kwargs):
        self._defaults.update(kwargs)

        # if these defaults match any existing arguments, replace
        # the previous default on the object with the new one
        for action in self._actions:
            if action.dest in kwargs:
                action.default = kwargs[action.dest]


`add_argument` gets `default` from the default parameter (kwarg), the container's `_defaults` or the parser `.argument_default`.  The earliest in that list has priority.

Finally, at the start of `parse_known_args`, each action's `default` is added to the namespace (IF it isn't already there), and values from `_defaults` are also add (also IF not already present).  So here the priority is user supplied `namespace`, action `default`, parser `_defaults`.

And finally, at the end of `_parse_known_args`, any string values in the namespace that match their action default are passed through `get_values`, which may convert them via the 'type'.

I've skimmed over a couple of things:

- defaults defined by the Action class (e.g. 'store_true' sets a False default)

- how parent's `_defaults` are copied

- when `_defaults` affects that final `get_values` action.

- the relative priority of parser and subparsers _defaults (a current bug issue).

So as you observed, `set_defaults` can change a previously defined argument's `default`, but it does not have priority over parameters supplied to new arguments.

In my opinion, `set_default` is most useful as a way of setting Namespace values that do not have their own argument.  The documentation has an example where each subparser sets its own 'func' attribute.

    parser_foo.set_defaults(func=foo)

Maybe the documentation could be refined, though it might be tricky to do so without adding further confusion.

Changing the priorities is probably not a good idea.  The recent bug issues about parser and subparser `set_defaults` a cautionary tale.  Even the earlier change in how 'get_values' is applied to defaults has potential pitfalls.
History
Date User Action Args
2015-03-31 22:20:24paul.j3setrecipients: + paul.j3, docs@python, kop
2015-03-31 22:20:23paul.j3setmessageid: <1427840423.94.0.661205419068.issue23814@psf.upfronthosting.co.za>
2015-03-31 22:20:23paul.j3linkissue23814 messages
2015-03-31 22:20:23paul.j3create