[Python-ideas] Re: use type hints and slices to specify a valid numerical range, example: `Angle = int[0:361]`

2020-08-08 Thread David Mertz
On Sun, Aug 9, 2020, 12:07 AM Steven D'Aprano

> > [*] For languages with bounded data types, this is more compelling. If
> I think a variable will *definitely* fit in a uint8, having the static tool
> tell me it might not is powerful.
>
> uint8 = int[0:256]
>
> So if it's useful to know that something might violate the type uint8,
> surely it is just as useful to know that it might violate the range
> int[0:256].
>

These seem like VERY different concerns. There's nothing all that special
about 255 per se, most of the time. My actual expectation might be that
I'll store a Natural number roughly under 50, for example. But 51 isn't per
se an error. Maybe this is the usage of a limited, but somewhat elastic
resource; using 256 things might be terrible performance, but it's not
logically wrong.

With a uint8 in a language that has that, we get suddenly different
behavior with 255+1, versus 254+1. Either it wraps around to zero in C11,
or it raises an exception in a guarded language.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/DYFBD6PEAJIJEETN5YWVT2W4GH3LSOUR/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: use type hints and slices to specify a valid numerical range, example: `Angle = int[0:361]`

2020-08-08 Thread Steven D'Aprano
On Sat, Aug 08, 2020 at 08:13:53PM -0400, David Mertz wrote:

> Yes, this is absolutely doable! I guess my argument in several posts is
> that this simple level of analysis of "possible bounds violation" is rarely
> useful (at least in a Python context[*]). Vastly more complicated formal
> proofs might be useful... But, y'know, way more work for tools.
> 
> [*] For languages with bounded data types, this is more compelling. If I
> think a variable will *definitely* fit in a uint8, having the static tool
> tell me it might not is powerful.

uint8 = int[0:256]

So if it's useful to know that something might violate the type uint8, 
surely it is just as useful to know that it might violate the range 
int[0:256].

For what it's worth, I have often had IndexErrors from indexing into a 
list or string that were a bugger to debug. But it is one thing to have 
a static checker that can tell me if i might exceed the bounds 0...256 
and another that can tell me if i might exceed the bounds 0...N where N 
is not known until runtime. I suppose this is why bounds checking so 
often gets turned into runtime checks, but Python already has that: you 
get an IndexError, not a seg fault.


-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/7XOKPBIRTJG7VCCQS4L7NTCDENMAOUDT/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Inline Try-Except Clause

2020-08-08 Thread Stephen J. Turnbull
Rob Cliffe via Python-ideas writes:
 > Steven d'Aprano wrote:

 > > You don't have to agree with Serhiy's preference to recognise that there
 > > are cases where this proposal will save no lines of code. And probably
 > > not rare cases -- I expect that they will be much more common than the
 > > short examples you quote:
 > >
 > >> If you read the PEP you will find plenty of short examples:
 > >>
 > >>   process(dic[key] except KeyError: None)
 > >>   value = (lst[2] except IndexError: "No value")
 > >>   cond = (args[1] except IndexError: None)
 > >>   pwd = (os.getcwd() except OSError: None)
 > >>   e.widget = (self._nametowidget(W) except KeyError: W)
 > >>   line = (readline() except StopIteration: '')
 > >> etc.
 > > The first is a poor example because that can so easily be written as:
 > >
 > >  process(dic.get(key))

