[Python-Dev] Re: PEP 701 – Syntactic formalization of f-strings

2022-12-22 Thread Rob Cliffe via Python-Dev

Great stuff! 
Rob Cliffe

On 19/12/2022 17:59, Pablo Galindo Salgado wrote:


Hi everyone,

I am very excited to share with you a PEP thatBatuhan Taskaya, 
Lysandros Nikolaou and myself have been working on recently:PEP 701 - 
PEP 701 – Syntactic formalization of f-strings 
.


We believe this will be a great improvement in both the 
maintainability of CPython and the usability of f-strings.


We look forward to hearing what you think about this and to get your 
feedback!


*Here is a TLDR for your convenience:*

  * The PEP proposes a formalized grammar for f-strings in Python by
adding f-strings directly into the Grammar instead of using a
two-pass hand-written parser.
  * This would lift some existing restrictions for f-strings that (we
believe) will improve the user experience with f-strings.
  * Other benefits include:
  o Reduced maintenance costs for f-string parsing code as well as
improved usability for users and library developers.
  o Better error messages involving f-strings by leveraging the
PEG parser machinery.
  o The proposed changes would improve the overall consistency of
the language and provide a way for alternative implementations
to accurately implement f-strings.

*** IMPORTANT: direct all discussions to the discussion thread on 
discourse: 
https://discuss.python.org/t/pep-701-syntactic-formalization-of-f-strings/22046 
***


Thanks a lot, everyone for your time!

Regards from rainy London,
Pablo Galindo Salgado

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


[Python-Dev] Re: A proposal to modify `None` so that it hashes to a constant

2022-12-11 Thread Rob Cliffe via Python-Dev

You are absolutely right, of course.  It was a wild idea, and a bad one.
I find myself moving towards supporting the OP.  I can't see anything 
terrible about the hash of None always being 0, or perhaps better some 
other arbitrary constant.

Rob

On 04/12/2022 03:20, Steven D'Aprano wrote:

On Thu, Dec 01, 2022 at 10:18:49PM +, Rob Cliffe via Python-Dev wrote:


Wild suggestion:
     Make None.__hash__ writable.
E.g.
     None.__hash__ = lambda : 0 # Currently raises AttributeError:
'NoneType' object attribute '__hash__' is read-only

You would have to write to `type(None).__hash__` because of the way
dunders work.

Now imagine that you have twenty different libraries or functions or
classes, each the `__hash__` method to a different function. Chaos.

You can simulate that chaos with this:

```
import random

class ChangingHash:
 def __repr__(self):
 return "MyNone"
 def __hash__(self):
 # Simulate the effect of many different callers changing
 # the hash value returned at unpredictable times.
 return random.randint(1, 9)

MyNone = ChangingHash()

data = {MyNone: 100}
print(MyNone in data)  # 8 in 9 chance of printing False
data[MyNone] = 200
print(data)  # 8 in 9 chance of {MyNone: 100, MyNone: 200}
print(MyNone in data)  # now 7 in 9 chance of printing False
```




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


[Python-Dev] Re: A proposal to modify `None` so that it hashes to a constant

2022-12-09 Thread Rob Cliffe via Python-Dev

You're right of course.  Oh well, it *was* a wild idea.
Rob Cliffe

On 04/12/2

On 04/12/2022 18:16, Chris Angelico wrote:

On Mon, 5 Dec 2022 at 05:11, Rob Cliffe via Python-Dev
 wrote:

Wild suggestion:
  Make None.__hash__ writable.
E.g.
  None.__hash__ = lambda : 0 # Currently raises AttributeError:
'NoneType' object attribute '__hash__' is read-only

Hashes have to be stable. If you change the hash of None after it's
been inserted into a dictionary, you'll get all kinds of entertaining
problems.


class X:

... def __init__(self): self.hash = 0
... def __hash__(self): return self.hash
...

x = X()
d = {x: "This is x"}
x.hash = 1
for key in d: print(key, key in d)

...
<__main__.X object at 0x7f2d07c6f1c0> False

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


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


[Python-Dev] Re: A proposal to modify `None` so that it hashes to a constant

2022-12-04 Thread Rob Cliffe via Python-Dev

Wild suggestion:
    Make None.__hash__ writable.
E.g.
    None.__hash__ = lambda : 0 # Currently raises AttributeError: 
'NoneType' object attribute '__hash__' is read-only

Best wishes
Rob Cliffe

On 01/12/2022 11:02, Oscar Benjamin wrote:

On Thu, 1 Dec 2022 at 06:56, Chris Angelico  wrote:

On Thu, 1 Dec 2022 at 17:26, Yoni Lavi  wrote:

So it's not like it's even possible to require this generally for all objects.

Well, I mean, in theory you could require that objects whose hash
isn't otherwise defined get given the hash of zero. That doesn't
violate any of the actual rules of hashes, but it does make those
hashes quite suboptimal :)

It's interesting how id() and hash() have opposite requirements (id
must return a unique number among concurrently-existing objects, hash
must return the same number among comparing-equal objects), yet a hash
can be built on an id.

This also demonstrates a significant reason why None is special: it's
a singleton that only compares equal to itself. The reason for using
id for hash in other cases is to make different instances have
different hashes but there is only ever one instance of None. A
singleton class can have a hash function that matches identity based
equality without using id: any constant hash function will do.

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


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


[Python-Dev] Re: A proposal to modify `None` so that it hashes to a constant

2022-12-02 Thread Rob Cliffe via Python-Dev

Thank you for this very clear analysis, Oscar.
It seems to me that this strengthens the OP's case.  I am curious as to 
whether others agree.

Best wishes
Rob Cliffe

On 30/11/2022 13:35, Oscar Benjamin wrote:

On Tue, 29 Nov 2022 at 23:46, Steven D'Aprano  wrote:

On Tue, Nov 29, 2022 at 08:51:09PM -, Yoni Lavi wrote:


