On Wed, Apr 15, 2020 at 12:49 PM Ivan Pozdeev via Python-Dev <python-dev@python.org> wrote:

First of all, be aware of the limitations of this approach (which will need to be clearly documented if we go this way):

Agreed, these are all problems that lead to long term code maintenance headaches (add a new method and a bunch of existing code mysteriously breaks).  The dict ['key'] lookup / get('key') syntax must always remain for access to those as a result.  this is mere syntactic sugar convenience.

Unfortunately it's a slippery slope; do this just for JSON and people will ask why it can't be done for any dict and why it isn't the default available everywhere.

Similar to -> in Perl.
  • It's not very scalable and will upset static code checkers and IDEs as it's impossible to determine if the attribute name is valid or provide typing hints

Not necessarily.  If you've given the JSON a schema, you can use that to teach tools attr names and types.  otherwise anything doing such checking should see that this is an instance of a type with a __getattr__ implemented and thus all attributes must be deemed valid.


Now, I think it's possible to make a class that would wrap an existing mapping.
This would completely decouple the convenience syntax from the storage semantics and any specific modules and types.

When writing a proof-of-concept implementation, however, I bumped into the need to distinguish which of the child objects are containers (thus need to be wrapped as well) and which are the leaves (thus need to be returned as is). I guess this is going to be application-specific. And the same problem will arise with any implementation, not only a wrapper.

On 15.04.2020 5:59, Raymond Hettinger wrote:
SimpleNamespace() is really good at giving attribute style-access. I would like to make that functionality available to the JSON module (or just about anything else that accepts a custom dict) by adding the magic methods for mappings so that this works:

     catalog = json.load(f, object_hook=SimpleNamespace)
     print(catalog['clothing']['mens']['shoes']['extra_wide']['quantity'])      # currently possible with dict()
     print(catalog.clothing.mens.shoes.extra_wide.quantity])                 # proposed with SimpleNamespace()
     print(catalog.clothing.boys['3t'].tops.quantity                                   # would also be supported

I've already seen something like this in production; however, people are having to write custom subclasses to do it.  This is kind of bummer because the custom subclasses are a pain to write, are non-standard, and are generally somewhat slow.  I would like to see a high-quality version this made more broadly available.

The core idea is keep the simple attribute access but make it easier to load data programmatically:

    >>> ns = SimpleNamespace(roses='red', violets='blue')
    >>> thing = input()
    sugar
    >>> quality = input()
    sweet
    >>> setattr(ns, thing, quality)            # current
    >>> ns['sugar'] = 'sweet'                   # proposed

If the PEP 584 __ior__ method were supported, updating a SimpleNamespace would be much cleaner:

      ns |= some_dict

I posted an issue on the tracker: https://bugs.python.org/issue40284 .  There was a suggestion to create a different type for this, but I don't see the point in substantially duplicating everything SimpleNamespace already does just so we can add some supporting dunder methods.   Please add more commentary so we can figure-out the best way to offer this powerful functionality.


Raymond


_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/JOMND56PJGRN7FQQLLCWONE5Z7R2EKXW/
Code of Conduct: http://python.org/psf/codeofconduct/
--
Regards,
Ivan
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/IEKXDY7HUUCGF4BI327URFAWV67WQJZJ/
Code of Conduct: http://python.org/psf/codeofconduct/