vltr / middle

Flexible, extensible Python data structures for general usage
https://middle.readthedocs.io/en/latest/
MIT License
10 stars 1 forks source link

Support for postponed evaluation of annotations #40

Open ahopkins opened 5 years ago

ahopkins commented 5 years ago

Pep 563 defines the ability to lazily define type annotations.

Say I have something like this:

class Foo:
    name: str

class Bar:
    foos: List[Foo]

This would work fine. But what if I am importing from another library, or have them in defined in a different order?

class Bar:
    foos: List[Foo]

class Foo:
    name: str

This will break.

Pep 563 addresses this with from __future__ import annotations. Basically it passes the type annotation as a string to then be resolved at runtime with: typing.get_type_hints().

Therefore, rather than grabbing self.__annotations__, you do something like what I did in pydiggy:

annotations = get_type_hints(self, globalns=globals(), localns=localns)

I think for middle it would be a relatively simple change, but it is a 3.7+ change. Just a thought.

vltr commented 5 years ago

I think for middle it would be a relatively simple change, but it is a 3.7+ change. Just a thought.

It may be simple, yes, but I intend to support Python 3.6 yet for middle 0.3.x. I know that middle uses some metaclass magic and perhaps I could workaround that, but I feel this would not be possible since middle evaluates the classes during declaration - or I could lazily evaluate them as they are registered and replacing the defined classes in runtime. Hmmm, this does need some testing to see if it can be done with Python 3.6 and would not break evaluation ...

ahopkins commented 5 years ago

I have not tried it... but does middle accept string annotations?

class Foo:
    bars: List["Bar"]
vltr commented 5 years ago

I have not tried it... but does middle accept string annotations?

Nope, a str is a str (for now). I was thinking about:

class Foo:
    bars: List[middle.lazy("Bar")]

Instead of the lazy annotations, but this will fall into the same problem as I mentioned earlier: lazily evaluate the entire class only when all classes are available and reload them inside sys.modules ... A bit hacky, I don't know if it'll work properly but it'll be almost the same thing as the metaclass making this magic (I guess).