It does make your argument invalid though, since it's based on this
assumption that I was asking for a requirement on iteration order
(e.g. like dict's iteration order = insertion order guarantee), which
is not the case.

Yoni, I think this answer is disingenious.

I don't think it is disingenuous. There are just a lot of people
talking past each other and not quite understanding what each person
means because there is confusion about even the intended meaning of
terms like "deterministic". I will expand here with enough detail that
we should hopefully be able to avoid misunderstanding each other.

There are probably other places where you could find mentions of this
in the docs but I just took a quick look in the Python 3.5 docs
(before hash randomisation) to find this mention of dictionary
iteration order:
https://docs.python.org/3.5/library/stdtypes.html#dictionary-view-objects

What it says is
"""
Keys and values are iterated over in an arbitrary order which is
non-random, varies across Python implementations, and depends on the
dictionary’s history of insertions and deletions.
"""
The key point is the use of the term "non-random" which here is
intended to mean that although no particular ordering is guaranteed
you can expect to rerun the same program and get the same result
deterministically. A different version or implementation of Python
might give a different order but rerunning the same program twice
without changing anything should give the same result even if that
result depends in some way on the iteration order of some
dictionaries. I can't immediately find a similar statement about sets
but in practice the same behaviour applied to sets as well. Note
carefully that it is this *narrow* form of determinism that Yoni is
interested in.

Of course there are some caveats to this and the obvious one is that
this statement does not apply if there are some objects that use
identity based hashing so this is not deterministic:

class A:
 def __init__(self, data):
 self.data = data
 def __repr__(self):
 return 'A(%s)' % self.data

a1 = A(1)
a2 = A(2)

for a in {a1, a2}:
 print(a)

Running this gives:

$ python3.5 t.py
A(2)
A(1)
$ python3.5 t.py
A(1)
A(2)

On the other hand if all of the hashes themselves are deterministic
then the program as a whole will be as well so this is deterministic:

class A:
 def __init__(self, data):
 self.data = data
 def __repr__(self):
 return 'A(%s)' % self.data
 def __hash__(self):
 return hash(self.data)
 def __eq__(self):
 return self.data == other.data

a1 = A(1)
a2 = A(2)

for a in {a1, a2}:
 print(a)

$ python3.5 t.py
A(1)
A(2)
$ python3.5 t.py
A(1)
A(2)

So we have two classes of hashable objects:

1. Those with deterministic hash
2. Those with non-deterministic hash

A program that avoids depending on the iteration order of sets or
dicts containing objects with non-deterministic hash could be
deterministic. It is not the case that the program would depend on the
iteration order for its *correctness* but just that the behaviour of
the program is *reproducible* which is useful in various ways e.g.:

- You could say to someone else "run this code with CPython 3.5 and
you should be able to reproduce exactly what I see when I run the
program". It is common practice e.g. in scientific programming to
record things like random seeds so that someone else can precisely
reproduce the results shown in a paper or some other work and this in
general requires that it is at least possible to make everything
deterministic.

- When debugging it is useful to be able to reproduce an error
condition precisely. Debugging non-deterministic failures can be
extremely difficult. In the same way that you might want to reproduce
correctly functioning code it is also very useful to be able to
reproduce bugs.

I can list more examples but really it shouldn't be necessary to
justify from first principles why determinism in programming is
usually a good thing. There can be reasons sometimes why determinism
is undesired or cannot or should not be guaranteed. It should not be
controversial though to say that all things being equal determinism is
usually a desirable feature and should be preferred by default. I
don't think that the 3.5 docs I quoted above used the words
"non-random" casually: it was an intended feature and people were
aware that breaking that behaviour would be problematic in many
situations.

Of course in Python 3.6 this determinism was broken with the
introduction of hash randomisation for strings. It was considered that
for security purposes it would be better to have some 

[Python-Dev] Re: Proto-PEP part 4: The wonderful third option

2022-04-26 Thread Rob Cliffe via Python-Dev




On 26/04/2022 20:48, Carl Meyer via Python-Dev wrote:

On Tue, Apr 26, 2022 at 1:25 PM Guido van Rossum  wrote:

I also would like to hear more about the problem this is trying to solve, when 
th real-world examples. (E.g. from pydantic?)

Yes please. I think these threads have jumped far too quickly into
esoteric details of implementation and syntax, without critical
analysis of whether the semantics of the proposal are in fact a good
solution to a real-world problem that someone has.

I've already outlined in a more detailed reply on the first thread why
I don't think forward declarations provide a practically useful
solution to forward reference problems for users of static typing
(every module that imports something that might be a forward reference
would have to import its implementation also, turning every one-line
import of that class into two or three lines) and causes new problems
for every user of Python due to its reliance on import side effects
causing global changes at a distance. See
https://mail.python.org/archives/list/python-dev@python.org/message/NMCS77YFM2V54PUB66AXEFTE4NXFHWPI/
for details.

Under PEP 649, forward references are a small problem confined to the
edge case of early resolution of type annotations. There are simple
and practical appropriately-scoped solutions easily available for that
small problem: providing a way to resolve type annotations at runtime
without raising NameError on not-yet-defined names. Such a facility
(whether default or opt-in) is practically useful for many users of
annotations (including dataclasses and documentation tools), which
have a need to introspect some aspects of annotations without
necessarily needing every part of the annotation to resolve. The
existence of such a facility is a reasonable special case for
annotations specifically, because annotations are fundamentally
special: they provide a description of code, rather than being only a
part of the code. (This special-ness is precisely also why they cause
more forward references in the first place.)

IMO, this forward declaration proposal takes a small problem in a
small corner of the language and turns it into a big problem for the
whole language, without even providing as nice and usable an option
for common use cases as "PEP 649 with option for lax resolution" does.
This seems like a case study in theoretical purity ("resolution of
names in annotations must not be special") running roughshod over
practicality.

Carl


Insofar as I understand the above (knowing almost nothing about typing), +1.
Best wishes
Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/DWA4AGXTBI5SU2R2T5O7KTQJ4F6DU27S/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Proto-PEP part 1: Forward declaration of classes

2022-04-25 Thread Rob Cliffe via Python-Dev
One reason I dislike this whole proposal is that I can see forward 
declarations (FDs) ending up in code that doesn't need them.  This could 
happen if
    (a) The FDs were needed at some point, but then the type 
declarations were taken out.  This could happen with someone modifying 
their own code, or lifting from someone else's code.
    (b) A relative newbie could see FDs in someone else's code and 
assume that they were necessary, or at least desirable, and put 
unnecessary FDs in their own code in imitation.

Result: Code clutter and confusion.
AIUI the problem to be solved is solely related to typing.  Is it not 
possible to solve it purely in the "typing world", rather than letting 
it leak out and "infect" something basic in the core language like how 
classes are declared?  By "core language" I guess I mean "Python without 
typing".

Best wishes
Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/F36RCN5GLRIKZJD44LGUFNJ2YQEBUMMZ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Proto-PEP part 1: Forward declaration of classes

2022-04-23 Thread Rob Cliffe via Python-Dev

UGH!

I thought there was a general understanding that when typing was added 
to Python, there would be no impact, or at least minimal impact, on 
people who didn't use it.  (Raises hand.)

Now we see an(other) instance of intention creep.
Rob Cliffe

On 23/04/2022 02:13, Larry Hastings wrote:



This document is a loose proto-PEP for a new "forward class" / 
"continue class" syntax.  Keep in mind, the formatting is a mess. If I 
wind up submitting it as a real PEP I'll be sure to clean it up first.



/arry

--


PEP : Forward declaration of classes

Overview


Python currently has one statement to define a class, the `class` 
statement:


```Python
    class X():
    # class body goes here
    def __init__(self, key):
    self.key = key
```

This single statement declares the class, including its bases and 
metaclass,

and also defines the contents of the class in the "class body".

This PEP proposes an additional syntax for declaring a class which splits
this work across two statements:
* The first statement is `forward class`, which declares the class and 
binds

  the class object.
* The second statement is `continue class`, which defines the contents
  of the class in the "class body".

To be clear: `forward class` creates the official, actual class object.
Code that wants to take a reference to the class object may take 
references

to the `forward class` declared class, and interact with it as normal.
However, a class created by `forward class` can't be *instantiated*
until after the matching `continue class` statement finishes.

Defining class `X` from the previous example using this new syntax 
would read

as follows:

```
    forward class X()

    continue class X:
    # class body goes here
    def __init__(self, key):
    self.key = key
```

This PEP does not propose altering or removing the traditional `class` 
statement;

it would continue to work as before.


Rationale
-

Python programmers have had a minor problem with classes for years: 
there's

no way to have early-bound circular dependencies between objects. If A
depends on B, and B depends on A, there's no linear order that allows
you to cleanly declare both.

Most of the time, the dependencies were in late-binding code, e.g. A 
refers
to B inside a method.  So this was rarely an actual problem at 
runtime.  When
this problem did arise, in code run at definition-time, it was usually 
only

a minor headache and could be easily worked around.

But the explosion of static type analysis in Python, particularly with
the `typing` module and the `mypy` tool, has made circular 
definition-time
dependencies between classes commonplace--and much harder to solve.  
Here's

one simple example:

```Python
    class A:
    value: B

    class B:
    value: A
```

An attribute of `B` is defined using a type annotation of `A`, and an
attribute of `A` is defined using a type annotation of `B`. There's
no order to these two definitions that works; either `A` isn't defined
yet, or `B` isn't defined yet.

Various workarounds and solutions have been proposed to solve this 
problem,
including two PEPs: PEP 563 (automatic stringized annotations) and PEP 
649

(delayed evaluation of annotations using functions).
But nothing so far has been both satisfying and complete; either it
is wordy and clumsy to use (manually stringizing annotations), or it
added restrictions and caused massive code breakage for runtime use of
annotations (PEP 563), or simply didn't solve every problem (PEP 649).
This proposed  `forward class` / `continue class` syntax should permit
solving *every* forward-reference and circular-reference problem faced
in Python, using an elegant and Pythonic new syntax.

As a side benefit, `forward class` and `continue class` syntax enables
rudimentary separation of "interface" from "implementation", at least for
classes.  A user seeking to "hide" the implementation details of their
code could put their class definitions in one module, and the
implementations of those classes in a different module.

This new syntax is not intended to replace the traditional `class`
declaration syntax in Python.  If this PEP were accepted, the `class`
statement would still be the preferred mechanism for creating classes
in Python; `forward class` should only be used when it confers some
specific benefit.


Syntax
--

The `forward class` statement is the same as the `class` statement,
except it doesn't end with a colon and is not followed by an indented 
block.

Without any base classes or metaclass, the `forward class` statement is
as follows:

```
    forward class X
```

This would declare class `X`.

If `X` needs base classes or metaclass, the corresponding `forward 
class` statement

would be as follows, rendered in a sort of "function prototype" manner:

```
    forward class X(*bases, metaclass=object, **kwargs)
```

The `continue class` statement is similar to 

[Python-Dev] Re: The current state of typing PEPs

2021-12-02 Thread Rob Cliffe via Python-Dev

I assume you accidentally pressed Send prematurely.
Still, maybe you have inadvertently listed everything that is agreed 
about typing PEPs. 

Rob Cliffe

On 02/12/2021 23:20, Christopher Barker wrote:


>for library authors.

Providing high quality stubs and the best user experience is not
easy.
But I believe that referring people to typeshed can help.


This is actually very helpful. It provides an answer for open source 
projects for which do users want typing.


One can say to the users that want type stubs for the library that 
they are encouraged to contribute those stubs to type shed themselves 
and once they have been tested and vetted they can be included in the 
project.


it’s not unlike any other feature request. The developer of an open 
source project is under no obligation to provide any feature asked 
for, but a well-managed project will encourage useful contributions 
from users.


-CHB
--
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython

___
Python-Dev mailing list --python-dev@python.org
To unsubscribe send an email topython-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived 
athttps://mail.python.org/archives/list/python-dev@python.org/message/ASO2PUTECTOB25HC7DURFOGOHOUQOCD5/
Code of Conduct:http://python.org/psf/codeofconduct/
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/7AF22G3S23S67FAHH7BI4XUNHWOU4YXT/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Expectations of typing (was: The current state of typing PEPs)

2021-11-30 Thread Rob Cliffe via Python-Dev



Heh. We could update PEP 8 to ban type annotations, then watch as the
people who over-zealously apply PEP 8 to everything AND
over-zealously
insist on adding type annotations to everything have their heads
explode.


-- 
Steve



I love it!
"Surtout, pas trop de zèle".  [Charles-Maurice de Talleyrand]
Rob Cliffe___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/EWPCRCFOPXXL2QLYMH7QADKXE7Q7PM5P/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Optimizing literal comparisons and contains

2021-11-28 Thread Rob Cliffe via Python-Dev
I am slightly surprised that it seems to be *easier* to fold selected 
constant expressions than to have more generic code to fold them all.

Or at least, all those that don't contain containers, such as
    1 in [0,1,2]
Rob Cliffe

On 28/11/2021 21:10, Eric V. Smith wrote:

On Nov 28, 2021, at 3:03 PM, Serhiy Storchaka  wrote:

28.11.21 17:13, Skip Montanaro пише:

That is not entirely true: 
https://github.com/python/cpython/pull/29639#issuecomment-974146979

The only places I've seen "if 0:" or "if False:" in live code was for
debugging. Optimizing that hardly seems necessary. In any case, the
original comment was about comparisons of two constants. I suppose
sweeping up all of that into a constant expression folding/elimination
step performed on the AST and/or during peephole optimization would
cover both cases.

"if 0:" and "if False:" is already optimized by the compiler. The OP
proposes to optimize "2 < 1", and I cannot imagine any use case for this.

I agree. I suggest we don’t add this optimization.

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


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


[Python-Dev] Re: The current state of typing PEPs

2021-11-25 Thread Rob Cliffe via Python-Dev
My 2¢ from a position of *extreme ignorance*, not to mention zero 
interest in annotations (all welcome to shoot me down in flames, or 
treat me with contemptuous silence.  But *occasionall*y the "idiot's" 
point of view is worth considering, so here goes).


ISTM that typing/annotations have been allowed to drift without a clear 
end in view, rather like a ship that is steered in one direction by one 
person, then in another by someone else, with nobody knowing what the 
destination port is.  As witness the conflicting views in this thread.  
At the risk of being rude, the phrase "headless chickens" comes to mind.
ISTM that it is time to take a step back and decide on a definite 
policy.  Perhaps a definitive pronouncement from Guido.  Or the SC. Or a 
discussion from all parties that reaches an acceptable conclusion.  Then 
stick to it.  Even if it causes some backward incompatibility - ISTM 
that things have changed so rapidly that this really would be an 
acceptable evil if it results in clarity for the future.  Meanwhile, do 
not change anything, do not approve any PEPs, until this conclusion is 
reached.
I apologise if I am being presumptuous in commenting on a subject I know 
almost nothing about.


/I'm just a soul whose intentions are good,//
//Oh Lord, please don't let me be misunderstood.//
/
Best wishes
Rob Cliffe


On 25/11/2021 23:51, Oscar Benjamin wrote:

On Thu, 25 Nov 2021 at 15:16, Stephen J. Turnbull
  wrote:

Executive summary:

The typing-suspicious crowd has a valid complaint about PEPs 563 and
649, but it's not that they weren't warned.

Christopher Barker writes:

  > Annotations can be, and are, used for other things than "typing". I
  > just noticed that PEP 563 apparently deprecated those other uses
  > (well, sort of: "uses for annotations incompatible with the
  > aforementioned PEPs should be considered deprecated")

Not a PEP proponent (or even a typing user), but I thought this had
been made clear long ago.  My understanding is that optional,
incremental type hints are and have always been considered the primary
use case for annotations by the BDFL and AFAICT the SC following the
BDFL.  If compatibility with typing is an issue, then the burden of
implementing that is on the other application.  Typing *might* do
something to help, but it's not obligated to do so.

This was not my understanding of annotations when they were introduced e.g.:
https://www.python.org/dev/peps/pep-3107/#use-cases

As I remember it, a decision about the purpose of annotations was
*explicitly* not made when they were introduced. It was clear that
typing was a major potential use and then at some point (around about
the introduction of the typing module) there seemed to be a shift in
people's understanding of what annotations were for. Eventually that
reached the point that people who were particularly interested in
typing had no memory of the fact that the purpose of annotations had
not really been specified as being about typing in the first place.

It looks to me like Chris has identified in PEP 563 what is
potentially the earliest reference (in an accepted PEP) to the idea
that non-typing uses of annotations are to be discouraged.

--
Oscar
___
Python-Dev mailing list --python-dev@python.org
To unsubscribe send an email topython-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived 
athttps://mail.python.org/archives/list/python-dev@python.org/message/BERGEZTXG4XSEIJQHQWC3IZLXYEZPZ6C/
Code of Conduct:http://python.org/psf/codeofconduct/
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/7NRLCIENXLWBPM3EA67ZIN3X3K25DMEY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: The current state of typing PEPs

2021-11-25 Thread Rob Cliffe via Python-Dev



On 25/11/2021 15:15, Stephen J. Turnbull wrote:

Executive summary:

The typing-suspicious crowd has a valid complaint about PEPs 563 and
649, but it's not that they weren't warned.


“As you will no doubt be aware, the plans for development of the 
outlying regions of the Galaxy require the building of a hyperspatial 
express route through your star system, and regrettably your planet is 
one of those scheduled for demolition. The process will take slightly 
less than two of your Earth minutes. Thank you.”


Well we were warned, so everything's fine.
Rob Cliffe___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/GKYEYE4XV2L276FMBWYFSIAZHZT3QXSX/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: The current state of typing PEPs

2021-11-21 Thread Rob Cliffe via Python-Dev



On 21/11/2021 11:04, Paul Moore wrote:

On Sun, 21 Nov 2021 at 07:50, Christopher Barker  wrote:
It's becoming harder and harder for people not particularly interested 
in static typing to simply ignore it

(Raises hand.)  +1
Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/YMZ4UE2TMRH5WNF6Y3KWGJS2R2YJQAZI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: containment and the empty container

2021-11-08 Thread Rob Cliffe via Python-Dev

On 08/11/2021 21:43, Ethan Furman wrote:

When is an empty container contained by a non-empty container?

For example:
These examples are not at all analogous.  `a in b` has different 
meanings for different classes of b.


{} in {1:'a', 'b':2]   <-- TypeError because of hashability

`x in aDict` means `x in aDict.keys()`
1 in {1:'a', 'b':2} == True
'a' in {1:'a', 'b':2} == False

set() in {1, 2, 'a', 'b'}  <-- ditto
[] in ['a', 'b', 1, 2]  <-- False
`x in aSet' / `x in a List` means x is one of the members of 
aSet/aList.  E.g. {1, 2, 'a', 'b'} has 4 members: 1, 2, 'a', 'b'. None 
of these equals set().


'' in 'a1b2'  <-- True
`x in aStr` means x is a substring of aStr (quite different).  The empty 
string is (vacuously but correctly) a substring of any string.  This may 
be inconvenient sometimes (as you say) but it is the logically correct 
behaviour.  Just as the modulus operator for ints returns the 
mathematically correct result (unlike in some languages such as C / C++) 
even though this may not always be what you want.


Best wishes
Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/OECCYUHZIX5JFG7MIAUURPIMXJTJ5R3T/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 505 (None-aware operators) for Python 3.11

2021-10-20 Thread Rob Cliffe via Python-Dev
Data point: I find all the examples in PEP 505 less readable using the 
proposed new operators.
Trying to explain why: The syntax feels *too* compact (Perl-like?) - 
when reading it, every time you see a None-aware operator (*if* you 
notice it), you have to jerk to a halt and say, "Whoa!  What's going on 
here?".
I have some sympathy with this use case of exploring a nested-dict (JSON 
derived?) structure, but this can be written as


try:
    config.get("handler").get("parameters").get("y")
except Attribute Error:
    # Handle missing value.

or something similar (I haven't tested it).  Even using the new 
operators, in a realistic case you would probably have to test if the 
result is None and take different action accordingly.

Best wishes
Rob Cliffe

On 18/10/2021 19:26, Guido van Rossum wrote:
On Mon, Oct 18, 2021 at 9:35 AM Paul Bryan > wrote:


NoneType is just another type, and in type checking scenarios
should be expressed with `Optional[type]` or more preferably in
the future `type | None`; `None` is not a non-value. Assuming what
I just wrote is true, I don't get what the basis of this thread
is; what am I missing?


To me the thread isn't about type checking. It is about APIs that are 
built into the language that special-case None, in particular 
dict.get(). In certain cases, encountered commonly in certain styles 
of coding (data science? web programming?), users encounter data that 
is structured as dicts nested multiple levels. This is often out of 
the user's control, as the dict is returned by reading a JSON value 
whose structure is controlled by some other framework (often not 
specific to Python).


For example, if we have a config structure like this:

config = {
  "timeout": 0.1,
  "handler: {
    "timeout-override": 0.4,
    "method-name": "plot",
    "parameters": {
  "x": 10,
  "y": "auto",
    }
  }
}

where the convention is that keys at any level may be omitted 
altogether and config itself may be NOne, then to safely access the 
value of config["handler"]["parameters"]["y"] we would have to write


y = None  # Default
if config is not None:
  handler = config.get("handler")
  if handler is not None:
    parameters = handler.get("parameters")
    if parameters is not None:
  y = parameters.get("y")

This kind of pattern (and all the various other ways of writing it, 
e.g. using the walrus or passing {} as the second argument to 
dict.get()) can be *very* common if that's the kind of data you're 
given and that's the kind of app you have to write, and you can't 
control the format of the data.


Using ?. this can be written as

y = config?.get("handler")?.get("parameters")?.get("y")

More examples are in PEP 505 itself, see 
https://www.python.org/dev/peps/pep-0505/#examples 



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



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


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


[Python-Dev] Re: PEP 505 (None-aware operators) for Python 3.11

2021-10-20 Thread Rob Cliffe via Python-Dev
This is very reminiscent of the (rejected) PEP 463, Exception-catching 
expressions (which I still hope will be resurrected some day).  It would 
allow you to write

    y = (config["handler"]["parameters"]["y"] except KeyError: None)
(possibly the parentheses might not be required) which IMO is even 
better; `except` makes the intent clearer than `with`.

Best wishes
Rob Cliffe

On 20/10/2021 03:05, h.vetin...@gmx.com wrote:

Baptiste Carvello wrote:

y = config["handler"]["parameters"]["y"] with KeyError as None

I love the look of this! While it doesn't address everything that PEP505 does, 
that's IMO a good thing, because - as other people mentioned already - None 
does too many things already.

On another note, the whole discussion reminds me of wg21.link/p0798, which is 
about adding something quite similar to C++ (was accepted into C++23), and 
contains a decent overview of how other languages solve the same thing.

Even though the approach there is probably not applicable (as all python types are 
implicitly `Optional` in the sense of "can be None", i.e. that API would have 
to be added all the way down to `object`), it's still ironic that C++'s `and_then` looks 
more pythonic than what's proposed here.
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/6JD5VGTVE2TVHUMU7OWIYT7QJEKAGRI7/
Code of Conduct: http://python.org/psf/codeofconduct/


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


[Python-Dev] Re: PEP 654 except* formatting

2021-10-04 Thread Rob Cliffe via Python-Dev



On 04/10/2021 00:57, Barry Warsaw wrote:

On Oct 3, 2021, at 10:42, Łukasz Langa  wrote:


Speaking just for myself, the `except *` syntax always bothered me, but I 
couldn’t come up with anything better and it wasn’t enough for me to vote 
against PEP 654.  `except group` is nicer though, and I would be in favor of 
that, or something like it.

Or perhaps `except for` ?


We could of course bike shed on the syntax forever.  The PSC did vote to accept 
the PEP but we left room for changes while during the 3.11 cycle.

-Barry



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


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


[Python-Dev] Re: PEP 467 feedback from the Steering Council

2021-09-12 Thread Rob Cliffe via Python-Dev



On 09/09/2021 18:54, raymond.hettin...@gmail.com wrote:

I would rather keep `bchr` and lose the `.fromint()` methods.

For me, "bchr" isn't a readable name.  If I expand mentally expand it to 
"byte_character", it becomes an oxymoron that opposes what we try teach about bytes and 
characters being different things.

Can you show examples in existing code of how this would be used? I'm unclear 
on how frequently users need to create a single byte from an integer.  For me, 
it is very rare.
It's probably rare, but recently I was converting from Python 2 to 
Python 3 a program that implements a data compression algorithm (LZW).  
It (now) constructs the compressed data as a bytes object. Sometimes it 
needs to add a series of bytes, sometimes a single byte converted from 
an int.  Not knowing if there was a "recommended" way to do the latter, 
I found something that worked, viz.

    bytes((i,))
But it felt a bit of a kludge.  I would have used something like bchr if 
(a) it existed (b) I knew about it.

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


[Python-Dev] Re: PEP 467 feedback from the Steering Council

2021-09-08 Thread Rob Cliffe via Python-Dev



On 08/09/2021 21:21, Christopher Barker wrote:


[snip]
NOTE: my objection to “bchr”, whether as a builtin or not is not the 
functionality, it’s the name.



[snip]

Why not byte() ?

I happened to need to convert an integer to a byte recently and I settled on
    bytes((i,))
I don't know if I missed a more elegant solution (suggestions welcome), 
but if I could write

    byte(i)
that would feel more Pythonic to me.
Best wishes
Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/YTR5XL5FR66KLXRVATZIZPNXPZRP7CLU/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Need help to debug a ssl crash on Windows which prevents merging PRs

2021-06-01 Thread Rob Cliffe via Python-Dev

Well done Victor!
This stuff is way over my head, but rest assured that humble Python 
programmers like me appreciate all the effort put in from guys like you 
into improving Python.

Rob Cliffe

On 01/06/2021 23:14, Victor Stinner wrote:

On Fri, May 28, 2021 at 6:40 PM Victor Stinner  wrote:

In the 3.10 branch, it became really hard to merge PRs because the
following ssl crashs on Windows:
https://bugs.python.org/issue44252

Update on this bug which blocked the Python 3.10 beta 2 release. It's
now fully fixed!

It was a simple bug in the _ssl.SSLError exception.

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


[Python-Dev] Re: PEP 563 in light of PEP 649

2021-04-19 Thread Rob Cliffe via Python-Dev



On 19/04/2021 22:01, Antoine Pitrou wrote:

Almost nobody uses -O. Optimizations that are enabled only in -O are
useless.
Data point: I use -O.¹  Not frequently, not usually, but I have a few 
large² programs that I add features to from time to time and will 
doubtless continue to do so.  I need their __debug__-enabled diagnostics 
and asserts during development and testing.  When I run them "for real", 
I use -O.
Of course, since I never use annotations, type hints or whatever, this 
may not be very relevant to this thread.

Best wishes
Rob Cliffe

¹ Which makes me "almost nobody" - well, I knew that already. 
² Your idea of "large" may not be the same as mine - I'm talking a few 
thousand lines.

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


[Python-Dev] Re: Typing syntax and ecosystem

2021-04-13 Thread Rob Cliffe via Python-Dev



On 13/04/2021 23:21, Barry Warsaw wrote:


I would still be opposed to requiring type hinting in Python.

-Barry
(Gasps in horror.)  I can only hope I've misunderstood this sentence.  
Has it ever been even tentatively suggested that type hinting become 
mandatory?  (What would that even mean: that the type of every function 
parameter or function return value must be specified?)  Some of us don't 
use type hinting or annotations (I don't even pretend to understand what 
they are) and don't intend to.  No offence to those who like them, carry 
on doing your thing.

Please reassure me, someone. 
Rob Cliffe


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


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


[Python-Dev] Re: NamedTemporaryFile and context managers

2021-04-08 Thread Rob Cliffe via Python-Dev

Well this works:

from tempfile import NamedTemporaryFile
import os

with NamedTemporaryFile(delete=False) as fp:
  fp.write(b'some data')
  fp.close()
  with open(fp.name, 'rb') as fp2:
    data = fp2.read()
  os.remove(fp.name)
assert data == b'some data'

Of course it is theoretically possible that another app will do 
something to the temporary file between the "fp.close()" and the "open" 
on the next line, or between closing fp2 and the "os.remove".  Is this a 
concern?

Rob Cliffe

On 08/04/2021 22:42, Ethan Furman wrote:

On 4/8/21 1:43 PM, Antoine Pitrou wrote:

On Thu, 8 Apr 2021 13:31:26 -0700
Ethan Furman  wrote:


```python
from tempfile import NamedTemporaryFile

with NamedTemporaryFile() as fp:
  fp.write(b'some data')
  fp.close()  # Windows workaround
  fp.open()
  data = fp.read()

assert data == 'some_data'
```

The problem is that, even though `fp.open()` is still inside the 
context manager, the `close()` call deletes the file

[2].  To handle this scenario, my proposal is two-fold:

1) stop using the TEMPFILE OS attribute so the OS doesn't delete the 
file on close

2) add `.open()` to NamedTemporaryFile


Instead, you could add a dedicated `.reopen()`?


The main hurdle is that on Windows we let the OS manage the lifetime 
of the file, which means that it is deleted as soon as it is closed.  
We would need to remove that branch and treat all NamedTemporaryFiles 
the same.


We could add reopen(), but since close() is already there... although 
I do like the name of `reopen`.


--
~Ethan~
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/2DGIFUS6SU56MP6OWOEJPSWEDR2PL5CS/

Code of Conduct: http://python.org/psf/codeofconduct/


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


[Python-Dev] Re: 3.10 change (?) for __bool__

2021-01-15 Thread Rob Cliffe via Python-Dev



On 12/01/2021 15:53, Mark Shannon wrote:

Hi everyone,



In master we convert `if x: pass` to `pass` which is equivalent, 
unless bool(x) has side effects the first time it is called. This is a 
recent change.


Suppose x is not a currently valid variable name at runtime.  Will the 
NameError still be "optimised" away?

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


[Python-Dev] Re: os.scandir bug in Windows?

2020-10-19 Thread Rob Cliffe via Python-Dev



On 19/10/2020 12:42, Steve Dower wrote:

On 15Oct2020 2239, Rob Cliffe via Python-Dev wrote:
TLDR: In os.scandir directory entries, atime is always a copy of 
mtime rather than the actual access time.


Correction - os.stat() updates the access time to _now_, while 
os.scandir() returns the last access time without updating it.


Eryk replied with a deeper explanation of the cause, but fundamentally 
this is what you are seeing.


Feel free to file a bug, but we'll likely only add a vague note to the 
docs about how Windows works here rather than changing anything. If 
anything, we should probably fix os.stat() to avoid updating the 
access time so that both functions behave the same, but that might be 
too complicated.


Cheers,
Steve

Sorry - what you say does not match the behaviour I observe, which is that
    (1) Neither os.stat, nor reading os.scandir directory entries, 
update any of the times on disk.
    (2) os.stat.st_atime returns the "correct" time the file was last 
accessed.

    (3) os.scandir always returns st.atime equal to st.mtime.

Modified demo program:

# osscandirtest.py
import time, os

print(f'[1] {time.time()=}')
with open('Test', 'w') as f: f.write('Anything\n')

time.sleep(20)

print(f'[2] {time.time()=}')
with open('Test', 'r') as f: f.readline() # Read the file

time.sleep(10)

print(f'[3] {time.time()=}')
print(os.stat('Test'))
for DirEntry in os.scandir('.'):
    if DirEntry.name == 'Test':
    stat = DirEntry.stat()
    print(f'scandir DirEntry {stat.st_ctime=} {stat.st_mtime=} 
{stat.st_atime=}')

print(os.stat('Test'))
for DirEntry in os.scandir('.'):
    if DirEntry.name == 'Test':
    stat = DirEntry.stat()
    print(f'scandir DirEntry {stat.st_ctime=} {stat.st_mtime=} 
{stat.st_atime=}')

print(f'[4] {time.time()=}')

Sample output:

[1] time.time()=1603166161.12121
[2] time.time()=1603166181.1306772
[3] time.time()=1603166191.1426473
os.stat_result(st_mode=33206, st_ino=9851624184951253, 
st_dev=2230120362, st_nlink=1, st_uid=0, st_gid=0, st_size=10,

st_atime=1603166181, st_mtime=1603166161, st_ctime=1603166161)
scandir DirEntry stat.st_ctime=1603166161.12121 
stat.st_mtime=1603166161.12121 stat.st_atime=1603166161.12121
os.stat_result(st_mode=33206, st_ino=9851624184951253, 
st_dev=2230120362, st_nlink=1, st_uid=0, st_gid=0, st_size=10,

st_atime=1603166181, st_mtime=1603166161, st_ctime=1603166161)
scandir DirEntry stat.st_ctime=1603166161.12121 
stat.st_mtime=1603166161.12121 stat.st_atime=1603166161.12121

[4] time.time()=1603166191.1426473

You will observe that
    (1) The results from the two os.stat calls are the same, as are the 
results from the two scandir calls.
    (2) The os.stat.st_atime (1603166181) *IS* the time that the file 
was read with the

            with open('Test', 'r') as f: f.readline() # Read the file
        line of code, as it matches the
            [2] time.time()=1603166181.1306772
        line of output (apart from discarded fractions of a second) and 
is 20 seconds (*not* 30 seconds) after the file creation time, as expected.
    (3) The os.scandir atime is a copy of mtime (and in this case, of 
ctime as well).


So it really does seem that the only thing "wrong" is that os.scandir 
returns atime as a copy of mtime, rather than the correct value.
And since os.stat returns the "right" answer and os.scandir doesn't, it 
really seems that this is a bug, or at least a deficiency, in os.scandir.


Demo run on Windows 10 Home version 1903 OS build 18362.1139
Python version 3.8.3 (32-bit).
Best wishes
Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/MGICSKCSTSKS36XUP6IZTXZOSGBPMQYY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: os.scandir bug in Windows?

2020-10-18 Thread Rob Cliffe via Python-Dev
How do I do that, please?  I can't see an obvious create option on that 
web page.  Do I need to log in?

Thanks
Rob Cliffe

On 18/10/2020 05:31, Gregory P. Smith wrote:
Could you please file this as an issue on bugs.python.org 
<http://bugs.python.org>?


Thanks!
-Greg


On Sat, Oct 17, 2020 at 7:25 PM Rob Cliffe via Python-Dev 
mailto:python-dev@python.org>> wrote:



TLDR: In os.scandir directory entries, atime is always a copy of
mtime
rather than the actual access time.

Demo program: Windows 10, Python 3.8.3:

# osscandirtest.py
import time, os
with open('Test', 'w') as f: f.write('Anything\n') # Write to a file
time.sleep(10)
with open('Test', 'r') as f: f.readline() # Read the file
print(os.stat('Test'))
for DirEntry in os.scandir('.'):
 if DirEntry.name == 'Test':
 stat = DirEntry.stat()
 print(f'scandir DirEntry {stat.st_ctime=} {stat.st_mtime=}
{stat.st_atime=}')

Sample output:

os.stat_result(st_mode=33206, st_ino=8162774324687317,
st_dev=2230120362, st_nlink=1, st_uid=0,
st_gid=0, st_size=10, st_atime=1600631381, st_mtime=1600631371,
st_ctime=1600631262)
scandir DirEntry stat.st_ctime=1600631262.951019
stat.st_mtime=1600631371.7062848 stat.st_atime=1600631371.7062848

For os.stat, atime is 10 seconds more than mtime, as would be
expected.
But for os.scandir, atime is a copy of mtime.
ISTM that this is a bug, and in fact recently it stopped me from
using
os.scandir in a program where I needed the access timestamp. No big
deal, but ...
If it is a feature for some reason, presumably it should be
documented.

Best wishes
Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
<mailto:python-dev@python.org>
To unsubscribe send an email to python-dev-le...@python.org
<mailto:python-dev-le...@python.org>
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at

https://mail.python.org/archives/list/python-dev@python.org/message/RIKQAXZVUAQBLECFMNN2PUOH322B2BYD/
Code of Conduct: http://python.org/psf/codeofconduct/



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


[Python-Dev] os.scandir bug in Windows?

2020-10-17 Thread Rob Cliffe via Python-Dev


TLDR: In os.scandir directory entries, atime is always a copy of mtime 
rather than the actual access time.


Demo program: Windows 10, Python 3.8.3:

# osscandirtest.py
import time, os
with open('Test', 'w') as f: f.write('Anything\n') # Write to a file
time.sleep(10)
with open('Test', 'r') as f: f.readline() # Read the file
print(os.stat('Test'))
for DirEntry in os.scandir('.'):
    if DirEntry.name == 'Test':
    stat = DirEntry.stat()
    print(f'scandir DirEntry {stat.st_ctime=} {stat.st_mtime=} 
{stat.st_atime=}')


Sample output:

os.stat_result(st_mode=33206, st_ino=8162774324687317, 
st_dev=2230120362, st_nlink=1, st_uid=0,
st_gid=0, st_size=10, st_atime=1600631381, st_mtime=1600631371, 
st_ctime=1600631262)
scandir DirEntry stat.st_ctime=1600631262.951019 
stat.st_mtime=1600631371.7062848 stat.st_atime=1600631371.7062848


For os.stat, atime is 10 seconds more than mtime, as would be expected.
But for os.scandir, atime is a copy of mtime.
ISTM that this is a bug, and in fact recently it stopped me from using 
os.scandir in a program where I needed the access timestamp. No big 
deal, but ...

If it is a feature for some reason, presumably it should be documented.

Best wishes
Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/RIKQAXZVUAQBLECFMNN2PUOH322B2BYD/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-09-04 Thread Rob Cliffe via Python-Dev




On 30/07/2020 00:34, Nick Coghlan wrote:
the proposed name binding syntax inherently conflicts with the 
existing assignment statement lvalue syntax in two areas:


* dotted names (binds an attribute in assignment, looks up a 
constraint value in a match case)
* underscore targets (binds in assignment, wildcard match without 
binding in a match case)



The former syntactic conflict presents a bigger problem, though, as it 
means that we'd be irrevocably committed to having two different 
lvalue syntaxes for the rest of Python's future as a language.




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


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-08-05 Thread Rob Cliffe via Python-Dev



On 03/08/2020 17:37, MRAB wrote:

[snip]
A thought occurred to me. By default, the current rules of the PEP 
could apply, but why not allow prefixing with "as" for a capture and 
"is" for a value?


Yes, I know, comparison of the values is not by identity, but "is" is 
a short keyword that already exists and matches up with "as".



What about 'match'?  Not as short, but fairly intuitive:

    case (x, y, match Z):
        print(f'A point whose z-coordinate equals {Z}')
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/TXMR3IVHSKOLMNGUGSGLJSULY4FFHSBW/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-08-05 Thread Rob Cliffe via Python-Dev

Welcome to python-dev, Rik!  Of course you can email to this list.

On 30/07/2020 14:30, Rik de Kort via Python-Dev wrote:


I think adding the Walrus operator is trying to solve a problem that 
doesn't exist. Compare the example from the PEP:

    [snip]

 case (x, y, z):

[snip]


To the one without:

[snip]

 case (x := _, y := _, z := _):
It's a lot more typing, it's a lot more ugly, and I'd argue it's not 
any more explicit than the earlier one.


The debate is still going on as to whether "capture" variables should be 
marked, and if so whether with the walrus operator or in some other way, 
and "var := _" wouldn't be my personal preference. However,


case (x := _, y := _, z := _):

*is* more explicit, because it explicitly says that x, y and z are 
variables that should capture (i.e. be bound to) whatever values are 
found.  Contrast this with say


case (x := _, y := _, z):

which says that z contains a value to be *matched*, and if such a match is 
found, x and y should capture the relevant values.

Best wishes
Rob Cliffe

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


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-31 Thread Rob Cliffe via Python-Dev



On 31/07/2020 17:24, Rik de Kort via Python-Dev wrote:
1. Semantic operator overloading in generic contexts is very different 
from this use case. It's surrounded by a clear context.
2. Python programmer intuition varies across python programmers, and I 
would find it hella unintuitive if I had to explicitly capture every 
variable. I just want to write down what the thing looks like and have 
the interpreter figure out the correct bindings. Extra binding syntax 
will get in the way rather than be helpful.


Until you want to do something slightly different, and the interpreter's 
choice is not what you want.


Python Dev  wrote:

+10. See

https://stackoverflow.com/questions/36825925/expressions-with-true-and-is-true-give-different-results/36826262#36826262
for concrete evidence where another semantically inconsistent
operator overloading caused trouble and what Stroustroup has to
say on the matter.


On 31.07.2020 13:42, Larry Hastings wrote:





On 7/31/20 12:36 AM, Tobias Kohn wrote:

And since pattern matching is really
 a new feature to be introduced to Python, a feature that can
 be seen in different lights, there is no 'Python-Programmer
 intuition' that would apply in this case.


It's not fair to say "intuition doesn't apply because it's new
syntax".  There are plenty of examples of intuition serving a
Python programmer well when encountering new syntax.  A Python
programmer's intuition is informed by existing syntax and
conventions in the language.  When they see a new construct,
its similarity to existing constructs can make understanding
the new syntax quite intuitive indeed.

Take for example list comprehensions.  Python 1 programmers
hadn't seen

a = [x for x in y]


But they knew what square brackets meant in that context, it
meant "creates a new list".  And they knew what "for x in y"
meant, that meant iteration.  Understanding those separate two
concepts, a Python 1 programmer would be well on their way to
guessing what the new syntax meant--and they'd likely be
right.  And once they understood list comprehensions, the
first time they saw generator expressions and set and dict
comprehensions they'd surely intuit what those did immediately.


The non-intuitiveness of PEP 622, as I see it, is that it
repurposes what looks like existing Python syntax but
frequently has wholly different semantics.  For example, a
"class pattern" looks like it's calling a function--perhaps
instantiating an object?--but the actual semantics and
behavior is very different.  Similarly, a "mapping pattern"
looks like it's instantiating a dict, but it does something
very different, and has unfamiliar and seemingly arbitrary
rules about what is permitted, e.g. you can't use full
expressions or undotted-identifiers when defining a key.  Add
the "capture pattern" to both of these, and a Python
programmer's intuition about what this syntax traditionally
does will be of little help when encountering a PEP 622 match
statement for the first time.


Cheers,





//arry/




___

Python-Dev mailing list --python-dev@python.org  


To unsubscribe send an email topython-dev-le...@python.org  


https://mail.python.org/mailman3/lists/python-dev.python.org/

Message archived 
athttps://mail.python.org/archives/list/python-dev@python.org/message/Q5KULD7E3TZSSQ5CFUOQSJTGS5JQS4WM/

Code of Conduct:http://python.org/psf/codeofconduct/


-- 
 Regards,

 Ivan


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


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


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-30 Thread Rob Cliffe via Python-Dev



On 08/07/2020 16:02, Guido van Rossum wrote:

Today I’m happy (and a little trepidatious) to announce the next
version of PEP 622, Pattern Matching.
After all the discussion on the issue, I can still not stop thinking 
that there needs to be a visual distinction between "capture" and 
"match" variables.
Having rules ("plain names are capture, dotted names are match") is one 
more thing to be learnt.  One more bit of mystery when (a near newbie 
is) reading code.


Possible compromise: *two* sigils - one for capture, one for match. Both 
would be optional, only required when the default is not what is wanted, 
but could be added regardless if the author felt it added clarity.


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


[Python-Dev] Re: PEP 622: Structural Pattern Matching -- followup

2020-07-26 Thread Rob Cliffe via Python-Dev

I think we are storing up trouble unless we
    1) Allow arbitrary expressions after `case`, interpreted *as now*
    2) Use *different* syntaxes, not legal in expressions, for
            alternative matching values (i.e. not `|` or `or`) (NB 
simply stacking with multiple `case` lines is one possibility)

            templates such as `Point(x, 0)`
            anything else particular to `match`
I am reminded of the special restrictions for decorator syntax, which 
were eventually removed.


On 24/06/2020 20:38, Guido van Rossum wrote:

Everyone,

If you've commented and you're worried you haven't been heard, please 
add your issue *concisely* to this new thread. Note that the following 
issues are already open and will be responded to separately; please 
don't bother commenting on these until we've done so:


- Alternative spellings for '|'
- Whether to add an 'else' clause (and how to indent it)
- A different token for wildcards instead of '_'
- What to do about the footgun of 'case foo' vs. 'case .foo'

(Note that the last two could be combined, e.g. '?foo' or 'foo?' to 
mark a variable binding and '?' for a wildcard.)


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



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


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


[Python-Dev] Re: PEP 622: Structural Pattern Matching -- followup

2020-07-26 Thread Rob Cliffe via Python-Dev



On 24/06/2020 20:38, Guido van Rossum wrote:

Everyone,

If you've commented and you're worried you haven't been heard, please 
add your issue *concisely* to this new thread. Note that the following 
issues are already open and will be responded to separately; please 
don't bother commenting on these until we've done so:


- Alternative spellings for '|'
- Whether to add an 'else' clause (and how to indent it)
- A different token for wildcards instead of '_'
- What to do about the footgun of 'case foo' vs. 'case .foo'

(Note that the last two could be combined, e.g. '?foo' or 'foo?' to 
mark a variable binding and '?' for a wildcard.)


(Prefatory remarks:  I am sure you get a lot of questions to which the 
answer is basically "Read the PEP".  I myself have been guilty in this 
regard.  But I fear this is inevitable when the PEP is so long and there 
is so much new stuff to absorb.  Apologies if this is yet another one.)


_First question_: Sometimes no action is needed after a case clause.  If 
the Django example had been written


if (
isinstance(value, (list, tuple)) and
len(value) > 1 and
isinstance(value[-1], (Promise, str))
):
*value, label = value
else:
label = key.replace('_', ' ').title()

the replacement code would/could be

match value:
case [*value, label := (Promise() | str())] if value:
pass
case _:
label = key.replace('_', ' ').title()

AFAICS the PEP does not *explicitly* state that the 'pass' line is necessary 
(is it?), i.e. that the block following `case` cannot (or can?) be empty.
The term `block` is not defined in the PEP, or in 
https://docs.python.org/3/reference/grammar.html.
But an empty block following a line ending in `:` would AFAIK be unprecedented 
in Python.  I think it is worth clarifiying this.

_Second question_: in the above example replacement, if `case _:` does not bind 
to `_`, does that mean that the following line will not work?
Is this one of the "two bugs" that Mark Shannon alluded to?  (I have read every 
message in the threads and I don't remember them being spelt out.)
And I'm curious what the other one is (is it binding to a variable `v`?).

Best wishes
Rob Cliffe

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


[Python-Dev] Re: PEP 622: Structural Pattern Matching -- followup

2020-07-25 Thread Rob Cliffe via Python-Dev
Without arguing for or against allowing a capture variable, IMO rather 
than syntax like

    match  into :
it would be far better (and not require a new keyword) to write this as
    with  as match :
Rob Cliffe

On 24/06/2020 20:38, Guido van Rossum wrote:

Everyone,

If you've commented and you're worried you haven't been heard, please 
add your issue *concisely* to this new thread. Note that the following 
issues are already open and will be responded to separately; please 
don't bother commenting on these until we've done so:


- Alternative spellings for '|'
- Whether to add an 'else' clause (and how to indent it)
- A different token for wildcards instead of '_'
- What to do about the footgun of 'case foo' vs. 'case .foo'

(Note that the last two could be combined, e.g. '?foo' or 'foo?' to 
mark a variable binding and '?' for a wildcard.)


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



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


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


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-21 Thread Rob Cliffe via Python-Dev



On 18/07/2020 11:23, emmanuel.coir...@caissedesdepots.fr wrote:

Ethan Furman wrote:

The problem with any kind of sigil/keyword is that it becomes line noise
-- we would have to train ourselves to ignore them in order to see the
structure and variables we are actually interested in.  Once we become

Every syntax element can become noise once we're used to it. This is how Groovy is built 
from Java : they removed everything that can be removed, and still be 
"understandable" by the compiler. The result is the language being counter 
intuitive for people that don't do Groovy everyday... Can I write thing like this ? Seems 
to work... And with that ? Works too, but I don't know if it produces the same effect...

We can also think about syntax elements as strucural elements like pillars, 
helping the thought to elaborate while reading the code. Pillars are 
constraints for people in a building (they block your view, you have to bypass 
them, ...), but they helps building bigger constructions, and we're all used to 
them.

In this slightly modified example from the PEP :

 match entree[-1]:
 case Sides.SPAM:
 response = "Have you got anything without Spam?"
 case "letuce":
 response = "blablabla"
 case side:
 response = f"Well, could I have their Spam instead of the {side} 
then?"
 case 1542 | "plop":
 response = "blablabla2"

It's difficult for someone not mastering this feature to see immediatly that 
"side" will get it's value changed and that the last case will never match.


+1



 match entree[-1]:
 case Sides.SPAM:
 response = "Have you got anything without Spam?"
 case "letuce":
 response = "blablabla"
 case side=:
 response = f"Well, could I have their Spam instead of the {side} 
then?"
 case 1542 | "plop":
 response = "blablabla2"

Here we immediatly see that the first two cases don't work in the same way as the third, 
because there is "something more". It will even maybe indicate that the last 
case is useless...


adept at ignoring them, we will again have difficulties when debugging
as we won't easily see them.
Besides which, the problem is solved:

namespace.var is a lookup
var is a store

These rules can't be deduced from a few examples, or from experience from other 
languages. You have to explicitly learn them.


+1


  Since newcomers won't propably learn them first (if at all), they won't understand how it works, 
and they will propably introduce bugs hard to debug. They'll think it's a kind of "swith 
case" new construct, and will use it that way, completly ignoring the "capturing" 
property that shows in some cases and not in others.

 match entree[-1]:
 case Sides.SPAM:
 # newcomers will understand that entree[-1] == Sides.SPAM and 
write the code they need

 SPAM = "spam"
 match entree[-1]:
 case SPAM:
 # newcomers will understand that entree[-1] == "spam" and write 
the code they need
 # ignoring that now, in the following code, SPAM == anything but 
"spam"
 # introducing a bug anywhere in the following code where SPAM is 
expected to hold the
 # initial value

Only a unit test case that test that SPAM has changed can detect this kind of bug. 
Generally speaking, unit test cases don't test values of "constants" before and 
after a test case. So it won't even help.

Here, we can argue that match is not a "switch case" like syntax, but newcomers from C, Java, 
Javascript, whatever WILL use it like a "switch case", and WILL read code where it will be used 
like that. Even if it's not the main use case, it will be used for that, because of 50 years of history of C 
that we can't ignore. Adding a "=" or something else will at least ring a bell.

We can argue that constants should be namespaced, but is it a general way of doing ? People can 
write "from module import SPAM" or "import module; module.SPAM". This is 
equivalent, but in one case, it may introduce a bug.

Do not forget that Python will be used by many more newcomers, new learners, new 
developers, data scientists, people with unknow backgrounds, and perhaps few, or no 
experience in programming. IMHO Python strength is that it's syntax is easy to learn 
because it is easy to deduce. The some rules that are counter-intuitive like the 
"else" clause for the loops can't cause any harm if misused because their 
misuse is detected immediatly, and we can avoid writing them (and most people do).

On the other hand, "capturing" variables mixed with "match" variables is 
counter-intuitive unless you explicitly learn the rules. You can't deduce it (there rules don't 
exist anywhere else). This feature is central of the PEP and will be used, and will introduce 
subtle bugs when misused.

That's why I consider the rules you stated is not the right way for this 
feature, and that we 

[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-20 Thread Rob Cliffe via Python-Dev



On 16/07/2020 18:13, MRAB wrote:

On 2020-07-16 17:37, Steve Holden wrote:
While I understand the point of view that says that match ... : 
should encapsulate a sequence of indented suites, it seems to me that 
match/case/case/.../else has a natural affinity with 
try/except/except/.../finally/else, and nobody seems to think that 
the excepts should be indented. Or the finally. And naturally the 
match/else case are at the same indentation level, just as for/else, 
while/else and try/finally. So why, exactly, should case be indented?


My apologies for being a Bear of Very Little Brain.


[snip]
For all other statement structures (if, while, try, etc.), the first 
line ends with a colon and the second line is indented (and is a 
statement). Therefore the cases should be indented.


However, for all other statement structures (if, while, try, etc.), 
the other parts of the structure itself (elif, else, except, etc.) 
aren't indented. Therefore the cases shouldn't be indented.


Either way, it's inelegant.

Absolutely true.  However:

I think that equal indentation suggests suites of equal status. 
Increased indentation suggests suites are subordinate to a previous suite.

Consider these examples:

(1) if..elif...else: Suites are definitely co-equal (they are 
alternatives, only one of which is chosen).  So if/elif/else have equal 
indentation.
(2) for...else or while...else: It's arguable IMO (YMMV); Python has 
chosen to indent them equally.  I don't think it would have been 
outrageous to indent the 'else:';  one reason not to is that the 'else' 
might not stand out (it would typically be indented equally with the 
preceding line of code), unless it was allowed/forced to be indented 
*less than* 'for'.
(3) try...except...else:  IMO also arguable (at most one of 'except' and 
'else' can be executed).
(4) try...finally: The suites have equal status (both are always 
executed), so they have equal indentation.


Now to me, 'case' clauses are *subordinate* to 'match'.  After all, the 
value after 'match' applies to all the following 'case's.  So I would 
argue in favour of indenting 'case' statements.  This would make them 
stand out *more* (making a virtue out of 'match' *not* being followed by 
an indented suite).  A Good Thing.  One of the purposes of indentation 
is to make program structure clearly visible, which IMO this would do.


Or from a slightly different point of view: "match...case...case..." is 
a single construct, a self-contained program component. Indenting the 
'case's would stop them from distracting visually from other suites that 
are indented the same as 'match'.  (I.e. other program components of 
equal status.)


(If 'else' were allowed after 'match', I would argue that it should also 
be indented, for the same reasons, and because it is logically a case, 
albeit a special one.)


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


[Python-Dev] Re: PEP 622 constant value syntax idea

2020-07-20 Thread Rob Cliffe via Python-Dev



On 16/07/2020 08:16, Baptiste Carvello wrote:

Hello,

Le 15/07/2020 à 13:37, Mohammad Foroughi via Python-Dev a écrit :

Hi, I had an idea regarding the pattern matching issue of comparing with
a previous constant variable instead of assigning to a new local
variable. I'm not sure if this has been brought up before but instead of
using a symbol with the case statement what if we used a keyword.

[...]

Other ideas for the keyword are "const" or "static" but these 2 are more
difficult to recognise since they aren't in other parts of python but
the "global" keyword is already implemented so it would be easy to
understand.

What about simply "is", which is already a keyword?

AFAIK "is" has no meaning as a prefix operator as of now, so hopefully
it would not make the grammar ambiguous (how can one check that for sure?).

match color:
 case is RED:
 print("red")
 case is BLUE:
 print("blue")
 case other:
 print(f"unknown color {other}")

or with Rhodri James' example:

match value:
 case is x:
 print("value matches")
 case Point(is x, y):
 print("value matches x, y captured")
 case Line(Point(is x1, y1), Point(x2, is y2)):
 print("wouldn't call that pretty, but not ugly either")


Cheers,
Baptiste

P.S.: granted, it could mislead some users into thinking that the
comparison is done with "is" instead of "=="; but then, patterns are
special in many ways, users will have to just learn them…
Hm, plus ca change...  Your last paragraph inevitably suggests actually 
using '==' rather than 'is'.
Which is something I suggested way back, but I was firmly asked by Guido 
to "drop it".  (Which, up to now, I have.)

The specific objection he raised was that e.g. this example from the PEP
      case BinaryOp(left=Number(value=x), op=op, right=Number(value=y)):
would become
      case BinaryOp(left=Number(value===x), op===op, 
right=Number(value===y)):

which is unparseable.  Although I can't see why it couldn't be written
      case BinaryOp(left=Number(value=    ==x), op=    ==op, 
right=Number(value=   ==y)): # multiple spaces here for clarity

Rob Cliffe

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

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


[Python-Dev] Re: PEP 622: Structural Pattern Matching -- followup

2020-07-19 Thread Rob Cliffe via Python-Dev



On 08/07/2020 16:15, MRAB wrote:

On 2020-07-08 03:08, Rob Cliffe via Python-Dev wrote:

Why not use '=' to distinguish binding from equality testing:
      case Point(x, =y): # matches a Point() with 2nd parameter equal to
y; if it does, binds to x.

This would allow a future (or present!) extension to other relative
operators:
      case Point(x, >y):
(although the syntax doesn't AFAICS naturally extend to specifying a
range, i.e. an upper and lower bound, which might be a desirable thing
to do.
Perhaps someone can think of a way of doing it).

Whether
      case =42:
      case 42:
would both be allowed would be one issue to be decided.

In Python, '=' is assignment and '==' is equality. Using '=' for 
equality could lead to confusion.

Fair enough.  In that case use `==` instead:
    case Point(x, ==y): # if matches a Point with the given y-value, 
bind to x


___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/KYUZQRZNDOVFEOC5XBYOFXKTPK7LAZI4/

Code of Conduct: http://python.org/psf/codeofconduct/

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


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-11 Thread Rob Cliffe via Python-Dev



On 12/07/2020 02:04, Guido van Rossum wrote:
On Sat, Jul 11, 2020 at 5:58 PM Chris Angelico > wrote:



Hang on. Matching happens before assignment, so this should use the
previous value of x for the matching. At least, that's my
understanding. If you do something like:

case Point(x, 2):

it won't assign x unless the second coordinate is 2, right?


Good catch. That's actually undefined -- we want to let the optimizer 
have some leeway in how to generate  the best code for matching. See 
https://www.python.org/dev/peps/pep-0622/#performance-considerations


Currently it doesn't optimize all that much -- it just processes 
patterns from left to right:

```
>>> match Point(3, 3):
...   case Point(x, 42): pass
...
>>> print(x)
3
>>>
```

If I've understood this correctly, my immediate reaction is one of 
horror.  I'd assumed that a case that failed to match would have no effect.

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


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-09 Thread Rob Cliffe via Python-Dev

One thing I don't understand about the PEP:

    case [x,y]:

IIUC matches any 2-element sequence.
How would you match specifically a 2-item list (say)?
Would it be

    case list([x,y]):

I would appreciate it if some kind person could enlighten me.
TIA
Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/NJLVOPNAZIDOCYYGJ2RJKK23ZK5FCLXT/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 version 2 (Structural Pattern Matching)

2020-07-08 Thread Rob Cliffe via Python-Dev



On 08/07/2020 16:02, Guido van Rossum wrote:


```
    USE_POLAR = "polar"
    USE_RECT = "rect"
```
Now we would like to be able to replace those literals with the
corresponding names throughout our code and have everything work like
before:
```
    match t:
        case (USE_RECT, real, imag):
            return complex(real, imag)
        case (USE_POLAR, r, phi):
            return complex(r * cos(phi), r * sin(phi))
```
Alas, the compiler doesn’t know that we want `USE_RECT` to be a
constant value to be matched while we intend `real` and `imag` to be
variables to be given the corresponding values captured from the
subject. So various clever ways have been proposed to distinguish the
two cases.
I apologise for posting a second message re the same idea, but I can't 
contain my enthusiasm for it:-)

and I want to make sure it's not overlooked:
*Use '==' to mark* (when necessary) *load-and-compare items*:
    match t:
        case (==USE_RECT, real, imag):
            return complex(real, imag)
        case (==USE_POLAR, r, phi):
            return complex(r * cos(phi), r * sin(phi))

allowing incidentally a possible future extension to other relational 
operators:

    case Point(x, >YMAX):
    case >= 42:



If this really is a deal-breaker after all other issues have been
settled, we could go back to considering some special markup for
load-and-compare of simple names (even though we expect this case to
be very rare). But there’s no pressing need to decide to do this now
-- we can always add new markup for this purpose in a future version,
as long as we continue to support dotted names without markup,
since that *is* a commonly needed case.


Except that if this idea were taken to its logical conclusion,
    mod.var        would be a capture variable (contrary to the PEP)
    ==mod.var    would be a load-and-compare value
Which may be controversial, but seems to have more overall consistency.
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/LRCZBUEULXZN2OZWVUHKH5RJ6LICUMEA/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622: Structural Pattern Matching -- followup

2020-07-07 Thread Rob Cliffe via Python-Dev

Why not use '=' to distinguish binding from equality testing:
    case Point(x, =y): # matches a Point() with 2nd parameter equal to 
y; if it does, binds to x.


This would allow a future (or present!) extension to other relative 
operators:

    case Point(x, >y):
(although the syntax doesn't AFAICS naturally extend to specifying a 
range, i.e. an upper and lower bound, which might be a desirable thing 
to do.

Perhaps someone can think of a way of doing it).

Whether
    case =42:
    case 42:
would both be allowed would be one issue to be decided.
Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/MENII4GJ66JHWBKNTNJSJOYCMSMLSIRO/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622 railroaded through?

2020-07-07 Thread Rob Cliffe via Python-Dev
I would like to thank everyone who responded to me for their civilised 
and courteous replies.  I actually expected to get a lot of slagging 
off, but was prepared to accept that for what seemed to me at the time 
to be a legitimate concern.

If my fears were unfounded, I am delighted.
If I have been unfair to Guido and the other developers (and it seems 
that I probably have), I apologise.

Thank you.

FWIW:
    I am not against the PEP.
    I do not have a personal axe to grind, in the form of my own pet 
idea which I want to see incorporated.
    I don't like the .name syntax (grit on Tim's monitor; does not 
suggest the meaning).  Nor am I keen on "expressions" being interpreted 
differently after 'case' than elsewhere in Python.  But I don't know 
what syntax (where necessary) to suggest.
    I'm not keen on special treatment of the '_' variable, and would 
prefer to be able to use 'else:' after 'match'.


Best wishes
Rob Cliffe

On 03/07/2020 15:56, Chris Angelico wrote:


The PEP is still a draft and has not been accepted. Don't worry, the
normal process is still happening :)

Having a reference implementation is a HUGE help, because people can
play around with it. There's a fork running an interactive playground
so you can go right now and get a feel for the way the syntax works.

The implementation has *not* been merged into the CPython trunk. It's
not a fait accompli - it's a tool to help people evaluate the proposal
(and all of the different variants of the proposal as it evolves).

Speaking with my PEP Editor hat on, I would be *thrilled* if more
proposals came with ready-to-try code. Only a very few have that
luxury, and a lot of the debating happens with nothing but theory -
people consider what they *think* they'd do, without actually being
able to try it out and see if it really does what they expect. Having
a reference implementation isn't necessary, of course, but it's
definitely a benefit and not a downside. Also, there HAVE been
proposals with full reference implementations that have ended up
getting rejected; it's not a guarantee that it'll end up getting
merged.

Hope that lessens your fears a bit :)

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

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


[Python-Dev] PEP 622 railroaded through?

2020-07-03 Thread Rob Cliffe via Python-Dev

Whoa!

I have an uneasy feeling about this PEP.

AFAIK the usual procedure for adding a new feature to Python is:
    An idea is raised and attracts some support.
    Someone sufficiently motivated writes a PEP.
    The PEP is thoroughly discussed.
    Eventually a consensus (or at least an "agree to differ" stalemate) 
is reached.

    The PEP is accepted (if it is).
    (Then and only then) Someone works on the implementation.
        etc.

However, PEP 622 only seems to have been presented to the Python 
community only *after* a well-developed (if not finalised) 
implementation was built.  A fait accompli.  So there will inevitably be 
resistance from the developers to accept changes suggested on 
python-dev.  And since the PEP has Guido's authority behind it, I think 
it is likely that it will eventually be accepted pretty much as it was 
originally written.
This means that most of the discussion we have seen on python-dev (and 
there has been a lot) will end up being just pissing in the wind.  (I 
don't mean to be vulgar or disrespectful; I just can't think of another 
phrase that conveys my meaning so well.)  And Guido's 2nd email ("PEP 
622: Structural Pattern Matching -- followup") already to me (YMMV) 
reads rather like "OK, you've had your fun, now try not to joggle our 
elbows too much while we get on with the work".


I don't know how many of the decisions made in the PEP are right and how 
many could be improved (it is of course a subjective question anyway).
I do think it's a pity that the Python community did not have the chance 
to supply feedback earlier down the road (when IMO it would have been 
taken more seriously).
While Guido and the other developers have obviously already put a huge 
amount of work into this PEP (and by now probably have a significant 
emotional investment in it), I do hope that they will take the time to 
consider seriously and on their merits most/all suggested changes, 
rather than being tempted to rush through the acceptance and 
implementation of the PEP.


Best wishes
Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/IG4VNKZF4J7OR3L665PE26KL7L6SFQSQ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Flexible assignment targets

2020-07-02 Thread Rob Cliffe via Python-Dev



On 03/07/2020 00:12, Nick Coghlan wrote:
On Fri., 3 Jul. 2020, 2:27 am MRAB, > wrote:



IMHO, the assignment statement should remain as it is, not sometimes
assign and sometimes not.

There could be another form that does matching:

     try ?x, 0 = (4,5)



Huh, this made me wonder if "match/try" may fit people's brains better 
than "match/case". I know for me that I want to read case clauses the 
same way I would read them in C, which is thoroughly unhelpful.


The following looks weird though, so I don't think I actually like it 
in practice:


===
match shape:
    try Point(x, y):
        ...
    try Rectangle(x0, y0, x1, y1, painted=True):
        ...
===

I don't think it looks at all weird in this example, I think it reads 
quite naturally, in my brain at least.

It is maybe not quite so good when comparing with actual values:
    match value:
        try 42:
            ...
        try -1:
            ...
  And it has the virtue of adding one less keyword.


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


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


[Python-Dev] Re: PEP 622: Structural Pattern Matching

2020-06-26 Thread Rob Cliffe via Python-Dev

Yes, my brain went through the same path.
Another minor nitpick: It would be kinda nice if the various types of 
pattern were listed in the grammar in the same order as the 
corresponding paragraphs subsequently appear.


On 26/06/2020 11:53, Daniel Moisset wrote:

Just a minor editorial thing on the PEP text:

The section 
https://www.python.org/dev/peps/pep-0622/#case-clauses presents a 
simplified syntax. That one mentions "group_pattern", but the document 
never mentions (in prose) what a group pattern is. It confused me 
until I found the definition in the full grammar, which seems to refer 
to those sequence patterns using () rather than []. Probably it makes 
more sense for a quick read to remove the "| group_pattern" from the 
simplified grammar, it looks more like an intermediate construct.



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


[Python-Dev] Re: PEP 622: Structural Pattern Matching

2020-06-26 Thread Rob Cliffe via Python-Dev



On 23/06/2020 20:35, Chris Angelico wrote:

On Wed, Jun 24, 2020 at 5:30 AM Rob Cliffe via Python-Dev
 wrote:

The PEP is great, but this strikes me as horribly confusing, given that 
401|403|404 is already legal syntax.
IIUC any legal expression can come between `case` and `:`, but expressions that 
contain `|` at their outermost level are interpreted differently than from in 
other contexts.
Presumably adding parentheses:
 case (401|403|404):
would make it equivalent to
 case 407:

Is a separator (other than whitespace) actually needed?  Can the parser cope 
with
 case 401 403 404:

Failing that IMO preferable, albeit not ideal, possibilities would be
   1) Use colon as the separator.
   2) Use comma as the separator - this is already legal syntax too, but IMO it 
reads more naturally.
   (And IIRC there are already contexts where brackets are necessary to 
indicate a tuple.)
Perhaps someone can think of something better.

I also (with others) prefer `else:` or perhaps `case else:` to using the`_` 
variable.
The latter is obscure, and woudn't sit well with code that already uses that 
variable for its own purposes.


It's not really arbitrary expressions, though. It's more like an
assignment target list, but with some handling of constants.

case (x, y):

is very similar to

(x, y) = ...



If arbitrary expressions are not allowed
    - the power of this new feature is reduced
    - we have to remember another set of  rules about what is allowed 
and what isn't.  Just as we did with decorator syntax - until that 
restriction was done away with.

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


[Python-Dev] Re: PEP 622: Structural Pattern Matching

2020-06-26 Thread Rob Cliffe via Python-Dev

Some proof-reading of the PEP.  I apologise if this is out of date.

1) In the beginning of the "Mapping Pattern" section:
         "{" (pattern ":" pattern)+ "}"
    This is spelt inconsistently: there is a `+` before the closing `}` 
but not after the opening `{`.


2) The second code snippet in the "Guards" section:

values = [0]

match value:
case [x] if x:
...  # This is not executed
case _:
...
print(x)  # This will print "0"

   Inconsistent spelling: `values` and `value`

3) At the end of the "Named sub-patterns" section:
"PEP 572"
   It would be more helpful to say "PEP 572 (Assignment Expressions)"

Rob Cliffe

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


[Python-Dev] Re: PEP 622: Structural Pattern Matching -- followup

2020-06-25 Thread Rob Cliffe via Python-Dev
Without arguing for or against allowing a capture variable, IMO rather 
than syntax like

    match  into :
it would be far better (and not require a new keyword) to write this as
    with  as match :
Rob Cliffe
PS:  Or
     = match 

On 24/06/2020 20:38, Guido van Rossum wrote:

Everyone,

If you've commented and you're worried you haven't been heard, please 
add your issue *concisely* to this new thread. Note that the following 
issues are already open and will be responded to separately; please 
don't bother commenting on these until we've done so:


- Alternative spellings for '|'
- Whether to add an 'else' clause (and how to indent it)
- A different token for wildcards instead of '_'
- What to do about the footgun of 'case foo' vs. 'case .foo'

(Note that the last two could be combined, e.g. '?foo' or 'foo?' to 
mark a variable binding and '?' for a wildcard.)


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



___
Python-Dev mailing list --python-dev@python.org
To unsubscribe send an email topython-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived 
athttps://mail.python.org/archives/list/python-dev@python.org/message/STJSSAETMTUY7FK5AE53IM73Z2WORNYN/
Code of Conduct:http://python.org/psf/codeofconduct/


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


[Python-Dev] Re: PEP 622: Structural Pattern Matching

2020-06-24 Thread Rob Cliffe via Python-Dev


I also (with others) prefer `else:` or perhaps `case else:` to using 
the`_` variable.
The latter is obscure, and woudn't sit well with code that already 
uses that variable for its own purposes.



I think that's done for consistency. '_' is a wildcard and you can have:

    case (_, _):

to match any 2-tuple, so:

    case _:

would match any value, and can thus already serve as the default.


Consistency with what?  Where else is `_` currently used as a wildcard?
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/SXLNU6FB3Z5AT6APEQUYVGUAJKJH7BZO/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 622: Structural Pattern Matching

2020-06-23 Thread Rob Cliffe via Python-Dev



On 23/06/2020 17:01, Guido van Rossum wrote:


You can combine several literals in a single pattern using `|` ("or"):

```py
        case 401|403|404:
            return "Not allowed"
The PEP is great, but this strikes me as horribly confusing, given that 
401|403|404 is already legal syntax.
IIUC any legal expression can come between `case` and `:`, but 
expressions that contain `|` at their outermost level are *interpreted 
differently* than from in other contexts.

Presumably adding parentheses:
    case (401|403|404):
would make it equivalent to
    case 407:

Is a separator (other than whitespace) actually needed?  Can the parser 
cope with

    case 401 403 404:

Failing that IMO preferable, albeit not ideal, possibilities would be
  1) Use colon as the separator.
  2) Use comma as the separator - this is already legal syntax too, but 
IMO it reads more naturally.
  (And IIRC there are already contexts where brackets are necessary 
to indicate a tuple.)

Perhaps someone can think of something better.

I also (with others) prefer `else:` or perhaps `case else:` to using 
the`_` variable.
The latter is obscure, and woudn't sit well with code that already uses 
that variable for its own purposes.


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


[Python-Dev] REPL output bug

2020-06-15 Thread Rob Cliffe via Python-Dev

If I run the following program (using Python 3.8.3 on a Windows 10 laptop):

import sys, time
for i in range(1,11):
    sys.stdout.write('\r%d' % i)
    time.sleep(1)

As intended, it displays '1', replacing it at 1-second intervals with 
'2', '3' ... '10'.


Now run the same code inside the REPL:

Python 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:20:19) [MSC v.1925 32 
bit (Intel)] on win32