I disagree with Steven here to the extent that one purpose of the PEP
is to provide a common idiom that allows us to express this *without*
proliferating methods like dict.get.  I hope he will unpack this by
arguing "d.get(k)" is *better* than "(d[k] except KeyError: None)".
Given my present understanding of the situation, I would be perfectly
happy with an outcome where methods like dict.get were deprecated (as
a matter of style and TOOWTDI, I don't mean DeprecationWarning) in
favor of the uniform except-clause syntax, unless there's a reason
this syntax is *bad*.  There are many times I choose to split a long
if-else expression across lines, and others where I choose the
statement form, and of course I use "x or default" instead of "x if x
else default".  I see no reason why this construct wouldn't "work" the
same way, although it might be much less common (then again, it might
be *more* common than if-else expressions).

The kind of anti-except-expression argument I have in mind can be
exemplified using the fourth example:

pwd = (os.getcwd() except OSError: None)

where I would find the argument that this really is an environmental
condition that probably shouldn't be papered over with "pwd=None" in
almost all contexts, and therefore should be emphasized with a try
*statement*, pretty plausible.  But that might be a style argument
("use 'try', not 'except' expressions when the Error indicates a
broken environment rather than an uncommon but reasonable state"),
rather than an argument that we *should not* unify these usages with a
single idiom.

Interestingly, Steven takes the opposite position:

 > > The fourth example of os.getcwd is excellent.

I just don't know.  "Infinite are the arguments of mages." ;-)

Steve
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/KZFK5GB3W7RW67F4CXD73QD4OIKMTMAF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: use type hints and slices to specify a valid numerical range, example: `Angle = int[0:361]`

2020-08-08 Thread Greg Ewing

On 9/08/20 10:43 am, Guido van Rossum wrote:
But integer ranges? I guess they would be useful to catch array indexing 
mistakes,


I'm not sure they would. For an index error to be caught at compile
time, the thing being indexed has to have a size known to the
compiler. This was always the case in Pascal, and sometimes is in
C/C++/C#/Java, but almost never is in Python.

--
Greg
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/5JP2FHLG2DYBJ6QXHSWL5GQIJFAJF2GV/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Changing item dunder method signatures to utilize positional arguments (open thread)

2020-08-08 Thread Ricky Teachey
I misunderstood thanks for the clarification and if an apology is
appropriate I gladly offer mine.

On Sat, Aug 8, 2020, 9:01 PM Edwin Zimmerman 
wrote:

> On 8/7/2020 10:47 PM, Ricky Teachey wrote:
>
> On Fri, Aug 7, 2020 at 9:25 PM Edwin Zimmerman 
> wrote:
>
>> On 8/7/2020 8:28 PM, Greg Ewing wrote:
>> >  I don't think anyone has the appetite for a Python 4 any
>> > time soon.
>> >
>> I'm included in "anyone" here.  From reading this list, it seems to me
>> that "Python 4" is invoked as some folks favorite magical justification for
>> proposing major breaking changes.  Python 3 works quite well, I think.
>> Non-breaking, incremental changes suite me much better that large breaking
>> ones.  I have better things to do with my time than complete software
>> rewrites of all the software projects I work on.
>>
>
> Nobody is asking you to rewrite anything in this thread.
>
> Thankfully not.  I did not intend to come across as commenting on this
> thread in particular, but rather as voicing a general comment against large
> breaking changes.  Apparently, I wasn't clear enough about my intent.
>
> --Edwin
>
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/6CZTRFOI5ZGEBMWSPK72BRPTNEDGYNFX/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Changing item dunder method signatures to utilize positional arguments (open thread)

2020-08-08 Thread Edwin Zimmerman
On 8/7/2020 10:47 PM, Ricky Teachey wrote:
> On Fri, Aug 7, 2020 at 9:25 PM Edwin Zimmerman  > wrote:
>
> On 8/7/2020 8:28 PM, Greg Ewing wrote:
> >  I don't think anyone has the appetite for a Python 4 any
> > time soon.
> >
> I'm included in "anyone" here.  From reading this list, it seems to me 
> that "Python 4" is invoked as some folks favorite magical justification for 
> proposing major breaking changes.  Python 3 works quite well, I think.  
> Non-breaking, incremental changes suite me much better that large breaking 
> ones.  I have better things to do with my time than complete software 
> rewrites of all the software projects I work on.
>
>
> Nobody is asking you to rewrite anything in this thread.
Thankfully not.  I did not intend to come across as commenting on this thread 
in particular, but rather as voicing a general comment against large breaking 
changes.  Apparently, I wasn't clear enough about my intent.

--Edwin
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/PHD66FZMMGQOKGRBBDFBBUZDNA2P37FU/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: use type hints and slices to specify a valid numerical range, example: `Angle = int[0:361]`

2020-08-08 Thread David Mertz
On Sat, Aug 8, 2020, 7:40 PM Steven D'Aprano

> Any checker capable of doing bounds checks would know that the range of
> possible ints is unbounded in both directions, and therefore an int does
> not fit into the range [1:10**9]. Hence that will be a static bounds
> check failure:


Just so you can win a bet at the library or the bar, the largest Python int
is 2**(2**63)-1, and the smallest -2**(2**63). Ints have a struct member of
bit_length that is a fixed size in C. :-)

A computer capable of storing that number cannot, of course, fit in the
physical universe.

Let's be less vague:
>
> def step()->int[-3:4]:
> pass
>
> n = 0: int[-100:101]
> for i in range(N):
> n += step()
>
> You and I can reason that after N steps, the maximum possible value of n
> is 3*N, which could be greater than 100 unless N was provably less than 34,
> which it may not be. And so the bounds check fails.
>

Yes, this is absolutely doable! I guess my argument in several posts is
that this simple level of analysis of "possible bounds violation" is rarely
useful (at least in a Python context[*]). Vastly more complicated formal
proofs might be useful... But, y'know, way more work for tools.

[*] For languages with bounded data types, this is more compelling. If I
think a variable will *definitely* fit in a uint8, having the static tool
tell me it might not is powerful.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/L5NCUMURE7ZA2UYNHSBLZG76BUYCHAEG/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: `property.apply` decorator

2020-08-08 Thread Roger Serwy
That's an excellent point about argument unpacking. Thank you for your 
feedback, I'll consider this idea resolved.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/NKNRBHWMEHW63H65APGOOQWH2RALUPMS/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: use type hints and slices to specify a valid numerical range, example: `Angle = int[0:361]`

2020-08-08 Thread Steven D'Aprano
On Sat, Aug 08, 2020 at 01:28:59AM -0400, David Mertz wrote:
> On Sat, Aug 8, 2020, 1:12 AM Steven D'Aprano
> 
> > Static languages often check what
> > bounds they can at compile time, and optionally insert bound checking
> > runtime code for ambiguous places.
> 
> 
> Yep. That's an assert, or it's moral equivalent.

No, asserts are not checked at compile time. Assertions are purely 
runtime checks. But bounds checking can be done (at least in part) at 
compile time, depending on how smart your compiler is. (In the case of 
Python, that would be entirely delegated to a third-party checker.)

If a static checker knows that x is a float, and that n is an int 
between 0 and 100, it shouldn't be hard to tell that this is a bounds 
error:

x: float
n: int[0:100]
n = int(x)

but this isn't:

n = int(x) % 5

But there is a big gap between what a human can reason about code and 
what a tool can do in practice (as opposed to in theory), and I don't 
know what the state of art in range checking is, or how sophisticated it 
may be.

Compared to type systems, compile time range checking has been neglected 
for decades and (as far as I can tell) the state of the art is far more 
primitive. But I could be wrong and this could be one of the simplest 
things that they can handle for all I know :-)

We should remember that the requirement for static checking isn't to 
detect at compile time that something *will* be a runtime error, but 
that it *could* be a runtime so that you can fix your code to avoid the 
possibility. Just as type checking doesn't tell you that you certainly 
will get a type error at runtime, only that you could.

I suggested this proposed feature be deferred unless people in the MyPy 
and other static checking projects express interest. It may be that 
nobody in the MyPy and other static checker projects has the knowledge, 
time or interest in pursuing this, in which case supporting this would 
be a waste of time.


