[Python-ideas] __dir__ in which folder is this py file

2018-05-05 Thread Yuval Greenfield
Hi Ideas,

I often need to reference a script's current directory. I end up writing:

import os
SRC_DIR = os.path.dirname(__file__)


But I would prefer to have a new dunder for that. I propose: "__dir__".  I
was wondering if others would find it convenient to include such a shortcut.


Here are some examples of dirname(__file__) in prominent projects.

https://github.com/tensorflow/models/search?l=Python&q=dirname&type=
https://github.com/django/django/search?l=Python&q=dirname&type=
https://github.com/nose-devs/nose/search?l=Python&q=dirname&type=

Reasons not to add __dir__:
* There already is one way to do it and it's clear and fairly short.
* Avoid the bikeshed discussion of __dir__, __folder__, and other
candidates.

Reasons to add it:
* os.path.dirname(__file__) returns the empty string when you're in the
same directory as the script. Luckily, os.path.join understands an empty
string as a ".", but this still is suboptimal for logging where it might be
surprising to find the empty string. __dir__ could be implemented to
contain a "." in that case.
* I would save about 20 characters and a line from 50% of my python scripts.
* This is such a common construct that everyone giving it their own name
seems suboptimal for communicating. Common names include: here, path,
dirname, module_dir.

Cheers,

Yuval Greenfield

P.s. nodejs has it -
https://nodejs.org/docs/latest/api/modules.html#modules_dirname also I
apologize if this has been suggested before - my googling didn't find a
previous thread.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-05 Thread Tim Peters
[Nick]
>...
> There were a couple key reasons I left the "for x in y" case out of the
> initial proposal:
>
> 1. The "for x in y" header is already quite busy, especially when tuple
> unpacking is used in the assignment target
> 2. Putting the "given" clause at the end would make it ambiguous as to
> whether it's executed once when setting up the iterator, or on every
> iteration
> 3. You can stick in an explicit "if True" if you don't need the given
> variable in the filter condition
>
> [(fx**2, fx**3) for x in xs if True given fx = f(x)]
>
> And then once you've had an entire release where the filter condition was
> mandatory for the comprehension form, allowing the "if True" in "[(fx**2,
> fx**3) for x in xs given fx = f(x)]" to be implicit would be less ambiguous.

And some people claim ":=" would make Python harder to teach ;-)


[Tim]
>> ...
>> It''s certain sanest as
>>
>> if x**2 + y**2 > 9 given x, y = func_returning_twople():
>>
>> "given" really shines there!

> Yep, that's why I don't have the same immediate reaction of "It would need
> to be limited to simple names as targets" reaction as I do for assignment
> expressions. It might still be a good restriction to start out with, though

I contrived that specific "use case", of course - I actually didn't
stumble into any real code where multiple targets would benefit to my
eyes.  Perhaps because, as you noted above of `"for x in y" headers`,
multiple-target assignment statements are often quite busy already too
(I have no interest in cramming as much logic as possible into each
line - but "sparse is better than dense" doesn't also mean "almost
empty is better than sparse" ;-) ).


> (especially if we wanted to allow multiple name bindings in a single given
> clause).

>> ...
>> The one-letter variable name obscures that it doesn't
>> actually reduce _redundancy_, though.  That is, in the current
>>
>> match = pattern.search(data)
>> if match:
>>
>> it's obviously less redundant typing as:
>>
>> if match := pattern.search(data):
>>
>> In
>>
>> if match given match = pattern.search(data):
>>
>> the annoying visual redundancy (& typing) persists.

> Right, but that's specific to the case where the desired condition really is
> just "bool(target)".

Not only.  If the result _needs_ to be used N times in total in the
test, binding expressions allow for that, but `given` requires N+1
instances of the name (the "extra one" to establish the name to begin
with).

For example, where `probable_prime()` returns `True` or `False`, and
`bool(candidate)` is irrelevant:

# highbit is a power of 2 >= 2; create a random prime
# whose highest bit is highbit

while (not probable_prime(candidate) given candidate =
highbit | randrange(1, highbit, 2)):
pass

versus

while not probable_prime(candidate :=
 highbit | randrange(1, highbit, 2)):
pass

There I picked a "long" name to make the redundancy visually annoying ;-)


> That's certainly likely to be a *common* use case,

In all the code I looked at where I believe a gimmick like this would
actually help, it was indeed by far _most_ common that the result only
needed to be used once in the test.  In all such cases, the binding
expression spelling of the test requires one instance of the name, and
the `given` spelling two.


> but if we decide that it's *that* particular flavour of redundancy that really
> bothers us, then there's always the "if expr as name:" spelling (similar to
> the way that Python had "a and b" and "a or b" logical control flow
> operators long before it got "a if c else b").

Reducing each redundancy is a small win to me, but reaches
"importance" because it's so frequent.  Binding expressions have more
uses than _just_ that, though.