Type "help", "copyright", "credits" or "license" for more information.
>>> import sys, time
>>> for i in range(1,11):
... sys.stdout.write('\r%d' % i)
... time.sleep(1)
...
12
22
32
42
52
62
72
82
92
103
>>>

It appears that the requested characters are output, *followed by* the 
number of characters output

(which is the value returned by sys.stdout.write) and a newline.
Surely this is not the intended behaviour.
sys.stderr behaves the same as sys.stdout.

Python 2 does NOT exhibit this behaviour:

Python 2.7.18 (v2.7.18:8d21aa21f2, Apr 20 2020, 13:19:08) [MSC v.1500 32 
bit (Intel)] on win32

Type "help", "copyright", "credits" or "license" for more information.
>>> import sys, time
>>> for i in range(1,11):
... sys.stdout.write('\r%d' % i)
... time.sleep(1)
...
10>>>
# displays '1', '2' ... '10' as intended.

Best wishes
Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/T3BVZMBLWK3PMLRL2XCQFMLATGRTUPYE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: Improvement to SimpleNamespace

2020-04-27 Thread Rob Cliffe via Python-Dev
Here's another revolutionary thought:  add a new operator and associated 
dunder method (to object?)
whose meaning is *undefined*.  Its default implementation would do 
*nothing* useful (raise an error? return None?).