> Here's a deterministic program using the hypothetical new feature.
> 
> def plusone(i: int[1:1_000_000_000]):
> return i+1
> 
> random.seed(42)
> for n in range(1_000_000):
>   random.randint(1, 1_000_000_001)
> 
> Is this program type safe? Tell me by static analysis of Mersenne Twister.

I assume there was supposed to be a call to plusone there :-)

randint will surely be declared as returning an int, since we can't be 
more specific than that without getting into serious levels of 
automated correctness checking.

Any checker capable of doing bounds checks would know that the range of 
possible ints is unbounded in both directions, and therefore an int does 
not fit into the range [1:10**9]. Hence that will be a static bounds 
check failure: the checker detects that there is a chance that the input 
to plusone could be out of range.


> Or if you want to special case the arguments to randint,

Of course not.


> will, lots of
> things. Let's say a "random" walk on the integer number line where each
> time through the loop increments or decrements some (deterministic but hard
> to calculate) amount. After N steps are we within certain bounds?

Let's be less vague:

def step()->int[-3:4]:
pass

n = 0: int[-100:101]
for i in range(N):
n += step()


You and I can reason that after N steps, the maximum possible value of n 
is 3*N, which could be greater than 100 unless N was provably less than 
34, which it may not be. And so the bounds check fails.

I know very little about the state of art of bounds checking, but I 
would imagine that this would probably be beyond the capability of a 
simple checker, and maybe a sophisticated one too, but not the most 
sophisticated formal correctness proof checkers.

So what? The value of static checking is not diminished by the problems 
not found, since they wouldn't be found if you had no static checking in 
the first place. The value of static checking is in the problems which 
are found.

Whether or not MyPy etc are capable of such range checking, or even 
simpler checks, is a question best asked of them. If they have any 
interest in range checking, adding subscripting to `int` would be easy. 
Until then, YAGNI.


-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/SR4SVS6MOWZY7NX5L4NBIFBWLNKZH7ZP/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: use type hints and slices to specify a valid numerical range, example: `Angle = int[0:361]`

2020-08-08 Thread 2QdxY4RzWzUUiLuE
On 2020-08-08 at 18:53:36 -0400,
David Mertz  wrote:

> ... my discovery was that "LLVM figures out Gauss' simplification and
> does it in constant time no matter the N.  After that I looked at the
> LLVM bytecode to see, "Yup, it does."  The optimizer is pretty smart
> about variations in writing the code in some slightly different ways,
> but I don't know exactly what it would take to fool it into missing
> the optimization.

I was trying to learn something about 80X86 (where X might have been the
empty string) assembly language by examing the output from Microsoft's C
compiler.  It made the same optimization, thus thwarting that particular
effort, and that was probably 35 years ago now.  For small N, it's
really just constant folding, loop unrolling, and peephole
optimizations; these days, "small N" might be a billion or 2**32.

The point isn't that it't not suprising, of course, but that it's not
something new.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/J6YDNJTMWNWXDVR5JPM4WSOVGK6YRMHE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: `property.apply` decorator

2020-08-08 Thread Steven D'Aprano
On Sat, Aug 08, 2020 at 10:22:20PM -, Roger Serwy wrote:

> The property decorator, with its .setter and .deleter chaining, is a 
> bit cumbersome and repetitive. If we can add `.apply` as a method on 
> property that calls a function that returns the fget/fset/fdel/doc 
> arguments, it would simplify instantiating the descriptor. For 
> example:

You don't need an apply method for that, property already takes four 
arguments, so you can write:

def factory():
def fget(self): pass
def fset(self, value): pass
def fdel(self): pass
return (fget, fset, fdel, "doc")

attr = property(*factory())
# optional: del factory

but frankly, having to write the property getters and setters as nested 
functions is (in my opinion) uglier looking and more annoying than the 
usual property chaining version.

So if you want to use this with decorator notation, you need a one-line 
helper:

def myproperty(func):
return property(*func())

and change the name of "factory" to "attr".

-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/AWY3ORTCRR6KVGV4KEUNURUZUFGSCKWK/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: use type hints and slices to specify a valid numerical range, example: `Angle = int[0:361]`

2020-08-08 Thread David Mertz
On Sat, Aug 8, 2020 at 5:49 PM Michael Smith  wrote:

> This kind of thing is so powerful, and I would love to see tooling capable
> of it in the python ecosystem. I believe folks who say it's very hard to
> implement correctly, but I don't know that that's a good reason not to make
> the proposed range syntax legal for some primitive types like int. Tools
> like mypy can choose not to handle int[A:B] until they are ready, or
> forever, but someone else can still work on it.


As Steven notes, there *are* some compilers in static languages that do a
limited amount of this.  But the cases where it is *provable* that some
bounds are not exceeded are very limited, or take a great deal of work to
construct the proof.  I don't feel like Mypy or similar tools are going to
stray quite there.  And in those static languages, a great deal of the
time, they must give up and just insert assertions to raise exceptions if
the bounds are violated rather than *proving* the constraint.

I slightly regret using the randint() example because you and I can so very
easily recognize that `random.randint(0, 1_000_000_001)` MIGHT return a
result of a billion-and-one.  That was just to have something short.  But a
great many computations, even ones that mathematically HAVE bounds, are not
easy to demonstrate the bounds.  Let me try again, still slightly
hand-wavey.

def final_number(seed: int):
"Something mathy with primes, modulo arithmetic, factorization, etc"
x = seed
while some_condition(x):
while other_condition(x):
if my_predicate(x):
x += 1
elif other_predicate(x):
x += 2
   else:
   x -= 1

def my_fun(i: int[1:1_000_000]):
pass

my_fun(final_number(42))

Depending on what the called functions do, this is the sort of thing where
number theorists might prove bounds.  But the bounds might depend in weird,
chaotic ways on the seed.  For some it will fly off to infinity or negative
infinity.  For others it bounces around in a small cycle.  For others it
bounces around for billions of times through the loop within small bounds
until flying off.  It's really NOT that hard to write functions like that,
even without really realizing their oddness.