But I'm sure I don't know what they all are.  When a _general_ feature
is added, people find surprising uses for it.

For example, at times I'd love to write code like this, but can't:

while any(n % p == 0 for p in small_primes):
# divide p out - but what is p?

Generator expressions prevent me from seeing which value of `p`
succeeded.  While that's often "a feature", sometimes it's a PITA.  I
don't know whether this binding-expression stab would work instead
(I'm not sure the PEP realized there's "an issue" here, about the
intended scope for `thisp`):

while any(n % (thisp := p) == 0 for p in small_primes):
n //= thisp

If that is made to work, I think that counts as "a surprising use"
(capturing a witness for `any(genexp)` and a counterexample for
`all(genexp)`, both of which are wanted at times, but neither of which
`any()`/`all()` will ever support on their own)..

I suppose I could do it with `given` like so:

while p is not None given p = next(
(p for p in small_primes if n % p == 0),
None):
n //= p

but at that point I'd pay to go back to the original loop-and-a-half ;-)


>> One more, a

Re: [Python-ideas] Add "default" kw argument to operator.itemgetter and operator.attrgetter

2018-05-05 Thread Guido van Rossum
Hi Vincent,

Your idea is interesting but we are worried that there are not enough real
use cases where it would be useful. Have you encountered situations
yourself where this would make a difference? I am asking not for clarifying
examples (you already provided one and from that it's perfectly clear to me
what you are proposing) but for real-world code that would benefit from
this addition to the itemgetter API.

--Guido

On Wed, May 2, 2018 at 1:08 AM, Vincent Maillol 
wrote:

> Hi everybody,
>
> Our PEP idea would be to purpose to add a global default value for
> itemgeet and attrgetter method.
>
> This was inspired from bug 14384 (https://bugs.python.org/issue14384);
> opened by Miki TEBEKA.
>
> For example, we could do:
>
> p1 = {'x': 43; 'y': 55}
> x, y, z = itemgetter('x', 'y', 'z', default=0)(values)
> print(x, y, z)
> 43, 55, 0
>
> instead of:
>
> values = {'x': 43; 'y': 55}
> x = values.get('x', 0)
> y = values.get('y', 0)
> z = values.get('z', 0)
> print(x, y, z)
> 43, 55, 0
>
> The goal is to have have concise code and improve consistency with
> getattr, attrgetter and itemgetter
>
> What are you thinking about this?
>
> MAILLOL Vincent
> GALODE Alexandre
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>



-- 
--Guido van Rossum (python.org/~guido)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Python-ideas Digest, Vol 138, Issue 32

2018-05-05 Thread Nick Coghlan
On 6 May 2018 at 07:59, Angus Hollands  wrote:

> If, however, the motivation for the PEP was deemed significant enough that
> warrant its inclusion in a future release, then I would like to suggest
> that the keyword approach is superior to the operator variant. In
> particular, I prefer the `where` to the `given` or 'let' candidates, as I
> think it is more descriptive and slightly shorter to type ;)
>

Aside from an API naming conflict with NumPy, the key problem with using
"where" for this purpose is that "where" is explicitly used to name
*filtering* clauses in SQL, NumPy, and other contexts ("having" is used in
a similar way for filtering on SQL aggregate groups). So in "[(x, y, x/y)
for x in data if y where y = f(x)]", having both an "if" clause and a
"where" clause makes it look like there are two filters being defined (and
a mispelt "==" in the second one), rather than a filter and a name binding.

The virtue of "given" is that in any context which uses it, the intended
meaning is to associate a name with a value (either directly, as in the
mathematical usage, or indirectly, as in the hypothesis API usage), which
is exactly the meaning we're interested in here.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-05 Thread Nick Coghlan
On 6 May 2018 at 02:06, Nick Coghlan  wrote:

> On 4 May 2018 at 22:06, Nick Coghlan  wrote:
>
>> (Note: Guido's already told me off-list that he doesn't like the way this
>> spelling reads, but I wanted to share it anyway since it addresses one of
>> the recurring requests in the PEP 572 discussions for a more targeted
>> proposal that focused specifically on the use cases that folks had agreed
>> were reasonable potential use cases for inline assignment expressions.
>>
>> I'll also note that another potential concern with this specific proposal
>> is that even though "given" wasn't used as a term in any easily discovered
>> Python APIs back when I first wrote PEP 3150, it's now part of the
>> Hypothesis testing API, so adopting it as a keyword now would be markedly
>> more disruptive than it might have been historically)
>>
>
> Since I genuinely don't think this idea is important enough to disrupt
> hypothesis's public API, I've been pondering potential synonyms that are
> less likely to be common in real world code, while still being
> comprehensible and useful mnemonics for the proposed functionality.
>