E.g. suppose the operator were `..`
Then in a specific class you could implement x..y to mean x['y']
and then you could write
    obj..abc..def..ghi
Still fairly concise, but warns that what is happening is not normal 
attribute lookup.


On 15/04/2020 22:34, Glenn Linderman wrote:

On 4/15/2020 12:47 PM, Ivan Pozdeev via Python-Dev wrote:
When writing a proof-of-concept implementation, however, I bumped 
into the need to distinguish which of the child objects are 
containers (thus need to be wrapped as well) and which are the leaves 
(thus need to be returned as is). I guess this is going to be 
application-specific. And the same problem will arise with any 
implementation, not only a wrapper.


Do the child objects truly need to be wrapped, or just accessed?

Thanks for your comments though, they inspired a thought.

The problem with the glom syntax versus the dotted syntax is that the 
minimal syntax is bulky.


obj.abc.def.ghi versus   glom( obj, 'abc.def.ghi')

The problem with attribute syntax is the conflict with regular 
attributes, and the limitation of valid identifier characters. Glom 
probably doesn't have these problems.


So my new thought is that we need a new syntax.  The minimal existing 
syntax might be


obj._('abc.def.ghi')     or maybe   obj['abc.def.ghi']

although the latter would conflict with regular dict lookups, but obj 
isn't a regular dict, so that might not matter.



