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

improve argparse.Namespace __repr__ for invalid identifiers. #68548

Closed
Carreau mannequin opened this issue Jun 2, 2015 · 12 comments
Closed

improve argparse.Namespace __repr__ for invalid identifiers. #68548

Carreau mannequin opened this issue Jun 2, 2015 · 12 comments
Assignees
Labels
stdlib Python modules in the Lib dir type-feature A feature request or enhancement

Comments

@Carreau
Copy link
Mannequin

Carreau mannequin commented Jun 2, 2015

BPO 24360
Nosy @bitdancer, @berkerpeksag, @serhiy-storchaka, @Carreau
Files
  • improve-namespace-repr.patch: improve argparse.namespace repr.
  • 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 = 'https://github.com/berkerpeksag'
    closed_at = <Date 2015-07-29.20:53:28.309>
    created_at = <Date 2015-06-02.06:00:51.940>
    labels = ['type-feature', 'library']
    title = 'improve argparse.Namespace __repr__ for invalid identifiers.'
    updated_at = <Date 2015-07-29.21:26:33.221>
    user = 'https://github.com/Carreau'

    bugs.python.org fields:

    activity = <Date 2015-07-29.21:26:33.221>
    actor = 'mbussonn'
    assignee = 'berker.peksag'
    closed = True
    closed_date = <Date 2015-07-29.20:53:28.309>
    closer = 'berker.peksag'
    components = ['Library (Lib)']
    creation = <Date 2015-06-02.06:00:51.940>
    creator = 'mbussonn'
    dependencies = []
    files = ['39593']
    hgrepos = []
    issue_num = 24360
    keywords = ['patch']
    message_count = 12.0
    messages = ['244655', '244659', '244778', '244779', '244788', '244792', '244795', '244796', '247580', '247624', '247626', '247633']
    nosy_count = 7.0
    nosy_names = ['bethard', 'r.david.murray', 'python-dev', 'berker.peksag', 'paul.j3', 'serhiy.storchaka', 'mbussonn']
    pr_nums = []
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue24360'
    versions = ['Python 3.6']

    @Carreau
    Copy link
    Mannequin Author

    Carreau mannequin commented Jun 2, 2015

    The argparse Namespace can be missleading in case where the args names are not valid identifiers, eg thinks like a closing bracket:

    In [5]: Namespace(a=1, **{')':3})
    Out[5]: Namespace()=3, a=1)

    more funny:

    In [3]: Namespace(a=1, **{s:3})
    Out[3]: Namespace(a=1, b=2), Namespace(c=3)

    for s = 'b=2), Namespace(c'

    With this patch the args that are not valid identifiers are shown in ** unpacked-dict, which has the side effect of almost always having repr(eval(repr(obj)))== repr(obj). I'm sure we can find counter example with quotes and triple-quoted string... but anyway.

    with this patch (indentation mine for easy comparison):
    >>> from argparse import Namespace
    >>> Namespace(a=1, **{')': 3})
        Namespace(a=1, **{')': 3})

    Which is I think what most user would expect.

    Test passes locally (except SSL cert, network thingies, curses and threaded_lru_cache) which look unrelated and is most likely due to my machine.

    @Carreau Carreau mannequin added stdlib Python modules in the Lib dir type-feature A feature request or enhancement labels Jun 2, 2015
    @serhiy-storchaka
    Copy link
    Member

    LGTM.

    @paulj3
    Copy link
    Mannequin

    paulj3 mannequin commented Jun 3, 2015

    Off hand I don't see a problem with this patch (but I haven't tested it yet).

    But I have a couple of cautions:

    The docs say, regarding the Namespace class:

    This class is deliberately simple, just an object subclass with a readable string representation.

    This patch improves the 'readable' part, but adds some complexity.

    The docs also note that the user can provide their own namespace object, and by implication, a custom Namespace class with this improved '__repr__'.

    The Namespace '__repr__' is mainly of value during code development, especially when trying ideas in an interactive shell. It's unlikely that you would want to show the whole namespace to your end user. So even if your final API requires funny characters, you don't need to use them during development.

    @Carreau
    Copy link
    Mannequin Author

    Carreau mannequin commented Jun 3, 2015

    Sure and anyway if you have a huge namespace, things will become unreadable.
    But during development/teaching, having object that have a "sane" representation is useful, otherwise your brain (well at least mine), choke on the output and break the flow of my thoughts.

    One could also just use __repr(self)__ = repr(self.__dict__), that woudl be even simpler and readable :-)

    @paulj3
    Copy link
    Mannequin

    paulj3 mannequin commented Jun 3, 2015

    An alternative would be to wrap a non-identifier name in 'repr()':

        def repr1(self):
            def fmt_name(name):
                if name.isidentifier():
                    return name
                else:
                    return repr(name)
            type_name = type(self).__name__
            arg_strings = []
            for arg in self._get_args():
                arg_strings.append(repr(arg))
            for name, value in self._get_kwargs():
                arg_strings.append('%s=%r' % (fmt_name(name), value))
            return '%s(%s)' % (type_name, ', '.join(arg_strings))

    This would produce lines like:

        Namespace(baz='one', 'foo bar'='test', 'x __y'='other')
        
        Namespace(a=1, b=2, 'double " quote'='"', "single ' quote "="'")
    Namespace(')'=3, a=1)
    
    Namespace(a=1, 'b=2), Namespace(c'=3)
    

    With names that are deliberately messy, it is hard to say which is clearer.

    @Carreau
    Copy link
    Mannequin Author

    Carreau mannequin commented Jun 3, 2015

    Namespace(a=1, 'b=2), Namespace(c'=3)

    :-) I read that a prime-b=2 and c-prime=3.

    I just feel like having a repr which is closer to the constructor signature is better, but I guess it's a question of taste. Anyway, both would be fine.

    @paulj3
    Copy link
    Mannequin

    paulj3 mannequin commented Jun 4, 2015

    I mentioned in the related bug/issue that no one has to use odd characters and spaces in the Namespace. While they are allowed by 'getattr' etc, the programmer has the option of supplying rational names in the 'dest' parameter.

    There's also the question of what kinds of strings can you supply via 'sys.argv'. For example, I have to use quotes to enter

        $ python echoargv.py '--b=2), Namespace(c' test

    Without them 'bash' gives me an error.

    Strings like this may be nice for exercising a patch, they may not be realistic in full argparse context.

    @Carreau
    Copy link
    Mannequin Author

    Carreau mannequin commented Jun 4, 2015

    As far as I remember, argparse is not only use to parse things from sys.argv where the quoting is not necessary. And Namespace is not only use in argparse.

    But if you don't want improvement, feel free to close.

    @bitdancer
    Copy link
    Member

    If one is going to have a repr at all, I think it should be as accurate as practical. I think this is worthwhile, and favor the existing patch.

    @berkerpeksag berkerpeksag self-assigned this Jul 29, 2015
    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Jul 29, 2015

    New changeset dcc00d9ba8db by Berker Peksag in branch 'default':
    Issue bpo-24360: Improve __repr__ of argparse.Namespace() for invalid identifiers.
    https://hg.python.org/cpython/rev/dcc00d9ba8db

    @berkerpeksag
    Copy link
    Member

    Thanks for the patch, Matthias.

    @Carreau
    Copy link
    Mannequin Author

    Carreau mannequin commented Jul 29, 2015

    Thanks for accepting the patch. Looking forward to 3.6 ! :-)

    @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-feature A feature request or enhancement
    Projects
    None yet
    Development

    No branches or pull requests

    3 participants