I've also been pondering Tim's suggestion of instead enhancing the code
generation pipeline's native support for pseudo-keywords in a way that can
be explicitly represented in the Grammar and AST, rather than having to be
hacked in specifically every time we want to introduce a new keyword
without a mandatory __future__ statement (and without creating major
compatibility headaches for code that uses those new keywords as attribute
or variable names).

While I haven't actually tried this out yet, the way I'm thinking that
might look is to add the following nodes to the grammar:

name_plus: NAME | pseudo_keyword
pseudo_keyword: 'given'

and the replace all direct uses of 'NAME' in the grammar with 'name_plus'.

That way, to allow a new keyword to be used as a name in addition to its
syntactic use case, we'd add it to the pseudo_keyword list in addition to
adding it to .

To avoid ambiguities in the grammar, this could only be done for keywords
that *can't* be used to start a new expression or statement (so it wouldn't
have been sufficient for the async/await case, since 'async' can start
statements, and 'await' can start both statements and expressions).

So if Guido's view on the out-of-order execution approach to inline name
binding softens, I think this would be a better approach to pursue than
making a more awkward keyword choice.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Add "default" kw argument to operator.itemgetter and operator.attrgetter

2018-05-05 Thread Rob Cliffe via Python-ideas



At some point, we're really better off just using a lambda.

Maybe I'm slow today, but I'm having trouble seeing how to write this as
a lambda.

>>> values = {'x': 43, 'y': 55}
>>> x, y, z = (lambda *args : tuple(values.get(arg,0) for arg in 
args))('x','y','z')

>>> print(x, y, z)
(43, 55, 0)
>>>

Rob Cliffe
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Python-ideas Digest, Vol 138, Issue 32

2018-05-05 Thread Angus Hollands
Hi all!
Really interesting discussion on here.

Personally I feel that PEP 572, as it stands, undermines the readability of
the language, in particular for those new to the language, programming.
I have issue with both the in-expression assignment, and the current
proposed operator approach.

Below is a modified version of a comment I made on a Reddit thread about
this.

I think the first point is that, beginners often read more code than they
write - to build a mental picture of how the language works, and to build
their solution from existing parts. Whether this is a good means of
learning, or not, it's quite commonplace (and I learned using such a
method).

If this PEP passes, you will find people use the syntax. And it may well
end up being disproportionately used in the early stages because of "new
feature" semantics.

Here is an extract from the Wikipedia A* search

function reconstruct_path(cameFrom, current)
total_path := [current]
while current in cameFrom.Keys:
current := cameFrom[current]
total_path.append(current)
return total_path

In Python 3.7, that looks like this:

def reconstruct_path(cameFrom, current):
total_path = [current]
while current in cameFrom.keys():
current = cameFrom[current]
total_path.append(current)
return total_path

(of course it's not entirely Pythonic), but the point is - the pseudo code
is designed to be semantically readable, and the Python code is very similar

However with PEP572, now, the beginner will encounter both := assignments,
and = assignments. When to use which one? Now they need to learn the edge
cases / semantic differences between expression and statement explicitly,
rather than picking this up as they go. I am not making this argument
because I think that this is they best way to learn a programming language,
I'm simply arguing that there is more cognitive overhead when unfamiliar
with the language, in order to use the appropriate feature.

In terms of implementation, it's especially odd that the current proposal
(AFAICT) only binds to a name, rather than an assignment target. This feels
very wrong, despite the fact that I can understand why it is suggested. I
feel like the Python 3 series in particular has been making syntax more
uniform, so that there aren't quirks and edge cases of "this only works in
this context" (besides async, of course), which is one of the things that
makes Python so expressive.

Furthermore, with this PEP, assignment can now happen inside of expressions
- and so one of the most fundamental benefits of expressions being
effectively immutable in terms of local names is lost.

In terms of prevalence, I don't think that these situations do occur all
that often. I definitely agree that regex is the prime candidate for this
kind of syntax. However, in the examples given (matching 3+ regexes), I
would use a loop for simplicity anyway. When it comes to assigning to a
result that is only used in the conditional block, this is certainly a case
that benefits from the PEP.


If, however, the motivation for the PEP was deemed significant enough that
warrant its inclusion in a future release, then I would like to suggest
that the keyword approach is superior to the operator variant. In
particular, I prefer the `where` to the `given` or 'let' candidates, as I
think it is more descriptive and slightly shorter to type ;)

Thanks!
Angus Hollands
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Pattern Matching Syntax

2018-05-05 Thread Tim Peters
[Tim]
 ... I liked the way he _reached_ that conclusion:  by looking at real-
 life Python code that may have been written instead to use constructs
 "like this".  I find such examination far more persuasive than abstract
 arguments or made-up examples.

[Serhiy]
>>> I would like to see such examination for PEP 572. And for all other
>>> syntax changing ideas.

[Tim]
>> I did it myself for 572, and posted several times about what I found.