A new syntax might be:

obj.'abc.def.ghi'


In any of these syntaxes, one could enhance it to use variables in 
some spots similarly to f-strings (but from the beginning, so no 'f' 
would be required)


foo = 'def'
obj.'abc.{foo}.ghi'

would access the same item as previous examples.
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/3A5V62LY3DAPAREZMB7MVRYX4432NR7F/

Code of Conduct: http://python.org/psf/codeofconduct/

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


[Python-Dev] Re: Comments on PEP 554 (Multiple Interpreters in the Stdlib)

2020-04-22 Thread Rob Cliffe via Python-Dev



On 22/04/2020 19:40, Ned Batchelder wrote:


On 4/21/20 12:32 PM, Mark Shannon wrote:

Hi,

I'm generally in favour of PEP 554, but I don't think it is ready to 
be accepted in its current form.



BTW, thanks for including the name of the PEP in the subject.  As a 
casual reader of this list, it's very helpful to have more than just 
the number, so I can decide whether to read into the deeper details.

Hear, hear!  This is a point which is always worth bearing in mind.
Whenever I send an email to my boss (usually containing a software 
update) I try to include all relevant "keywords" in the subject so that 
he can easily search for it months later.

In other words I try to make my emails a valuable resource.
Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/Q3N63NCWL4CBGYQ3GYHZW5SRYGJBSMLS/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 616 -- String methods to remove prefixes and suffixes

2020-03-29 Thread Rob Cliffe via Python-Dev



On 28/03/2020 17:02, Victor Stinner wrote:

What do you think of adding a Version History section which lists most
important changes since your proposed the first version of the PEP? I
recall:

* Version 3: don't accept tuple
* Version 2: Rename cutprefix/cutsuffix to removeprefix/removesuffix,
accept tuple
* Version 1: initial version

For example, for my PEP 587, I wrote detailed changes, but I don't
think that you should go into the details ;-)
https://www.python.org/dev/peps/pep-0587/#version-history

Victor


IMHO that's overkill.  A list of rejected ideas, and why they were 
rejected, seems sufficient.

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


[Python-Dev] Re: PEP 616 -- String methods to remove prefixes and suffixes

2020-03-23 Thread Rob Cliffe via Python-Dev
Sorry, another niggle re handling an empty affix:  With your Python 
implementation,

'aba'.cutprefix(('', 'a')) == 'aba'
'aba'.cutsuffix(('', 'a')) == 'ab'
This seems surprising.
Rob Gadfly Cliffe


On 22/03/2020 23:23, Dennis Sweeney wrote:

Much appreciated! I will add that single quote and change those snippets to::

  >>> s = 'FooBar' * 100 + 'Baz'
  >>> prefixes = ('Bar', 'Foo')
  >>> while len(s) != len(s := s.cutprefix(prefixes)): pass
  >>> s
  'Baz'

and::

  >>> s = 'FooBar' * 100 + 'Baz'
  >>> prefixes = ('Bar', 'Foo')
  >>> while s.startswith(prefixes): s = s.cutprefix(prefixes)
  >>> s
  'Baz'
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/QJ54X6WHQQ5HFROSJOLGJF4QMFINMAPY/
Code of Conduct: http://python.org/psf/codeofconduct/

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


[Python-Dev] Re: PEP 616 -- String methods to remove prefixes and suffixes

2020-03-22 Thread Rob Cliffe via Python-Dev



On 22/03/2020 22:25, Dennis Sweeney wrote:

Here's an updated version.

Online: https://www.python.org/dev/peps/pep-0616/
Source: https://raw.githubusercontent.com/python/peps/master/pep-0616.rst

Changes:
 - More complete Python implementation to match what the type checking in 
the C implementation would be
 - Clarified that returning ``self`` is an optimization
 - Added links to past discussions on Python-Ideas and Python-Dev
 - Specified ability to accept a tuple of strings
 - Shorter abstract section and fewer stdlib examples
 - Mentioned
 - Typo and formatting fixes

I didn't change the name because it didn't seem like there was a strong 
consensus for an alternative yet. I liked the suggestions of ``dropprefix`` or 
``removeprefix``.

All the best,
Dennis
___


Proofreading:

