[Python-Dev] Re: Implementation of PEP-0604

2019-11-13 Thread Richard Eames
Thanks for the encouragement! 

I've been working some more on it since I had some more free cycles in the last 
few days and I think I've got to the limit of my capabilities. I think I've got 
it to a point where it needs more eyes because my experience level writing code 
in the python interpreter is pretty low, so I know that I have holes in there, 
especially around using INCREF/DECREF. 
I'm currently stuck on 3 things:

1. repr( pickle.loads( pickle.dumps(int | str) ) ) causes an infinite recursion 
that I can't figure out. I might end up re-specializing `repr()` again since it 
isn't defined in the PEP.

2.
- `None | "forwardref"` and `None | None`
- `"forwardref" | None` and `"forwardRefA" | "forwardRefB"` 
I've had a go at adding a `type.__ror__` as suggested by GvR, but I think I'm 
missing something.

3. type parameters
- I'm not sure how to handle this:
```
MaybeT = None | "T" # creates shadow union
T = TypeVar('T')
maybe_int = MaybeT[int] # should this stay in shadow land, or go back to 
typing.py
isinstance(1, maybe_int)
isinstance(1, MaybeT[int])
```
I have a couple options for this:
- implement the type substitution in c; which can be done, but feels like 
overkill?
- store the type parameters on the shadow object and vivify when needed (which 
will end up being in the isinstance call)
- implement the __getitem__ as a call into the typing.py library and promote as 
it's requested. This is how I've currently implemented it.

I'm happy to keep going on this if/when needed,

Richard
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@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/RYH3TYK5RXII5ESUYMTJAROBUAE3SY7H/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Implementation of PEP-0604

2019-11-08 Thread Richard Eames
Hi Philippe and list, 

Long time lurker here, I've had a few spare cycles at $work this week that I 
spent exploring an alternate implementation to PEP604 starting with the 
implementation from Philippe. I don't say "reference implementation", because 
it doesn't implement PEP604 faithfully, but it does try to implement it's goal. 
 My thinking was that the "runtime" component to it only needs to support the 
isinstance/issubclass methods and so can be pretty minimal without need to 
import all the typing.py machinery. At which point, when actual type checking 
was done (anything in typing.py or mypy), the `union` type can be special 
cased, or promoted to a `typing.Union`.

I started by creating a built-in "union" type, that was a thin wrapper around a 
tuple, such that type.__or__ will return `union(lhs, rhs)` which stored the two 
items in a 2-length tuple. I also changed the methods in `typing.Union` to 
return a `union`. However, I hit my first issue: `int | int | str` would then 
return `union(int, union(int, str))`, whereas it should deduplicate the types. 
So, I implemented logic to detect and merge union | union, but changed the 
underlying data to a plain flat tuple. And the next issue I hit was that some 
of the other `typing.py` types weren't being detected as valid types (probably 
due to my limited understanding of the PyObject datastructure/flags), 
specifically, `int | "forwardref"`, I needed a way to signal to typing.py that 
I had a forwardref without importing it. This is where I changed my approach to 
the problem.

I wanted to find a way to have these metatypes (Union/TypeVar/ForwardRef) 
without re-implementing them in c, or importing them. My Idea was to change the 
builtin type to what I called a "shadow type". In the C layer it's just holds a 
tuple of objects/parameters, and has a type field to say what it is, then when 
in the type checking/typing.py layer, if it detects an object is a 
"shadowobject", then it promotes it to a full type. What I liked about this 
approach, is that for isinstance/issubclass, when it see a "shadowobject" it 
can just grab the underlying types from the shadowobject->params tuple and no 
import magic needs to happen. All of the type magic can be left to 
mypy/typing.py without much knowledge of the shadowobject. I've mostly got 
through this implementation with all but one test passing. 

At this point, I've got as far as I can go without help, so I'm posting here, 
looking for feedback or discussion. I expect that maybe the next step should be 
me commenting on the PEP604 itself for implementation concerns regarding 
`_GenericAlias`?

Implementation is located at https://github.com/Naddiseo/cpython/tree/PEP604

Richard
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@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/P56ZE6USNIGCQU5PIOLKC65VHD5DM37U/
Code of Conduct: http://python.org/psf/codeofconduct/