[Serhiy]
> Could you please give links to these results? It is hard to find something
> in hundreds of messages.

It's no easier for me to find old messages, and you'd just ask for
more & more anyway ;-)  The "short course" I already gave didn't skip
anything vital:

Short course:  I found a small win frequently, a large win rarely, but
in most cases wouldn't use it.  In all I expect I'd use it significantly
more often than ternary "if", but far less often than augmented assignment.

More importantly:

But that's me - everybody needs to look at their own code to apply
_their_ judgment.

It's _applying_ the approach I find persuasive & productive, not
someone else writing up the results of _their_ taking the approach.
I'm not trying to change peoples' minds - just suggesting a more
fruitful way (than abstract arguments, fashion, ...) to make up their
minds to begin with.


> I withdrew some my ideas and patches when my examinations showed that the
> number of cases in the stdlib that will take a benefit from rewriting using
> a new feature or from applying a compiler optimization is not large enough.

Bingo!  Note your "my examinations" in that.  Someone who hasn't done
their own examination is basically guessing.  They may or may not
reach the same conclusions if they did the work, but neither eloquence
nor confidence is a reliable predictor of whether they would.  Passion
may even be negatively correlated ;-)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-05 Thread Nick Coghlan
On 4 May 2018 at 22:06, Nick Coghlan  wrote:

> (Note: Guido's already told me off-list that he doesn't like the way this
> spelling reads, but I wanted to share it anyway since it addresses one of
> the recurring requests in the PEP 572 discussions for a more targeted
> proposal that focused specifically on the use cases that folks had agreed
> were reasonable potential use cases for inline assignment expressions.
>
> I'll also note that another potential concern with this specific proposal
> is that even though "given" wasn't used as a term in any easily discovered
> Python APIs back when I first wrote PEP 3150, it's now part of the
> Hypothesis testing API, so adopting it as a keyword now would be markedly
> more disruptive than it might have been historically)
>

Since I genuinely don't think this idea is important enough to disrupt
hypothesis's public API, I've been pondering potential synonyms that are
less likely to be common in real world code, while still being
comprehensible and useful mnemonics for the proposed functionality.

The variant I've most liked is the word "letting" (in the sense of "while
letting these names have these values, do ..."):

# Exactly one branch is executed here
if m letting m = pattern.search(data):
...
elif m letting m = other_pattern.search(data)):
...
else:
...

# This name is rebound on each trip around the loop
while m letting m = pattern.search(remaining_data):
...

# "f(x)" is only evaluated once on each iteration
result = [(x, y, x/y) for x in data if y letting y = f(x)]

# Tim's "bind two expressions" example
if diff and g > 1 letting diff = x - x_base, g = gcd(diff, n):
return g

# The "bind two expressions" example across multiple lines
while diff and g > 1 letting (
diff = x - x_base,
g = gcd(diff, n),
):
... # Do something with diff and g

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-05 Thread Nick Coghlan
On 5 May 2018 at 13:36, Tim Peters  wrote:

> [Nick Coghlan ]
> > ...
> > The essence of the given clause concept would be to modify *these
> specific
> > cases* (at least initially) to allow the condition expression to be
> followed
> > by an inline assignment, of the form "given TARGET = EXPR".
>
> I'm not clear on what "these specific cases" are, specifically ;-)
> Conditions in "if", "elif", and "while" statement expressions?
>

Exactly the 3 cases presented (if/elif/while conditions). The usage in
comprehensions would mirror the usage in if statements, and avoid allowing
name bindings in arbitrary locations due to the implicity nested scopes
used by comprehensions.

Conditional expressions would be initially omitted since including them
would allow arbitrary name bindings in arbitrary locations via the quirky
"x if x given x = expr else x" spelling, and because "else" isn't as
distinctive an ending token as "given ... :", "given ... )", "given ... ]",
or "given ... }".


> Restricted to one "given" clause, or can they chain?  In a listcomp,
> is it one "given" clause per "if", or after at most one "if"?  Or is
> an "if" even needed at all in a listcomp?  For example,
>
> [(f(x)**2, f(x)**3) for x in xs]
>
> has no conditions, and
>
> [(fx := f(x))**2, fx**3) for x in xs]
>
> is one reasonable use for binding expressions.
>
> [(fx**2, fx**3) for x in xs given fx = f(x)]
>
> reads better, although it's initially surprising (to my eyes) to find
> fx defined "at the end".  But no more surprising than the current:
>
> [(fx**2, fx**3) for x in xs for fx in [f(x)]]
>
> trick.
>
>
There were a couple key reasons I left the "for x in y" case out of the
initial proposal:

1. The "for x in y" header is already quite busy, especially when tuple
unpacking is used in the assignment target
2. Putting the "given" clause at the end would make it ambiguous as to
whether it's executed once when setting up the iterator, or on every
iteration
3. You can stick in an explicit "if True" if you don't need the given
variable in the filter condition

