[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 597 bikeshedding: envvar / option name.

2021-02-14 Thread Ivan Pozdeev via Python-Dev

I see plenty of envvars with similarly long names at 
https://docs.python.org/3/using/cmdline.html .

So your initial name "PYTHONWARNDEFAULTENCODING" LGTM.

The first intuitive choice is often the right one ('cuz it's, well, intuitive).

On 15.02.2021 8:28, Inada Naoki wrote:

I am updating PEP 597 to include discussions in the thread.
Before finishing the PEP, I need to decide the option name.

I used PYTHONWARNDEFAULTENCODING (envvar name) /
warn_default_encoding (-X option and sys.flags name) before, but it
seems too long and hard to type, easy to misspell.

Currently, I use PYTHONWARNENCODING / warn_encoding, but it is not so explicit.

Which name is the best balance between explicitness and readability?

* PYTHONWARNENCODING / warn_ecoding
* PYTHONWARNOMITENCODING / warn_omit_encoding
* PYTHONWARNDEFAULTENCODING / warn_default_encoding
* Anything else

Regards,


--
Regards,
Ivan
___
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/2T2O2CNK4CQ67G4MZ2BT5KS26EWQEMY4/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 597 bikeshedding: envvar / option name.

2021-02-14 Thread Paul Bryan
Let the bikeshedding begin. How about with the underscores in place?
More readable to my eyes.

On Mon, 2021-02-15 at 14:28 +0900, Inada Naoki wrote:
> I am updating PEP 597 to include discussions in the thread.
> Before finishing the PEP, I need to decide the option name.
> 
> I used PYTHONWARNDEFAULTENCODING (envvar name) /
> warn_default_encoding (-X option and sys.flags name) before, but it
> seems too long and hard to type, easy to misspell.
> 
> Currently, I use PYTHONWARNENCODING / warn_encoding, but it is not so
> explicit.
> 
> Which name is the best balance between explicitness and readability?
> 
> * PYTHONWARNENCODING / warn_ecoding
> * PYTHONWARNOMITENCODING / warn_omit_encoding
> * PYTHONWARNDEFAULTENCODING / warn_default_encoding
> * Anything else
> 
> Regards,

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


[Python-Dev] PEP 597 bikeshedding: envvar / option name.

2021-02-14 Thread Inada Naoki
I am updating PEP 597 to include discussions in the thread.
Before finishing the PEP, I need to decide the option name.

I used PYTHONWARNDEFAULTENCODING (envvar name) /
warn_default_encoding (-X option and sys.flags name) before, but it
seems too long and hard to type, easy to misspell.

Currently, I use PYTHONWARNENCODING / warn_encoding, but it is not so explicit.

Which name is the best balance between explicitness and readability?

* PYTHONWARNENCODING / warn_ecoding
* PYTHONWARNOMITENCODING / warn_omit_encoding
* PYTHONWARNDEFAULTENCODING / warn_default_encoding
* Anything else

Regards,
-- 
Inada Naoki  
___
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/JMTBJKNMO7AHDNXFSIB4EYQK33D2ODZD/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP: Deferred Evaluation Of Annotations Using Descriptors

2021-02-14 Thread Inada Naoki
On Mon, Feb 15, 2021 at 10:20 AM Joseph Perez  wrote:
>
> > How about having a pseudo-module called __typing__ that is
> > ignored by the compiler:
> >
> > from __typing__ import ...
> >
> > would be compiled to a no-op, but recognised by type checkers.
>
> If you want to do run-time typing stuff, you would use
> There is already a way of doing that: `if typing.TYPE_CHECKING: ...` 
> https://docs.python.org/3/library/typing.html#typing.TYPE_CHECKING
> But yes, the issue with it is that this constant is defined in the `typing` 
> module …
>
> However, I think this is a part of the solution. Indeed, the language could 
> define another builtin constants, let's name it `__static__`, which would 
> simply be always false (at runtime), while linters/type checkers would use it 
> the same way `typing.TYPE_CHECKING` is used:
> ```python
> if __static__:
> import typing
> import expensive_module
> ```


Please note that this is a thread about PEP 649.

If PEP 649 accepted and PEP 563 dies, all such idioms breaks
annotation completely.

Users need to import all heavy modules and circular references used
only type hints, or user can not get even string form annotation which
is very useful for REPLs.


-- 
Inada Naoki  
___
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/GB5ZD2OQ5XALMZX46DK3HWVV7ROZJHH2/
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: Deferred Evaluation Of Annotations Using Descriptors

2021-02-14 Thread Joseph Perez
By the way, without adding an other constant, `__debug__` can also be used. It 
discards runtime overhead when it matters, in optimized mode.
___
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/FSNLQARSUQ3DP4X3DD4UMEK2TAIUNJHD/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP: Deferred Evaluation Of Annotations Using Descriptors

2021-02-14 Thread Joseph Perez
> How about having a pseudo-module called __typing__ that is
> ignored by the compiler:
> 
> from __typing__ import ...
> 
> would be compiled to a no-op, but recognised by type checkers.

If you want to do run-time typing stuff, you would use
There is already a way of doing that: `if typing.TYPE_CHECKING: ...` 
https://docs.python.org/3/library/typing.html#typing.TYPE_CHECKING
But yes, the issue with it is that this constant is defined in the `typing` 
module … 

However, I think this is a part of the solution. Indeed, the language could 
define another builtin constants, let's name it `__static__`, which would 
simply be always false (at runtime), while linters/type checkers would use it 
the same way `typing.TYPE_CHECKING` is used:
```python
if __static__:
import typing
import expensive_module 
```
___
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/ORL4B4RISFYIROSPGL4B4AVNWEOXP2TS/
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