Discussions-To PEP-0604: Complementary syntax for Union[] and Optional[]
Hello everybody, I just publish the PEP-0604 <https://www.python.org/dev/peps/pep-0604/> for discussions (https://www.python.org/dev/peps/pep-0604/). Scala 3 propose a new syntax for Union type. See here <https://dotty.epfl.ch/docs/reference/new-types/union-types.html>. I propose to add a similar syntax in Python. # Operator for Union assert( int | str == Union[int,str]) assert( int | str | float == Union[int,str,float]) # Operator for Optional assert( ~int == Optional[int]) Now, it's possible to write: def fn(bag:List[int | str], option: ~int = None) -> float | str: ... in place of def fn(bag:List[Option[int,str]], option: Optional[int] = None) -> Union[float,str]: ... The discussion on python-new@python.org here <https://mail.python.org/archives/list/python-ideas@python.org/thread/FCTXGDT2NNKRJQ6CDEPWUXHVG2AAQZZY/> have emerged the idea of extending also issubclass() and isinstance(). isinstance(int, int | str) I think these syntaxes are more clear, and can help with the adoption of typing. I test and implement these ideas in a two fork : One for CPython <https://github.com/pprados/cpython/tree/updage_isinstance> and one for MyPy <https://github.com/pprados/mypy/tree/add_INVERT_to_types>. See the branches add_OR_to_types (for Union syntax), add_INVERT_to_types (for Union and Optional syntax) or updage_isinstance (for new isinstance() and issubclass()). How I implement that ? I add the operators __or__ and __revert__ to PyType_Type. The C code is similar of : from typing import * def type_or(self,right): return Union[self,right] type(type).__or__ = type_or with some check before return Union. Actually, the accepted BNF syntax for typing is : annotation: name_type name_type: NAME (args)? args: '[' paramslist ']' paramslist: annotation (',' annotation)* [','] I propose to extend the BNF syntax to : annotation: ( name_type | or_type | invert_type ) name_type: NAME (args)? args: '[' paramslist ']' paramslist: annotation (',' annotation)* [','] or_type: name_type '|' annotation invert_type: '~' annotation Your remarks are welcome. Philippe Prados
For me the feeling is that the ? denotes better optional, ~int to me feels more like not int... than int or None :-) On Fri, Sep 20, 2019 at 10:19 AM Philippe Prados <philippe.prados@gmail.com> wrote:
Hello everybody,
I just publish the PEP-0604 <https://www.python.org/dev/peps/pep-0604/> for discussions (https://www.python.org/dev/peps/pep-0604/).
Scala 3 propose a new syntax for Union type. See here <https://dotty.epfl.ch/docs/reference/new-types/union-types.html>. I propose to add a similar syntax in Python.
# Operator for Union assert( int | str == Union[int,str]) assert( int | str | float == Union[int,str,float]) # Operator for Optional assert( ~int == Optional[int])
Now, it's possible to write:
def fn(bag:List[int | str], option: ~int = None) -> float | str: ...
in place of
def fn(bag:List[Option[int,str]], option: Optional[int] = None) -> Union[float,str]: ...
The discussion on python-new@python.org here <https://mail.python.org/archives/list/python-ideas@python.org/thread/FCTXGDT2NNKRJQ6CDEPWUXHVG2AAQZZY/> have emerged the idea of extending also issubclass() and isinstance().
isinstance(int, int | str)
I think these syntaxes are more clear, and can help with the adoption of typing.
I test and implement these ideas in a two fork : One for CPython <https://github.com/pprados/cpython/tree/updage_isinstance> and one for MyPy <https://github.com/pprados/mypy/tree/add_INVERT_to_types>. See the branches add_OR_to_types (for Union syntax), add_INVERT_to_types (for Union and Optional syntax) or updage_isinstance (for new isinstance() and issubclass()).
How I implement that ? I add the operators __or__ and __revert__ to PyType_Type. The C code is similar of :
from typing import * def type_or(self,right): return Union[self,right] type(type).__or__ = type_or
with some check before return Union.
Actually, the accepted BNF syntax for typing is :
annotation: name_type name_type: NAME (args)? args: '[' paramslist ']' paramslist: annotation (',' annotation)* [',']
I propose to extend the BNF syntax to :
annotation: ( name_type | or_type | invert_type ) name_type: NAME (args)? args: '[' paramslist ']' paramslist: annotation (',' annotation)* [',']
or_type: name_type '|' annotation
invert_type: '~' annotation
Your remarks are welcome. Philippe Prados _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
On 20 Sep 2019, at 11:38, Bernat Gabor <gaborjbernat@gmail.com> wrote:
For me the feeling is that the ? denotes better optional, ~int to me feels more like not int... than int or None :-)
On Fri, Sep 20, 2019 at 10:19 AM Philippe Prados <philippe.prados@gmail.com> wrote: Hello everybody,
I just publish the PEP-0604 for discussions (https://www.python.org/dev/peps/pep-0604/). Scala 3 propose a new syntax for Union type. See here. I propose to add a similar syntax in Python. # Operator for Union assert( int | str == Union[int,str]) assert( int | str | float == Union[int,str,float]) # Operator for Optional assert( ~int == Optional[int]) Now, it's possible to write: def fn(bag:List[int | str], option: ~int = None) -> float | str: ... in place of def fn(bag:List[Option[int,str]], option: Optional[int] = None) -> Union[float,str]: ...
The discussion on python-new@python.org here have emerged the idea of extending also issubclass() and isinstance(). isinstance(int, int | str) I think these syntaxes are more clear, and can help with the adoption of typing. I test and implement these ideas in a two fork : One for CPython and one for MyPy. See the branches add_OR_to_types (for Union syntax), add_INVERT_to_types (for Union and Optional syntax) or updage_isinstance (for new isinstance() and issubclass()). How I implement that ? I add the operators __or__ and __revert__ to PyType_Type. The C code is similar of : from typing import * def type_or(self,right): return Union[self,right] type(type).__or__ = type_or with some check before return Union. Actually, the accepted BNF syntax for typing is : annotation: name_type name_type: NAME (args)? args: '[' paramslist ']' paramslist: annotation (',' annotation)* [','] I propose to extend the BNF syntax to : annotation: ( name_type | or_type | invert_type ) name_type: NAME (args)? args: '[' paramslist ']' paramslist: annotation (',' annotation)* [','] or_type: name_type '|' annotation invert_type: '~' annotation Your remarks are welcome. Philippe Prados _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
I have a similar feeling. I’d read ~int as “not int” or “kinda int”, depending on the context, but not really “optionally int”. That said I like the Union syntax and I believe it’s a nice feature from a Python programmer’s point of view. Best regards, Jakub
Yes, but ? is used by IPython :-( Le ven. 20 sept. 2019 à 11:38, Bernat Gabor <gaborjbernat@gmail.com> a écrit :
For me the feeling is that the ? denotes better optional, ~int to me feels more like not int... than int or None :-)
On Fri, Sep 20, 2019 at 10:19 AM Philippe Prados < philippe.prados@gmail.com> wrote:
Hello everybody,
I just publish the PEP-0604 <https://www.python.org/dev/peps/pep-0604/> for discussions (https://www.python.org/dev/peps/pep-0604/).
Scala 3 propose a new syntax for Union type. See here <https://dotty.epfl.ch/docs/reference/new-types/union-types.html>. I propose to add a similar syntax in Python.
# Operator for Union assert( int | str == Union[int,str]) assert( int | str | float == Union[int,str,float]) # Operator for Optional assert( ~int == Optional[int])
Now, it's possible to write:
def fn(bag:List[int | str], option: ~int = None) -> float | str: ...
in place of
def fn(bag:List[Option[int,str]], option: Optional[int] = None) -> Union[float,str]: ...
The discussion on python-new@python.org here <https://mail.python.org/archives/list/python-ideas@python.org/thread/FCTXGDT2NNKRJQ6CDEPWUXHVG2AAQZZY/> have emerged the idea of extending also issubclass() and isinstance().
isinstance(int, int | str)
I think these syntaxes are more clear, and can help with the adoption of typing.
I test and implement these ideas in a two fork : One for CPython <https://github.com/pprados/cpython/tree/updage_isinstance> and one for MyPy <https://github.com/pprados/mypy/tree/add_INVERT_to_types>. See the branches add_OR_to_types (for Union syntax), add_INVERT_to_types (for Union and Optional syntax) or updage_isinstance (for new isinstance() and issubclass()).
How I implement that ? I add the operators __or__ and __revert__ to PyType_Type. The C code is similar of :
from typing import * def type_or(self,right): return Union[self,right] type(type).__or__ = type_or
with some check before return Union.
Actually, the accepted BNF syntax for typing is :
annotation: name_type name_type: NAME (args)? args: '[' paramslist ']' paramslist: annotation (',' annotation)* [',']
I propose to extend the BNF syntax to :
annotation: ( name_type | or_type | invert_type ) name_type: NAME (args)? args: '[' paramslist ']' paramslist: annotation (',' annotation)* [',']
or_type: name_type '|' annotation
invert_type: '~' annotation
Your remarks are welcome. Philippe Prados _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
Am 20.09.19 um 11:19 schrieb Philippe Prados:
I just publish the PEP-0604 <https://www.python.org/dev/peps/pep-0604/> for discussions (https://www.python.org/dev/peps/pep-0604/).
I'm strongly in favor of a more succinct syntax for both Union and Optional. But just to add my own bike-shedding to it: I prefer using the "or" operator over the "|" operator for Union. This feels more in line with existing Python operators and the preference for speaking code. "or" is the logical OR, while "|" is used for bit-wise operations. "x: int or str" is also quite intuitive. I also echo the sentiments of using "~" for Optional. As the bit-wise inversion operator it has quite a different meaning at the moment. - Sebastian
It's not possible now, before the PEP 335 <https://www.python.org/dev/peps/pep-0335/> was accepted, to overload the "or" operator. Le ven. 20 sept. 2019 à 14:41, Sebastian Rittau <srittau@rittau.biz> a écrit :
Am 20.09.19 um 11:19 schrieb Philippe Prados:
I just publish the PEP-0604 <https://www.python.org/dev/peps/pep-0604/> for discussions (https://www.python.org/dev/peps/pep-0604/).
I'm strongly in favor of a more succinct syntax for both Union and Optional. But just to add my own bike-shedding to it: I prefer using the "or" operator over the "|" operator for Union. This feels more in line with existing Python operators and the preference for speaking code. "or" is the logical OR, while "|" is used for bit-wise operations. "x: int or str" is also quite intuitive. I also echo the sentiments of using "~" for Optional. As the bit-wise inversion operator it has quite a different meaning at the moment.
- Sebastian _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
On Fri, Sep 20, 2019 at 10:41 PM Sebastian Rittau <srittau@rittau.biz> wrote:
Am 20.09.19 um 11:19 schrieb Philippe Prados:
I just publish the PEP-0604 for discussions (https://www.python.org/dev/peps/pep-0604/).
I'm strongly in favor of a more succinct syntax for both Union and Optional. But just to add my own bike-shedding to it: I prefer using the "or" operator over the "|" operator for Union. This feels more in line with existing Python operators and the preference for speaking code. "or" is the logical OR, while "|" is used for bit-wise operations. "x: int or str" is also quite intuitive. I also echo the sentiments of using "~" for Optional. As the bit-wise inversion operator it has quite a different meaning at the moment.
Both "int or str" and "str?" have the problem that they don't work under existing Python syntax, so they would be far greater changes. The definition of the "or" operator is baked into the language, but the "|" operator can have its semantics defined by the objects on either side. ChrisA
Am 20.09.19 um 14:49 schrieb Chris Angelico:
Both "int or str" and "str?" have the problem that they don't work under existing Python syntax, so they would be far greater changes. The definition of the "or" operator is baked into the language, but the "|" operator can have its semantics defined by the objects on either side.
"or" works with "from __future__ import annotations", which is a fine limitation in my opinion. - Sebastian
The Resolving type hints at runtime <https://www.python.org/dev/peps/pep-0563/#resolving-type-hints-at-runtime> says: “For code which uses annotations for other purposes, a regular eval(ann, globals, locals) call is enough to resolve the annotation.”. Without add a new operator `__or__` in type `type`, it’s not possible to resolve type hints at runtime.
from __future__ import annotations def foo() -> int | str: pass ... eval(foo.__annotations__['return']) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module> TypeError: unsupported operand type(s) for |: 'type' and 'type'
Le ven. 20 sept. 2019 à 15:35, Sebastian Rittau <srittau@rittau.biz> a écrit :
Am 20.09.19 um 14:49 schrieb Chris Angelico:
Both "int or str" and "str?" have the problem that they don't work under existing Python syntax, so they would be far greater changes. The definition of the "or" operator is baked into the language, but the "|" operator can have its semantics defined by the objects on either side.
"or" works with "from __future__ import annotations", which is a fine limitation in my opinion.
- Sebastian _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
I'd like to see a backward compatibility concern highlighted in the PEP -- given it's possible (and likely?) that some metaclass in the wild already defines `__or__` or `__invert__` semantics
class M(type): ... def __or__(self, other): return self ... class C(metaclass=M): pass ... C | int <class '__main__.C'>
Anthony On Fri, Sep 20, 2019 at 7:16 AM Philippe Prados <philippe.prados@gmail.com> wrote:
The Resolving type hints at runtime <https://www.python.org/dev/peps/pep-0563/#resolving-type-hints-at-runtime> says: “For code which uses annotations for other purposes, a regular eval(ann, globals, locals) call is enough to resolve the annotation.”. Without add a new operator `__or__` in type `type`, it’s not possible to resolve type hints at runtime.
from __future__ import annotations def foo() -> int | str: pass ... eval(foo.__annotations__['return']) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module> TypeError: unsupported operand type(s) for |: 'type' and 'type'
Le ven. 20 sept. 2019 à 15:35, Sebastian Rittau <srittau@rittau.biz> a écrit :
Am 20.09.19 um 14:49 schrieb Chris Angelico:
Both "int or str" and "str?" have the problem that they don't work under existing Python syntax, so they would be far greater changes. The definition of the "or" operator is baked into the language, but the "|" operator can have its semantics defined by the objects on either side.
"or" works with "from __future__ import annotations", which is a fine limitation in my opinion.
- Sebastian _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
_______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
Code that defines dunder methods on meta classes is likely already broken due to use of __getitem__ for generics. So there exists a precedent for not caring about such code. On September 20, 2019 6:04:04 PM GMT+02:00, Anthony Sottile <asottile@umich.edu> wrote:
I'd like to see a backward compatibility concern highlighted in the PEP -- given it's possible (and likely?) that some metaclass in the wild already defines `__or__` or `__invert__` semantics
class M(type): ... def __or__(self, other): return self ... class C(metaclass=M): pass ... C | int <class '__main__.C'>
Anthony
On Fri, Sep 20, 2019 at 7:16 AM Philippe Prados <philippe.prados@gmail.com> wrote:
The Resolving type hints at runtime
<https://www.python.org/dev/peps/pep-0563/#resolving-type-hints-at-runtime>
says: “For code which uses annotations for other purposes, a regular eval(ann, globals, locals) call is enough to resolve the annotation.”. Without add a new operator `__or__` in type `type`, it’s not possible to resolve type hints at runtime.
from __future__ import annotations def foo() -> int | str: pass ... eval(foo.__annotations__['return']) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module> TypeError: unsupported operand type(s) for |: 'type' and 'type'
Le ven. 20 sept. 2019 à 15:35, Sebastian Rittau <srittau@rittau.biz> a écrit :
Am 20.09.19 um 14:49 schrieb Chris Angelico:
Both "int or str" and "str?" have the problem that they don't work under existing Python syntax, so they would be far greater changes. The definition of the "or" operator is baked into the language, but the "|" operator can have its semantics defined by the objects on either side.
"or" works with "from __future__ import annotations", which is a fine limitation in my opinion.
- Sebastian _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
_______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
how so? I don't see how this interferes at all unless the metaclass is trying to implement genericism itself Anthony On Fri, Sep 20, 2019, 9:48 PM Markus Unterwaditzer <markus@unterwaditzer.net> wrote:
Code that defines dunder methods on meta classes is likely already broken due to use of __getitem__ for generics. So there exists a precedent for not caring about such code.
On September 20, 2019 6:04:04 PM GMT+02:00, Anthony Sottile < asottile@umich.edu> wrote:
I'd like to see a backward compatibility concern highlighted in the PEP -- given it's possible (and likely?) that some metaclass in the wild already defines `__or__` or `__invert__` semantics
class M(type): ... def __or__(self, other): return self ... class C(metaclass=M): pass ... C | int <class '__main__.C'>
Anthony
On Fri, Sep 20, 2019 at 7:16 AM Philippe Prados < philippe.prados@gmail.com> wrote:
The Resolving type hints at runtime <https://www.python.org/dev/peps/pep-0563/#resolving-type-hints-at-runtime> says: “For code which uses annotations for other purposes, a regular eval(ann, globals, locals) call is enough to resolve the annotation.”. Without add a new operator `__or__` in type `type`, it’s not possible to resolve type hints at runtime.
from __future__ import annotations def foo() -> int | str: pass ... eval(foo.__annotations__['return']) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module> TypeError: unsupported operand type(s) for |: 'type' and 'type'
Le ven. 20 sept. 2019 à 15:35, Sebastian Rittau <srittau@rittau.biz> a écrit :
Am 20.09.19 um 14:49 schrieb Chris Angelico:
Both "int or str" and "str?" have the problem that they don't work under existing Python syntax, so they would be far greater changes. The definition of the "or" operator is baked into the language, but the "|" operator can have its semantics defined by the objects on either side.
"or" works with "from __future__ import annotations", which is a fine limitation in my opinion.
- Sebastian _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
_______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
_______________________________________________
Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
I am thinking of code that has been written long before typing existed, and overloads __getitem__ with something else. Now if one had to define stub/typeshed files for that code and had to use generics, it would conflict.
On 20.09.2019, at 21:51, Anthony Sottile <asottile@umich.edu> wrote:
how so? I don't see how this interferes at all unless the metaclass is trying to implement genericism itself
Anthony
On Fri, Sep 20, 2019, 9:48 PM Markus Unterwaditzer <markus@unterwaditzer.net> wrote: Code that defines dunder methods on meta classes is likely already broken due to use of __getitem__ for generics. So there exists a precedent for not caring about such code.
On September 20, 2019 6:04:04 PM GMT+02:00, Anthony Sottile <asottile@umich.edu> wrote: I'd like to see a backward compatibility concern highlighted in the PEP -- given it's possible (and likely?) that some metaclass in the wild already defines `__or__` or `__invert__` semantics
class M(type): ... def __or__(self, other): return self ... class C(metaclass=M): pass ... C | int <class '__main__.C'>
Anthony
On Fri, Sep 20, 2019 at 7:16 AM Philippe Prados <philippe.prados@gmail.com> wrote: The Resolving type hints at runtime says: “For code which uses annotations for other purposes, a regular eval(ann, globals, locals) call is enough to resolve the annotation.”. Without add a new operator `__or__` in type `type`, it’s not possible to resolve type hints at runtime.
from __future__ import annotations def foo() -> int | str: pass ... eval(foo.__annotations__['return']) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module> TypeError: unsupported operand type(s) for |: 'type' and 'type'
Le ven. 20 sept. 2019 à 15:35, Sebastian Rittau <srittau@rittau.biz> a écrit : Am 20.09.19 um 14:49 schrieb Chris Angelico:
Both "int or str" and "str?" have the problem that they don't work under existing Python syntax, so they would be far greater changes. The definition of the "or" operator is baked into the language, but the "|" operator can have its semantics defined by the objects on either side.
"or" works with "from __future__ import annotations", which is a fine limitation in my opinion.
- Sebastian _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
generic of T where T defines __getitem__ is not a problem, I don't see your point On Fri, Sep 20, 2019, 10:07 PM Markus Unterwaditzer < markus@unterwaditzer.net> wrote:
I am thinking of code that has been written long before typing existed, and overloads __getitem__ with something else. Now if one had to define stub/typeshed files for that code and had to use generics, it would conflict.
On 20.09.2019, at 21:51, Anthony Sottile <asottile@umich.edu> wrote:
how so? I don't see how this interferes at all unless the metaclass is trying to implement genericism itself
Anthony
On Fri, Sep 20, 2019, 9:48 PM Markus Unterwaditzer < markus@unterwaditzer.net> wrote: Code that defines dunder methods on meta classes is likely already broken due to use of __getitem__ for generics. So there exists a precedent for not caring about such code.
On September 20, 2019 6:04:04 PM GMT+02:00, Anthony Sottile < asottile@umich.edu> wrote: I'd like to see a backward compatibility concern highlighted in the PEP -- given it's possible (and likely?) that some metaclass in the wild already defines `__or__` or `__invert__` semantics
class M(type): ... def __or__(self, other): return self ... class C(metaclass=M): pass ... C | int <class '__main__.C'>
Anthony
On Fri, Sep 20, 2019 at 7:16 AM Philippe Prados < philippe.prados@gmail.com> wrote: The Resolving type hints at runtime says: “For code which uses annotations for other purposes, a regular eval(ann, globals, locals) call is enough to resolve the annotation.”. Without add a new operator `__or__` in type `type`, it’s not possible to resolve type hints at runtime.
from __future__ import annotations def foo() -> int | str: pass ... eval(foo.__annotations__['return']) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module> TypeError: unsupported operand type(s) for |: 'type' and 'type'
Le ven. 20 sept. 2019 à 15:35, Sebastian Rittau <srittau@rittau.biz> a écrit : Am 20.09.19 um 14:49 schrieb Chris Angelico:
Both "int or str" and "str?" have the problem that they don't work under existing Python syntax, so they would be far greater changes. The definition of the "or" operator is baked into the language, but the "|" operator can have its semantics defined by the objects on either side.
"or" works with "from __future__ import annotations", which is a fine limitation in my opinion.
- Sebastian _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
I checked the impacts with the meta-classes.
class M(type): ... def __or__(self,other): return "Hello" ... def __invert__(self): return "World" ... class C(metaclass=M):pass ... C | int 'Hello' ~C 'Word' int | C typing.Union[int, __main__.C] Union[C,int] typing.Union[__main__.C, int]
Because type is the top level metaclass, there is no impact of the current code. The user can continue to use the old syntax with Union, to resolve ambiguities. I add this in the new draft of the PEP <https://github.com/pprados/peps/blob/pep-0604/pep-0604.rst> Philippe Le ven. 20 sept. 2019 à 22:12, Anthony Sottile <asottile@umich.edu> a écrit :
generic of T where T defines __getitem__ is not a problem, I don't see your point
On Fri, Sep 20, 2019, 10:07 PM Markus Unterwaditzer < markus@unterwaditzer.net> wrote:
I am thinking of code that has been written long before typing existed, and overloads __getitem__ with something else. Now if one had to define stub/typeshed files for that code and had to use generics, it would conflict.
On 20.09.2019, at 21:51, Anthony Sottile <asottile@umich.edu> wrote:
how so? I don't see how this interferes at all unless the metaclass is trying to implement genericism itself
Anthony
On Fri, Sep 20, 2019, 9:48 PM Markus Unterwaditzer < markus@unterwaditzer.net> wrote: Code that defines dunder methods on meta classes is likely already broken due to use of __getitem__ for generics. So there exists a precedent for not caring about such code.
On September 20, 2019 6:04:04 PM GMT+02:00, Anthony Sottile < asottile@umich.edu> wrote: I'd like to see a backward compatibility concern highlighted in the PEP -- given it's possible (and likely?) that some metaclass in the wild already defines `__or__` or `__invert__` semantics
class M(type): ... def __or__(self, other): return self ... class C(metaclass=M): pass ... C | int <class '__main__.C'>
Anthony
On Fri, Sep 20, 2019 at 7:16 AM Philippe Prados < philippe.prados@gmail.com> wrote: The Resolving type hints at runtime says: “For code which uses annotations for other purposes, a regular eval(ann, globals, locals) call is enough to resolve the annotation.”. Without add a new operator `__or__` in type `type`, it’s not possible to resolve type hints at runtime.
from __future__ import annotations def foo() -> int | str: pass ... eval(foo.__annotations__['return']) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module> TypeError: unsupported operand type(s) for |: 'type' and 'type'
Le ven. 20 sept. 2019 à 15:35, Sebastian Rittau <srittau@rittau.biz> a écrit : Am 20.09.19 um 14:49 schrieb Chris Angelico:
Both "int or str" and "str?" have the problem that they don't work under existing Python syntax, so they would be far greater changes. The definition of the "or" operator is baked into the language, but the "|" operator can have its semantics defined by the objects on either side.
"or" works with "from __future__ import annotations", which is a fine limitation in my opinion.
- Sebastian _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
_______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
The code "works" in that it doesn't crash, but it may result in unintended import-time side-effects when an annotation was requested (an example I've seen of `|` in the wild on a metaclass is a subprocess piping library) -- and you don't get the type annotation either you end up with the type's `|` or `~` being used so `__annotations__` is wrong On Sun, Sep 22, 2019 at 11:46 PM Philippe Prados <philippe.prados@gmail.com> wrote:
I checked the impacts with the meta-classes.
class M(type): ... def __or__(self,other): return "Hello" ... def __invert__(self): return "World" ... class C(metaclass=M):pass ... C | int 'Hello' ~C 'Word' int | C typing.Union[int, __main__.C] Union[C,int] typing.Union[__main__.C, int]
Because type is the top level metaclass, there is no impact of the current code. The user can continue to use the old syntax with Union, to resolve ambiguities. I add this in the new draft of the PEP <https://github.com/pprados/peps/blob/pep-0604/pep-0604.rst>
Philippe
Le ven. 20 sept. 2019 à 22:12, Anthony Sottile <asottile@umich.edu> a écrit :
generic of T where T defines __getitem__ is not a problem, I don't see your point
On Fri, Sep 20, 2019, 10:07 PM Markus Unterwaditzer < markus@unterwaditzer.net> wrote:
I am thinking of code that has been written long before typing existed, and overloads __getitem__ with something else. Now if one had to define stub/typeshed files for that code and had to use generics, it would conflict.
On 20.09.2019, at 21:51, Anthony Sottile <asottile@umich.edu> wrote:
how so? I don't see how this interferes at all unless the metaclass is trying to implement genericism itself
Anthony
On Fri, Sep 20, 2019, 9:48 PM Markus Unterwaditzer < markus@unterwaditzer.net> wrote: Code that defines dunder methods on meta classes is likely already broken due to use of __getitem__ for generics. So there exists a precedent for not caring about such code.
On September 20, 2019 6:04:04 PM GMT+02:00, Anthony Sottile < asottile@umich.edu> wrote: I'd like to see a backward compatibility concern highlighted in the PEP -- given it's possible (and likely?) that some metaclass in the wild already defines `__or__` or `__invert__` semantics
> class M(type): ... def __or__(self, other): return self ... > class C(metaclass=M): pass ... > C | int <class '__main__.C'>
Anthony
On Fri, Sep 20, 2019 at 7:16 AM Philippe Prados < philippe.prados@gmail.com> wrote: The Resolving type hints at runtime says: “For code which uses annotations for other purposes, a regular eval(ann, globals, locals) call is enough to resolve the annotation.”. Without add a new operator `__or__` in type `type`, it’s not possible to resolve type hints at runtime.
> from __future__ import annotations > def foo() -> int | str: pass ... > eval(foo.__annotations__['return']) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module> TypeError: unsupported operand type(s) for |: 'type' and 'type'
Le ven. 20 sept. 2019 à 15:35, Sebastian Rittau <srittau@rittau.biz> a écrit : Am 20.09.19 um 14:49 schrieb Chris Angelico:
Both "int or str" and "str?" have the problem that they don't work under existing Python syntax, so they would be far greater changes. The definition of the "or" operator is baked into the language, but the "|" operator can have its semantics defined by the objects on either side.
"or" works with "from __future__ import annotations", which is a fine limitation in my opinion.
- Sebastian _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
_______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
My point on the operator __invert__. - The old style string formatting <https://docs.python.org/2/library/stdtypes.html#string-formatting> use '%', the modulo operator. But in this context, the user can not make a mistake. I think, it is the same for toto:~int - The operator __invert__ (~) is not the best, like '?', but '?' is use by IPython and at time, Python has no operator for that. - This operator is not bad, because '~' is very little used by normal user and the usage of tilde <https://www.thecut.com/article/why-the-internet-tilde-is-our-most-perfect-tool-for-snark.html> is compatible with this proposition, as Guido van Rossum reminded - Why the typing propose the class Optional[T] ? I think it's because Union[T,None] is not exactly the same in the mind of the user. Optional say "Something or nothing". Union say "This type or this other type". I think the same arguments to accept the class Optional can be used to accept the operator __invert__. Philippe Le lun. 23 sept. 2019 à 14:38, Anthony Sottile <asottile@umich.edu> a écrit :
The code "works" in that it doesn't crash, but it may result in unintended import-time side-effects when an annotation was requested (an example I've seen of `|` in the wild on a metaclass is a subprocess piping library) -- and you don't get the type annotation either you end up with the type's `|` or `~` being used so `__annotations__` is wrong
On Sun, Sep 22, 2019 at 11:46 PM Philippe Prados < philippe.prados@gmail.com> wrote:
I checked the impacts with the meta-classes.
class M(type): ... def __or__(self,other): return "Hello" ... def __invert__(self): return "World" ... class C(metaclass=M):pass ... C | int 'Hello' ~C 'Word' int | C typing.Union[int, __main__.C] Union[C,int] typing.Union[__main__.C, int]
Because type is the top level metaclass, there is no impact of the current code. The user can continue to use the old syntax with Union, to resolve ambiguities. I add this in the new draft of the PEP <https://github.com/pprados/peps/blob/pep-0604/pep-0604.rst>
Philippe
Le ven. 20 sept. 2019 à 22:12, Anthony Sottile <asottile@umich.edu> a écrit :
generic of T where T defines __getitem__ is not a problem, I don't see your point
On Fri, Sep 20, 2019, 10:07 PM Markus Unterwaditzer < markus@unterwaditzer.net> wrote:
I am thinking of code that has been written long before typing existed, and overloads __getitem__ with something else. Now if one had to define stub/typeshed files for that code and had to use generics, it would conflict.
On 20.09.2019, at 21:51, Anthony Sottile <asottile@umich.edu> wrote:
how so? I don't see how this interferes at all unless the metaclass is trying to implement genericism itself
Anthony
On Fri, Sep 20, 2019, 9:48 PM Markus Unterwaditzer < markus@unterwaditzer.net> wrote: Code that defines dunder methods on meta classes is likely already broken due to use of __getitem__ for generics. So there exists a precedent for not caring about such code.
On September 20, 2019 6:04:04 PM GMT+02:00, Anthony Sottile < asottile@umich.edu> wrote: I'd like to see a backward compatibility concern highlighted in the PEP -- given it's possible (and likely?) that some metaclass in the wild already defines `__or__` or `__invert__` semantics
>> class M(type): ... def __or__(self, other): return self ... >> class C(metaclass=M): pass ... >> C | int <class '__main__.C'>
Anthony
On Fri, Sep 20, 2019 at 7:16 AM Philippe Prados < philippe.prados@gmail.com> wrote: The Resolving type hints at runtime says: “For code which uses annotations for other purposes, a regular eval(ann, globals, locals) call is enough to resolve the annotation.”. Without add a new operator `__or__` in type `type`, it’s not possible to resolve type hints at runtime.
>> from __future__ import annotations >> def foo() -> int | str: pass ... >> eval(foo.__annotations__['return']) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module> TypeError: unsupported operand type(s) for |: 'type' and 'type'
Le ven. 20 sept. 2019 à 15:35, Sebastian Rittau <srittau@rittau.biz> a écrit : Am 20.09.19 um 14:49 schrieb Chris Angelico:
Both "int or str" and "str?" have the problem that they don't work under existing Python syntax, so they would be far greater changes. The definition of the "or" operator is baked into the language, but the "|" operator can have its semantics defined by the objects on either side.
"or" works with "from __future__ import annotations", which is a fine limitation in my opinion.
- Sebastian _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
_______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
I'm not convinced by this argument. %-style formatting has been superseded by new-style formatting using str.format and f-strings more recently. The PEP for new-style formatting does not mention that overloading % is confusing for people who know it as modulo, but I would not count it as endorsement of this sort of thing either. Then there's the argument that mentions Option. I recognize that this successfully argues why we should have a shortcut for optional types at all, but to me it does not argue why ~ is a good choice. Optional as a class name does not overload existing concepts in the same way.
On 24.09.2019, at 18:37, Philippe Prados <philippe.prados@gmail.com> wrote:
My point on the operator __invert__. • The old style string formatting use '%', the modulo operator. But in this context, the user can not make a mistake. I think, it is the same for toto:~int • The operator __invert__ (~) is not the best, like '?', but '?' is use by IPython and at time, Python has no operator for that. • This operator is not bad, because '~' is very little used by normal user and the usage of tilde is compatible with this proposition, as Guido van Rossum reminded • Why the typing propose the class Optional[T] ? I think it's because Union[T,None] is not exactly the same in the mind of the user. Optional say "Something or nothing". Union say "This type or this other type". I think the same arguments to accept the class Optional can be used to accept the operator __invert__. Philippe
Le lun. 23 sept. 2019 à 14:38, Anthony Sottile <asottile@umich.edu> a écrit : The code "works" in that it doesn't crash, but it may result in unintended import-time side-effects when an annotation was requested (an example I've seen of `|` in the wild on a metaclass is a subprocess piping library) -- and you don't get the type annotation either you end up with the type's `|` or `~` being used so `__annotations__` is wrong
On Sun, Sep 22, 2019 at 11:46 PM Philippe Prados <philippe.prados@gmail.com> wrote: I checked the impacts with the meta-classes.
class M(type): ... def __or__(self,other): return "Hello" ... def __invert__(self): return "World" ... class C(metaclass=M):pass ... C | int 'Hello' ~C 'Word' int | C typing.Union[int, __main__.C] Union[C,int] typing.Union[__main__.C, int]
Because type is the top level metaclass, there is no impact of the current code. The user can continue to use the old syntax with Union, to resolve ambiguities. I add this in the new draft of the PEP
Philippe
Le ven. 20 sept. 2019 à 22:12, Anthony Sottile <asottile@umich.edu> a écrit : generic of T where T defines __getitem__ is not a problem, I don't see your point
On Fri, Sep 20, 2019, 10:07 PM Markus Unterwaditzer <markus@unterwaditzer.net> wrote: I am thinking of code that has been written long before typing existed, and overloads __getitem__ with something else. Now if one had to define stub/typeshed files for that code and had to use generics, it would conflict.
On 20.09.2019, at 21:51, Anthony Sottile <asottile@umich.edu> wrote:
how so? I don't see how this interferes at all unless the metaclass is trying to implement genericism itself
Anthony
On Fri, Sep 20, 2019, 9:48 PM Markus Unterwaditzer <markus@unterwaditzer.net> wrote: Code that defines dunder methods on meta classes is likely already broken due to use of __getitem__ for generics. So there exists a precedent for not caring about such code.
On September 20, 2019 6:04:04 PM GMT+02:00, Anthony Sottile <asottile@umich.edu> wrote: I'd like to see a backward compatibility concern highlighted in the PEP -- given it's possible (and likely?) that some metaclass in the wild already defines `__or__` or `__invert__` semantics
class M(type): ... def __or__(self, other): return self ... class C(metaclass=M): pass ... C | int <class '__main__.C'>
Anthony
On Fri, Sep 20, 2019 at 7:16 AM Philippe Prados <philippe.prados@gmail.com> wrote: The Resolving type hints at runtime says: “For code which uses annotations for other purposes, a regular eval(ann, globals, locals) call is enough to resolve the annotation.”. Without add a new operator `__or__` in type `type`, it’s not possible to resolve type hints at runtime.
from __future__ import annotations def foo() -> int | str: pass ... eval(foo.__annotations__['return']) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module> TypeError: unsupported operand type(s) for |: 'type' and 'type'
Le ven. 20 sept. 2019 à 15:35, Sebastian Rittau <srittau@rittau.biz> a écrit : Am 20.09.19 um 14:49 schrieb Chris Angelico:
Both "int or str" and "str?" have the problem that they don't work under existing Python syntax, so they would be far greater changes. The definition of the "or" operator is baked into the language, but the "|" operator can have its semantics defined by the objects on either side.
"or" works with "from __future__ import annotations", which is a fine limitation in my opinion.
- Sebastian _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
_______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
On Wed, Sep 25, 2019 at 3:14 AM Markus Unterwaditzer <markus@unterwaditzer.net> wrote:
I'm not convinced by this argument. %-style formatting has been superseded by new-style formatting using str.format and f-strings more recently. The PEP for new-style formatting does not mention that overloading % is confusing for people who know it as modulo, but I would not count it as endorsement of this sort of thing either.
Percent formatting isn't superseded or replaced, and the new Path objects overload division in an intuitive way. There IS precedent for (ab)using operators because their symbols are appropriate. But ~int isn't nearly as appealing to me as int|str, proposal-wise. If ~ gets dropped from this proposal, someone else can always pick it up separately and repropose it. ChrisA
Since you mentioned my name, let me explain my current position on how to spell "optional". - We've had a lot of feedback from mypy users who were confused by Optional[T] and thought this was needed for "optional" function arguments (i.e. those that have a default). - Another situation where people have been confused Optional is in TypedDict, where we wanted to have a way to say "this key may be present or absent" (in the end we couldn't find a good keyword for this so we went with "total=<bool>" for the entire dict). - It would probably have been less confusing if it had been called "nullable" (or "noneable"? Ruby's Sorbet type system calls it "nilable"). - In TypeScript you just write "int | None", and that looks readable enough to me -- and perfectly unambiguous. So my preference would be to drop the "~" proposal (or aspirations for "?") and instead just write "int | None". IIRC at last Friday's Bay Area typing meetup there was general agreement with this sentiment. --Guido On Tue, Sep 24, 2019 at 9:38 AM Philippe Prados <philippe.prados@gmail.com> wrote:
My point on the operator __invert__.
- The old style string formatting <https://docs.python.org/2/library/stdtypes.html#string-formatting> use '%', the modulo operator. But in this context, the user can not make a mistake. I think, it is the same for toto:~int - The operator __invert__ (~) is not the best, like '?', but '?' is use by IPython and at time, Python has no operator for that. - This operator is not bad, because '~' is very little used by normal user and the usage of tilde <https://www.thecut.com/article/why-the-internet-tilde-is-our-most-perfect-tool-for-snark.html> is compatible with this proposition, as Guido van Rossum reminded - Why the typing propose the class Optional[T] ? I think it's because Union[T,None] is not exactly the same in the mind of the user. Optional say "Something or nothing". Union say "This type or this other type". I think the same arguments to accept the class Optional can be used to accept the operator __invert__.
Philippe
Le lun. 23 sept. 2019 à 14:38, Anthony Sottile <asottile@umich.edu> a écrit :
The code "works" in that it doesn't crash, but it may result in unintended import-time side-effects when an annotation was requested (an example I've seen of `|` in the wild on a metaclass is a subprocess piping library) -- and you don't get the type annotation either you end up with the type's `|` or `~` being used so `__annotations__` is wrong
On Sun, Sep 22, 2019 at 11:46 PM Philippe Prados < philippe.prados@gmail.com> wrote:
I checked the impacts with the meta-classes.
class M(type): ... def __or__(self,other): return "Hello" ... def __invert__(self): return "World" ... class C(metaclass=M):pass ... C | int 'Hello' ~C 'Word' int | C typing.Union[int, __main__.C] Union[C,int] typing.Union[__main__.C, int]
Because type is the top level metaclass, there is no impact of the current code. The user can continue to use the old syntax with Union, to resolve ambiguities. I add this in the new draft of the PEP <https://github.com/pprados/peps/blob/pep-0604/pep-0604.rst>
Philippe
Le ven. 20 sept. 2019 à 22:12, Anthony Sottile <asottile@umich.edu> a écrit :
generic of T where T defines __getitem__ is not a problem, I don't see your point
On Fri, Sep 20, 2019, 10:07 PM Markus Unterwaditzer < markus@unterwaditzer.net> wrote:
I am thinking of code that has been written long before typing existed, and overloads __getitem__ with something else. Now if one had to define stub/typeshed files for that code and had to use generics, it would conflict.
On 20.09.2019, at 21:51, Anthony Sottile <asottile@umich.edu> wrote:
how so? I don't see how this interferes at all unless the metaclass is trying to implement genericism itself
Anthony
On Fri, Sep 20, 2019, 9:48 PM Markus Unterwaditzer < markus@unterwaditzer.net> wrote: Code that defines dunder methods on meta classes is likely already broken due to use of __getitem__ for generics. So there exists a precedent for not caring about such code.
On September 20, 2019 6:04:04 PM GMT+02:00, Anthony Sottile < asottile@umich.edu> wrote: I'd like to see a backward compatibility concern highlighted in the PEP -- given it's possible (and likely?) that some metaclass in the wild already defines `__or__` or `__invert__` semantics
>>> class M(type): ... def __or__(self, other): return self ... >>> class C(metaclass=M): pass ... >>> C | int <class '__main__.C'>
Anthony
On Fri, Sep 20, 2019 at 7:16 AM Philippe Prados < philippe.prados@gmail.com> wrote: The Resolving type hints at runtime says: “For code which uses annotations for other purposes, a regular eval(ann, globals, locals) call is enough to resolve the annotation.”. Without add a new operator `__or__` in type `type`, it’s not possible to resolve type hints at runtime. >>> from __future__ import annotations >>> def foo() -> int | str: pass ... >>> eval(foo.__annotations__['return']) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module> TypeError: unsupported operand type(s) for |: 'type' and 'type'
Le ven. 20 sept. 2019 à 15:35, Sebastian Rittau <srittau@rittau.biz> a écrit : Am 20.09.19 um 14:49 schrieb Chris Angelico: > Both "int or str" and "str?" have the problem that they don't work > under existing Python syntax, so they would be far greater changes. > The definition of the "or" operator is baked into the language, but > the "|" operator can have its semantics defined by the objects on > either side.
"or" works with "from __future__ import annotations", which is a fine limitation in my opinion.
- Sebastian _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
_______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
_______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
-- --Guido van Rossum (python.org/~guido) *Pronouns: he/him/his **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
On Tue, 24 Sep 2019 at 13:13, Guido van Rossum <guido@python.org> wrote:
Since you mentioned my name, let me explain my current position on how to spell "optional".
- We've had a lot of feedback from mypy users who were confused by Optional[T] and thought this was needed for "optional" function arguments (i.e. those that have a default).
- Another situation where people have been confused Optional is in TypedDict, where we wanted to have a way to say "this key may be present or absent" (in the end we couldn't find a good keyword for this so we went with "total=<bool>" for the entire dict).
- It would probably have been less confusing if it had been called "nullable" (or "noneable"? Ruby's Sorbet type system calls it "nilable").
- In TypeScript you just write "int | None", and that looks readable enough to me -- and perfectly unambiguous.
So my preference would be to drop the "~" proposal (or aspirations for "?") and instead just write "int | None".
IIRC at last Friday's Bay Area typing meetup there was general agreement with this sentiment.
Yes, most people agreed that `~` is not a good idea, and we should just go ahead with `int | None`. Also most people agreed we may reconsider `int?` in a separate PEP later (possibly in conjunction with PEP 505). Btw, majority of people also agreed that allowing `isinstance(x, int | str)` is a good idea (mostly for type aliases that can be used both at runtime and in an annotation) assuming `isinstance(x, str | List[str])` is still an error. If the PEP authors don't have problems with this, then I would propose to move towards discussing details of the proposed implementation. -- Ivan
Ok. I agree. I will split the PEP. The next version I'm going to submit propose only int | str, int | None, and isinstance(x str | int). What do you think about that ? except int | str : Philippe Prados Le mar. 24 sept. 2019 à 22:42, Ivan Levkivskyi <levkivskyi@gmail.com> a écrit :
On Tue, 24 Sep 2019 at 13:13, Guido van Rossum <guido@python.org> wrote:
Since you mentioned my name, let me explain my current position on how to spell "optional".
- We've had a lot of feedback from mypy users who were confused by Optional[T] and thought this was needed for "optional" function arguments (i.e. those that have a default).
- Another situation where people have been confused Optional is in TypedDict, where we wanted to have a way to say "this key may be present or absent" (in the end we couldn't find a good keyword for this so we went with "total=<bool>" for the entire dict).
- It would probably have been less confusing if it had been called "nullable" (or "noneable"? Ruby's Sorbet type system calls it "nilable").
- In TypeScript you just write "int | None", and that looks readable enough to me -- and perfectly unambiguous.
So my preference would be to drop the "~" proposal (or aspirations for "?") and instead just write "int | None".
IIRC at last Friday's Bay Area typing meetup there was general agreement with this sentiment.
Yes, most people agreed that `~` is not a good idea, and we should just go ahead with `int | None`. Also most people agreed we may reconsider `int?` in a separate PEP later (possibly in conjunction with PEP 505). Btw, majority of people also agreed that allowing `isinstance(x, int | str)` is a good idea (mostly for type aliases that can be used both at runtime and in an annotation) assuming `isinstance(x, str | List[str])` is still an error.
If the PEP authors don't have problems with this, then I would propose to move towards discussing details of the proposed implementation.
-- Ivan
Let's not do `except E1|E2`. It doesn't look like a readability improvement over `except (E1, E2)`, and I don't think there's much of a use case for having a type alias such as `E = E1|E2` that's both used in annotations and in an except clause. (If you show me real code that contradicts me I might change my mind.) Even though exceptions are classes, their use and handling is almost completely separate from the types we use for type checking. (In contrast with isinstance(), which does play a legitimate role in type refinements.) --Guido On Wed, Sep 25, 2019 at 1:25 AM Philippe Prados <philippe.prados@gmail.com> wrote:
Ok. I agree.
I will split the PEP. The next version I'm going to submit propose only int | str, int | None, and isinstance(x str | int). What do you think about that ? except int | str :
Philippe Prados
Le mar. 24 sept. 2019 à 22:42, Ivan Levkivskyi <levkivskyi@gmail.com> a écrit :
On Tue, 24 Sep 2019 at 13:13, Guido van Rossum <guido@python.org> wrote:
Since you mentioned my name, let me explain my current position on how to spell "optional".
- We've had a lot of feedback from mypy users who were confused by Optional[T] and thought this was needed for "optional" function arguments (i.e. those that have a default).
- Another situation where people have been confused Optional is in TypedDict, where we wanted to have a way to say "this key may be present or absent" (in the end we couldn't find a good keyword for this so we went with "total=<bool>" for the entire dict).
- It would probably have been less confusing if it had been called "nullable" (or "noneable"? Ruby's Sorbet type system calls it "nilable").
- In TypeScript you just write "int | None", and that looks readable enough to me -- and perfectly unambiguous.
So my preference would be to drop the "~" proposal (or aspirations for "?") and instead just write "int | None".
IIRC at last Friday's Bay Area typing meetup there was general agreement with this sentiment.
Yes, most people agreed that `~` is not a good idea, and we should just go ahead with `int | None`. Also most people agreed we may reconsider `int?` in a separate PEP later (possibly in conjunction with PEP 505). Btw, majority of people also agreed that allowing `isinstance(x, int | str)` is a good idea (mostly for type aliases that can be used both at runtime and in an annotation) assuming `isinstance(x, str | List[str])` is still an error.
If the PEP authors don't have problems with this, then I would propose to move towards discussing details of the proposed implementation.
-- Ivan
-- --Guido van Rossum (python.org/~guido) *Pronouns: he/him/his **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
I just publish a new version of PEP-604 with only the __or__ operator. I thinks, now, it's can be accepted. What is the next step ? Philippe Le sam. 28 sept. 2019 à 21:29, Ivan Levkivskyi <levkivskyi@gmail.com> a écrit :
On Wed, 25 Sep 2019 at 16:20, Guido van Rossum <guido@python.org> wrote:
Let's not do `except E1|E2`
I agree with this. This feels much less valuable, and will likely cause implementation "friction".
-- Ivan
On Tue, Oct 1, 2019 at 11:18 PM Philippe Prados <philippe.prados@gmail.com> wrote:
I just publish a new version of PEP-604 with only the __or__ operator.
I thinks, now, it's can be accepted. What is the next step ?
Philippe
I'd recommend first re-posting your PEP, full text, as a brand new thread (altered subject, and not a reply to anything in this thread). Invite a second round of discussion. There'll be more bikeshedding to come, I'm confident of that :) ChrisA
Not all types fit in a type annotation context. Due to Python's eager resolution of logical "or"s and "and"s, using this syntax is out of the question. The binary or is cute though. - Ł
On 20 Sep 2019, at 15:34, Sebastian Rittau <srittau@rittau.biz> wrote:
Am 20.09.19 um 14:49 schrieb Chris Angelico:
Both "int or str" and "str?" have the problem that they don't work under existing Python syntax, so they would be far greater changes. The definition of the "or" operator is baked into the language, but the "|" operator can have its semantics defined by the objects on either side.
"or" works with "from __future__ import annotations", which is a fine limitation in my opinion.
- Sebastian _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/
Using binary negation to mean something other than negation bothers me. Using binary or seems useful and intuitive given precedence from at least Typescript. I believe "x | None" is already an improvement over the status quo. I would suggest to focus on getting the Union shorthand stabilized and defer the decision over Optional. On September 20, 2019 11:19:06 AM GMT+02:00, Philippe Prados <philippe.prados@gmail.com> wrote:
Hello everybody,
I just publish the PEP-0604 <https://www.python.org/dev/peps/pep-0604/> for discussions (https://www.python.org/dev/peps/pep-0604/).
Scala 3 propose a new syntax for Union type. See here <https://dotty.epfl.ch/docs/reference/new-types/union-types.html>. I propose to add a similar syntax in Python.
# Operator for Union assert( int | str == Union[int,str]) assert( int | str | float == Union[int,str,float]) # Operator for Optional assert( ~int == Optional[int])
Now, it's possible to write:
def fn(bag:List[int | str], option: ~int = None) -> float | str: ...
in place of
def fn(bag:List[Option[int,str]], option: Optional[int] = None) -> Union[float,str]: ...
The discussion on python-new@python.org here <https://mail.python.org/archives/list/python-ideas@python.org/thread/FCTXGDT2NNKRJQ6CDEPWUXHVG2AAQZZY/> have emerged the idea of extending also issubclass() and isinstance().
isinstance(int, int | str)
I think these syntaxes are more clear, and can help with the adoption of typing.
I test and implement these ideas in a two fork : One for CPython <https://github.com/pprados/cpython/tree/updage_isinstance> and one for MyPy <https://github.com/pprados/mypy/tree/add_INVERT_to_types>. See the branches add_OR_to_types (for Union syntax), add_INVERT_to_types (for Union and Optional syntax) or updage_isinstance (for new isinstance() and issubclass()).
How I implement that ? I add the operators __or__ and __revert__ to PyType_Type. The C code is similar of :
from typing import * def type_or(self,right): return Union[self,right] type(type).__or__ = type_or
with some check before return Union.
Actually, the accepted BNF syntax for typing is :
annotation: name_type name_type: NAME (args)? args: '[' paramslist ']' paramslist: annotation (',' annotation)* [',']
I propose to extend the BNF syntax to :
annotation: ( name_type | or_type | invert_type ) name_type: NAME (args)? args: '[' paramslist ']' paramslist: annotation (',' annotation)* [',']
or_type: name_type '|' annotation
invert_type: '~' annotation
Your remarks are welcome. Philippe Prados
participants (10)
-
Anthony Sottile
-
Bernat Gabor
-
Chris Angelico
-
Guido van Rossum
-
Ivan Levkivskyi
-
Jakub Stasiak
-
Markus Unterwaditzer
-
Philippe Prados
-
Sebastian Rittau
-
Łukasz Langa