[(fx**2, fx**3) for x in xs if True given fx = f(x)]

And then once you've had an entire release where the filter condition was
mandatory for the comprehension form, allowing the "if True" in "[(fx**2,
fx**3) for x in xs given fx = f(x)]" to be implicit would be less ambiguous.

[snip]


> It''s certain sanest as
>
> if x**2 + y**2 > 9 given x, y = func_returning_twople():
>
> "given" really shines there!
>

Yep, that's why I don't have the same immediate reaction of "It would need
to be limited to simple names as targets" reaction as I do for assignment
expressions. It might still be a good restriction to start out with, though
(especially if we wanted to allow multiple name bindings in a single given
clause).

[snip]

The one-letter variable name obscures that it doesn't
> actually reduce _redundancy_, though.  That is, in the current
>
> match = pattern.search(data)
> if match:
>
> it's obviously less redundant typing as:
>
> if match := pattern.search(data):
>
> In
>
> if match given match = pattern.search(data):
>
> the annoying visual redundancy (& typing) persists.
>

Right, but that's specific to the case where the desired condition really
is just "bool(target)". That's certainly likely to be a *common* use case,
but if we decide that it's *that* particular flavour of redundancy that
really bothers us, then there's always the "if expr as name:" spelling
(similar to the way that Python had "a and b" and "a or b" logical control
flow operators long before it got "a if c else b").

One more, a lovely (to my eyes) binding expression simplification
> requiring two bindings in an `if` test, taken from real-life code I
> happened to write during the PEP discussion:
>
> diff = x - x_base
> if diff:
> g = gcd(diff, n)
> if g > 1:
> return g
>
> collapsed to the crisp & clear:
>
> if (diff := x - x_base) and (g := gcd(diff, n)) > 1:
> return g
>
> If only one trailing "given" clause can be given per `if` test
> expression, presumably I couldn't do that without trickery.


I was actually thinking that if we did want to allow multiple assignments,
and we limited targets to single names, we could just use a comma as a
separator:

if diff and g > 1 given diff = x - x_base, g = gcd(diff, n):
return g

Similar to import statements, optional parentheses could be included in the
grammar, allowing the name bindings to be split across multiple lines:

if diff and g > 1 given (
diff = x - x_base,
g = gcd(diff, n),
):
return g

(Other potential separators would be ";", but that reads weirdly to me
since my brain expects the semi-colon to end the entire statement, and
"and", but that feels overly verbose, while also being overly different
from its regular meaning)


>   If it's
> more general,
>
> if (diff given diff = x _ xbase) and g > 1 given g = gcd(diff, n):

Re: [Python-ideas] Runtime assertion with no overhead when not active

2018-05-05 Thread Serhiy Storchaka

05.05.18 18:04, Eloi Gaudry пише:
By 'self-contained', I meant that using the assert keyword and its 
expression is sufficient. An inline assertive expression as the one you 
describe does not fulfill this assert requirement.


Sufficient for what? And why writing with using the existing syntax is 
not sufficient?


My proposal is simply to extend the current assert to non-debug builds 
and allow to switch it off/on at runtime.


The main property of the assert statement is that has a zero overhead in 
non-debug run. If you remove this property, it will be not the assert 
statement, and you will not need a special syntax support for writing 
this runtime check.



The syntax example I gave illustrated what I meant by syntax aware.


It doesn't illustrate why a new syntax is necessary. Or I can't 
understand this illustration.


___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-05 Thread Serhiy Storchaka

05.05.18 18:26, Nick Coghlan пише:
3. writing back to the local namespace via exec doesn't work 
consistently at function scope (and assuming PEP 558 is eventually 
accepted, will some day reliably *never* work)


At end you can convert the source of the whole script to a string 
literal and write the whole script in one line. The problem solved!


___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Runtime assertion with no overhead when not active

2018-05-05 Thread Steven D'Aprano
On Sat, May 05, 2018 at 08:04:45AM +, Eloi Gaudry wrote:

> Hi folks,
> I intend to add a runtime assertion feature in python.

I'm very interested in this idea, but I'm afraid your draft PEP isn't 
very clear about this feature. Comments below.


> Rationale
> There is no runtime assert relying on python grammar available. For 
> diagnostics and/or debugging reasons, it would be valuable to add such 
> a feature.

Why not this?

if DEBUG_ENABLED:
run_check(expression)

where run_check is an ordinary function. If DEBUG_ENABLED is false, the 
only runtime overhead is the name lookup and bool test, the expression 
is not evaluated.

What features does your suggestion offer over this simple technique?


[...]
> A brief example why avoiding evaluating the expression is needed to 
> avoid any overhead in case the runtime assert should be ignored.
> ::
> runtime_assert( 999 in { i:None for i in range( 1000 ) } )