it would not be obvious for users to have to call 
'foobar'.cutprefix(('foo,)) for the common use case of a single prefix.


Missing single quote after the last foo.


s = 'foobar' * 100 + 'bar'
prefixes = ('bar', 'foo')
while len(s) != len(s := s.cutprefix(prefixes)): pass
s

'bar'

or the more obvious and readable alternative:


s = 'foo' * 100 + 'bar'
prefixes = ('bar', 'foo')
while s.startswith(prefixes): s = s.cutprefix(prefixes)
s

'bar'


Er no, in both these examples s is reduced to an empty string.

Best wishes
Rob Cliffe

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


[Python-Dev] Re: PEP 616 -- String methods to remove prefixes and suffixes

2020-03-21 Thread Rob Cliffe via Python-Dev



On 21/03/2020 20:16, Ned Batchelder wrote:

On 3/21/20 12:51 PM, Rob Cliffe via Python-Dev wrote:



On 21/03/2020 16:15, Eric V. Smith wrote:

On 3/21/2020 11:20 AM, Ned Batchelder wrote:

On 3/20/20 9:34 PM, Cameron Simpson wrote:

On 20Mar2020 13:57, Eric Fahlgren  wrote:
On Fri, Mar 20, 2020 at 11:56 AM Dennis Sweeney 


wrote:

If ``s`` is one these objects, and ``s`` has ``pre`` as a 
prefix, then
``s.cutprefix(pre)`` returns a copy of ``s`` in which that 
prefix has

been removed.  If ``s`` does not have ``pre`` as a prefix, an
unchanged copy of ``s`` is returned.  In summary, 
``s.cutprefix(pre)``
is roughly equivalent to ``s[len(pre):] if s.startswith(pre) 
else s``.




The second sentence above unambiguously states that cutprefix 
returns 'an
unchanged *copy*', but the example contradicts that and shows 
that 'self'

may be returned and not a copy.  I think it should be reworded to
explicitly allow the optimization of returning self.


My versions of these (plain old functions) return self if 
unchanged, and are explicitly documented as doing so.


This has the concrete advantage that one can test for nonremoval 
if the suffix with "is", which is very fast, instead of == which 
may not be.


So one writes (assuming methods):

   prefix = cutsuffix(s, 'abc')
   if prefix is s:
   ... no change
   else:
   ... definitely changed, s != prefix also

I am explicitly in favour of returning self if unchanged.


Why be so prescriptive? The semantics of these functions should be 
about what the resulting string contains.  Leave it to implementors 
to decide when it is OK to return self or not.


The only reason I can think of is to enable the test above: did a 
suffix/prefix removal take place? That seems like a useful thing. I 
think if we don't specify the behavior one way or the other, people 
are going to rely on Cpython's behavior here, consciously or not.


Is there some python implementation that would have a problem with 
the "is" test, if we were being this prescriptive? Honest question.


Of course this would open the question of what to do if the suffix 
is the empty string. But since "'foo'.startswith('')" is True, maybe 
we'd have to return a copy in that case. It would be odd to have 
"s.startswith('')" be true, but "s.cutprefix('') is s" also be True. 
Or, since there's already talk in the PEP about what happens if the 
prefix/suffix is the empty string, and if we adopt the "is" behavior 
we'd add more details there. Like "if the result is the same object 
as self, it means either the suffix is the empty string, or self 
didn't start with the suffix".


Eric

*If* no python implementation would have a problem with the "is" test 
(and from a position of total ignorance I would guess that this is 
the case :-)), then it would be a useful feature and it is easier to 
define it now than try to force conformance later. I have no problem 
with 's.startswith("") == True and s.cutprefix("") is s'.  YMMV.


Why take on that "*If*" conditional?  We're constantly telling people 
not to compare strings with "is".  So why define how "is" will behave 
in this PEP?  It's the implementation's decision whether to return a 
new immutable object with the same value, or the same object.


As Steven points out elsewhere in this thread, Python's builtins' 
behavior differ, across methods and versions, in this regard.  I 
certainly didn't know that, and it was probably news to you as well.  
So why do we need to nail it down for suffixes and prefixes?


There will be no conformance to force later, because if the value 
doesn't change, then it doesn't matter whether it's a new string or 
the same string.


--Ned.

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


[Python-Dev] Re: PEP 616 -- String methods to remove prefixes and suffixes

2020-03-21 Thread Rob Cliffe via Python-Dev



On 21/03/2020 16:15, Eric V. Smith wrote:

On 3/21/2020 11:20 AM, Ned Batchelder wrote:

On 3/20/20 9:34 PM, Cameron Simpson wrote:

On 20Mar2020 13:57, Eric Fahlgren  wrote:
On Fri, Mar 20, 2020 at 11:56 AM Dennis Sweeney 


wrote:

If ``s`` is one these objects, and ``s`` has ``pre`` as a prefix, 
then

``s.cutprefix(pre)`` returns a copy of ``s`` in which that prefix has
been removed.  If ``s`` does not have ``pre`` as a prefix, an
unchanged copy of ``s`` is returned.  In summary, 
``s.cutprefix(pre)``
is roughly equivalent to ``s[len(pre):] if s.startswith(pre) else 
s``.




The second sentence above unambiguously states that cutprefix 
returns 'an
unchanged *copy*', but the example contradicts that and shows that 
'self'

may be returned and not a copy.  I think it should be reworded to
explicitly allow the optimization of returning self.


My versions of these (plain old functions) return self if unchanged, 
and are explicitly documented as doing so.


This has the concrete advantage that one can test for nonremoval if 
the suffix with "is", which is very fast, instead of == which may 
not be.


So one writes (assuming methods):

   prefix = cutsuffix(s, 'abc')
   if prefix is s:
   ... no change
   else:
   ... definitely changed, s != prefix also

I am explicitly in favour of returning self if unchanged.


Why be so prescriptive? The semantics of these functions should be 
about what the resulting string contains.  Leave it to implementors 
to decide when it is OK to return self or not.


The only reason I can think of is to enable the test above: did a 
suffix/prefix removal take place? That seems like a useful thing. I 
think if we don't specify the behavior one way or the other, people 
are going to rely on Cpython's behavior here, consciously or not.


Is there some python implementation that would have a problem with the 
"is" test, if we were being this prescriptive? Honest question.


Of course this would open the question of what to do if the suffix is 
the empty string. But since "'foo'.startswith('')" is True, maybe we'd 
have to return a copy in that case. It would be odd to have 
"s.startswith('')" be true, but "s.cutprefix('') is s" also be True. 
Or, since there's already talk in the PEP about what happens if the 
prefix/suffix is the empty string, and if we adopt the "is" behavior 
we'd add more details there. Like "if the result is the same object as 
self, it means either the suffix is the empty string, or self didn't 
start with the suffix".


Eric

*If* no python implementation would have a problem with the "is" test 
(and from a position of total ignorance I would guess that this is the 
case :-)), then it would be a useful feature and it is easier to define 
it now than try to force conformance later.  I have no problem with 
's.startswith("") == True and s.cutprefix("") is s'.  YMMV.

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


[Python-Dev] Re: PEP 616 -- String methods to remove prefixes and suffixes

2020-03-21 Thread Rob Cliffe via Python-Dev



On 20/03/2020 22:21, Victor Stinner wrote:



Motivating examples from the Python standard library


The examples below demonstrate how the proposed methods can make code
one or more of the following: (...)

IMO there are too many examples. For example, refactor.py and
c_annotations.py are more or less the same. Just keep refactor.py.

Overall, 2 or 3 examples should be enough.


In which case adding something like

`There were many other such examples in the stdlib.`

would make the PEP more compelling.

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


[Python-Dev] Python Profilers documentation - typo?

2019-10-08 Thread Rob Cliffe via Python-Dev

The documentation at
    https://docs.python.org/3.2/library/profile.html
contains the sentence
    For example, if your_integer_time_func() returns times measured in 
thousands of seconds, you would construct the Profile instance as follows:


"thousands of seconds" should ISTM be "thousandths of a second".

There is essentially the same thing in the Python 2 docs at
    https://docs.python.org/2/library/profile.html
viz.
    For example, if the timer returns times measured in _thousands_ of 
seconds, the time unit would be |.001|.


Just trying for perfection!
Best wishes
Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/JNAFSXJS3ZYZHVNFSV53SDZIBHHU7YNU/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: The Python 2 death march

2019-09-25 Thread Rob Cliffe via Python-Dev



On 24/09/2019 04:21:45, Benjamin Peterson wrote:


On Fri, Sep 13, 2019, at 18:18, Sumana Harihareswara wrote:

Hi. I've joined python-dev to participate in this thread (I don't have
email delivery turned on; I'll be checking back via the web).

sorry :)


Benjamin, I am sorry that I didn't check in with you, and assumed that
January 1, 2020 would be the the date of the final 2.7 point release.
(My understanding was based on Guido's EOL announcement from March last
year https://mail.python.org/pipermail/python-dev/2018-March/152348.html
   -- I should have also gotten a review from you and not just the
Steering Council in https://github.com/python/steering-council/issues/14
.) I'm going to continue this discussion here so I can make sure I
understand the policy decision properly, and then (if necessary) update
the FAQ.

Based on what I've read here and what I see in
https://www.python.org/dev/peps/pep-0373/#maintenance-releases , it
sounds like the timeline will go something like:

* 2019-10-19: release of 2.7.17 October
* October, November, and December 2019: developers continue to fix
issues in 2.7
* 2020-01-01: code freeze for 2.7.18 release candidate
* January and February 2020: flexibility to fix any issues introduced
since the 2.7.17 release, but no other bugs or security issues, and no
3.x backports

Security issues will probably be fixed. At least, I wouldn't in abstract find 
that objectionable assuming someone wants to write a patch.


* ~2020-04-02: release candidate for 2.7.18
* 2020-04-17: final 2.7.18 release

I don't know if these will be the exact dates but probably close.


Is this right? (If so, I can submit an update to PEP 373.)

This is a little more complicated than I had anticipated when
communicating out about the sunsetting. But I can find a way either to
concisely communicate this, or to point to a user-friendly explanation
elsewhere.

A succinct statement of the relevant information is: "After 10 years, the core 
developers of CPython are stopping development on the 2.7.x line. The last release will 
be in April 2020." If it's easier to communicate that the sunset of CPython 2 is 
April 2020, that seems fine with me.

January 1 was a somewhat arbitrary date we put in the PEP when 2020 still 
seemed like a long way off but people wanted to know whether 2.7 would be 
released until 2021 or not. I was never going to make a 2.7 release literally 
on January 1. (Fighting with GPG would make short work of New Year's 
resolutions pertaining to temperance and strong language.) I failed to 
anticipate how strongly people would latch onto that exact moment in time as 
the end of Python 2.

I additionally share the bemusement of some other commentators on this thread to the idea of Python 2 
"support", which is not something ever promised to Python 2 (or 3) users by CPython core developers. 
Essentially, next year, we're changing our "support" policy of Python 2.7 from "none, but we're nice 
people" to "none".
I understand, but I hope that if a clear bug (perhaps especially a 
security bug) is found in Python 2.7 (perhaps one that is also in Python 
3.x) the core devs will not be in principle opposed to fixing it.  At 
least if one of them (or someone else sufficiently qualified) is 
prepared to do the work.  Especially as you're "essentially" (and you 
ARE :-) -:) ) "such nice people".

Best wishes
Rob Cliffe



Thanks.

--
Sumana Harihareswara
Changeset Consulting
https://changeset.nyc
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/python-dev@python.org/message/MXCGMTXDY7BX6JBBU36O5YFRWWBB3NQE/


___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/ETOBPFVKKS5ZBIUAYLOBXFXPOZB7A357/

---
This email has been checked for viruses by AVG.
https://www.avg.com



___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/KQU7AQ5FZSOX5Z2HMX7LELJYUZTKMFXO/


[Python-Dev] Re: PEP 601: discussion-to discuss.python.org

2019-09-07 Thread Rob Cliffe via Python-Dev




On 04/09/2019 14:53:41, Victor Stinner wrote:

A litte bit more context.

PEP 601: "Forbid return/break/continue breaking out of finally"
https://www.python.org/dev/peps/pep-0601/

Abstract

This PEP proposes to forbid return, break and continue statements
within a finally suite where they would break out of the finally.
Their use in such a location silently cancels any active exception
being raised through the finally, leading to unclear code and possible
bugs.

Continue is currently not supported in a finally in Python 3.7 (due to
implementation issues) and the proposal is to not add support for it
in Python 3.8. For return and break the proposal is to deprecate their
use in Python 3.9, emit a compilation warning in Python 3.10 and then
forbid their use after that.

Victor
I can't make sense of this sentence in the PEP, I suspect there is a 
typo in it:


"Since this is the removal of a feature teaching users will be one by 
the raising of a SyntaxError if/when the forbidden feature is used."


Rob Cliffe

___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/LVGOPXZ57XU3E5CAZDPLX47ETPIIDOZ3/

---
This email has been checked for viruses by AVG.
https://www.avg.com



___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/KNYY4D6NL2DAG5ZGNDH3HPXQLSLGXLBT/


[Python-Dev] Re: What to do about invalid escape sequences

2019-08-15 Thread Rob Cliffe via Python-Dev



On 15/08/2019 12:17:36, Petr Viktorin wrote:

On 8/15/19 10:40 AM, Greg Ewing wrote:

If we want a truly raw string format that allows all characters,
including any kind of quote, we could take a tip from Fortran:

 s = 31HThis is a "totally raw" string!


Or from Rust:

let s = r"Here's a raw string";
let s = r#"Here's a raw string with "quotes" in it"#;
let s = r##"Here's r#"the raw string syntax"# in raw string"##;
let s = r###"and here's a '##"' as well"###;
___
I rather like the idea!  (Even though it would add to the proliferation 
of string types.)
Obviously Python can't use # as the special character since that 
introduces a comment,
and a lot of other possibilities are excluded because they would lead to 
ambiguous syntax.
Say for the sake of argument we used "!" (exclamation mark). Possible 
variations include:

(1) Like Rust:
    s = r"Here's a raw string";
    s = r!"Here's a raw string with "quotes" in it"!;
    s = r!!"Here's r!"the raw string syntax"! in raw string"!!;
    s = r!!!"and here's a '!!"' as well"!!!;
(2) Same, but omit the leading 'r' when using !:
    s = r"Here's a raw string";
    s = !"Here's a raw string with "quotes" in it"!;
    s = !!"Here's a raw string with "quotes" and !exclamation marks! in 
it"!!;

    s = !!!"and here's a '!!"' as well"!!!;
    # Cons: Would conflict with adding ! as an operator (or at minimum, 
as a unary operator) for some other purpose in future.

    #    Makes it less obvious that a !string! is a raw string.
(3) Allow the user to specify his own delimiting character:
    s = r!|This raw string can't contain a "bar".|
(4) As above, but the "!" is not required:
    s = r|This raw string can't contain a "bar".|
    # In this case the delimiter ought not to be a letter
    # (it might conflict with current or future string prefixes);
    # this could be forbidden.
(5) Similar, but allow the user to specify his own delimiting *string* 
(specified between "!"s) (as long as it doesn't contain !):

    let s = r!?@!Could this string could contain almost anything? Yes!?@
    # The text in this string is:
    #    Could this string could contain almost 
anything?  Yes!
(6) Same except the first "!" is not required.  In this case the first 
character of the delimiting string should not be a letter:

    let s = r?@!Could this string could contain almost anything? Yes!?@
    # The text in this string is:
    #       Could this string could contain almost 
anything?  Yes!


I can dream ...

A point about the current syntax: It is not true that a raw string can't 
end in a backslash,
as https://en.wikipedia.org/wiki/String_literal points out.  It can't 
end in an *odd number*
of backslashes.  42 is fine, 43 is no good.  Which makes it seem even 
more of a language wart

(think of program-generated art).

Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/AZVQBRODB64WAP22J4VSVOBAIEKLUMB5/


[Python-Dev] Re: What to do about invalid escape sequences

2019-08-10 Thread Rob Cliffe via Python-Dev



On 10/08/2019 23:30:18, Greg Ewing wrote:

Rob Cliffe via Python-Dev wrote:


Also, the former is simply more *informative* - it tells the reader 
that baz is expected to be a directory, not a file.


On Windows you can usually tell that from the fact that filenames
almost always have an extension, and directory names almost never
do.

Usually, but not always.  I have not infrequently used files with a 
blank extension.
I can't recall using a directory name with an extension (but I can't 
swear that I never have).

Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/2LDAY5FU64X5HH3GUVGAQNHRSWEB/


[Python-Dev] Re: What to do about invalid escape sequences

2019-08-10 Thread Rob Cliffe via Python-Dev



On 10/08/2019 11:50:35, eryk sun wrote:

On 8/9/19, Steven D'Aprano  wrote:

I'm also curious why the string needs to *end* with a backslash. Both of
these are the same path:

 C:\foo\bar\baz\
 C:\foo\bar\baz
Also, the former is simply more *informative* - it tells the reader that 
baz is expected to be a directory, not a file.

Rob Cliffe

The above two cases are equivalent. But that's not the case for the
root directory. Unlike Unix, filesystem namespaces are implemented
directly on devices. For example, "//./C:" might resolve to a volume
device such as "\\Device\\HarddiskVolume2". With a trailing slash
added, "//./C:/" resolves to "\\Device\\HarddiskVolume2\\", which is
the root directory of the mounted filesystem on the volume.

Also, as a classic DOS path, "C:" without a trailing slash expands to
the working directory on drive "C:". The system runtime library looks
for this path in a hidden environment variable named "=C:". The
Windows API never sets these hidden "=X:" drive variables. The C
runtime sets them, as does Python's os.chdir.

Some volume-management functions require a trailing slash or
backslash, such as GetVolumeInformationW [1].
GetVolumeNameForVolumeMountPointW [2] actually requires it to be a
trailing backslash. It will not accept a trailing forward slash such
as "C:\\Mount\\Volume/" (a bug since Windows 2000). The volume name
(e.g. "?\\Volume{----}\\")
returned by the latter includes a trailing backslash, which must be
present in the target path in order for a mountpoint to function
properly as a directory, else it would resolve to the volume device
instead of the root directory.

[1] 
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationw
[2] 
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumenameforvolumemountpointw


If they're Windows developers, they ought to be aware that the Windows
file system API allows / anywhere you can use \ and it is the
common convention in Python to use forward slashes.

The Windows file API actually does not allow slash to be used anywhere
that we can use backslash. It's usually allowed, but not always. For
the most part, the conditions where forward slash is not supported are
intentional.

Windows replaces forward slash with backslash in normal DOS paths and
normal device paths. But sometimes we have to use a special form of
device path that bypasses normalization. A path that isn't normalized
can only use backslash as the path separator. For example, the most
common case is that the process doesn't have long paths enabled. In
this case we're limited to MAX_PATH, which limits file paths to a
paltry 259 characters (sans the terminating null); the current
directory to 258 characters (sans a trailing backslash and null); and
the path of a new directory to 247 characters (subtract 12 from 259 to
leave space for an 8.3 filename). By skipping DOS normalization, we
can access a path with up to about 32,750 characters (i.e. 32,767 sans
the length of the device name in the final NT path under
"\\Device\\").

(Long normalized paths are available starting in Windows 10, but the
system policy that allows this is disabled by default, and even if
enabled, each application has to declare itself to be long-path aware
in its manifest. This is declared for python[w].exe in Python 3.6+.)

A device path is an explicit reference to a user's local device
directory (in the object namespace), which shadows the global device
directory. In NT, this directory is aliased to a special "\\??\\"
prefix (backslash only). A local device directory is created for each
logon session (not terminal session) by the security system that runs
in terminal session 0 (i.e. the system services session). The
per-logon directory is located at "\\Sessions\\0\\DosDevices\\". In the Windows API, it's accessible as "//?/" or "//./",
or with any mix of forward slashes or backslashes, but only the
all-backslash form is special-cased to bypass the normalization step.
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/3SDFM2EKFO3UNTATS7KVBY2WOUTFMAF5/

---
This email has been checked for viruses by AVG.
https://www.avg.com




