This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author desbma
Recipients barry, desbma, paul.j3
Date 2015-11-03.17:24:34
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1446571474.73.0.115120862249.issue25061@psf.upfronthosting.co.za>
In-reply-to
Content
I came up with something that satisfies my needs (no boilerplate code, and intuitive add_argument call).

I modified your factory, and defined a simple action class (this is a quick and dirty prototype for discussion, I am in no way asking that such thing should be merged as such):

class EnumType(object):
    """Factory for creating enum object types
    """
    def __init__(self, enumclass, action):
        self.enums = enumclass
        self.action = action

    def __call__(self, astring):
        name = self.enums.__name__
        try:
            v = self.enums[astring.upper()]
        except KeyError:
            msg = ', '.join([t.name.lower() for t in self.enums])
            msg = '%s: use one of {%s}'%(name, msg)
            raise argparse.ArgumentTypeError(msg)
        else:
            self.action.choices = None  # hugly hack to prevent post validation from choices
            return v

    def __repr__(self):
        astr = ', '.join([t.name.lower() for t in self.enums])
        return '%s(%s)' % (self.enums.__name__, astr)


class StoreEnumAction(argparse._StoreAction):

  def __init__(self,
               option_strings,
               dest,
               type,
               nargs=None,
               const=None,
               default=None,
               required=False,
               help=None,
               metavar=None):
      super().__init__(option_strings=option_strings,
                       dest=dest,
                       nargs=nargs,
                       const=const,
                       default=default,
                       type=EnumType(type, self),
                       choices=tuple(t.name.lower() for t in type),
                       required=required,
                       help=help,
                       metavar=metavar)

Then all I have to do is to pass 'action=StoreEnumAction, type=TheEnum' to the add_argument call.

The good:
I get a proper usage line (which takes into account the value of 'nargs'), relevant error messages, and what is stored in the namespace after validation is the proper enum type, not a string.

The bad:
* The reference to the action inside the factory is ugly. This should probably be refractored to be all contained inside StoreEnumAction.
* The meaning of the 'type' parameter for StoreEnumAction is somewhat different than for other actions (enum class vs callable that validates)

What do you think?
History
Date User Action Args
2015-11-03 17:24:34desbmasetrecipients: + desbma, barry, paul.j3
2015-11-03 17:24:34desbmasetmessageid: <1446571474.73.0.115120862249.issue25061@psf.upfronthosting.co.za>
2015-11-03 17:24:34desbmalinkissue25061 messages
2015-11-03 17:24:34desbmacreate