Yours, David...

P.S. Compilers can do shockingly clever things.  LLVM has an optimization
that took me by surprise.  I was playing around with it via Numba a few
years ago.  Actually, for teaching material; my intention was just to say
"Look, this is way faster than plain Python."  But here's the case I
stumbled on:

Folks all probably know the story of Gauss in elementary school in which
(at least in anecdote) the teacher assigned the students to add all the
integers from 1 to 100 so she could get some coffee or whatever.  Gauss had
the solution in a couple seconds to her annoyance.  Because sum(range(1,
N+1)) == (N*(N+1))/2 by some straightforward reasoning that most 10 year
olds don't see (and in the story, neither did the teacher).

Anyway, my silly example for my training students (i.e. working programmers
and scientists) was loop to 100, add latest, with and without Numba.  Then
do it up to a billion.  My intentions was "Numba is lots faster, but has a
minor JIT overhead" ... my discovery was that "LLVM figures out Gauss'
simplification and does it in constant time no matter the N.  After that I
looked at the LLVM bytecode to see, "Yup, it does."  The optimizer is
pretty smart about variations in writing the code in some slightly
different ways, but I don't know exactly what it would take to fool it into
missing the optimization.

I asked one of the LLVM developers how I could find out what optimizations
are there.  Their answer was "Become a core developer and study the source
code of LLVM." Apparently the Gauss thing isn't actually documented anyway
outside the code. :-)

-- 
The dead increasingly dominate and strangle both the living and the
not-yet born.  Vampiric capital and undead corporate persons abuse
the lives and control the thoughts of homo faber. Ideas, once born,
become abortifacients against new conceptions.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/YZRSXAGZHD7XS7LKG6OIKFLUB5YQBRDZ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Function suggestion: itertools.one()

2020-08-08 Thread Stefano Borini
+1 very useful also for me. Once in a while I have this exact
scenario. Not often enough to get annoyed, but often enough that it
would be nice to have.