___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/IVNUAUUHURCS4P77ZVFFK3H665ZKXGBC/


[Python-Dev] Re: What to do about invalid escape sequences

2019-08-10 Thread Rob Cliffe via Python-Dev



On 06/08/2019 23:41:25, Greg Ewing wrote:

Rob Cliffe via Python-Dev wrote:


Sorry, that won't work.  Strings are parsed at compile time, open() 
is executed at run-time.


It could check for control characters, which are probably the result
of a backslash accident. Maybe even auto-correct them...


By "It", do you mean open() ?  If so:
It already checks for control characters, at least with Python 2.7 on 
Windows:


>>> open('mydir\test')
Traceback (most recent call last):
  File "", line 1, in 
IOError: [Errno 22] invalid mode ('r') or filename: 'mydir\test'

As for auto-correct (presumably "\a" to "\\a", "\b" to "\\b" etc.), I 
hope you're not serious.
"In the face of gibberish, refuse the temptation to show how smart your 
guessing is."

___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/UK46EASIZVFTIQPORH7AG3EFB522NFI3/


[Python-Dev] Re: PEP 572 TargetScopeError

2019-08-09 Thread Rob Cliffe via Python-Dev



On 09/08/2019 12:50:14, Steven D'Aprano wrote:

On Thu, Aug 08, 2019 at 04:28:28PM -0700, Barry Warsaw wrote:
I find it difficult to imagine a more meaningful distinction than that
between syntax and semantics.

The distinction between syntax and semantics can sometimes be blurred.
Certainly in spoken languages.  What about program code?


Should x/0 be a SyntaxError? It too is "disallowed", and we have to
change our code.
No, because x might be an instance of a class (extended numbers?) that 
allows division by zero.


Should None[x] be a SyntaxError? It too is "disallowed", and we have to
change our code.


It's allowable syntax with defined runtime semantics: raise a TypeError 
if x exists,
and a NameError if it isn't.  Conceivably some programmer might find a 
use for it.
But since it always raises an exception, it would probably be more 
helpful in the long
run if it *were* a SyntaxError.  It *isn't*, because (I assume) 
detecting this and similar

idioms, e.g.    {}[0]   , would complicate the parser/compiler too much.

Your examples show, I claim, that even in program code the distinction 
between

syntax and semantics is not always obvious.

I suggest the only watertight definition of a syntax error is something 
which raises
an exception at compile time.  Obviously this can depend not only on the 
code,

but also on the compiler.

Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/FKZSJS2JZ3DXENYOI3AFPGDH3TOH5C5U/


[Python-Dev] Re: PEP 572 TargetScopeError

2019-08-08 Thread Rob Cliffe via Python-Dev



On 08/08/2019 22:58:15, Steven D'Aprano wrote:

On Thu, Aug 08, 2019 at 10:00:01AM -0700, Barry Warsaw wrote:


"The two invalid cases listed above raise TargetScopeError, a new
subclass of SyntaxError (with the same signature).”

The PEP doesn’t really go into the rationale for why a new exception
is being defined, and in the issue I’ve argued that we should just
raise SyntaxError in those cases.  To me, “TargetScopeError” is pretty
obscure and doesn’t give users an obvious clue as to what’s going
wrong, without searching the interwebs.

It's not a syntax error. There's nothing wrong with the syntax per-say:
we still have ``target := expression``. There's a problem with the
*semantics* not the syntax.

The name is perfectly self-descriptive: TargetScopeError means that
there's an error with the scope of the target. What else could it mean?
That's easy for an experienced programmer to say.  IMHO it's about as 
helpful to a
newbie as saying GrobKunkError means that there's an error with the kunk 
of the grob.


I think AmbiguousScopeError is somewhat better than TargetScopeError,
but perhaps someone will think of something even better.
(ScopeConflictError?  InvalidVariableReuse?  I dunno.)

What's wrong with having to look up an unfamiliar exception by searching
the interwebs? The first few times I hit KeyError, I had no idea what a
"key" was (I was a beginner) and if I had internet access, I would have
looked it up on the web. I didn't, so I looked it up in the book I was
reading.

The first times I hit UnboundLocalError, I did have internet access, so
I googled it. Once I understood that it meant that the local I was
trying to use was unbound, and that "unbound" mean "undefined", all was
clear.

(Well, not all, I still had to work out why it was undefined. But at
least the exception name was more clear.)
Sure, people should be encouraged to look things up on the web (if they 
haven't

already acquired the habit).  But that doesn't mean we shouldn't make things
as clear as reasonably possible in the first place.


One of the frustrations I have is that it's near to impossible to
programmatically distinguish wrong number of arguments from bad keyword
arguments from providing the wrong type of argument without relying on
the error message. (And yes, I have needed to do this.) All of these
raise the same TypeError, even though only one of them is an actual
error with the type:

 len(1)  # An actual TypeError

 len([], None)  # The type of the argument is fine.

 len(spam=[])   # The type of the argument is fine.

Please let's not use SyntaxError for something that's not an error
with the syntax.
(For reference the error messages are, depending a bit on the Python 
version, respectively

    object of type 'int' has no len()
    len() takes exactly one argument (2 given)
    len() takes no keyword arguments .
.)
I'm mildly curious as to why you couldn't rely on the error message, but 
I'm sure you had a good reason.
FWIW IMHO the last two ought to produce an exception called 
ArgumentError or ParameterError or some such
or even more specific names such as TooManyArguments and 
KeywordArgumentsDisallowed.
I guess I'm agreeing with you to the extent that I'm proposing more 
(specific) exceptions.

Rob Cliffe





___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/GEOWJTBNMTE6KWCVR5AJTQNSWIRALXOD/


[Python-Dev] Re: What to do about invalid escape sequences

2019-08-06 Thread Rob Cliffe via Python-Dev



On 07/08/2019 01:14:08, Chris Angelico wrote:

On Wed, Aug 7, 2019 at 10:03 AM Steven D'Aprano  wrote:

- Keep the SyntaxWarning silent by default for 3.8. That gives us
another year or more to gently pressure third-party libraries to fix
their code, and to find ways to encourage developers to run with
warnings enabled.

How do you propose to apply this pressure?

How about: whenever a third-party library uses a potentially-wrong
escape sequence, it creates a message on the console. Then when
someone sees that message, they can post a bug report against the
package.

In other words, a non-silent warning.

ChrisA
___


The interpreter knows which module contains the questionable string.
So: is it feasible for the warning message to include something like
"...  If you are not the maintainer of xxxmodule.py, please contact 
them, or post a bug report on ..."

___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/JJULDRHOTETV2LDLJE6RWKZ6HCCPHTUP/


[Python-Dev] Re: What to do about invalid escape sequences

2019-08-06 Thread Rob Cliffe via Python-Dev



On 06/08/2019 07:14:35, Michael wrote:


For "filenames" you could, perhaps, make an exception in the calls that
use them. e.g., when they are hard-coded in something such as
open("..\training\new_memo.doc").

Sorry, that won't work.  Strings are parsed at compile time, open() is 
executed at run-time.

And the use of open might be masked by using a synonym for it;
open might be shadowed by the program assigning to it;
the argument to open() might be an expression such as 
("..training\new_memo" + extn)    etc., etc.

Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/5G2JKQKSLAA5CQRUHCN7JFKY2KPIGYYX/


[Python-Dev] Re: Comparing dict.values()

2019-07-24 Thread Rob Cliffe via Python-Dev
I considered an alternative: return True if the underlying dicts were 
identical or equal, and raise an Exception otherwise.
But I soon decided that this was a terrible idea: it could hide a bug by 
making faulty code work intermittently.
Apologies for doubtless belabouring the blindingly obvious (but then 
again, if I don't mention this possibility, maybe someone even more 
idiotic than me will suggest it ).


On 25/07/2019 00:49:56, Rob Cliffe via Python-Dev wrote:



On 25/07/2019 00:09:37, David Mertz wrote:

I agree with Greg.

There are various possible behaviors that might make sense, but 
having `d.values() != d.values()` is about the only one I can see no 
sense in.

+1


This really feels like a good cade for reading a descriptive 
exception. If someone wants too compare `set(d.values())` that's 
great. If they want `list(d.values())`, also a sensible question. But 
the programmer should spell it explicitly.



So, a helpful error message including something like "Cannot compare 
dict.values directly, consider converting to sets / lists / sorted 
lists before comparing" ?

___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/CSTSLCDEJYKDLADQV5PJRCSSVTMB5RIG/


---
This email has been checked for viruses by AVG.
https://www.avg.com



___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/5K4EP5AKR5XPGJ5657RCHRTS6QVSJVWE/


[Python-Dev] Re: Comparing dict.values()

2019-07-24 Thread Rob Cliffe via Python-Dev




On 25/07/2019 00:09:37, David Mertz wrote:

I agree with Greg.

There are various possible behaviors that might make sense, but having 
`d.values() != d.values()` is about the only one I can see no sense in.

+1


This really feels like a good cade for reading a descriptive 
exception. If someone wants too compare `set(d.values())` that's 
great. If they want `list(d.values())`, also a sensible question. But 
the programmer should spell it explicitly.



So, a helpful error message including something like "Cannot compare 
dict.values directly, consider converting to sets / lists / sorted lists 
before comparing" ?

___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/CSTSLCDEJYKDLADQV5PJRCSSVTMB5RIG/


[Python-Dev] Re: Comparing dict.values()

2019-07-24 Thread Rob Cliffe via Python-Dev




On 24/07/2019 10:31:46, Steven D'Aprano wrote:


How does this seem to you? Two dict.values objects are equal if:

- they are in fact the same object (identity test on the views);

- they are both views of the same dict (identity test on the dicts);

- they are views of distinct, but equal, dicts;

Naive question: Is there a way (in Python) to get at the underlying dict 
from a dict.values object,

or more generally from any dict view object?

>>> dir({}.values())
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', 
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '
__init__', '__init_subclass__', '__iter__', '__le__', '__len__', 
'__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '

__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

Rob Cliffe
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/NZDVGFXMTUDW5ZSTAAMWFDLUEFLWGEGG/


Re: [Python-Dev] Overloading comparison operator for lists

2019-05-28 Thread Rob Cliffe via Python-Dev



On 27/05/2019 04:52:17, Montana Burr wrote:
NumPy arrays have this awesome feature, where array == 3 does an 
element-wise comparison and returns a list. For example:


np.array([1,2,3,4,5])==3

returns

[False,False,True,False,False]

It would be cool if Python had similar functionality for lists.


Well, it does have:
>>>  [x==3 for x in [1,2,3,4,5]]
[False, False, True, False, False]

This is IMHO much more intuitive than your construct overloading "==".
It is also more flexible (any operation can be performed on x, not just 
an equality comparison).
So sorry, but I can see no justification for changing the Python 
language to do something, which can already be done, to be done in a 
more obscure way.

Also
    [1,2,3,4,5]==3
is already legal syntax (it evaluates to False, since the operands are 
not equal), so you are proposing a code-breaking change.


Apologies if someone has already pointed all this out, as is very likely 
(I have only just (re-)joined python-ideas and may have missed the 
relevant posts).

Best wishes
Rob Cliffe
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] datetime.timedelta total_microseconds

2019-02-15 Thread Rob Cliffe via Python-Dev
A function with "microseconds" in the name IMO misleadingly suggests 
that it has something closer to microsecond accuracy than a 1-second 
granularity.

Rob Cliffe

On 14/02/2019 05:05:54, Richard Belleville via Python-Dev wrote:
In a recent code review, the following snippet was called out as 
reinventing the

wheel:

_MICROSECONDS_PER_SECOND = 100


def _timedelta_to_microseconds(delta):
  return int(delta.total_seconds() * _MICROSECONDS_PER_SECOND)


The reviewer thought that there must already exist a standard library 
function
that fulfills this functionality. After we had both satisfied 
ourselves that we
hadn't simply missed something in the documentation, we decided that 
we had

better raise the issue with a wider audience.

Does this functionality already exist within the standard library? If 
not, would
a datetime.timedelta.total_microseconds function be a reasonable 
addition? I

would be happy to submit a patch for such a thing.

Richard Belleville

 
	Virus-free. www.avg.com 
 



<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/rob.cliffe%40btinternet.com


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 572: Assignment Expressions -- intention to accept, near-final draft

2018-07-09 Thread Rob Cliffe via Python-Dev
I apologise for not replying in the form of a Pull Request - I don't 
know how to make one.



On 10/07/2018 02:00, Guido van Rossum wrote:

Rationale
=

Naming the result of an expression is an important part of programming,
allowing a descriptive name to be used in place of a longer expression,
and permitting reuse.  Currently, this feature is available only in
statement form, making it unavailable in list comprehensions and other
expression contexts.
I think the wording of the last sentence gives too much importance to 
list comprehensions (IMO influenced by the amount of discussion of the 
PEP that was related to list comprehensions, understandably since that 
was the case where the semantics were most debatable).  I would suggest

"... making it unavailable in expression contexts."
or maybe
"... making it unavailable in expression contexts (including list 
comprehension)."



Another example illustrates that programmers sometimes do more work to
save an extra level of indentation::

    match1 = pattern1.match(data)
    match2 = pattern2.match(data)
    if match1:
    return match1.group(1)
    elif match2:
    return match2.group(2)

This code tries to match ``pattern2`` even if ``pattern1`` has a match
(in which case the match on ``pattern2`` is never used). The more
efficient rewrite would have been::

    match1 = pattern1.match(data)
    if match1:
    return match1.group(1)
    else:
    match2 = pattern2.match(data)
    if match2:
    return match2.group(2)

I suggest
... The more efficient rewrite would have been:
    match1 = pattern1.match(data)
    if match1:
    return match1.group(1)
    match2 = pattern2.match(data)
    if match2:
    return match2.group(2)
(a more natural way to write it which avoids cascading indentation).


    # Handle a matched regex
    if (match := pattern.search(data)) is not None:
    ...

I suggest
    # Handle a matched regex
    if (match := pattern.search(data)) is not None:
    # do something with match
I think it is really important to make clear the benefit of the PEP 
here: that "match" is bound to a value and can be used subsequently.



    # A more explicit alternative to the 2-arg form of iter() invocation
    while (value := read_next_item()) is not None:
    ...
As the 2-arg form of iter() is not that well known, I suggest that the 
iter version is spelled out for contrast.  (Sorry, I can't quite work it 
what it would be.)


    # Share a subexpression between a comprehension filter clause and 
its output

    filtered_data = [y for x in data if (y := f(x)) is not None]
That's fine, but what about also having an example that illustrates, 
simply, the "permitting reuse" in an expression part of the Rationale, e.g.

        powers = [ (y := x+1), y**2, y**3, y**4 ]
(I appreciate that this sort of overlaps with the section "Simplifying 
list comprehensions", but it seems to me to be such an important part of 
the Rationale that it should be illustrated here.)



Relative precedence of ``:=``
-

The ``:=`` operator groups more tightly than a comma in all syntactic
positions where it is legal, but less tightly than all operators,
including ``or``, ``and`` and ``not``.

and presumably including "if" and "else", as in
    x := y if y else -1
Might it be worth adding "if" and "else" to the list?



- Single assignment targets other than than a single ``NAME`` are
  not supported::

    # No equivalent
    a[i] = x
    self.rest = []

[snip]

- Iterable packing and unpacking (both regular or extended forms) are
  not supported::

    # Equivalent needs extra parentheses
    loc = x, y  # Use (loc := (x, y))
    info = name, phone, *rest  # Use (info := (name, phone, *rest))

    # No equivalent
    px, py, pz = position
    name, phone, email, *other_info = contact

[snip]
    total += tax  # Equivalent: (total := total + tax)
Is it conceivable that some of these restrictions might be removed in a 
future version of Python?  If so, the PEP might include a note to this 
effect.


Oh, and what I think are typos:

(Note that ``with EXPR as VAR`` does *not* simply assing the value
   of ``EXPR`` to ``VAR`` -- it calls ``EXPR.__enter__()`` and assigns
   the result of *that* to ``VAR``.)

    assing -> assign

(eg where the condition is ``f(x) < 0``

    eg -> e.g.

members of the core-mentorship mailing list

    core-mentorship -> core mentorship

is a vast improvment over the briefer::

    improvment -> improvement

Best wishes
Rob Cliffe


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Assignment expression and coding style: the while True case

2018-07-04 Thread Rob Cliffe via Python-Dev



On 05/07/2018 00:15, Nathaniel Smith wrote:

On Wed, Jul 4, 2018 at 3:51 PM, Victor Stinner  wrote:

My question is now: for which "while True" patterns are the assignment
expression appropriate? There identified different patterns.


== Pattern 1, straighforward ==

while True:
 line = input.readline()
 if not line:
 break
 ...

IMHO here assingment expression is appropriate here. The code remains
straighfoward to read.

while (line := input.readline()):
 ...

There are some obvious caveats here – no-one has real experience with
:= yet, so any opinions right now are informed guesswork that will
probably change some if/when we get more experience with it.

Of course, this is absolutely true.  But ...

  Also, the
stdlib is a big place, and it seems inevitable that maintainers of
different modules will have different preferences. So I don't think it
makes sense to try to define some Official Universal Rule about when
:= is appropriate and when it isn't.

That said, FWIW, my current feeling is that this simplest case is the
only one where I would use :=; for your other examples I'd stick with
the loop-and-a-half style.
... even you, Nathaniel (correct me if I'm wrong, but you seem to be 
generally against PEP 572) would use := in (at least) one case.
I predict:  We'll all end up loving Assignment Expressions (like 
f-strings) once we've got used to them.  Or just taking them for 
granted.  No doubt some of us will use them more than others, some 
perhaps not at all.