You say that you have been using this feature in production for two 
years. You should give real-life examples, not fake examples like the 
above. That example would be better written as:

runtime_assert(True)

since no part of the test actually depends on either the enormous dict 
or range objects that you build only to throw away.


> Usage
> ::
> 
> runtime_assert( expr )
> 
> #would result in 
> if expr and runtime_assert_active:
> print RuntimeAssertionError()

Surely the test should be the other way around?

if runtime_assert_active and expr:
print(RuntimeAssertionError())

otherwise the expression is evaluated regardless of whether the runtime 
assertions are active or not.

Please use Python 3 syntax for the PEP, as Python 2 is in maintenance 
mode and will absolutely not get any new language features.


Some more observations:

I like the idea of more control over runtime checking, but your PEP 
should justify why this is a good idea and why "just write more unit 
tests" isn't the solution.

What happens if the caller has defined their own function or variable 
called runtime_assert?

Can the caller customise the assertion error message?

If you are changing the grammar, why not make runtime_assert a statement?

Can the caller set an application-wide global across all modules, or do 
they have to set

runtime_assert_active = True

in every module they want to use runtime_assert?



-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-05 Thread Nick Coghlan
On 6 May 2018 at 00:33, Mikhail V  wrote:

> recently I have discovered interesting fact: it seems one
> can already use 'inline assignment' with current syntax. E.g.:
>
> if exec("m = input()") or m:
> print (m)
>
> It seem to work as inline assignment correctly.
> Yes it is just coincidence, BUT: this has the wanted effect!
> - hides one line in "if" and "while"
> - leaves the assignment statement (or is it expression now? ;)
> - has explicit appearance
>
> So we have it already?
>

Not really, since:

1. exec with a plain string has a very high runtime cost (the compiler is
pretty slow, since we assume the results will be cached)
2. exec'ed strings are generally opaque to static analysis tools
3. writing back to the local namespace via exec doesn't work consistently
at function scope (and assuming PEP 558 is eventually accepted, will some
day reliably *never* work)

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Runtime assertion with no overhead when not active

2018-05-05 Thread Eloi Gaudry
By 'self-contained', I meant that using the assert keyword and its expression 
is sufficient. An inline assertive expression as the one you describe does not 
fulfill this assert requirement.

My proposal is simply to extend the current assert to non-debug builds and 
allow to switch it off/on at runtime.

The syntax example I gave illustrated what I meant by syntax aware.



De : Serhiy Storchaka
Envoyé : samedi 5 mai à 15:10
Objet : Re: [Python-ideas] Runtime assertion with no overhead when not active
À : python-ideas@python.org


05.05.18 15:54, Eloi Gaudry пише: > I meant avoiding the overhead of the 
expression evaluation enclosed in the assert itself, not the active/disabled 
state (that comes at virtually no cost). > ex:  runtime_assert( { i:None 
for i in range( 1000 ) } ) > > By using the syntax you describe ('boolean 
and not expr'), you loose all the benefit of the Python grammar: > - 
self-contained Could you please explain what you mean? > - able to catch 
semantic/syntax bugs > > ex:  f=1  runtime_assert( f==1 )  
runtime_assert( f=1 ) > File "", line 1 > runtime_assert( f=1 ) > ^ > 
SyntaxError: invalid syntax Until inline assignment expression is implemented, 
this is an error too: >>> if debug and not f=1: File "", line 1 if debug and 
not f=1: ^ SyntaxError: invalid syntax 
___ Python-ideas mailing list 
Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas 
Code of Conduct: http://python.org/psf/codeofconduct/



___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-05 Thread Mikhail V
On Fri, May 4, 2018 at 3:06 PM, Nick Coghlan  wrote:

>
> With that spelling, the three examples above would become:
>
> # Exactly one branch is executed here
> if m given m = pattern.search(data):
> ...
> elif m given m = other_pattern.search(data)):
> ...
> else:
> ...
>
> # This name is rebound on each trip around the loop
> while m given m = pattern.search(remaining_data):
> ...
>
> # "f(x)" is only evaluated once on each iteration
> result = [(x, y, x/y) for x in data if y given y = f(x)]
>

Well, I think it looks good. Nice job Nick!
I like that it leaves the "=" alone finally (but it's maybe the
reason why I am biased towards this syntax :)
It has clear look so as not to confuse with conditionals and
the variable is emphasized so it's well understood what it means.

I wish I could like the whole idea of inline assignments more now -
but well, it is just what it is. Something that can help on rare occasion.
But as said, your variant feels right to me. Unlike with most other
proposed constructs here my first impression - this is Python.