On Tue, 28 Jul 2020 at 20:27, Noam Yorav-Raphael  wrote:
>
> Hello,
>
> There's a simple function that I use many times, and I think may be a good 
> fit to be added to itertools. A function that gets an iterator, and if it has 
> exactly one element returns it, and otherwise raises an exception. This is 
> very useful for cases where I do some sort of query that I expect to get 
> exactly one result, and I want an exception to be raised if I'm wrong. For 
> example:
>
> jack = one(p for p in people if p.id == '1234')
>
> sqlalchemy already has such a function for queries: 
> https://docs.sqlalchemy.org/en/13/orm/query.html#sqlalchemy.orm.query.Query.one
>
> more-itertools has this exact function:
> https://more-itertools.readthedocs.io/en/latest/api.html#more_itertools.one
>
> Here is a simple implementation:
>
> def one(iterable):
> it = iter(iterable)
> try:
> first = next(it)
> except StopIteration:
> raise ValueError("Iterator is empty")
> try:
> second = next(it)
> except StopIteration:
> return first
> else:
> raise ValueError("Iterator has more than one item")
>
> I brought this up on python-dev, but it should be discussed here.
> Here is the discussion:
> https://mail.python.org/archives/list/python-...@python.org/thread/D52MPKLIN4VEXBOCKVMTWAK66MAOEINY/
>
> Brett Cannon said that this idea has been brought up at least twice before. I 
> found:
> https://mail.python.org/archives/list/python-ideas@python.org/thread/FTJ6JRDTZ57HUVZ3PVIZV2NHU2NLAC4X/#RMWV3SNZ2N4KZLPKPIDE42H46QDEIVHE
>
> https://mail.python.org/archives/list/python-ideas@python.org/thread/REYDJFCXQNQG4SAWKELQMCGM77IZG47Q/#ITR2ILPVCKYR52U2D7RHGENASZTNVDHN
>
> The first thread hasn't reached any operative conclusion. The second thread 
> was very long, and seemed to focus mostly on another function, first(), that 
> doesn't check if there is more than one item. Joao S. O Bueno said that it 
> passed "general approval". I think that perhaps a new discussion, focused 
> just on one (no pun intended) function in the itertools module may reach a 
> conclusion.
>
> It was suggested that instead of an additional function, one can use iterator 
> unpacking:
>
> jack, = (p for p in people if p.id == '1234')
> or
> [jack] = (p for p in people if p.id == '1234')
>
> I still think that having a one() function would be useful, since:
> 1. I think it spells the intention more clearly. It is not symbols that you 
> need to understand their meaning in order to understand that I expect the 
> iterable to have exactly one item, it's spelled in code.
> 2. The exception would be easier to understand, since errors in tuple 
> unpacking usually mean something else.
> 3. The one() function allows you to use the result inside an expression 
> without assigning it to a variable. Therefore, I think it encourages writing 
> better code. It's very easy to write:
> print([p for p in people if p.id == '1234][0])
> (which has the problem of not verifying the assumption that there's no more 
> than one result), and I find it easier to replace _[0] with one(_) than to be 
> required to name a new variable, and instead of having an operation on the 
> iterable, change the way I'm assigning to it.
>
> WDYT?
>
> Cheers,
> Noam
>
>
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at 
> https://mail.python.org/archives/list/python-ideas@python.org/message/6OLEL4XTUWXRI7ENODKEDOYFBRVDYKI7/
> Code of Conduct: http://python.org/psf/codeofconduct/



-- 
Kind regards,

Stefano Borini
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/FZGXJ36VUMU5XYVOSZR4AXV2FDSQLXEJ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] `property.apply` decorator

2020-08-08 Thread Roger Serwy
The property decorator, with its .setter and .deleter chaining, is a bit 
cumbersome and repetitive. If we can add  `.apply` as a method on property that 
calls a function that returns the fget/fset/fdel/doc arguments, it would 
simplify instantiating the descriptor. For example:

@property.apply
def attr():
def fget(self): pass
def fset(self, value): pass
def fdel(self): pass
return (fget, fset, fdel, "doc")

instead of

@property
def attr(self): pass

@attr.setter
def attr(self, value): pass

@attr.deleter
def attr(self): pass

An example implementation using `fproperty` exists at 
https://github.com/serwy/fproperty
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/VO537YXAALG3C2QJXEI5T7BPNV3ZHM5T/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: use type hints and slices to specify a valid numerical range, example: `Angle = int[0:361]`

2020-08-08 Thread Guido van Rossum
This thread seems light on real use cases. I know there are people eager to
have integer generics, since they are essential for typing numpy, pandas,
tensorflow and friends. And so there are good proposals floating around for
this on typing-sig; I expect implementations within a year.

But integer ranges? I guess they would be useful to catch array indexing
mistakes, but I don’t believe IndexError is the bane of anyone’s existence.
And float ranges? I wouldn’t want to touch those with a 10-foot pole. What
am I missing?

On Sat, Aug 8, 2020 at 15:28 Ricky Teachey  wrote:

> On Sat, Aug 8, 2020 at 5:51 PM Michael Smith 
> wrote:
>
>> This kind of thing is so powerful, and I would love to see tooling
>> capable of it in the python ecosystem. I believe folks who say it's very
>> hard to implement correctly, but I don't know that that's a good reason not
>> to make the proposed range syntax legal for some primitive types like int.
>> Tools like mypy can choose not to handle int[A:B] until they are ready, or
>> forever, but someone else can still work on it.
>>
>
> I agree.
>
> A total, complete solution that successfully catches everything might well
> be out of reach. But that doesn't seem like a reason to not catch what can
> be caught.
>
>  On Sat, Aug 8, 2020 at 5:51 PM Michael Smith 
> wrote:
>
>> Are we just talking about the language features here, or does this list
>> include ideas for tooling like mypy?
>>
>
> Others will surely know better than me but it seems like that in order to
> add the ability to use the [ ]  operator on the int (and perhaps float)
> type, and to be able to "get at" the arguments that were provided to them,
> the language would first have to change to support that,.
>
> But on the other hand there is no stopping someone from writing a library
> that writes its own Int and Float type hints that supports all of this, and
> putting it out in the universe to see what traction it gets.
>
> I know for a fact I am not skilled enough to do this, unfortunately, so
> I'd have to leave it to someone else.
>
> On Sat, Aug 8, 2020 at 4:42 PM Dominik Vilsmeier 
> wrote:
>
>> By the way, I would find it more intuitive if the `stop` boundary was
>> included in the interval, i.e. `int[0:10]` means all the integer numbers
>> from 0 to 10 (including 10). I don't think that conflicts with the current
>> notion of slices since they always indicate a position in the sequence, not
>> the values directly (then `int[0:10]` would mean "the first 10 integer
>> numbers", but where do they even start?).
>>
> It's always interesting how people's intuitions can differ. Making the
> stop value inclusive by default is a little jarring to me since it is so
> inconsistent with sequence indexing elsewhere. But I do see your point that
> in reality this is NOT slicing positions in a sequence (since it has no
> beginning and end). I don't think it would be a terrible thing for both
> start and stop to be inclusive by default.
>
> But regardless of whether the stop value is inclusive or not, there are
> certainly going to be instances when someone will want inclusivity and
> others when they want exclusivity, and this applies to both the start and
> the stop value.
>
> In other words, any syntax that did not provide the ability to state all
> of these number lines would seem pretty wanting:
>
> 0 < x < ∞  # all positive integers
> -∞ < x < 0  # all negative integers
> 0.0 < x < ∞  # all positive floats
> -∞ < x < 0.0  # all negative floats
>
> 0 <= x < ∞  # all positive integers, zero included
> -∞ < x <= 0  # all negative integers, zero included
> 0.0 <= x < ∞  # all positive floats, zero included
> -∞ < x <= 0.0  # all negative floats, zero included
> 0 <= x <= 10  # some inclusive int interval
> 0 < x < 10  # some exclusive int interval
> 0 < x <= 10  # some int interval, combined boundaries
> 0 <= x < 10  # some int interval, combined boundaries
> 0.0 <= x <= 10.0  # some inclusive float interval
> 0.0 < x < 10.0  # some exclusive float interval
> 0.0 < x <= 10.0  # some float interval, combined boundaries
> 0.0 <= x < 10.0  # some float interval, combined boundaries
>
> And versions of all of these with step arguments.
>
> A way around the inclusive vs exclusive problem might be to define some
> sort of indicator, or function, to modify the boundaries.
>
> Here's several ideas of how to spell the number line 0 < x <=10:
>
> >>> x: int[excv(0):incv(10)]  # where incv and excv stand for "inclusive"
> and "exclusive"
> >>> x: int[@0:10]  # where the @ is read "almost" or "about" or "around"
> -- the idea is all boundaries are inclusive by default and the @ makes a
> boundary exclusive
> >>> x: int[(0,"incv"):(10,"excv")]  # here we just pass tuples to the
> start and stop slice arguments, and the text indicates whether each
> boundary is inclusive (incv) or exclusive (excv)
>
> I think the third is my favorite - it reads pretty nicely. Although it
> would be nicer if it didn't need the parentheses. The second one i

[Python-ideas] Re: use type hints and slices to specify a valid numerical range, example: `Angle = int[0:361]`

2020-08-08 Thread Ricky Teachey
On Sat, Aug 8, 2020 at 5:51 PM Michael Smith  wrote:

> This kind of thing is so powerful, and I would love to see tooling capable
> of it in the python ecosystem. I believe folks who say it's very hard to
> implement correctly, but I don't know that that's a good reason not to make
> the proposed range syntax legal for some primitive types like int. Tools
> like mypy can choose not to handle int[A:B] until they are ready, or
> forever, but someone else can still work on it.
>

I agree.

A total, complete solution that successfully catches everything might well
be out of reach. But that doesn't seem like a reason to not catch what can
be caught.

 On Sat, Aug 8, 2020 at 5:51 PM Michael Smith  wrote:

> Are we just talking about the language features here, or does this list
> include ideas for tooling like mypy?
>

Others will surely know better than me but it seems like that in order to
add the ability to use the [ ]  operator on the int (and perhaps float)
type, and to be able to "get at" the arguments that were provided to them,
the language would first have to change to support that,.

But on the other hand there is no stopping someone from writing a library
that writes its own Int and Float type hints that supports all of this, and
putting it out in the universe to see what traction it gets.

I know for a fact I am not skilled enough to do this, unfortunately, so I'd
have to leave it to someone else.

On Sat, Aug 8, 2020 at 4:42 PM Dominik Vilsmeier 
wrote:

> By the way, I would find it more intuitive if the `stop` boundary was
> included in the interval, i.e. `int[0:10]` means all the integer numbers
> from 0 to 10 (including 10). I don't think that conflicts with the current
> notion of slices since they always indicate a position in the sequence, not
> the values directly (then `int[0:10]` would mean "the first 10 integer
> numbers", but where do they even start?).
>
It's always interesting how people's intuitions can differ. Making the stop
value inclusive by default is a little jarring to me since it is so
inconsistent with sequence indexing elsewhere. But I do see your point that
in reality this is NOT slicing positions in a sequence (since it has no
beginning and end). I don't think it would be a terrible thing for both
start and stop to be inclusive by default.

But regardless of whether the stop value is inclusive or not, there are
certainly going to be instances when someone will want inclusivity and
others when they want exclusivity, and this applies to both the start and
the stop value.

In other words, any syntax that did not provide the ability to state all of
these number lines would seem pretty wanting:

0 < x < ∞  # all positive integers
-∞ < x < 0  # all negative integers
0.0 < x < ∞  # all positive floats
-∞ < x < 0.0  # all negative floats

0 <= x < ∞  # all positive integers, zero included
-∞ < x <= 0  # all negative integers, zero included
0.0 <= x < ∞  # all positive floats, zero included
-∞ < x <= 0.0  # all negative floats, zero included
0 <= x <= 10  # some inclusive int interval
0 < x < 10  # some exclusive int interval
0 < x <= 10  # some int interval, combined boundaries
0 <= x < 10  # some int interval, combined boundaries
0.0 <= x <= 10.0  # some inclusive float interval
0.0 < x < 10.0  # some exclusive float interval
0.0 < x <= 10.0  # some float interval, combined boundaries
0.0 <= x < 10.0  # some float interval, combined boundaries

And versions of all of these with step arguments.

A way around the inclusive vs exclusive problem might be to define some
sort of indicator, or function, to modify the boundaries.

Here's several ideas of how to spell the number line 0 < x <=10:

>>> x: int[excv(0):incv(10)]  # where incv and excv stand for "inclusive"
and "exclusive"
>>> x: int[@0:10]  # where the @ is read "almost" or "about" or "around" --
the idea is all boundaries are inclusive by default and the @ makes a
boundary exclusive
>>> x: int[(0,"incv"):(10,"excv")]  # here we just pass tuples to the start
and stop slice arguments, and the text indicates whether each boundary is
inclusive (incv) or exclusive (excv)

I think the third is my favorite - it reads pretty nicely. Although it
would be nicer if it didn't need the parentheses. The second one is
interesting though.

But of course regardless of which of these spellings (or some other) is
preferred, the default behavior would still need to be defined.


---
Ricky.

"I've never met a Kentucky man who wasn't either thinking about going home
or actually going home." - Happy Chandler
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/WAIJ2OEFMVATEZFAQWAEHDJLIP7PHX56/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Inline Try-Except Clause

2020-08-08 Thread Rob Cliffe via Python-ideas



On 08/08/2020 02:16, Steven D'Aprano wrote:

On Fri, Aug 07, 2020 at 06:40:33PM +0100, Rob Cliffe via Python-ideas wrote:


On 07/08/2020 17:16, Serhiy Storchaka wrote:

The main problem to me with the exception catching expression is that
you need to add the exception name and several keywords, and it makes
real-world examples too long, so you will need to split the expression
on several lines, and add extra parenthesis. And in this case there is
no much difference between expression

 x = (
 
except LongExceptionName:
 
 )

and statement

 try:
 x = 
 except LongExceptionName:
 x = 

(actually the statement may be shorter and better aligned).

Serhiy is correct that some examples will be long and cumbersome, but
many other expressions are long and cumbersome, and we leave it up to
the writer of the code to decide whether to extend a single expression
over multiple lines or split it into multiple statements using temporary
variables.

In Serhiy's example above, it is up to the coder and their aesthetic
sense to decide whether to use the expression form or the statement
form, just as today they can decide between:


 if :
 x = 
 else:
 x = 


and


 x = (
  if 
  else 
  )


Neither is necessarily better or worse than the other, it will depend on
the surrounding code, whether the value is being bound to a variable or
being immediately used in another expression:

 function(arg,
  another_arg,
  spam=long_conditional_or_except_expression,
  eggs=expression
  )


Just like if statements vs ternary if expressions, the writer will get
to choose which is better for their purposes, and whether or not to use
temporary variables.



This is a strawman argument.  You set up a case where exception-catching
expressions are poor (long expression, long exception name) and then
knock it down.

Please don't misuse "strawman argument" in this way. Serhiy is making a
legitimate criticism of the feature, and explicitly labelling it as a a
reason he personally does not like the feature.

It is not a strawman to point out your personal reasons for disliking a
feature. This is a legitimate issue with the suggested syntax: it is not
especially terse, and if the expressions and exceptions are long, as
they sometimes will be, the whole thing will be little better, or not
better at all, than using a try...except statement.
Yes but Serhiy implied that the whole thing will *always* be too long, 
which won't be true.  He said, without qualification, "it makes 
real-world examples too long".


You don't have to agree with Serhiy's preference to recognise that there
are cases where this proposal will save no lines of code. And probably
not rare cases -- I expect that they will be much more common than the
short examples you quote:


If you read the PEP you will find plenty of short examples:

process(dic[key] except KeyError: None)
value = (lst[2] except IndexError: "No value")
cond = (args[1] except IndexError: None)
pwd = (os.getcwd() except OSError: None)
e.widget = (self._nametowidget(W) except KeyError: W)
line = (readline() except StopIteration: '')
etc.

The first is a poor example because that can so easily be written as:

 process(dic.get(key))

The second and third are basically the same example.

The fourth example of os.getcwd is excellent. But the fifth example
strikes me as exceedingly weak. You are calling a private method, which
presumably means you wrote the method yourself. (Otherwise you have no
business calling the private method of a class you don't control.) So
why not just add an API for providing a default instead of raising?

And the final example is also weak. If readline is a bound method of a
file object:

 readline = open(path, 'r').readline

then it already returns the empty string at the end of file. And if it
isn't, then perhaps it should, rather than raising a completely
inappropriate StopIteration exception.
I just copied the first few examples from the PEP without analysing 
them, so you are criticising the PEP, not me.  I hope Chris Angelico 
appreciates the criticism (I mean that seriously, not as a piece of 
sarcasm).



Other problem specific to the PEP 463 syntax is using colon in
expression. Colon is mainly used before indented block in complex
statements. It was introduced in this role purely for aesthetic reasons.

I disagree with Serhiy here: I believe that there is objective evidence
in the form of readability studies which suggest that colons before
indented blocks aid readability, although I have lost the reference.



Using it in other context is very limited (dict display, lambda,
annotations, what else?).


Slice notation.  As you would have discovered if you read the PEP.


No need to be so catty over a minor bit of forgetfulness, I'm sure that
Serhiy has read the PEP, a

[Python-ideas] Re: use type hints and slices to specify a valid numerical range, example: `Angle = int[0:361]`

2020-08-08 Thread Michael Smith
On Sat, Aug 8, 2020 at 16:41 Dominik Vilsmeier 
wrote:

> On 08.08.20 05:48, David Mertz wrote:
>
> On Fri, Aug 7, 2020, 6:03 PM Paul Moore  wrote:
>
>> > x: int[0:]  # any ints greater than or equal to zero would match,
>> others would fail
>> > x: int[:101]  # any ints less than 101 match
>> > x: int[0:101:2]  # even less than 101
>>
>> I suspect the biggest issue with this is that it's likely to be
>> extremely hard (given the dynamic nature of Python) to check such type
>> assertions statically.
>
>
> Yes, it's hard in the sense that it would require solving the halting
> problem.
>
> How is it any more difficult than already existing type checks? The
> proposal talks about type hints for static type analysis and hence implies
> using literals for the slices. There's no dynamic nature to it. You can
> define `int[x]` to be a subtype of `int[y]` if the numbers defined by `x`
> are a subset of those defined by `y`.
>
> Referring to one of the examples including `random.randint`:
>
> def foo(x: int[0:11]):
> pass
>
> foo(random.randint(0, 10))
>
> Regarding static type analysis, the only information about
> `random.randint` is that it returns an `int` and hence this should be an
> error. If you want to use it that way, you'd have to manually cast the
> value:
>
> foo(typing.cast(int[0:11], random.randint(0, 10)))
>
> This of course raises questions about the usefulness of the feature.
>
> By the way, I would find it more intuitive if the `stop` boundary was
> included in the interval, i.e. `int[0:10]` means all the integer numbers
> from 0 to 10 (including 10). I don't think that conflicts with the current
> notion of slices since they always indicate a position in the sequence, not
> the values directly (then `int[0:10]` would mean "the first 10 integer
> numbers", but where do they even start?).
>

> This of course raises questions about the usefulness of the feature.

I feel like this discussion boils down to one argument being the checking
is doable as long as you keep it to something with very limited usefulness
(static literal ranges) and the other being in order to make it useful
you'd need dependent typing and a sophisticated theorem prover.

I think about dependent typing when I look at TypeVar and Literal, but for
it to work, you'd have to be able to do gnarly things like add and compare
two TypeVars according to the operations of their literal types, like in
this case

A = TypeVar('A', int)
B = TypeVar('B', int)

def randint(a: A, b: B) -> int[A:Literal[1]+B]:  # ?
...

And randint(1, 1_000_000_001)

means B = Literal[1_000_000_001]

but plusone's type int[1:1_000_000_000] requires B
< Literal[1_000_000_000], which fails.

This kind of thing is so powerful, and I would love to see tooling capable
of it in the python ecosystem. I believe folks who say it's very hard to
implement correctly, but I don't know that that's a good reason not to make
the proposed range syntax legal for some primitive types like int. Tools
like mypy can choose not to handle int[A:B] until they are ready, or
forever, but someone else can still work on it.

Are we just talking about the language features here, or does this list
include ideas for tooling like mypy?

- Mike Smith
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/5ZPXR5FAL24PMFKTZ5ZGZ67WXLT6HNHH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: use type hints and slices to specify a valid numerical range, example: `Angle = int[0:361]`

2020-08-08 Thread Dominik Vilsmeier

On 08.08.20 05:48, David Mertz wrote:


On Fri, Aug 7, 2020, 6:03 PM Paul Moore mailto:p.f.mo...@gmail.com>> wrote:

> x: int[0:]  # any ints greater than or equal to zero would
match, others would fail
> x: int[:101]  # any ints less than 101 match
> x: int[0:101:2]  # even less than 101

I suspect the biggest issue with this is that it's likely to be
extremely hard (given the dynamic nature of Python) to check such
type assertions statically.


Yes, it's hard in the sense that it would require solving the halting
problem.


How is it any more difficult than already existing type checks? The
proposal talks about type hints for static type analysis and hence
implies using literals for the slices. There's no dynamic nature to it.
You can define `int[x]` to be a subtype of `int[y]` if the numbers
defined by `x` are a subset of those defined by `y`.

Referring to one of the examples including `random.randint`:

    def foo(x: int[0:11]):
    pass

    foo(random.randint(0, 10))

Regarding static type analysis, the only information about
`random.randint` is that it returns an `int` and hence this should be an
error. If you want to use it that way, you'd have to manually cast the
value:

    foo(typing.cast(int[0:11], random.randint(0, 10)))

This of course raises questions about the usefulness of the feature.

By the way, I would find it more intuitive if the `stop` boundary was
included in the interval, i.e. `int[0:10]` means all the integer numbers
from 0 to 10 (including 10). I don't think that conflicts with the
current notion of slices since they always indicate a position in the
sequence, not the values directly (then `int[0:10]` would mean "the
first 10 integer numbers", but where do they even start?).

___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/JWQHHUR66YPRRV5Y62ONJ4WQY6HJUZFU/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: bpo-41231: wraps default behavior with __annotations__

2020-08-08 Thread David Caro
On 08/07 10:49, Joao S. O. Bueno wrote:
> "3" would "break stuff around".
> I'd be glad if "2" worked - but that have to be well documented and
> easy to see.

I've update the PR with improved documentation and comments to make it easier
to see.

At this point I'd appreciate if I get some reviews to improve the patch,
thanks!

> 
> "1" is basically a workaround the current behavior, and people who
> care for it will have to continue doing that until Python 3.10 is
> widespread - but ultimately it basically requires that everyone doing that
> re-implements whatever logic you have in that PR for "2"  (thus defeating
> the very purpose of "@wraps" - I'd rather rebind wrapper.__name__ and
> __wrapped__ manually)
> 
> TL;DR: I agree that "2" is the way to go.
> 
> 
> On Fri, 7 Aug 2020 at 09:14, David Caro  wrote:
> 
> >
> > Hi!
> >
> > Some time ago I opened a bug and sent a patch, but I realize that I
> > should have started a chat here first, better late than never.
> >
> > The default behavior of the `functools.wraps` decorator, is to copy over
> > the `__annotations__` from the wrapped function to the wrapper function.
> >
> > This is ok if the wrapper function has the same signature that the
> > wrapped one (that I guess was the main goal behind it, just a simple
> > wrapper).
> >
> > The issue comes when the wrapper function has a different signature than
> > the wrapped, for example, the `contextlib.contextmanager` decorator,
> > changes the return value, returning a `_GeneratorContextManager`:
> >
> > ```
> > def contextmanager(func):
> > """...
> > """
> > @wraps(func)
> > def helper(*args, **kwds):
> > return _GeneratorContextManager(func, args, kwds)
> > return helper
> > ```
> >
> > but as it uses `wraps`, the `__annotations__` will be copied over, and
> > the new function will have an incorrect return type there.
> >
> >
> > In order to improve this, I have some proposals:
> >
> > 1. Keep the default behavior of `wraps`, but change the usage around the
> > library to not copy over the `__annotations__` in places (like
> > `contextmanager`) where the types change.
> >
> > Advantages are that `wraps` keeps being backwards compatible, though the
> > change in `contextmanager` might force some people to "fix" their
> > annotations, I would consider that a "bugfix", more than a behavior change.
> >
> > The disadvantage is that you have to know that `wraps` will overwrite
> > the wrapped function annotations by default, and I think that it's
> > broadly used when creating decorators that have different signature/types
> > than
> > the wrapped function, so people will have to explicitly change their
> > code.
> >
> >
> > 2. Change `wraps` so if there's any type of annotation in the wrapper
> > function, will not overwrite it.
> > This is what I did in the PR (though I'm not convinced).
> >
> > Advantages are that only people that took the time to annotate the
> > wrapper function will see the change, and that will be the change they
> > expect (that's my guess though).
> > It's a bit smart with it, so if you don't specify a return type, will
> > get it from the wrapped function, or if you don't specify types for the
> > arguments will get them from the wrapped function, filling only the gap
> > that was not specified.
> > For everyone else, `wraps` is backwards compatible.
> >
> > Disadvantages, it's a bit more convoluted as it requires some logic to
> > detect what annotations are defined in the wrapper and which ones in the
> > wrapped and merge them.
> >
> >
> > 3. Change the default behavior of `wraps` and don't overwrite the
> > `__annotations__` property. This is non-backwards compatible, but imo
> > the simplest.
> >
> > Advantages are that it's very simple, and you'll end up with valid,
> > straight-forward `__annotations__` in the wrapped function (that is,
> > whatever you declare when writing the wrapped function).
> >
> > Disadvantages, if the goal of the `wraps` decorator was as a helper when
> > wrapping functions in a simple manner (not changing the signature), then
> > this becomes a bit more inconvenient, as it will not copy the
> > `__annotations__` as it was doing by default. It also changes the
> > current default behavior, so it will potentially affect everyone that
> > uses `wraps` currently.
> >
> >
> > Ideas?
> >
> >
> > Thanks!
> >
> > --
> > David Caro
> > ___
> > Python-ideas mailing list -- python-ideas@python.org
> > To unsubscribe send an email to python-ideas-le...@python.org
> > https://mail.python.org/mailman3/lists/python-ideas.python.org/
> > Message archived at
> > https://mail.python.org/archives/list/python-ideas@python.org/message/LFF3EXFPZG3FMXY4AXORU6SXXKBPSZOY/
> > Code of Conduct: http://python.org/psf/codeofconduct/
> >

-- 
David Caro
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@pytho