Regards
Rob Cliffe

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Assignment expression and coding style: the while True case

2018-07-04 Thread Rob Cliffe via Python-Dev



On 05/07/2018 01:25, Tim Peters wrote:


== Pattern 5, two variables ==

while True:
    m = match()
    if not m:
        break
    j = m.end()
    if i == j:
        break
    ...

replaced with:

while (m := match()) and (j := m.end()) == i:


I assume (sorry to be pedantic :-)) this is a typo for
        while (m := match()) and (j := m.end()) != i:


    ...

Maybe we reached here the maximum acceptable complexity of a single
Python line? :-)


It's at my limit.  But, as in an earlier example, I'd be tempted to do 
"the obvious part":


    while m:= match():
        j = m.end()
        if i == j::
            break

Then the start reads like "while there's something _to_ look at::" and 
the body of the loop is happily guaranteed that there is.


.
Or you could compromise with this "intermediate density" version that 
does two "obvious parts":


    while m:=match():
        if  (j:=m.end()) == i:
            break

(or as I might write it

    while m:=match():
        if  (j:=m.end()) == i:  break

).
Some might prefer this as shorter than non-AE version but less dense 
than the one-liner.  Others might not. /De gustibus non est disputandum./
My conclusion:  Assignment expressions are - like any other Python 
feature - a tool, to be used with discretion and judgement.  Not the 
start of a competition to see who can write the most slick/unreadable code.

Regards
Rob Cliffe
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Examples for PEP 572

2018-07-04 Thread Rob Cliffe via Python-Dev



On 04/07/2018 02:54, Terry Reedy wrote:


The 2-argument form of iter is under-remembered and under-used. The 
length difference is 8.

    while (command := input("> ")) != "quit":
    for command in iter(lambda: input("> "), "quit"):
A general principle that Chris Angelico has repeatedly mention applies 
here:  If you want (as I instinctively would)

    while (command := input("> ")).lower() != "quit":
you can't express that in your iter version.
Regards
Rob Cliffe
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part)

2018-07-03 Thread Rob Cliffe via Python-Dev

On 03/07/2018 06:47, Tim Peters wrote:

[Rob Cliffe]
> It's late to raise this,

By months, yes ;-)

> but what exactly are the objections to the syntax
>         expr -> name  # or variations such as  expr => name
> instead of
>         name := expr

>
> The PEP mentions that this syntax does not have a problem that "as"
> does, but does not list any downsides of it.

My guess:  it probably strikes too many as "excessive novelty",  
 These are assignment expressions.  Python's assignment statements put 
the target at the left.  Why change that?  ":=" is used for assignment 
in many more other languages than "->" is.  Why fight that?


> It conforms to left-to-right evaluation, where name:=expr does not.

?  Only "expr" is evaluated, so left-to-right seems irrelevant here.  
The "evaluation" of a simple name as a binding target is a no-op (no 
code is generated).  If you really do see this as a wart anyway, then 
it's positively a Good Thing that it's exactly the same "wart" as in 
Python's assignment statements.


> It (I would argue) reduces the asymmetry of the first use of a
> sub-expression in cases such as
>     [ ( (f(x) -> y)**2, y**3, y**4) for x in iterable ]
>  vs
>     [ ( (y := f(x))**2, y**3, y**4) for x in iterable ]
> because the first "y" is closer to the way it is used, viz "**2".

The first form reads a little better to me too, but not a lot better.  
The problem I have with variations of this example on its own (which 
comes up surprisingly often with minor changes) is that it's clearer 
spelled today via


    [(y**2, y**3, y**4) for y in map(f, iterable)]

Spelling that with either form of assignment expression reads 
significantly worse than that to my eyes


But more importantly, it's expected that assignment expressions will 
be used _most_ often to make some common `if` and `while` patterns 
briefer.  Hardly all. Our eyes are already trained to "look at the far 
right end" for the value being tested, and, e.g.,


    while data := sock.recv():

preserves that.  Especially in code that doesn't _always_ use 
assignment expressions in such contexts (which is likely all 
significant blobs of code), it would be visually jarring to have to 
"sometimes look in the middle instead" to extract the important part of:


    while sockrecv() -> data:

"Look to the left for the name, look to the right for the value" is 
the rule for assignment statements, assignment expressions, and `for` 
loop targets.


But there's no "QED" here because this isn't a deductive science.  The 
final answer is "because that's what Guido liked best" ;-)

Thanks, Tim, for a thoughtful answer.
Don't get me wrong, I feel quite happy with ":=".  Perhaps you have 
managed to articulate some thoughts that were buried in my 
subconscious.  It's just that I couldn't come up with any rational 
objections to "->".

Rob Cliffe



 
	Virus-free. www.avg.com 
 



<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part)

2018-07-02 Thread Rob Cliffe via Python-Dev



On 02/07/2018 19:19, Guido van Rossum wrote:
Thank you all. I will accept the PEP as is. I am happy to accept 
*clarification* updates to the PEP if people care to submit them as 
PRs to the peps repo (https://github.com/python/peps), and that could 
even (to some extent) include summaries of discussion we've had, or 
outright rejected ideas. But even without any of those I think the PEP 
is very clear so I will not wait very long (maybe a week).



It's late to raise this, but what exactly are the objections to the syntax
        expr -> name  # or variations such as  expr => name
instead of
        name := expr

The PEP mentions that this syntax does not have a problem that "as" 
does, but does not list any downsides of it.

It conforms to left-to-right evaluation, where name:=expr does not.
It (I would argue) reduces the asymmetry of the first use of a 
sub-expression in cases such as

    [ ( (f(x) -> y)**2, y**3, y**4) for x in iterable ]
vs
    [ ( (y := f(x))**2, y**3, y**4) for x in iterable ]
because the first "y" is closer to the way it is used, viz "**2".

Regards
Rob Cliffe
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python3 compiled listcomp can't see local var - bug or feature?

2018-06-12 Thread Rob Cliffe via Python-Dev

Ah yes, I see what you mean:

class Test():
   x = 1
   print (x) # Prints 1
   print([x+i for i in range(1,3)])  # NameError (x)

Anyway, I  apologise for posting to Python-Dev on was a known issue, and 
turned out to be more me asking for help with development with Python, 
rather than development of Python.  (My original use case was a 
scripting language that could contain embedded Python code).  Thanks to 
Nick for his original answer.


Rob Cliffe


On 11/06/2018 23:31, Eric Fahlgren wrote:
On Mon, Jun 11, 2018 at 3:10 PM Rob Cliffe via Python-Dev 
mailto:python-dev@python.org>> wrote:


Skip, I think you have misunderstood the  point I was making.  It was
not whether the loop variable should leak out of a list
comprehension.
Rather, it was whether a local variable should, so to speak, "leak
into"
a list comprehension.  And the answer is: it depends on whether
the code
is executed normally, or via exec/eval.  Example:

def Test():
       x = 1
       print([x+i for i in range(1,3)])          # Prints [2,3]
   exec('print([x+i for i in range(1,3)])') # Raises NameError (x)
Test()

I (at least at first) found the difference in behaviour surprising.


​Change 'def' to 'class' and run it again.  You'll be even more 
surprised.​


<http://www.avg.com/email-signature?utm_medium=email_source=link_campaign=sig-email_content=emailclient> 
	Virus-free. www.avg.com 
<http://www.avg.com/email-signature?utm_medium=email_source=link_campaign=sig-email_content=emailclient> 



<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python3 compiled listcomp can't see local var - bug or feature?

2018-06-11 Thread Rob Cliffe via Python-Dev
Skip, I think you have misunderstood the  point I was making.  It was 
not whether the loop variable should leak out of a list comprehension.  
Rather, it was whether a local variable should, so to speak, "leak into" 
a list comprehension.  And the answer is: it depends on whether the code 
is executed normally, or via exec/eval.  Example:


def Test():
      x = 1
      print([x+i for i in range(1,3)])          # Prints [2,3]
  exec('print([x+i for i in range(1,3)])') # Raises NameError (x)
Test()

I (at least at first) found the difference in behaviour surprising.

Regards

Rob Cliffe


On 08/06/2018 19:27, Skip Montanaro wrote:

Is this a bug or a feature?

The bug was me being so excited about the new construct (I pushed in
someone else's work, can't recall who now, maybe Fredrik Lundh?) that
I didn't consider that leaking the loop variable out of the list
comprehension was a bad idea. Think of the Py3 behavior as one of
those "corrections" to things which were "got wrong" in Python 1 or 2.
:-)

Skip

---
This email has been checked for viruses by AVG.
http://www.avg.com




___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Python3 compiled listcomp can't see local var - bug or feature?

2018-06-05 Thread Rob Cliffe via Python-Dev

Is this a bug or a feature?
Consider the following program:

# TestProgram.py
def Test():
  # global x
    x = 1
    exec(compile('print([x+1,x+2])', 'MyTest', 'exec'))
    exec(compile('print([x+i for i in range(1,3)])', 'MyTest', 'exec'))
Test()

In Python 2.7.15 the output is

[2, 3]
[2, 3]

In Python 3.6.5 the output is
[2, 3]
Traceback (most recent call last):
  File "TestProgram.py", line 7, in 
    Test()
  File "TestProgram.py", line 6, in Test
    exec(compile('print([x+i for i in range(1,3)])', 'MyTest', 'exec'))
  File "MyTest", line 1, in 
  File "MyTest", line 1, in 
NameError: name 'x' is not defined

If the "global x" declaration is uncommented, this "fixes" the Python 
3.6.5 behaviour,

i.e. no error occurs and the output is the same as for Python 2.7.15.

*In other words, it looks as if in Python 3.6.5, the compiled list 
comprehension**

**can "see" a pre-existing global variable but not a local one.*

I have used dis to examine the code objects returned by compile()
(they are the same with or without the "global x"):

Python 2.7.15 first code object from 'print([x+1,x+2])':
  1   0 LOAD_NAME    0 (x)
  3 LOAD_CONST   0 (1)
  6 BINARY_ADD
  7 LOAD_NAME    0 (x)
 10 LOAD_CONST   1 (2)
 13 BINARY_ADD
 14 BUILD_LIST   2
 17 PRINT_ITEM
 18 PRINT_NEWLINE
 19 LOAD_CONST   2 (None)
 22 RETURN_VALUE
Python 2.7.15 second code object from 'print([x+i for i in range(1,3)])':
  1   0 BUILD_LIST   0
  3 LOAD_NAME    0 (range)
  6 LOAD_CONST   0 (1)
  9 LOAD_CONST   1 (3)
 12 CALL_FUNCTION    2
 15 GET_ITER
    >>   16 FOR_ITER    16 (to 35)
 19 STORE_NAME   1 (i)
 22 LOAD_NAME    2 (x)
 25 LOAD_NAME    1 (i)
 28 BINARY_ADD
 29 LIST_APPEND  2
 32 JUMP_ABSOLUTE   16
    >>   35 PRINT_ITEM
 36 PRINT_NEWLINE
 37 LOAD_CONST   2 (None)
 40 RETURN_VALUE
Python 3.6.5 first code object from 'print([x+1,x+2])':
  1   0 LOAD_NAME    0 (print)
  2 LOAD_NAME    1 (x)
  4 LOAD_CONST   0 (1)
  6 BINARY_ADD
  8 LOAD_NAME    1 (x)
 10 LOAD_CONST   1 (2)
 12 BINARY_ADD
 14 BUILD_LIST   2
 16 CALL_FUNCTION    1
 18 POP_TOP
 20 LOAD_CONST   2 (None)
 22 RETURN_VALUE
Python 3.6.5 second code object from 'print([x+i for i in range(1,3)])':
  1   0 LOAD_NAME    0 (print)
  2 LOAD_CONST   0 ( at 
0x029F79C0, file "MyTest", line 1>)

  4 LOAD_CONST   1 ('')
  6 MAKE_FUNCTION    0
  8 LOAD_NAME    1 (range)
 10 LOAD_CONST   2 (1)
 12 LOAD_CONST   3 (3)
 14 CALL_FUNCTION    2
 16 GET_ITER
 18 CALL_FUNCTION    1
 20 CALL_FUNCTION    1
 22 POP_TOP
 24 LOAD_CONST   4 (None)
 26 RETURN_VALUE

You will see that in Python 3.6.5 the dis output for the second code object
does not show the internals of the listcomp, and in particular whether,
and how, it refers to the variable 'x'.  I don't know how to investigate 
further.


Best wishes
Rob Cliffe

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-05-05 Thread Rob Cliffe via Python-Dev
Reading this sub-thread, it struck me that a good way to make PEP 562 
more likely to be accepted is to launch an over-the-top attack on it.
Then more moderate people - who were/are not necessarily in favour of 
the PEP - feel pressurised into defending it.


Hah!
Watch this space for my vicious, vitriolic, withering attack on PEP 463 
(Exception-catching expressions)! :-)


Best wishes
Rob Cliffe
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 572: Assignment Expressions

2018-04-17 Thread Rob Cliffe via Python-Dev



On 17/04/2018 15:01, Chris Angelico wrote:

On Tue, Apr 17, 2018 at 10:17 PM, Nick Coghlan  wrote:


Style guide recommendations
===

As this adds another way to spell some of the same effects as can already be
done, it is worth noting a few broad recommendations. These could be included
in PEP 8 and/or other style guides.

1. If either assignment statements or assignment expressions can be
used, prefer statements; they are a clear declaration of intent.

2. If using assignment expressions would lead to ambiguity about
execution order, restructure it to use statements instead.

3. Chaining multiple assignment expressions should generally be avoided.
More than one assignment per expression can detract from readability.

Given the many different uses for ":" identified on python-ideas, I'm
inclined to suggest making these proposed style guidelines more
prescriptive (at least initially) by either:

1. Listing out specific approved unambiguous use cases (i.e. if
statement conditions, while loop conditions, list comprehensions,
generation expressions)
2. Making the 3rd admonition more general by advising against using
":" for more than one purpose in the same expression (i.e. don't
combine assignment expressions with slicing syntax, lambda
expressions, function headers, variable annotations, dict or set
displays, dict or set comprehensions)

I'm actually dubious about the third point as it stands.
I'm more than dubious - I disagree with Nick on this point.  It is 
already possible to have multiple uses of ":" in an expression; surely 
we wouldn't advise that such existing code should be changed, in cases 
where it is arises naturally and is genuinely useful.

Best wishes
Rob Cliffe
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The `for y in [x]` idiom in comprehensions

2018-02-26 Thread Rob Cliffe via Python-Dev



On 26/02/2018 19:08, Guido van Rossum wrote:
I would like to remind all wannabe language designers that grammar 
design is not just solving puzzles. It's also about keeping the 
overall feel of the language readable. I'm getting the idea that none 
of the proposals discussed so far (whether new syntax or clever use of 
existing syntax) satisfy that constraint. Sometimes a for-loop is just 
better.


I don't know if you intended these remarks to include my proposal (to 
allow "for VAR = EXPR"), as your message was posted only 27 minutes 
after mine.
With respect, I honestly feel that this is a relatively small change 
that makes the language *more* readable.


Feel free, one and all, to tell me why I'm wrong.
Best wishes,
Rob Cliffe
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The `for y in [x]` idiom in comprehensions

2018-02-26 Thread Rob Cliffe via Python-Dev



On 22/02/2018 19:04, Serhiy Storchaka wrote:
Yet one discussion about reusing common subexpressions in 
comprehensions took place last week on the Python-ideas maillist (see 
topic "Temporary variables in comprehensions" [1]). The problem is 
that in comprehension like `[f(x) + g(f(x)) for x in range(10)]` the 
subexpression `f(x)` is evaluated twice. In normal loop you can 
introduce a temporary variable for `f(x)`. The OP wanted to add a 
special syntax for introducing temporary variables in comprehensions. 
This idea already was discussed multiple times in the past.


There are several ways of resolving this problem with existing syntax.

[snip]


Stephan Houben proposed an idiom which looks similar to new hypothetic 
syntax:


    result = [y + g(y) for x in range(10) for y in [f(x)]]

`for y in [expr]` in a comprehension means just assigning expr to y. I 
never seen this idiom before, but it can be a good replacement for a 
hypothetic syntax for assignment in comprehensions. It changes the 
original comprehension less than other approaches, just adds yet one 
element in a sequence of for-s and if-s. I think that after using it 
more widely it will become pretty idiomatic.


I have created a patch that optimizes this idiom, making it as fast as 
a normal assignment. [2] Yury suggested to ask Guido on the mailing 
list if he agrees that this language patten is worth 
optimizing/promoting.



Here's a thought: allow the syntax
    for VAR = EXPR
to define a for-loop that is executed exactly once (both inside and 
outside comprehensions), i.e. pretty much a synonym for

    for VAR in [ EXPR ]
    for VAR in ( EXPR , )
especially if Serhiy's optimisation means that the list/tuple is not 
actually constructed in the latter.


Pros:
(1) Stephan Houben's example could be written as
        result = [y + g(y) for x in range(10) for y = f(x)]
    which I find more readable.
(2) Code such as
            for i in xrange(10):
    could be changed on the fly to:
            for i = 1:
    I see this as especially useful in debugging, where you want to 
limit the program execution to a known problematic bit.

    But it some contexts it could be good style.
(3) Preserves the compatibility between a list comprehension and its 
"expansion" into for-loops.

(4) Backward compatible, since it is currently illegal syntax
(5) No extra keyword needed
(6) It goes some way towards providing the functionality of
            with VAR as EXPR
        that has been discussed multiple times.

Best wishes
Rob Cliffe
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com