I had a brief test of Jelle’s branch and had one question on something that’s been bugging me about the PEP.
It’s entirely possible there’s something I’ve missed, but is there a specific reason why the generated __annotate__
functions are not planning to support FORWARDREF or STRING formats?
Currently I have code that’s roughly like this, intended to create slots automatically from annotations:
class MakeSlotsMeta(type):
def __new__(cls, name, bases, ns, **kwargs):
if "__slots__" not in ns:
cls_annotations = ns.get("__annotations__", {})
... # logic to handle string annotations
cls_slots = [
k
for k, v in cls_annotations
if not is_classvar(v)
]
ns["__slots__"] = cls_slots
... # additional logic to store and remove attributes
new_cls = super().__new__(cls, name, bases, ns, **kwargs)
return new_cls
As expected this no longer works on the PEP branch as __annotations__
is not present. __annotate__
exists and is callable, but only with format=1
, which will NameError
if there are forward references. As far as I can tell for this to work correctly under PEP649 I will need to replicate the full logic of the ‘fake globals’ method that inspect.get_annotations
is going to use.
The PEP indicates that the ‘fake globals’ logic is only expected to work correctly on the __annotate__
methods Python generates. In fact it creates a specific opt-in flag for this case.
I’m trying to understand why - given this requirement - the ‘fake globals’ logic isn’t included in the generated __annotate__
functions, but instead requires a function from a separate import which then has to check this flag to see if it’s allowed to use ‘fake globals’, which are only expected to work on generated __annotate__
in the first place?
Ideally I would like to be able to use something like this inside the __new__
method:
cls_annotations = {}
annotate = ns.get("__annotate__")
if annotate:
cls_annotations = annotate(2) # NotImplementedError currently