[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-03-14 Thread Guido van Rossum
FWIW after reviewing the feedback on the PEP, I think now that we should
proceed with the original proposal and submit it to the Steering  Council's
tracker (https://github.com/python/steering-council/issues) for their
review.

Eric, what do you think?

--Guido


On Tue, Feb 9, 2021 at 8:21 AM Guido van Rossum  wrote:

> I think we have reached consensus on PEP 647 in typing-sig. We have
> implementations for mypy and pyright, not sure about the rest. This PEP
> does not affect CPython directly except for the addition of one special
> item (TypeGuard) to typing.py -- it would be nice to get that in the 3.10
> stdlib.
>
> I'm CC'ing python-dev here to see if there are any further comments; if
> not, we can initiate the approval process by creating an issue at
> https://github.com/python/steering-council.
>
> --
> --Guido van Rossum (python.org/~guido)
> *Pronouns: he/him **(why is my pronoun here?)*
> 
>


-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
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/IUYVIWDWH2OI4NERJHV4632YURP6LVLG/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-16 Thread Jim J. Jewett
Eric Traut wrote:

"""It must be possible to express the type guard within the function signature. 
In other words, the implementation should not need to be present. This is 
important for compatibility with type stubs and to guarantee consistent 
behaviors between type checkers."""

Can type stubs include a docstring?  If so, then adding subsequent lines that 
are only parameter annotations doesn't seem like a problem.  

And frankly, allowing subsequent lines (possibly restricted to 
first-except-docstrings) doesn't seem any more invasive than adding another 
magic type that has to be interpreted differently.  (I understand it might be 
more coding in practice, based on one solution having already been written.)

def is_str_list(val: List[object]) -> bool:
"""Determines whether all objects in the list are strings"""
val: NarrowsTo[List[str]]

I agree that Greg's suggestion of 

def is_str_list(val: Constrains[List[object]:List[str]) -> bool:

also meets the criteria you list, but ... as a human reader, that signature is 
getting too heavy.

I'll also note that I don't think TypeScript is a good model for "this won't be 
a problem."  It is probably a good model for "this will work for the people who 
*want* to go whole hog on explicit typing", but for people who are at best 
agnostic about typing ... they would stick with JavaScript, instead of using 
TypeScript.  Alas, this change isn't being proposed just for TypedPython; it is 
being proposed for baseline python.

-jJ
___
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/DXVRLPGFUYQ2CDNMQSS66M7RITSGIB3R/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-16 Thread Jim J. Jewett
Another advantage of annotating the variable is that it moves some stuff out 
the signature line.

def is_str_list(val: List[object]) -> TypeGuard[List[str]]:

is probably OK on length, but if there were even a second typed and defaulted 
parameter, it would start to get unwieldy.  And if the answer is "there won't 
be, these are simple functions", then that sort of screams that these are a 
special kind of function that should be decorated to alert readers to the 
restriction.

def is_str_list(val: List[object]) -> bool:
val: NarrowsTo[List[str]]

is still near the top (like a docstring), and doesn't require a change in how 
to interpret existing syntax.  Someone who doesn't care about typing can wonder 
why you bothered to quote/assert val, just as they can wonder why you did that 
to a docstring, but it will be (almost) as obvious that the line doesn't *do* 
anything -- so at least they won't assume it is doing something else (such as 
returning some custom type that you happen to call TypeGuard). 

-jJ
___
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/IZULNMCU6SHAFDO4BFGWEDE3ZNUHWPFZ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-16 Thread Joseph Perez
> Could you summarize your proposal in a few lines?
Use PEP 593 `Annotated` the way Adrian has proposed, but with an additional 
parameter which maps the type guard on the given function parameter name:
```python
def check_int_and_str(x, y) -> Annotated[bool, TypeGuard(int, "x"), 
TypeGuard(str, "y")]:
return isinstance(x, int) and isinstance(y, str)
```
Provide the following shortcuts:
- `TypeGuard` second parameter can be omitted,  i.e. `TypeGuard(int)`; the type 
guard then apply to the first parameter of the function
- `TypeGuard` can be used like a type, i.e. `def is_int(x) -> TypeGuard[int]` 
(and the type guard apply then to the first parameter), but it has to be 
evaluated to `Annotated[bool, TypeGuard(int)]` at runtime (by implementing 
`TypeGuard.__class_getitem__`).
To be interpreted by type checkers, type guard must be evaluated as a boolean 
condition (exactly as the current proposal):
```python
def is_int(x) -> TypeGuard[int]:
return isinstance(x, int)
x = ...
if is_int(x):
# reveal_type(x) -> int
while is_int(x):
# reveal_type(x) -> int
def foo(x):
assert is_int(x)
# reveal_type(x) -> int
```
Restriction: `TypeGuard` second parameter must be a string literal 
corresponding to the name of a function whose return type is annotated, or must 
be omitted.

A possible implementation of `TypeGuard` would be:
```python
class TypeGuard:
def __init__(self, tp, param=None):
self.tp = tp
if param is not None and not isinstance(param, str):
raise TypeError("Type guard parameter mapping must be a string")
self.param = param

def __class_getitem__(self, item):
return Annotated[bool, TypeGuard(item)]
```

(It's not really different than my first mail, but I've fixed my mistake by 
using `__class_getitem__` instead of `__getitem__)

I see the following advantages of using PEP 593:
-  it will not break type checkers implementation when it will be released (at 
the condition of using the raw `Annotated` form and not the second shortcut)
- the second shortcut makes it as easy to use than the current proposal using a 
special form
- it allows supporting type guard for multiple parameters (but this use case 
should be quite occasional)
- it will not break tools using runtime introspection (I think the case where 
return type of type guard predicate is inspected at runtime will also be very 
uncommon)
- it allows returning other thing than a boolean, for example an `Optional` 
value:
```python
def get_bar(foo) -> Annotated[Optional[Bar], TypeGuard(Foo)]:
return foo.bar if isinstance(foo, Foo) else None

foo = …
if bar := get_bar(foo):
# foo will be inferred as Foo
```
but this use case should be quite occasional too (and it's kind of tricky 
because if the type guard function returns an `Optional[int]` and the return is 
`0`, the type guard will still *fail*)
- lastly, it would be a good way to introduce PEP 593 into the standard 
library, as I see other use cases for it (especially `ClassVar` and `InitVar`), 
but that's an other subject.

The drawbacks:
- `TypeGuard` will not be interpreted when present in a `Callable` signature, 
and the following example will not be possible:
```python
def infer_list(l: list, guard: Callable[[Any], TypeGuard[T]]) -> 
TypeGuard[list[T]]:
return all(map(guard, l))
```
but this use case should also be occasional (especially because of the lack of 
generic type var, that make impossible to replace `list` by a `TypeVar`). By 
the way, I don't know if things like this are possible in TypeScript.
- your quote:
> I see PEP 593 as a verbose solution to the problem "how do we use annotations 
> for static typing and for runtime metadata simultaneously". Type guards solve 
> a problem that's entirely in the realm of static typing, so IMO it would be 
> an abuse of Annotated.

because I quite agree with you; contrary to `ClassVar` and `InitVar` which are 
used at runtime, `TypeGuard` should only be used by type checkers.

So there are pros and cons, but they are mostly about occasional use cases.
Personally, I would be more in favor of PEP 593, but the current proposal if 
also fine to me.
___
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/BISHSBSOYAYRY736P7RRONNVJWVWGJTY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-16 Thread Guido van Rossum
Could you summarize your proposal in a few lines? I've tried to read that
email several times now and I still don't follow the proposal. You can
leave the reasoning *why* you believe your proposal is better out -- I just
want to see what it will look like (how to define a type guard, and how to
use it).

On Tue, Feb 16, 2021 at 11:39 AM Joseph Perez  wrote:

> I've proposed PEP 593 `Annotated` too, but in the typing-sig mailing list:
> https://mail.python.org/archives/list/typing-...@python.org/message/CVLLRWU7MU7T2AMC4P7ZEG4IMJF6V5UL/
> and Guido had the following answer:
> > I see PEP 593 as a verbose solution to the problem "how do we use
> annotations for static typing and for runtime metadata simultaneously".
> Type guards solve a problem that's entirely in the realm of static typing,
> so IMO it would be an abuse of Annotated.
>
> (I've also written in the mail about checked cast as an alternative
> solution to type guard.)
>
> > For the most extensible approach both -> TypeGuard(...)  and
> -> Annotated[bool, TypeGuard(...)] could be allowed, which would open the
> path for future non-type-annotations, which could be used regardless of
> whether the code
> is type-annotated.
> I've proposed a possible implementation in my mail linked above.
> ___
> 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/B3QZTPW6S6LHQKX476VRYAWEVMZ26VHH/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
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/RL7KWEW6OKWW7TLZAX4AE76EJHG5LAWD/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-16 Thread Joseph Perez
I've proposed PEP 593 `Annotated` too, but in the typing-sig mailing list: 
https://mail.python.org/archives/list/typing-...@python.org/message/CVLLRWU7MU7T2AMC4P7ZEG4IMJF6V5UL/
and Guido had the following answer:
> I see PEP 593 as a verbose solution to the problem "how do we use
annotations for static typing and for runtime metadata simultaneously".
Type guards solve a problem that's entirely in the realm of static typing,
so IMO it would be an abuse of Annotated.

(I've also written in the mail about checked cast as an alternative solution to 
type guard.)

> For the most extensible approach both -> TypeGuard(...)  and
-> Annotated[bool, TypeGuard(...)] could be allowed, which would open the
path for future non-type-annotations, which could be used regardless of whether 
the code
is type-annotated.
I've proposed a possible implementation in my mail linked above.
___
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/B3QZTPW6S6LHQKX476VRYAWEVMZ26VHH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-15 Thread Emily Bowman
FWIW, it would really be nice if this was called IsInstance[...]; I feel
like that would neatly encapsulate its meaning to both old and new, that
it's just a yes/no on whether this is an instance of [...]. TypeScript has
the concept of a type guard but doesn't use that name in code, so there's
no reason to be wedded to it.

-Em
___
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/T3XEKYHDOFC6EDVUSC55AQKLW2NY3JWK/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-14 Thread David Mertz
On Sun, Feb 14, 2021, 5:34 PM Guido van Rossum  wrote:

> But note that 'bool' in Python is not subclassable.
>

Sure. But that's why I suggested 'Bool' rather than 'bool'. It's a
different spelling, but one with a really obvious connection.

>
> I.e. if I read this:
>>
>> def is_str_list(v: List[Any]) -> Bool[List[str]]:
>> ...
>>
>> I just think, "OK, it returns a bool, and those mypy people are doing
>> something else funny that I don't need to worry about."
>>
>
>> So maybe you should just stick to "bool". TypeGuard is really only useful
> for people who care about what type checkers do (a surprisingly large
> contingent, actually, but I would not recommend it for the education
> department).
>

I'm fairly sure I *will* just stick with 'bool' in code I write, no matter
the outcome of this PEP. But I'm also sure I'll read code written by other
people in the future... And EXPLAIN code written by other people to people
less knowledgeable than I am.

When explaining code to students or junior colleagues, it feels MUCH easier
to explain "Bool[...] is a funny way of spelling 'bool' (in annotations)"
than explaining the same of TypeGuard [...].
___
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/XAFHBVTZAT5CASC6QTZFGTSJ5DTHLLM5/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-14 Thread Sebastian Kreft
That pattern is used almost as much as multi-argument guards.

I checked the typings from DefinitelyTyped (JS equivalent of typeshed) and
found the following statistics:

7501 packages
100 (1.3%) packages defining type guards
13 (0.17%) packages defining multi-argument type guards
10 (0.13%) packages defining type guards for this (self)

On Fri, Feb 12, 2021 at 12:00 AM Guido van Rossum  wrote:

> I think the use case (for x.is_foo()) is rare. And instead of writing
> x.is_foo(x), if you make the guard a function you can write is_foo(x).
>
> On Thu, Feb 11, 2021 at 6:51 PM Sebastian Kreft  wrote:
>
>> I still think that we should reconsider deferring what happens to class
>> and instance methods.
>>
>> The arguments given in https://www.python.org/dev/peps/pep-0647/#id13
>> seem insufficient, specially considering than the workaround provided is
>> quite awkward.
>>
>> The author suggests to write def check(self, self2) -> Typeguard[T] and
>> call it as self.check(self).
>> ___
>> 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/CA2MFS4XXDPC6PDBW53BZWLWEMQOBBP6/
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>
>
> --
> --Guido van Rossum (python.org/~guido)
> *Pronouns: he/him **(why is my pronoun here?)*
> 
>


-- 
Sebastian Kreft
___
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/HI3TW2SPJW5XKUYNFPWB5O4J3KZTR2EO/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-14 Thread Larry Hastings


On 2/14/21 2:34 PM, Guido van Rossum wrote:
On Sun, Feb 14, 2021 at 12:51 PM David Mertz > wrote:


On Sun, Feb 14, 2021, 2:53 PM Gregory P. Smith mailto:g...@krypto.org>> wrote:

*TL;DR of my TL;DR* - Not conveying bool-ness directly in the
return annotation is my only complaint.  A BoolTypeGuard
spelling would alleviate that.


This is exactly my feeling as well. In fact, I do not understand
why it cannot simply be a parameterized Bool. That would avoid all
confusion. Yes, it's not the technical jargon type system
designers use... But the existing proposal moves all the mental
effort to non-experts who may never use type checking tools.


But note that 'bool' in Python is not subclassable.



No, but this hypothetical 'Bool'--presumably added to typing.py--might 
well be.



Cheers,


//arry/

___
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/5OVN7MIXJZZE6C6PSA3UQSLQJRM26NQ4/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-14 Thread Guido van Rossum
On Sun, Feb 14, 2021 at 12:51 PM David Mertz  wrote:

> On Sun, Feb 14, 2021, 2:53 PM Gregory P. Smith  wrote:
>
>> *TL;DR of my TL;DR* - Not conveying bool-ness directly in the return
>> annotation is my only complaint.  A BoolTypeGuard spelling would
>> alleviate that.
>>
>
> This is exactly my feeling as well. In fact, I do not understand why it
> cannot simply be a parameterized Bool. That would avoid all confusion. Yes,
> it's not the technical jargon type system designers use... But the existing
> proposal moves all the mental effort to non-experts who may never use type
> checking tools.
>

But note that 'bool' in Python is not subclassable.


> I.e. if I read this:
>
> def is_str_list(v: List[Any]) -> Bool[List[str]]:
> ...
>
> I just think, "OK, it returns a bool, and those mypy people are doing
> something else funny that I don't need to worry about." If I see
> TypeGuard[...whatever..] I automatically think "that's a weird thing I
> don't understand, but it looks like it returns a boolean when I read the
> body."
>

Then again, someone who tries to understand your version beyond "fuzzy
matching of words while ignoring stuff they don't comprehend" (that's a
real thing and we all do it all the time :-) might be confused by the
conundrum posed by a parameterized boolean.


> FWIW, this hypothetical non-expert is me. I've actually gotten in the
> habit of using simply type annotations in most of the code I write (a lot
> of which is for teaching). But I never actually check using type checkers.
> It's quite likely some of my annotations are not actually sound, but to me
> they are documentation. I.e. I'll use an annotation of str/list/float, but
> not precisely parameterized types, union, generics, etc.
>

So maybe you should just stick to "bool". TypeGuard is really only useful
for people who care about what type checkers do (a surprisingly large
contingent, actually, but I would not recommend it for the education
department).

And I'm sure that when five years from now you're seeing TypeGuard in the
wild, you'll remember this thread and you'll know that it is a boolean. :-)

-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
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/RF5KF3O7AELQDWJZP7KPVWV6MTMPO5V2/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-14 Thread Guido van Rossum
On Sun, Feb 14, 2021 at 11:49 AM Gregory P. Smith  wrote:

> *TL;DR of my TL;DR* - Not conveying bool-ness directly in the return
> annotation is my only complaint.  A BoolTypeGuard spelling would
> alleviate that.  I'm +0.3 now.  Otherwise I elaborate on other guarding
> options and note a few additional Rejected/Postponed/Deferred Ideas
> sections that the PEP should mention as currently out of scope:
> Unconditional guards, multiple guarded parameters, and type mutators.
> Along the way I work my way towards suggestions for those, but I think they
> don't belong in _this_ PEP and could serve as input for future ones if/when
> desired.
>

Thanks for having an open mind. We should try to find a name that conveys
the boolean-ness to casual readers. But I note that "naming is hard" and
there are other aspects that already convey the boolean-ness (e.g. the
naming convention starting with 'is', and the presence of 'return True' in
the body :-), and I don't think that the proposed 'BoolTypeGuard' adds
readability.

-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
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/J3DX2DACGA4YIXOKICO4IY5L6F36SAKT/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-14 Thread David Mertz
On Sun, Feb 14, 2021, 2:53 PM Gregory P. Smith  wrote:

> *TL;DR of my TL;DR* - Not conveying bool-ness directly in the return
> annotation is my only complaint.  A BoolTypeGuard spelling would
> alleviate that.
>

This is exactly my feeling as well. In fact, I do not understand why it
cannot simply be a parameterized Bool. That would avoid all confusion. Yes,
it's not the technical jargon type system designers use... But the existing
proposal moves all the mental effort to non-experts who may never use type
checking tools.

I.e. if I read this:

def is_str_list(v: List[Any]) -> Bool[List[str]]:
...

I just think, "OK, it returns a bool, and those mypy people are doing
something else funny that I don't need to worry about." If I see
TypeGuard[...whatever..] I automatically think "that's a weird thing I
don't understand, but it looks like it returns a boolean when I read the
body."

FWIW, this hypothetical non-expert is me. I've actually gotten in the habit
of using simply type annotations in most of the code I write (a lot of
which is for teaching). But I never actually check using type checkers.
It's quite likely some of my annotations are not actually sound, but to me
they are documentation. I.e. I'll use an annotation of str/list/float, but
not precisely parameterized types, union, generics, etc.
___
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/SX2FB46PIQZCHNEQWE6ATPWCX66R65TG/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-14 Thread Gregory P. Smith
(there's a small TL;DR towards the end of my reply if you want to read in
reverse to follow my thought process from possible conclusions to how i got
there - please don't reply without reading the whole thing first)

*TL;DR of my TL;DR* - Not conveying bool-ness directly in the return
annotation is my only complaint.  A BoolTypeGuard spelling would alleviate
that.  I'm +0.3 now.  Otherwise I elaborate on other guarding options and
note a few additional Rejected/Postponed/Deferred Ideas sections that the
PEP should mention as currently out of scope: Unconditional guards,
multiple guarded parameters, and type mutators.  Along the way I work my
way towards suggestions for those, but I think they don't belong in _this_
PEP and could serve as input for future ones if/when desired.

On Sun, Feb 14, 2021 at 8:53 AM Paul Bryan  wrote:

> I'm a +1 on using Annotated in this manner. Guido mentioned that it was
> intended for only third-parties though. I'd like to know more about why
> this isn't a good pattern for use by Python libraries.
>
> On Sun, 2021-02-14 at 16:29 +0100, Adrian Freund wrote:
>
> Here's another suggestion:
>
> PEP 593 introduced the `Annotated` type annotation. This could be used to
> annotate a TypeGuard like this:
>
> `def is_str_list(val: List[object]) -> Annotated[bool,
> TypeGuard(List[str])]`
>
>
I like Annotated better than not having it for the sake of not losing the
return type.  BUT I still feel like this limits things too much and
disconnects the information about what parameter(s) are transformed. It
also doesn't solve the problem of why the guard _must_ be tied to the
return value. Clearly sometimes it is desirable to do that. But on many
other scenarios the act of not raising an exception is the narrowing
action: ie - it should be declared as always happening.  Nothing in the
above annotation reads explicitly to me as saying that the return value
determines the type outcome.


>
> Note that I used ( ) instead of [ ] for the TypeGuard, as it is no longer
> a type.
>
> This should fulfill all four requirements, but is a lot more verbose and
> therefore also longer.
> It would also be extensible for other annotations.
>
> For the most extensible approach both `-> TypeGuard(...)` and `->
> Annotated[bool, TypeGuard(...)]` could be allowed, which would open the
> path for future non-type-annotations, which could be used regardless of
> whether the code is type-annotated.
>
>
> --
> Adrian
>
> On February 14, 2021 2:20:14 PM GMT+01:00, Steven D'Aprano <
> st...@pearwood.info> wrote:
>
> On Sat, Feb 13, 2021 at 07:48:10PM -, Eric Traut wrote:
>
> I think it's a reasonable criticism that it's not obvious that a
> function annotated with a return type of `TypeGuard[x]` should return
> a bool.
>
>
> [...]
>
> As Guido said, it's something that a developer can easily
> look up if they are confused about what it means.
>
>
>
> Yes, developers can use Bing and Google :-)
>
> But it's not the fact that people have to look it up. It's the fact that
> they need to know that this return annotation is not what it seems, but
> a special magic value that needs to be looked up.
>
> That's my objection: we're overloading the return annotation to be
> something other than the return annotation, but only for this one
> special value. (So far.) If you don't already know that it is special,
> you won't know that you need to look it up to learn that its special.
>
>
>  I'm open to alternative formulations that meet the following requirements:
>
>  1. It must be possible to express the type guard within the function
>  signature. In other words, the implementation should not need to be
>  present. This is important for compatibility with type stubs and to
>  guarantee consistent behaviors between type checkers.
>
>
>
> When you say "implementation", do you mean the body of the function?
>
> Why is this a hard requirement? Stub files can contain function
> bodies, usually `...` by convention, but alternatives are often useful,
> such as docstrings, `raise NotImplementedError()` etc.
>
> https://mypy.readthedocs.io/en/stable/stubs.html
>
> I don't think that the need to support stub files implies that the type
> guard must be in the function signature. Have I missed something?
>
>
> 2. It must be possible to annotate the input parameter types _and_ the
> resulting (narrowed) type. It's not sufficient to annotate just one or
> the other.
>
>
>
> Naturally :-)
>
> That's the whole point of a type guard, I agree that this is a truly
> hard requirement.
>
>
> 3. It must be possible for a type checker to determine when narrowing
> can be applied and when it cannot. This implies the need for a bool
> response.
>
>
>
> Do you mean a bool return type? Sorry Eric, sometimes the terminology
> you use is not familiar to me and I have to guess what you mean.
>
>
> 4. It should not require changes to the grammar because that would
> prevent this from being adopted in most code bases for many years.
>
>
>
> Fair 

[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-14 Thread Paul Bryan
I'm a +1 on using Annotated in this manner. Guido mentioned that it was
intended for only third-parties though. I'd like to know more about why
this isn't a good pattern for use by Python libraries. 

On Sun, 2021-02-14 at 16:29 +0100, Adrian Freund wrote:
> Here's another suggestion:
> 
> PEP 593 introduced the `Annotated` type annotation. This could be
> used to annotate a TypeGuard like this:
> 
> `def is_str_list(val: List[object]) -> Annotated[bool,
> TypeGuard(List[str])]`
> 
> Note that I used ( ) instead of [ ] for the TypeGuard, as it is no
> longer a type.
> 
> This should fulfill all four requirements, but is a lot more verbose
> and therefore also longer.
> It would also be extensible for other annotations.
> 
> For the most extensible approach both `-> TypeGuard(...)` and `->
> Annotated[bool, TypeGuard(...)]` could be allowed, which would open
> the path for future non-type-annotations, which could be used
> regardless of whether the code is type-annotated.
> 
> 
> --
> Adrian
> 
> On February 14, 2021 2:20:14 PM GMT+01:00, Steven D'Aprano
>  wrote:
> > On Sat, Feb 13, 2021 at 07:48:10PM -, Eric Traut wrote:
> > 
> > > I think it's a reasonable criticism that it's not obvious that a 
> > > function annotated with a return type of `TypeGuard[x]` should
> return 
> > > a bool.
> > > 
> > [...]
> > > As Guido said, it's something that a developer can easily 
> > > look up if they are confused about what it means.
> > > 
> > 
> > Yes, developers can use Bing and Google :-)
> > 
> > But it's not the fact that people have to look it up. It's the fact
> that 
> > they need to know that this return annotation is not what it seems,
> but 
> > a special magic value that needs to be looked up.
> > 
> > That's my objection: we're overloading the return annotation to be 
> > something other than the return annotation, but only for this one 
> > special value. (So far.) If you don't already know that it is
> special, 
> > you won't know that you need to look it up to learn that its
> special.
> > 
> > 
> > > I'm open to alternative formulations that meet the following
> requirements:
> > > 
> > > 1. It must be possible to express the type guard within the
> function 
> > > signature. In other words, the implementation should not need to
> be 
> > > present. This is important for compatibility with type stubs and
> to 
> > > guarantee consistent behaviors between type checkers.
> > > 
> > 
> > When you say "implementation", do you mean the body of the
> function?
> > 
> > Why is this a hard requirement? Stub files can contain function 
> > bodies, usually `...` by convention, but alternatives are often
> useful, 
> > such as docstrings, `raise NotImplementedError()` etc.
> > 
> > https://mypy.readthedocs.io/en/stable/stubs.html
> > 
> > I don't think that the need to support stub files implies that the
> type 
> > guard must be in the function signature. Have I missed something?
> > 
> > 
> > > 2. It must be possible to annotate the input parameter types
> _and_ the 
> > > resulting (narrowed) type. It's not sufficient to annotate just
> one or 
> > > the other.
> > > 
> > 
> > Naturally :-)
> > 
> > That's the whole point of a type guard, I agree that this is a
> truly 
> > hard requirement.
> > 
> > 
> > > 3. It must be possible for a type checker to determine when
> narrowing 
> > > can be applied and when it cannot. This implies the need for a
> bool 
> > > response.
> > > 
> > 
> > Do you mean a bool return type? Sorry Eric, sometimes the
> terminology 
> > you use is not familiar to me and I have to guess what you mean.
> > 
> > 
> > > 4. It should not require changes to the grammar because that
> would 
> > > prevent this from being adopted in most code bases for many
> years.
> > > 
> > 
> > Fair enough.
> > 
> > 
> > > Mark, none of your suggestions meet these requirements.
> > > 
> > 
> > Mark's suggestion to use a variable annotation in the body meets 
> > requirements 2, 3, and 4. As I state above, I don't think that 
> > requirement 1 needs to be a genuinely hard requirement: stub files
> can 
> > include function bodies.
> > 
> > To be technically precise, stub functions **must** include function
> > bodies. It's just that by convention we use typically use `...` as
> the 
> > body.
> > 
> > 
> > > Gregory, one of your suggestions meets these requirements:
> > > 
> > > ```python
> > > def is_str_list(val: Constrains[List[object]:List[str]) -> bool:
> > > ...
> > > ```
> > > 
> > 
> > That still misleadingly tells the reader (or naive code analysis 
> > software) that parameter val is of type
> > 
> > Contrains[List[object]:List[str]]
> > 
> > whatever that object is, rather than what it *actually* is, namely 
> > `List[object]`. I dislike code that misleads the reader.
> > 
> > 
> > > As for choosing the name of the annotation
> > > 
> > [...]
> > > `TypeGuard` is the term that is used in other languages to
> describe 
> > > this notion, so it seems reasonable to me to adopt this term
> > 

[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-14 Thread Adrian Freund
Here's another suggestion:

PEP 593 introduced the `Annotated` type annotation. This could be used to 
annotate a TypeGuard like this:

`def is_str_list(val: List[object]) -> Annotated[bool, TypeGuard(List[str])]`

Note that I used ( ) instead of [ ] for the TypeGuard, as it is no longer a 
type.

This should fulfill all four requirements, but is a lot more verbose and 
therefore also longer.
It would also be extensible for other annotations.

For the most extensible approach both `-> TypeGuard(...)`  and `-> 
Annotated[bool, TypeGuard(...)]` could be allowed, which would open the path 
for future non-type-annotations, which could be used regardless of whether the 
code is type-annotated.


--
Adrian

On February 14, 2021 2:20:14 PM GMT+01:00, Steven D'Aprano 
 wrote:
>On Sat, Feb 13, 2021 at 07:48:10PM -, Eric Traut wrote:
>
>> I think it's a reasonable criticism that it's not obvious that a 
>> function annotated with a return type of `TypeGuard[x]` should return 
>> a bool.
>[...]
>> As Guido said, it's something that a developer can easily 
>> look up if they are confused about what it means.
>
>Yes, developers can use Bing and Google :-)
>
>But it's not the fact that people have to look it up. It's the fact that 
>they need to know that this return annotation is not what it seems, but 
>a special magic value that needs to be looked up.
>
>That's my objection: we're overloading the return annotation to be 
>something other than the return annotation, but only for this one 
>special value. (So far.) If you don't already know that it is special, 
>you won't know that you need to look it up to learn that its special.
>
>
>> I'm open to alternative formulations that meet the following requirements:
>>
>> 1. It must be possible to express the type guard within the function 
>> signature. In other words, the implementation should not need to be 
>> present. This is important for compatibility with type stubs and to 
>> guarantee consistent behaviors between type checkers.
>
>When you say "implementation", do you mean the body of the function?
>
>Why is this a hard requirement? Stub files can contain function 
>bodies, usually `...` by convention, but alternatives are often useful, 
>such as docstrings, `raise NotImplementedError()` etc.
>
>https://mypy.readthedocs.io/en/stable/stubs.html
>
>I don't think that the need to support stub files implies that the type 
>guard must be in the function signature. Have I missed something?
>
>
>> 2. It must be possible to annotate the input parameter types _and_ the 
>> resulting (narrowed) type. It's not sufficient to annotate just one or 
>> the other.
>
>Naturally :-)
>
>That's the whole point of a type guard, I agree that this is a truly 
>hard requirement.
>
>
>> 3. It must be possible for a type checker to determine when narrowing 
>> can be applied and when it cannot. This implies the need for a bool 
>> response.
>
>Do you mean a bool return type? Sorry Eric, sometimes the terminology 
>you use is not familiar to me and I have to guess what you mean.
>
>
>> 4. It should not require changes to the grammar because that would 
>> prevent this from being adopted in most code bases for many years.
>
>Fair enough.
>
>
>> Mark, none of your suggestions meet these requirements.
>
>Mark's suggestion to use a variable annotation in the body meets 
>requirements 2, 3, and 4. As I state above, I don't think that 
>requirement 1 needs to be a genuinely hard requirement: stub files can 
>include function bodies.
>
>To be technically precise, stub functions **must** include function 
>bodies. It's just that by convention we use typically use `...` as the 
>body.
>
>
>> Gregory, one of your suggestions meets these requirements:
>> 
>> ```python
>> def is_str_list(val: Constrains[List[object]:List[str]) -> bool:
>> ...
>> ```
>
>That still misleadingly tells the reader (or naive code analysis 
>software) that parameter val is of type
>
>Contrains[List[object]:List[str]]
>
>whatever that object is, rather than what it *actually* is, namely 
>`List[object]`. I dislike code that misleads the reader.
>
>
>> As for choosing the name of the annotation
>[...]
>> `TypeGuard` is the term that is used in other languages to describe 
>> this notion, so it seems reasonable to me to adopt this term
>
>Okay, this reasoning makes sense to me. Whether spelled as a decorator 
>or an annotation, using TypeGuard is reasonable.
>
>
>> Steven, you said you'd like to explore a decorator-based formulation. 
>> Let's explore that. Here's what that it look like if we were to meet 
>> all of the above requirements.
>> 
>> ```python
>> @type_guard(List[str])
>> def is_str_list(val: List[object]) -> bool: ...
>> ```
>
>Okay.
>
>
>I note that this could be easily extended to support narrowing in the 
>negative case as well:
>
>@type_guard(List[str], List[float])
>def is_str_list(val: List[Union[str, float]]) -> bool: ...
>
>
>> The problem here, as I mention in the "rejected ideas" 

[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-14 Thread Steven D'Aprano
On Sat, Feb 13, 2021 at 07:48:10PM -, Eric Traut wrote:

> I think it's a reasonable criticism that it's not obvious that a 
> function annotated with a return type of `TypeGuard[x]` should return 
> a bool.
[...]
> As Guido said, it's something that a developer can easily 
> look up if they are confused about what it means.

Yes, developers can use Bing and Google :-)

But it's not the fact that people have to look it up. It's the fact that 
they need to know that this return annotation is not what it seems, but 
a special magic value that needs to be looked up.

That's my objection: we're overloading the return annotation to be 
something other than the return annotation, but only for this one 
special value. (So far.) If you don't already know that it is special, 
you won't know that you need to look it up to learn that its special.


> I'm open to alternative formulations that meet the following requirements:
>
> 1. It must be possible to express the type guard within the function 
> signature. In other words, the implementation should not need to be 
> present. This is important for compatibility with type stubs and to 
> guarantee consistent behaviors between type checkers.

When you say "implementation", do you mean the body of the function?

Why is this a hard requirement? Stub files can contain function 
bodies, usually `...` by convention, but alternatives are often useful, 
such as docstrings, `raise NotImplementedError()` etc.

https://mypy.readthedocs.io/en/stable/stubs.html

I don't think that the need to support stub files implies that the type 
guard must be in the function signature. Have I missed something?


> 2. It must be possible to annotate the input parameter types _and_ the 
> resulting (narrowed) type. It's not sufficient to annotate just one or 
> the other.

Naturally :-)

That's the whole point of a type guard, I agree that this is a truly 
hard requirement.


> 3. It must be possible for a type checker to determine when narrowing 
> can be applied and when it cannot. This implies the need for a bool 
> response.

Do you mean a bool return type? Sorry Eric, sometimes the terminology 
you use is not familiar to me and I have to guess what you mean.


> 4. It should not require changes to the grammar because that would 
> prevent this from being adopted in most code bases for many years.

Fair enough.


> Mark, none of your suggestions meet these requirements.

Mark's suggestion to use a variable annotation in the body meets 
requirements 2, 3, and 4. As I state above, I don't think that 
requirement 1 needs to be a genuinely hard requirement: stub files can 
include function bodies.

To be technically precise, stub functions **must** include function 
bodies. It's just that by convention we use typically use `...` as the 
body.


> Gregory, one of your suggestions meets these requirements:
> 
> ```python
> def is_str_list(val: Constrains[List[object]:List[str]) -> bool:
> ...
> ```

That still misleadingly tells the reader (or naive code analysis 
software) that parameter val is of type

Contrains[List[object]:List[str]]

whatever that object is, rather than what it *actually* is, namely 
`List[object]`. I dislike code that misleads the reader.


> As for choosing the name of the annotation
[...]
> `TypeGuard` is the term that is used in other languages to describe 
> this notion, so it seems reasonable to me to adopt this term

Okay, this reasoning makes sense to me. Whether spelled as a decorator 
or an annotation, using TypeGuard is reasonable.


> Steven, you said you'd like to explore a decorator-based formulation. 
> Let's explore that. Here's what that it look like if we were to meet 
> all of the above requirements.
> 
> ```python
> @type_guard(List[str])
> def is_str_list(val: List[object]) -> bool: ...
> ```

Okay.


I note that this could be easily extended to support narrowing in the 
negative case as well:

@type_guard(List[str], List[float])
def is_str_list(val: List[Union[str, float]]) -> bool: ...


> The problem here, as I mention in the "rejected ideas" section of the 
> PEP, is that even with postponed type evaluations (as described in PEP 
> 563), the interpreter cannot postpone the evaluation of an expression 
> if it's used as the argument to a decorator. That's because it's not 
> being used as a type annotation in this context.

Agreed.


> So while Mark is 
> correct to point out that there has been a mechanism available for 
> forward references since PEP 484,

That was actually me who pointed out the quoting mechanism for forward 
references. (Unless Mark also did so.)


> we've been trying to eliminate the 
> use of quoted type expressions in favor of postponed evaluation. This 
> would add a new case that can't be handled through postponed 
> evaluation. Perhaps you still don't see that as a strong enough 
> justification for rejecting the decorator-based formulation. I'm not 
> entirely opposed to using a decorator here, but I 

[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-13 Thread Greg Ewing

On 14/02/21 8:48 am, Eric Traut wrote:


def is_str_list(val: Constrains[List[object]:List[str]) -> bool:
 ...


Maybe something like this?


def is_str_list(val: List[str] if True else List[object]) -> bool:
   ...

--
Greg
___
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/GLHQVM7NIYO2GZHGREJ5FE2KJ7AI3DTQ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-13 Thread Paul Sokolovsky
Hello,

On Sat, 13 Feb 2021 19:48:10 -
"Eric Traut"  wrote:

[]

> Paul said:
> >...to work around deficiencies in the current generation of Python
> >typecheckers  
> 
> It sounds like you're implying that this functionality will be no
> longer needed at some point in the future when type checkers improve
> in some (unspecified) manner. If that's what you meant to convey,
> then I disagree. I think there will be an ongoing need for this
> functionality. There's good evidence for this in TypeScript, where
> user-defined type guards have been adopted widely by developers.

That's certainly a good argument on its own (providing cross-language
functionality and adopting known best practices).

But taken without context like that, I wonder if the example from the
PEP647:

def is_str_list(val: List[object]) -> bool:
"""Determines whether all objects in the list are strings"""
return all(isinstance(x, str) for x in val)

def func1(val: List[object]):
if is_str_list(val):
print(" ".join(val)) # Error: invalid type 

would work if "type guard function" was inlined:

def func1(val: List[object]):
if all(isinstance(x, str) for x in val):
print(" ".join(val)) # Is this valid or not? 

If the answer is "no", then it points to pretty weak ability of
abstract interpretation of the current typecheckers. If the answer is
"yes", it's more reassuring, but then the problem is weak
interprocedural capabilities of the current typecheckers.

I certainly understand all the technical challenges with that (likely
performance), asymptotically turning into halting problem. And yet I
may imagine that many practically useful typeguards will be simple
enough (like above), and may be automatically type-inferred in the
future.

Then the syntax for explicit type guard annotation is less important
(would be used as an exception, not a rule), and if it's useful now to
keep up the pace of the typechecker research, then I'd be +1 with it
(instead of nitpicking at it, as seem to be the case with other recent
replies). 

> 
> --
> Eric Traut
> Contributor to Pyright & Pylance
> Microsoft Corp.

[]

-- 
Best regards,
 Paul  mailto:pmis...@gmail.com
___
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/SWRAN4MMYN3NUENFDN2ZUC7P4SVDORPY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-13 Thread Eric Traut
I think it's a reasonable criticism that it's not obvious that a function 
annotated with a return type of `TypeGuard[x]` should return a bool. That said, 
the idea of a user-defined type guard comes from TypeScript, where the syntax 
is described 
[here](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards).
 As you can see, the return type annotation here is also not a boolean. To my 
knowledge, that has not been a barrier for TypeScript developers. As Guido 
said, it's something that a developer can easily look up if they are confused 
about what it means.

I'm open to alternative formulations that meet the following requirements:
1. It must be possible to express the type guard within the function signature. 
In other words, the implementation should not need to be present. This is 
important for compatibility with type stubs and to guarantee consistent 
behaviors between type checkers.
2. It must be possible to annotate the input parameter types _and_ the 
resulting (narrowed) type. It's not sufficient to annotate just one or the 
other.
3. It must be possible for a type checker to determine when narrowing can be 
applied and when it cannot. This implies the need for a bool response.
4. It should not require changes to the grammar because that would prevent this 
from being adopted in most code bases for many years.

Mark, none of your suggestions meet these requirements. Gregory, one of your 
suggestions meets these requirements:

```python
def is_str_list(val: Constrains[List[object]:List[str]) -> bool:
...
```

So, the question is whether this is more understandable and readable than this:

```python
def is_str_list(val: List[object]) -> TypeGuard[List[str]]:
...
```

Both of these approaches would require a developer to do a search to understand 
the meaning. The former also introduces a novel use of the slice notation, 
which I find very unintuitive. Between these two, I find the latter to be 
clearly preferable, but that's admittedly a subjective opinion.

As for choosing the name of the annotation... Most annotations in Python are 
nouns, for good reason. (There are a few exceptions like `Optional` that are 
adjectives.) For that reason, I'm not a fan of `Narrows`. I definitely wouldn't 
use `Constrains` because there's already a meaning in the Python type system 
for a "constrained type variable" (a TypeVar can constrained to two or more 
different types). `TypeGuard` is the term that is used in other languages to 
describe this notion, so it seems reasonable to me to adopt this term rather 
than making up a new term. Yes, it's introducing a new term that most Python 
users are not yet familiar with, but I can tell you from experience that very 
few Python developers know what "type narrowing" means. Some education will be 
required regardless of the formulation we choose.

Steven, you said you'd like to explore a decorator-based formulation. Let's 
explore that. Here's what that it look like if we were to meet all of the above 
requirements.

```python
@type_guard(List[str])
def is_str_list(val: List[object]) -> bool: ...
```

The problem here, as I mention in the "rejected ideas" section of the PEP, is 
that even with postponed type evaluations (as described in PEP 563), the 
interpreter cannot postpone the evaluation of an expression if it's used as the 
argument to a decorator. That's because it's not being used as a type 
annotation in this context. So while Mark is correct to point out that there 
has been a mechanism available for forward references since PEP 484, we've been 
trying to eliminate the use of quoted type expressions in favor of postponed 
evaluation. This would add a new case that can't be handled through postponed 
evaluation. Perhaps you still don't see that as a strong enough justification 
for rejecting the decorator-based formulation. I'm not entirely opposed to 
using a decorator here, but I think on balance that the `TypeGuard[x]` 
formulation is better. Once again, that's a subjective opinion.

Paul said:
>...to work around deficiencies in the current generation of Python typecheckers

It sounds like you're implying that this functionality will be no longer needed 
at some point in the future when type checkers improve in some (unspecified) 
manner. If that's what you meant to convey, then I disagree. I think there will 
be an ongoing need for this functionality. There's good evidence for this in 
TypeScript, where user-defined type guards have been adopted widely by 
developers.

--
Eric Traut
Contributor to Pyright & Pylance
Microsoft Corp.
___
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/XLOTPVQMG53FXPP4HBGC6YGK2ZZJ5FMM/
Code of Conduct: 

[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-13 Thread Paul Moore
On Sat, 13 Feb 2021 at 17:33, Guido van Rossum  wrote:
> On Sat, Feb 13, 2021 at 2:38 AM Paul Moore  wrote:
>>
>> I have to agree here. I'm not a frequent user of type hints yet, but I
>> am starting to have to maintain code that has type hints, and from a
>> maintenance perspective, I have to say that this would be really hard
>> to deal with. If I saw this for the first time "in the wild", I'd have
>> no idea what to do with it.
>
>
> Think of it as new syntax. Of course you have to learn it (or Google it). Is 
> it easy to learn? I think so. Is it easy to recognize once you've seen and 
> understood it once? Yes.  Is it easy to use it correctly given an example? 
> Yes again.

But looking at it, it's *not* new syntax, it's a return type of
TypeGuard[List[str]], which is perfectly good syntax today. I can look
up what the type TypeGuard is, but most of the time, when maintaining
code, I don't do that - I just think "hmm, returns Foo, that's all I
need to know right now". But then I discover that it's returning a
boolean, and I'm confused. And it's always going to be an exception to
the rule that what's after the -> is the type of the return value. I
personally think "Special cases aren't special enough to break the
rules" applies here, but I admit I don't know how special this case
is, nor do I know why no less exceptional alternative is possible.

Of course I can look it up, but it's a distraction from what I was
trying to do. Of course it's easy to google, but it's the *only*
annotation I've ever needed to google. Of course it's optional and
only affects type checkers, but I don't control everything that gets
added to code bases I support.

*shrug* it makes little difference in the grand scheme of things,
it'll go in if enough people who have influence over the decision are
OK with it. And I'm sure it fills a need for certain types of project.
It's not going to make my life impossible either way. But if
impressions from casual users are being counted, I remain -1.

Paul
___
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/P6SZAUSQFLSOGMUDXYKD3MGGWZSJ7LYW/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-13 Thread Guido van Rossum
> On Sat, 13 Feb 2021 at 07:11, Steven D'Aprano  wrote:
> > Without reading the PEP, how is anyone supposed to know that this
> > returns a bool?
>

By looking at the name, or at the return statements in the body. These are
expected to be really short. Tooling can certainly easily be taught what
TypeGuard[...] means -- the whole *point* is to enable tooling (it provides
an essential, albeit minor, piece of new functionality for type checkers).

On Sat, Feb 13, 2021 at 2:38 AM Paul Moore  wrote:

> I have to agree here. I'm not a frequent user of type hints yet, but I
> am starting to have to maintain code that has type hints, and from a
> maintenance perspective, I have to say that this would be really hard
> to deal with. If I saw this for the first time "in the wild", I'd have
> no idea what to do with it.
>

Think of it as new syntax. Of course you have to learn it (or Google it).
Is it easy to learn? I think so. Is it easy to recognize once you've seen
and understood it once? Yes.  Is it easy to use it correctly given an
example? Yes again.

-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
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/FW3CPS553IAFIT4G27N47PW4PASNPBFK/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-13 Thread Paul Moore
On Sat, 13 Feb 2021 at 07:11, Steven D'Aprano  wrote:
>
> On Fri, Feb 12, 2021 at 10:27:01AM +, Mark Shannon wrote:
>
> > It impairs readability, because it muddles the return type.
> > The function in the example returns a bool.
> > The annotation is also misleading as the annotation is on the return
> > type, not on the parameter that is narrowed.
> >
> > At a glance, most programmers should be able to work out what
> >
> > def is_str_list(val: List[object]) -> bool:
> >
> > returns.
> >
> > But,
> >
> > def is_str_list(val: List[object]) -> TypeGuard[List[str]]:
> >
> > is likely to confuse and require careful reading.
> > Type hints are for humans as well as type checkers.
>
> This!
>
> Without reading the PEP, how is anyone supposed to know that this
> returns a bool?

I have to agree here. I'm not a frequent user of type hints yet, but I
am starting to have to maintain code that has type hints, and from a
maintenance perspective, I have to say that this would be really hard
to deal with. If I saw this for the first time "in the wild", I'd have
no idea what to do with it.

Paul
___
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/43A7TU2VYDIGFP3THLDFFUWJGWSZSIEM/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-13 Thread Paul Sokolovsky
Hello,

On Sat, 13 Feb 2021 18:08:30 +1100
Steven D'Aprano  wrote:

> On Fri, Feb 12, 2021 at 10:27:01AM +, Mark Shannon wrote:
> 
> > It impairs readability, because it muddles the return type.
> > The function in the example returns a bool.
> > The annotation is also misleading as the annotation is on the
> > return type, not on the parameter that is narrowed.
> > 
> > At a glance, most programmers should be able to work out what
> > 
> > def is_str_list(val: List[object]) -> bool:
> > 
> > returns.
> > 
> > But,
> > 
> > def is_str_list(val: List[object]) -> TypeGuard[List[str]]:
> > 
> > is likely to confuse and require careful reading.
> > Type hints are for humans as well as type checkers.  
> 
> This!
> 
> Without reading the PEP, how is anyone supposed to know that this 
> returns a bool? This is obfuscated code. It looks like it returns an 
> object of type `TypeGuard`. Even having read the PEP, it's still 
> misleading: instead of a straightforward return type, I have to
> memorise that `TypeGuard[...]` is a magic thing that means
> 
> * the return type is actually a bool;
> 
> * and the type checker can narrow the type of the first parameter.
> 
> Yuck.

My quick reading of PEP647 shows that it's yet another
patchy/throw-away PEP whose purpose is to work around deficiencies in
the current generation of Python typecheckers. In that regard, I'd take
it easy, and be +1 with it - it's better to support gradual evolution
of Python typecheckers with hacks like that, rather than block it
with proverbial "we can solve all the problems of universe right in
the version 1".


[]


-- 
Best regards,
 Paul  mailto:pmis...@gmail.com
___
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/OEQUWN3LZOQ5ZTFSKHL343ZQCUTBURIV/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-12 Thread Steven D'Aprano
On Fri, Feb 12, 2021 at 10:27:01AM +, Mark Shannon wrote:

> It impairs readability, because it muddles the return type.
> The function in the example returns a bool.
> The annotation is also misleading as the annotation is on the return 
> type, not on the parameter that is narrowed.
> 
> At a glance, most programmers should be able to work out what
> 
> def is_str_list(val: List[object]) -> bool:
> 
> returns.
> 
> But,
> 
> def is_str_list(val: List[object]) -> TypeGuard[List[str]]:
> 
> is likely to confuse and require careful reading.
> Type hints are for humans as well as type checkers.

This!

Without reading the PEP, how is anyone supposed to know that this 
returns a bool? This is obfuscated code. It looks like it returns an 
object of type `TypeGuard`. Even having read the PEP, it's still 
misleading: instead of a straightforward return type, I have to memorise 
that `TypeGuard[...]` is a magic thing that means

* the return type is actually a bool;

* and the type checker can narrow the type of the first parameter.

Yuck.

Consider:

def is_list_of(val: List[object], T: Type) -> bool:
return all(isinstance(x, T) for x in val)

`if is_list_of(items, str)` should narrow the type of items to 
`List[str]`, but I don't think that there is any way to specify that. In 
fact that seems to be explicitly rejected: the decorator syntax is 
rejected because "it requires runtime evaluation of the type, precluding 
forward references".

But type hints have to deal with forward references in other situations, 
and have had an effective mechanism for forward references since the 
beginning:

https://www.python.org/dev/peps/pep-0484/#forward-references

so I think that's a weak argument for rejection. And the argument that 
overriding the return type with a magic special value is "easier to 
understand" seems wrong to me.

I think that Mark's proposal reads well:

> An alternative, and more explicit, approach would be to use variable 
> annotations.
[...]
> def is_str_list(val: List[object]) -> bool:
> """Determines whether all objects in the list are strings"""
> val: NarrowsTo[List[str]]
> return all(isinstance(x, str) for x in val)
> 
> Although the above lacks flow control and is thus ambiguous without the 
> convention that `NarrowsTo` only applies if the result is True.

But we need that convention for the TypeGuard return value annotation 
too. 

def is_str_list(val: List[object]) -> TypeGuard[List[str]]:

only narrows the type of val if the function returns True. So I think 
that Mark's variable annotation has many benefits:

- doesn't mangle the return annotation;

- which is much more readable to the human reader;

- naive software that doesn't care about type narrowing doesn't need to 
  care about the variable annotation;
 
- explicitly tells you which parameter is being narrowed;

- easy to narrow any parameter, or more than one, without requiring
  special treatment of the first positional argument;

- because the parameter is explicit, there is no need for special 
  handling of self or cls.

The only weakness is that we need the convention that the variable 
annotation will only apply if the function returns True, but that's the 
same convention as the TypeGuard.


-- 
Steve
___
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/VENVXOTDSKPIC2BPFFKJ23G2DXFWJ6DO/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-12 Thread Gregory P. Smith
My primary reaction seems similar to Mark Shannon's.

When I see this code:

def is_str_list(val: List[object]) -> TypeGuard[List[str]]:
...

I cannot tell what it returns.  There is no readable indication in that
this returns a boolean so the reader cannot immediately see how to use the
function.  In fact my first reaction is to assume it returns some form of
List[str].  Which it most definitely does not do.

Additionally, it seems like restricting this concept of a type guard to
only a function that returns a bool is wrong.
It is also a natural idiom to encounter functions that raise an exception
if their type conditions aren't met.
Those should also narrow types within a non-exception caught codepath after
their return.  Be simple and assume that catching any exception from their
call ends their narrowing?

A narrowing is meta-information about a typing side effect, it isn't a type
itself.  It isn't a value.  So replacing a return type with it seems like
too much.  But if we do wind up going that route, at least make the name
indicate that the return value is a bool.  i.e.: def parse_num(thing: Any)
-> NarrowingBool[float]

The term TypeGuard is too theoretical for anyone reading code.  I don't
care if TypeScript uses it in their language... looking that up at a quick
glance -
https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards
- it doesn't look like they ever use the term TypeGuard in the language
syntax itself? good.

Perhaps this would be better expressed as an annotation on the argument(s)
that the function narrows?

def is_str_list(val: Constrains[List[object]:List[str]) -> bool:
...

I'm using Constrains as an alternative to Narrows here... still open to
suggestions.  But I do not think we should get hung up on TypeScript and
assume that TypeGuard is somehow a good name.  This particular proposed
example uses : slice notation rather than a comma as a proposal that may be
more readable.  I'd also consider using the 'as' keyword instead of , or :
but that wouldn't even parse today.  *Really* what might be nice for this
is our -> arrow.

def assert_str_list(var:  Narrows[List[object] -> List[str]]) -> None:
...

as the arrow carries the implication of something effective "after" the
call. I suspect adding new parsing syntax isn't what anyone had in mind for
now though.  : seems like a viable stopgap, whether syntax happens or not.
(i'm intentionally avoiding the comma as an exploration in readability)

The key point I'm trying to represent is that declaring it per argument
allows for more expressive functions and doesn't interfere with their
return value (if they even return anything). Clearly there's a use case
that _does_ want to make the narrowing conditional on the return value
boolness.  I still suggest expressing that on the arguments themselves.
More specific flavors of the guarding parameter such as ConstrainsWhenTrue
or NarrowsWhenFalse perhaps.


def is_set_of(val: Constrains[Set[Any]:Set[_T]], type: Type[_T]) -> bool:
   ...

which might also be written more concisely as:

def is_set_of(val: Set[Constrains[Any:_T]], type: Type[_T]) -> bool:

If we allow the full concept.

hopefully food for thought,  i'm -1 right now.
-gps


On Fri, Feb 12, 2021 at 2:34 AM Mark Shannon  wrote:

> Hi,
>
> First of all, sorry for not commenting on this earlier.
> I only became aware of this PEP yesterday.
>
>
> I like the general idea of adding a marker to show that a boolean
> function narrows the type of one (or more?) of its arguments.
> However, the suggested approach seems clunky and impairs readability.
>
> It impairs readability, because it muddles the return type.
> The function in the example returns a bool.
> The annotation is also misleading as the annotation is on the return
> type, not on the parameter that is narrowed.
>
> At a glance, most programmers should be able to work out what
>
> def is_str_list(val: List[object]) -> bool:
>
> returns.
>
> But,
>
> def is_str_list(val: List[object]) -> TypeGuard[List[str]]:
>
> is likely to confuse and require careful reading.
> Type hints are for humans as well as type checkers.
>
>
>
> Technical review.
> -
>
> For an annotation of this kind to be useful to a checker, that checker
> must perform both flow-sensitive and call-graph analysis. Therefore it
> is theoretically possible to remove the annotation altogether, using the
> following approach:
>
> 1. Scan the code looking for functions that return boolean and
> potentially narrow the type of their arguments.
> 2. Inline those functions in the analysis
> 3. Rely on pre-existing flow-senstive analysis to determine the correct
> types.
>
> However, explicit is better and implicit. So some sort of annotation
> seems sensible.
>
> I would contend that the minimal:
>
> @narrows
> def is_str_list(val: List[object]) -> bool:
>
> is sufficient for a checker, as the checker can inline anything marked
> @narrows.
> Plus, it does not mislead 

[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-12 Thread Guido van Rossum
On Fri, Feb 12, 2021 at 12:14 PM Jim J. Jewett  wrote:

> Current PEP 647 draft says:
>
> "Some built-in type guards provide narrowing for both positive and
> negative tests (in both the if and else clauses)"
>
> Should there be a separate (sub-?) type for those TypeGuards that *do*
> allow narrowing even on a False?  Leaving it as an implementation detail
> available only to (some) built-in types seems to confuse the issue in both
> directions.
>

I think the PEP is using the term in a wider sense here, referring to
things like `isinstance(x, C)` and `x is not None`. Note that mypy (at
least) also recognizes `if x:` as narrowing `Optional[T]` to `T`, but there
in the else clause we *cannot* assume that x is not a T, because it could
be a falsey instance.

-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
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/ZTKR6ZQF5PKR26HJICHMA2VPLQMNKMOH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-12 Thread Jim J. Jewett
Current PEP 647 draft says: 

"Some built-in type guards provide narrowing for both positive and negative 
tests (in both the if and else clauses)"

Should there be a separate (sub-?) type for those TypeGuards that *do* allow 
narrowing even on a False?  Leaving it as an implementation detail available 
only to (some) built-in types seems to confuse the issue in both directions.

-jJ
___
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/PRRQQLGEO3IKERM6QDGYBMGCYKTM2GAG/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-12 Thread Mark Shannon

Hi,

First of all, sorry for not commenting on this earlier.
I only became aware of this PEP yesterday.


I like the general idea of adding a marker to show that a boolean 
function narrows the type of one (or more?) of its arguments.

However, the suggested approach seems clunky and impairs readability.

It impairs readability, because it muddles the return type.
The function in the example returns a bool.
The annotation is also misleading as the annotation is on the return 
type, not on the parameter that is narrowed.


At a glance, most programmers should be able to work out what

def is_str_list(val: List[object]) -> bool:

returns.

But,

def is_str_list(val: List[object]) -> TypeGuard[List[str]]:

is likely to confuse and require careful reading.
Type hints are for humans as well as type checkers.



Technical review.
-

For an annotation of this kind to be useful to a checker, that checker 
must perform both flow-sensitive and call-graph analysis. Therefore it 
is theoretically possible to remove the annotation altogether, using the 
following approach:


1. Scan the code looking for functions that return boolean and 
potentially narrow the type of their arguments.

2. Inline those functions in the analysis
3. Rely on pre-existing flow-senstive analysis to determine the correct 
types.


However, explicit is better and implicit. So some sort of annotation 
seems sensible.


I would contend that the minimal:

@narrows
def is_str_list(val: List[object]) -> bool:

is sufficient for a checker, as the checker can inline anything marked 
@narrows.

Plus, it does not mislead the reader by mangling the return type.


An alternative, and more explicit, approach would be to use variable 
annotations.

So:

def is_str_list(val: List[object]) -> bool:
"""Determines whether all objects in the list are strings"""
return all(isinstance(x, str) for x in val)

might become:


def is_str_list(val: List[object]) -> bool:
"""Determines whether all objects in the list are strings"""
val: NarrowsTo[List[str]]
return all(isinstance(x, str) for x in val)

Although the above lacks flow control and is thus ambiguous without the 
convention that `NarrowsTo` only applies if the result is True.



An alternative formulation would require the annotation to dominate the 
function exit:


def is_str_list(val: List[object]) -> bool:
"""Determines whether all objects in the list are strings"""
if all(isinstance(x, str) for x in val):
val: NarrowsTo[List[str]]
return True
return False

This is unambiguous.


Finally, I would ask for a change of name.

The "Type" part is redundant, since it is a type annotation, and the 
"Guard" part is incorrect. It is only a guard when used, the function 
itself is a predicate that narrows the type of an argument. "Narrows" or 
"NarrowsTo" would be better.



Cheers,
Mark.


On 09/02/2021 4:21 pm, Guido van Rossum wrote:
I think we have reached consensus on PEP 647 in typing-sig. We have 
implementations for mypy and pyright, not sure about the rest. This PEP 
does not affect CPython directly except for the addition of one special 
item (TypeGuard) to typing.py -- it would be nice to get that in the 
3.10 stdlib.


I'm CC'ing python-dev here to see if there are any further comments; if 
not, we can initiate the approval process by creating an issue at 
https://github.com/python/steering-council.


--
--Guido van Rossum (python.org/~guido )
/Pronouns: he/him //(why is my pronoun here?)/ 



___
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/NOLCFYLYAQQHXISNMPYCEOAZ7ZPFCGUW/
Code of Conduct: http://python.org/psf/codeofconduct/


___
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/4LKI6IGCT7JHH5C3YQPA4SXHDQWJC5Q2/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-11 Thread Guido van Rossum
I think the use case (for x.is_foo()) is rare. And instead of writing
x.is_foo(x), if you make the guard a function you can write is_foo(x).

On Thu, Feb 11, 2021 at 6:51 PM Sebastian Kreft  wrote:

> I still think that we should reconsider deferring what happens to class
> and instance methods.
>
> The arguments given in https://www.python.org/dev/peps/pep-0647/#id13
> seem insufficient, specially considering than the workaround provided is
> quite awkward.
>
> The author suggests to write def check(self, self2) -> Typeguard[T] and
> call it as self.check(self).
> ___
> 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/CA2MFS4XXDPC6PDBW53BZWLWEMQOBBP6/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
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/MSGSGFJ6TBZMJBFZTQ5ORIAQH26TFZK3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-11 Thread Sebastian Kreft
I still think that we should reconsider deferring what happens to class and 
instance methods.

The arguments given in https://www.python.org/dev/peps/pep-0647/#id13 seem 
insufficient, specially considering than the workaround provided is quite 
awkward.

The author suggests to write def check(self, self2) -> Typeguard[T] and call it 
as self.check(self).
___
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/CA2MFS4XXDPC6PDBW53BZWLWEMQOBBP6/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-11 Thread Guido van Rossum
It means "I can't prove it matches". This should be clear from the spec
already (it's an important point actually, since it means type checkers
cannot narrow in an else clause). So please don't file a PR to "add" this.

On Thu, Feb 11, 2021 at 11:49 AM Jim J. Jewett  wrote:

> If a TypeGuard returns false, does that mean "it doesn't match", or just
> "I can't prove it matches, but it still might"?  That seems relevant to the
> else clause ... and seems to have changed since the last version I looked
> at.
>
> -jJ
> ___
> 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/KCJ2IIF4BUXGQEBLBPFNKPXZCGUHVIPD/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
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/5YP4NEEBV3NOHQZMDRTP5DV4DWWAYVFC/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-11 Thread Jim J. Jewett
If a TypeGuard returns false, does that mean "it doesn't match", or just "I 
can't prove it matches, but it still might"?  That seems relevant to the else 
clause ... and seems to have changed since the last version I looked at.

-jJ
___
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/KCJ2IIF4BUXGQEBLBPFNKPXZCGUHVIPD/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-11 Thread Guido van Rossum
On Thu, Feb 11, 2021 at 12:00 AM Jim J. Jewett  wrote:

> (1)  Is it really a TypeGuard, or more of a TypeAssertion?
>

It's a query, not an assertion. The same concept is called type guard in
TypeScript.


> (2)  Does this push too hard on "annotations only have one meaning"?  If
> it has to imported from typing, then probably not, but I think that is
> worth adding to the PEP.
>

No. *This* particular annotation has a meaning for static type checkers. If
you use annotations for something else, don't use it.


> (3)  Why can't the falsey case of an Optional String narrow to a set of
> literals {"", None}  Are you worried that a subclass of str might have its
> own empty string, or just that you don't want to promise this?  As written,
> it sounds like such a narrowing is forbidden.
>

 A type checker could do this, but I don't see a reason why we should
prescribe that type checkers *should* do that. Some type checkers (in
particular, mypy) are reluctant to infer union types, and there are good
reasons for this (but this margin isn't wide enough to explain it).

-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
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/TZ6UZAPFX7OG64PFMQUZKDPBVYD6A5WK/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-10 Thread Jim J. Jewett
(1)  Is it really a TypeGuard, or more of a TypeAssertion?
(2)  Does this push too hard on "annotations only have one meaning"?  If it has 
to imported from typing, then probably not, but I think that is worth adding to 
the PEP.
(3)  Why can't the falsey case of an Optional String narrow to a set of 
literals {"", None}  Are you worried that a subclass of str might have its own 
empty string, or just that you don't want to promise this?  As written, it 
sounds like such a narrowing is forbidden.

-jJ
___
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/XRE57ARQFY7IR7GGZH5EKQZMYD3NM3OY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 647 (type guards) -- final call for comments

2021-02-09 Thread Terry Reedy

On 2/9/2021 11:21 AM, Guido van Rossum wrote:
I think we have reached consensus on PEP 647 in typing-sig. We have 
implementations for mypy and pyright, not sure about the rest. This PEP 
does not affect CPython directly except for the addition of one special 
item (TypeGuard) to typing.py -- it would be nice to get that in the 
3.10 stdlib.


I'm CC'ing python-dev here to see if there are any further comments;


As a naive possible future user of typing, I have a couple of related 
comments on the presentation and suggested additions with regard to the 
type of TypeGuard 'instances' and the meaning of type guard function 
returns.


"Its return type would be changed from bool to TypeGuard[List[str]]."

My first thought was "Huh? The return type *is* a bool!"  Then I 
realized that a TypeGuard[List[str]] is a 'specified affirmative bool', 
a bool for which True means 'is a List[str]'.  More generally, a 
TypeGuard[X] is a bool for which True affirmatively means that the first 
argument of the function is specifically an X.  I mentally condensed 
that to 'bool subtype' and suspect that others have and will do the 
same, but you later reject 'subtype' because 'subtype' has a specific 
meaning in the typing world that does not apply here.


Suggestion 1:  Rather than mere say what a TypeGuard is not, follow the 
quoted sentence with a statement of what it is, such as I gave above.


"Specification\n TypeGuard Type \n "

The first paragraph specifies that the function must be a predicate 
(returns bool and only bool).  It leaves out that it must be a positive 
or affirmative predicate for which 'True' says what the first argument 
is, rather than what it is not.  The examples meet this requirement and 
narrowing only for 'if' clauses implies this requirement, but ...


Suggestion 2: End the first paragraph by stating the requirement.

--
Terry Jan Reedy
___
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/MF2DRQ3GIBNGFOUDWL4ZSVPBCQPVYVQO/
Code of Conduct: http://python.org/psf/codeofconduct/