If the new keyword is too much, there are some options too choose from.
(though I've no idea whether this is plausible due to parsing ambiguities)

if m given m = pattern.search(data): vs:
if m with m = pattern.search(data):
if m def m = pattern.search(data):
if m as m = pattern.search(data):

Yes, all these reads strange,  but IMO understandable.

BTW, using your keyword, in comprehensions vs the original idea
of Chris then merely I suppose:

result = [(x, y, x/y) given y = f(x)  for x in data if y ]vs
result = [(x, y, x/y) with y = f(x)  for x in data if y ]
result = [(x, y, x/y) def y = f(x)  for x in data if y ]
result = [(x, y, x/y) as y = f(x)  for x in data if y ]
vs
result = [(x, y, x/y) for x in data if y  given y = f(x)] vs
result = [(x, y, x/y) for x in data if y  with y = f(x)]
result = [(x, y, x/y) for x in data if y  def y = f(x)]
result = [(x, y, x/y) for x in data if y  as y = f(x)]

I can't say for sure what is better but the former order seems to
be slightly more appealing for some reson.


[Tim]
> it's obviously less redundant typing as:
> if match := pattern.search(data):
> In
> if match given match = pattern.search(data):

I disagree, I think it is not redundant but it's just how it is -
namely it does not introduce 'implicitness' in the first place,
and that is what I like about Nick's variant. But of course it is less compact.



PS:

recently I have discovered interesting fact: it seems one
can already use 'inline assignment' with current syntax. E.g.:

if exec("m = input()") or m:
print (m)

It seem to work as inline assignment correctly.
Yes it is just coincidence, BUT: this has the wanted effect!
- hides one line in "if" and "while"
- leaves the assignment statement (or is it expression now? ;)
- has explicit appearance

So we have it already?


Mikhail
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Runtime assertion with no overhead when not active

2018-05-05 Thread Serhiy Storchaka

05.05.18 15:54, Eloi Gaudry пише:

I meant avoiding the overhead of the expression evaluation enclosed in the 
assert itself, not the active/disabled state (that comes at virtually no cost).
ex:

runtime_assert( { i:None for i in range( 1000 ) } )


By using the syntax you describe ('boolean and not expr'), you loose all the 
benefit of the Python grammar:
- self-contained


Could you please explain what you mean?


- able to catch semantic/syntax bugs

ex:

f=1
runtime_assert( f==1 )
runtime_assert( f=1 )

   File "", line 1
 runtime_assert( f=1 )
  ^
SyntaxError: invalid syntax


Until inline assignment expression is implemented, this is an error too:

>>> if debug and not f=1:
  File "", line 1
if debug and not f=1:
  ^
SyntaxError: invalid syntax

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Runtime assertion with no overhead when not active

2018-05-05 Thread Eloi Gaudry
I meant avoiding the overhead of the expression evaluation enclosed in the 
assert itself, not the active/disabled state (that comes at virtually no cost).
ex:
>>> runtime_assert( { i:None for i in range( 1000 ) } )  

By using the syntax you describe ('boolean and not expr'), you loose all the 
benefit of the Python grammar:
- self-contained
- able to catch semantic/syntax bugs

ex:
>>> f=1
>>> runtime_assert( f==1 )
>>> runtime_assert( f=1 )
  File "", line 1
runtime_assert( f=1 )
 ^
SyntaxError: invalid syntax


-Original Message-
From: Python-ideas  On 
Behalf Of Serhiy Storchaka
Sent: Saturday, May 5, 2018 2:05 PM
To: python-ideas@python.org
Subject: Re: [Python-ideas] Runtime assertion with no overhead when not active

05.05.18 11:04, Eloi Gaudry пише:
> Briefly, the idea is to add a new assert that can be switch on/off
> depending on some variable/mechanism at runtime. The whole point of
> this assert is that it should not bring any overhead when off, i.e.
> by avoiding evaluating the expression enclosed in the runtime
> assert. It thus relies on Python grammar.

You should have an overhead for checking if it is switched on/off, isn't? And 
this overhead is virtually the same as testing the value of the global boolean 
variable.

> runtime_assert( expr )
> 
> #would result in if expr and runtime_assert_active:
> 
> print RuntimeAssertionError()

How this will be different from

 if debug and not expr:
 print(RuntimeAssertionError())

?

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Runtime assertion with no overhead when not active

2018-05-05 Thread Serhiy Storchaka

05.05.18 11:04, Eloi Gaudry пише:

Briefly, the idea is to add a new assert that can be switch on/off
depending on some variable/mechanism at runtime. The whole point of
this assert is that it should not bring any overhead when off, i.e.
by avoiding evaluating the expression enclosed in the runtime
assert. It thus relies on Python grammar.


You should have an overhead for checking if it is switched on/off, 
isn't? And this overhead is virtually the same as testing the value of 
the global boolean variable.



runtime_assert( expr )

#would result in if expr and runtime_assert_active:

print RuntimeAssertionError()


How this will be different from

if debug and not expr:
print(RuntimeAssertionError())

?

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Runtime assertion with no overhead when not active

2018-05-05 Thread Eloi Gaudry
Hi folks,
I intend to add a runtime assertion feature in python. Before submitting a PEP, 
I am sending a draft to this mailing list to discuss whether it would make 
sense (above this message). I have actually been using it for the last 2 years 
and it has proven to be robust and has achieved its primary goal.
Briefly, the idea is to add a new assert that can be switch on/off depending on 
some variable/mechanism at runtime. The whole point of this assert is that it 
should not bring any overhead when off, i.e. by avoiding evaluating the 
expression enclosed in the runtime assert. It thus relies on Python grammar.
Thanks for your feedback.
Eloi



Abstract

This PEP aims at offering a runtime assert functionnality, extending the 
compiletime assert already available.

Rationale

There is no runtime assert relying on python grammar available. For diagnostics 
and/or debugging reasons, it would be valuable to add such a feature.

A runtime assert makes sense when extra checks would be needed in a production 
environment (where non-debug builds are used).

By extending the current python grammar, it would be possible to limit the 
overhead induces by those runtime asserts when running in a non "assertive" 
mode (-ed). The idea here is to avoid evaluating the expression when runtime 
assertion is not active.

A brief example why avoiding evaluating the expression is needed to avoid any 
overhead in case the runtime assert should be ignored.
::
runtime_assert( 999 in { i:None for i in range( 1000 ) } )
Usage
::

runtime_assert( expr )

#would result in if expr and runtime_assert_active:
print RuntimeAssertionError()
Implementation details

There is already an implementation available, robust enough for production. The 
implementation is mainly grammar based, and thus the parser and the grammar 
needs to be updated:

  *   Python/graminit.c
  *   Python/ast.c
  *   Python/symtable.c
  *   Python/compile.c
  *   Python/Python-ast.c
  *   Python/sysmodule.c
  *   Modules/parsermodule.c
  *   Include/Python-ast.h
  *   Include/graminit.h
  *   Include/pydebug.h
  *   Grammar/Grammar
  *   Parser/Python.asdl
  *   Lib/lib2to3/Grammar.txt
  *   Lib/compiler/ast.py
  *   Lib/compiler/pycodegen.py
  *   Lib/compiler/transformer.py
  *   Lib/symbol.py
  *   Modules/parsermodule.c

References
[1]

PEP 306, How to Change Python's Grammar 
(http://www.python.org/dev/peps/pep-0306)

Copyright

This document has been placed in the public domain.

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-05 Thread Juancarlo Añez
I think that "expr as y"  was discarded too quickly.

It would be a syntax completely familiar to Python programmers, and the new
semantics would be obvious. That choice would also be in line with the Zen
of Python.

The special cases that may arise over "except"  and "with"  can be worked
out and documented.

Cheers,

On Sat, May 5, 2018 at 5:22 AM, Robert Vanden Eynde 
wrote:

> I agree it would be useful to have new keywords without being reserved,
> and we could even go with mechanism like infix operators created by user.
>
> It would allow things like [given for x in range(5) given given = x+1] or
> even [given for given in range(given) given given = given + 1] haha, but as
> other pointed out, it would be called Bad practice ^^
>
> By the way, I still prefer "where" to "given".
>
> Le sam. 5 mai 2018 à 10:52, Greg Ewing  a
> écrit :
>
>> Tim Peters wrote:
>> > "async def", "async for", and "async with" statements were added
>> > _without_ making "async" a new reserved word.  It may require pain in
>> > the parser, but it's often doable anyway.
>>
>> There would be less pain if the parser generator could
>> deal with non-reserved keywords more directly.
>>
>> --
>> Greg
>> ___
>> Python-ideas mailing list
>> Python-ideas@python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
>


-- 
Juancarlo *Añez*
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-05 Thread Robert Vanden Eynde
I agree it would be useful to have new keywords without being reserved, and
we could even go with mechanism like infix operators created by user.

It would allow things like [given for x in range(5) given given = x+1] or
even [given for given in range(given) given given = given + 1] haha, but as
other pointed out, it would be called Bad practice ^^

By the way, I still prefer "where" to "given".

Le sam. 5 mai 2018 à 10:52, Greg Ewing  a
écrit :

> Tim Peters wrote:
> > "async def", "async for", and "async with" statements were added
> > _without_ making "async" a new reserved word.  It may require pain in
> > the parser, but it's often doable anyway.
>
> There would be less pain if the parser generator could
> deal with non-reserved keywords more directly.
>
> --
> Greg
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-05 Thread Greg Ewing

Tim Peters wrote:

"async def", "async for", and "async with" statements were added
_without_ making "async" a new reserved word.  It may require pain in
the parser, but it's often doable anyway.


There would be less pain if the parser generator could
deal with non-reserved keywords more directly.

--
Greg
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/