> Dunder names are reserved for use by the Python interpreter.
That's convenient, because my suggestion is to add a magic attribute into the
Python specifications ;) It would be a `type` attribute, like `__mro__` or
others.
> So here we have `__attrs__` is not just a dunder attribute, but also a dunder
> built-in name.
It hasn't to be a built-in name in global scope but only in the scope of class
declaration (and could then be interpreted by type checkers has being owned by
the class being declared). Using it outside a class declaration should raise a
`NameError`.
By the way, I think you did not understand my suggestion, so maybe it was not
enough clear — that's maybe related too to the fact you precise in an other
post that your are "not aware of many refactoring tools for Python at all".
So I will develop my point by talking about an other pseudo-static (but
completely dynamic under the hood) standard Python feature; let's talk about
dataclasses.
Dataclasses are a dynamic thing, a decorator which rewrite class methods; this
is so dynamic that the method code is first written as a string and then
compiled with `exec`, and that it use regex parsing under the hood to check
types in stringified annotations. That's under the hood. However, for the user,
thanks to IDEs, type checkers, linters, etc. this is handled as a static
feature. Attribute access can be type checked, and `__init__` method parameters
are checked too.
Don't believe that IDEs and other tools execute the `dataclass` code for each
class in order to retrieve the signature of the generated method. No, they just
compute it themselves statically, because they **know that it will be generated
this way**. How do they know ? Because it's written in Python specifications,
so they have to handle it. And if you write code reassigning an attribute of a
frozen dataclass, linter will warn you, while the real check is dynamic and
realized in class generated `__setattr__`.
(To prove you that's purely static, try to do `dataclass2 = dataclass` and
execute mypy with a class decorated by `dataclass2`)
So, if tools are able to statically compute a signature of dataclass `__init__`
by using its fields annotations (even if it's dynamic like hell behind), I hope
you begin to understand how they could be able to interpret `__attrs__.bar` in
a different manner than raw `"bar"`; it's not "one more step" as you said, it's
a different processing, and because it's a different processing, type checking
can be added, using for example my suggested `_SpecialForm` `Attribute[Owner,
T]`
> So linters that cannot cope with `@validate('email')` will be able to cope
> with `@validate(__attrs__.email)`, because ... why?
Because it would be written in Python specification that this has a special
meaning for type checking, as it is for dataclasses methods. That's why I dare
use a dunder name, because it's a suggestion for the Python specification.
> Presumably these would work too:
> `assert getattr(foo, None.__attrs__.bar) == 0`
> `assert getattr(foo, foo.__attrs__.baz, 999) == 999`
It will works, yes, but the same way that passing a `str` to a function
annotated with an `int` parameter: type checker will shout at you. Python
static checks are never enforced dynamically, this suggestion does not aim to
change this behavior.
But in Python, dynamics things can be interpreted in a static way by tools,
they needs a specification to follow, dataclasses being again the best example.
> Apart from typing 15 chars to avoid 2 quotation marks, and making a runtime
> attribute lookup plus method call to avoid a literal, how will this help
> reduce dynamicism?
I hope that you've understood now with this complementary explanation (and yes,
there is more chars typed, but is that an issue when meanings are different?)
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/MNGFPIWUHH6C2UEO6BVTARMDLDNUX3XT/
Code of Conduct: http://python.org/psf/codeofconduct/