Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

argparse types (and actions) must be hashable #60720

Closed
jnothman mannequin opened this issue Nov 21, 2012 · 8 comments
Closed

argparse types (and actions) must be hashable #60720

jnothman mannequin opened this issue Nov 21, 2012 · 8 comments
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@jnothman
Copy link
Mannequin

jnothman mannequin commented Nov 21, 2012

BPO 16516
Nosy @gvanrossum, @krassowski, @BNMetrics
PRs
  • bpo-16516: Allow argparse types to be unhashable #10205
  • Files
  • patch.diff
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2018-12-16.18:36:05.869>
    created_at = <Date 2012-11-21.03:28:27.731>
    labels = ['type-bug', 'library']
    title = 'argparse types (and actions) must be hashable'
    updated_at = <Date 2018-12-16.18:36:05.868>
    user = 'https://bugs.python.org/jnothman'

    bugs.python.org fields:

    activity = <Date 2018-12-16.18:36:05.868>
    actor = 'gvanrossum'
    assignee = 'none'
    closed = True
    closed_date = <Date 2018-12-16.18:36:05.869>
    closer = 'gvanrossum'
    components = ['Library (Lib)']
    creation = <Date 2012-11-21.03:28:27.731>
    creator = 'jnothman'
    dependencies = []
    files = ['35936']
    hgrepos = []
    issue_num = 16516
    keywords = ['patch']
    message_count = 8.0
    messages = ['176040', '222780', '222890', '303907', '307864', '330863', '331658', '331932']
    nosy_count = 6.0
    nosy_names = ['gvanrossum', 'bethard', 'paul.j3', 'jnothman', 'krassowski', 'BNMetrics']
    pr_nums = ['10205']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue16516'
    versions = ['Python 2.7', 'Python 3.4', 'Python 3.5', 'Python 3.6']

    @jnothman
    Copy link
    Mannequin Author

    jnothman mannequin commented Nov 21, 2012

    The argparse documentation states that "type= can take any callable that takes a single string argument and returns the converted value". The following is an exception:

        >>> import argparse
        >>> ap = argparse.ArgumentParser()
        >>> ap.add_argument('foo', type={}.get)
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
          File "/usr/lib/python3/argparse.py", line 1294, in add_argument
            type_func = self._registry_get('type', action.type, action.type)
          File "/usr/lib/python3/argparse.py", line 1236, in _registry_get
            return self._registries[registry_name].get(value, default)
        TypeError: unhashable type: 'dict'

    Sadly, a method bound to an unhashable type is unhashable! (Of course, is trivial to use partial or lambda to make any function hashable.)

    The offending line in _registry_get is intended to look up named types (or actions), so it perhaps only relevant for string type= and action= values, which could be handled explicitly instead of using dict.get(x, x) to handle both cases. Alternatively, the TypeError could be caught and default returned.

    @jnothman jnothman mannequin added stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error labels Nov 21, 2012
    @BreamoreBoy
    Copy link
    Mannequin

    BreamoreBoy mannequin commented Jul 11, 2014

    @paul can you take a look at this please.

    @paulj3
    Copy link
    Mannequin

    paulj3 mannequin commented Jul 12, 2014

    This is a straight forward patch, modifying '_registry_get' to return 'default' if it gets this 'TypeError'. 'test_argparse.py' has a testcase based on jnothman's example. Temporarily it includes a skipped test that would pass the original code.

    The alternative would be to add a note to the documentation to the effect that the 'type' must also be hashable. But for an edge condition like this, that may be more confusing than enlightening.

    While 'dict(one=1, two=20).get' now works as a 'type' callable, it is not ideal. If there is no match it returns None. The alternative '.__getitem__' raises a KeyError. But '_get_values' handles TypeError and ValueErrors, the kinds returned by 'int' and 'float'. It also handles an ArgumentTypeError, giving a custom type more control over the error message. Is it worth noting something about the type errors in the documentation?

    I've seen users make a different error with the type parameter - 'type=boolean', thinking this means the input should be converted to boolean. They are thinking of 'type' as a datatype, rather than a function that converts a string into something else. I don't know of a solution other than explaining that 'boolean()' does not act like 'int()'.

    This patch also handles the 'action' case. However I can't think of a way write a Action subclass that would be unhashable. It would have to inherit from both Action and dict.

    @jnothman
    Copy link
    Mannequin Author

    jnothman mannequin commented Oct 8, 2017

    Clearly this is not in high demand

    @krassowski
    Copy link
    Mannequin

    krassowski mannequin commented Dec 8, 2017

    I've got confused with the "TypeError: unhashable type: 'dict'" error creating a choose-from-dictionary argument in Python 3.6. I used lambda as a workaround, but IMO it would be great to have this patch merged.

    @BNMetrics
    Copy link
    Mannequin

    BNMetrics mannequin commented Dec 1, 2018

    Hi bradengroom,
    I have reviewed your PR, it's just a small thing! If you could update your PR, it would be amazing!

    Thank you!

    @gvanrossum
    Copy link
    Member

    Luna and I talked a bit about this offline and we decided not to merge the PR (nor the original patch, which is the same). Instead Luna will add a note to the docs explaining the caveat.

    @gvanrossum
    Copy link
    Member

    Luna discovered that has actually been fixed in 3.8 (i.e. the master branch), by making {}.get hashable. So I'm closing this as fixed.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    1 participant