[Python-ideas] Re: os.workdir() context manager

2021-09-14 Thread David Mertz, Ph.D.
On Tue, Sep 14, 2021, 11:17 PM Finn Mason  wrote:

> I disagree. The way I see it, `pathlib` is home of *Path(). No functions.
> Just *Path(). Then again, I didn't write pathlib. I could be
> misunderstanding the intent.
>

When I wrote "in" I was thinking more of a method than a function. E.g.

with Path("/new/dir/").workdir() as wd:
# ... do stuff ...

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


[Python-ideas] Re: os.workdir() context manager

2021-09-14 Thread Finn Mason
On Tue, Sep 14, 2021, 7:58 PM David Mertz, Ph.D. 
wrote:

> I think this would be convenient.
>
> And yes, it's not thread safe. But neither is os.chdir() to start with.
> Someone whose script, or library, wants to chdir can already shoot
> themselves in the foot. This makes that slightly less likely, not more.
>

I agree.

In terms of the bikeshed color, I think putting this in `pathlib` is the
> best approach for "modern Python."
>

I disagree. The way I see it, `pathlib` is home of *Path(). No functions.
Just *Path(). Then again, I didn't write pathlib. I could be
misunderstanding the intent.
However, workdir() doesn't deal with Paths. Sure, it takes a PathLike as an
argument, but it doesn't perform operations on a Path or return a Path.
I think changing the CWD belongs squarely in the os module.

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


[Python-ideas] Re: Otherwise clause in for statement to run when a empty iterable is used

2021-09-14 Thread Valentin Berlier
I find that when I run into a similar scenario the reason why I need the 
iterable to be non-empty is because I'm trying to find something in it, and for 
this the `else` clause works pretty well:

for item in get_items():
if check(item):
do_thing(item)
break
else:
raise ValueError()

Early returns can also be useful:

for item in get_items():
if check(item):
return do_thing(item)
raise ValueError()
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/7PJDRJ6ESY5KT4VECU57P4PEPPOH4LK5/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Otherwise clause in for statement to run when a empty iterable is used

2021-09-14 Thread Andre Delfino
This should have been:

When working with generators in a for statement, AFAIK, there's currently no 
easy way to handle the case of an empty generator (which can be useful if such 
case is an error).
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/KYUJDM5JCQNLYS2LQO7FZZP5H3QR63C4/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Otherwise clause in for statement to run when a empty iterable is used

2021-09-14 Thread Andre Delfino
When working with generators, AFAIK, there's currently no easy way to handle 
the case of an empty generator (which can be useful if such case is an error).

Converting the generator to a, say, list, is not a solution if the generator is 
intrinsically infinite.

I propose to have an "otherwise" clause in the "for" statement that runs only 
if no items are to be processed; that is, to have the following code:

# where get_items() may be an infinite generator
for item in get_items():
SUITE1
otherwise:
SUITE2

be semantically equivalent to:

items_iter = iter(get_items())
try:
first_item = next(items_iter)
except StopIteration:
SUITE2
else:
for item in itertools.chain([first_item], items_iter):
SUITE1
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/7ELTFTLTOCUDYPDK5PMTGLYUVD7UYOXW/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: os.workdir() context manager

2021-09-14 Thread David Mertz, Ph.D.
I think this would be convenient.

And yes, it's not thread safe. But neither is os.chdir() to start with.
Someone whose script, or library, wants to chdir can already shoot
themselves in the foot. This makes that slightly less likely, not more.

In terms of the bikeshed color, I think putting this in `pathlib` is the
best approach for "modern Python."


On Tue, Sep 14, 2021, 7:37 PM Cameron Simpson  wrote:

> On 15Sep2021 07:50, Chris Angelico  wrote:
> >On Wed, Sep 15, 2021 at 7:43 AM Cameron Simpson  wrote:
> >> I know I'm atypical, but I have quite a lot of multithreaded stuff,
> >> including command line code. So while it'd be ok to avoid this context
> >> manager for my own code, I fear library modules, either stdlib or pypi,
> >> quietly using this in their code, making them unuseable in the general
> >> case. Unrepairably unuseable, for the user.
> >
> >Library code shouldn't be changing the working directory, context
> >manager or not. That belongs to the application.
>
> Entirely agree.
>
> I'm concerned that convenient stackable chdir is a bug magnet, and would
> creep into library code. Maybe not in the stdlib, but there's no point
> writing such a context manager if it isn't goingg to be used, and
> therefore it could get used in library code. Imagine when a popular pypi
> module starts using it internally and breaks a multithreaded app
> previously relying on it?
>
>
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/KM6NEMJTUIMRTRTR4IZCW3CAZ264JBY2/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: os.workdir() context manager

2021-09-14 Thread Guido van Rossum
For the stdlib context managers that I know of, all-lowercase seems the
convention. Would it even be a class? The simplest implementation would use
contextlib.contextmanager (unless that’s a undesirable dependency for
os.py).

—Guido

On Tue, Sep 14, 2021 at 17:53 Finn Mason  wrote:

> BTW, should it be `WorkDir` instead of `workdir` because it's a class, or
> would that be too inconsistent?
>
>
> On Tue, Sep 14, 2021, 6:47 PM Finn Mason  wrote:
>
>>
>> On Tue, Sep 14, 2021, 5:36 PM Cameron Simpson  wrote:
>>
>>> On 15Sep2021 07:50, Chris Angelico  wrote:
>>> >On Wed, Sep 15, 2021 at 7:43 AM Cameron Simpson  wrote:
>>> >> I know I'm atypical, but I have quite a lot of multithreaded stuff,
>>> >> including command line code. So while it'd be ok to avoid this context
>>> >> manager for my own code, I fear library modules, either stdlib or
>>> pypi,
>>> >> quietly using this in their code, making them unuseable in the general
>>> >> case. Unrepairably unuseable, for the user.
>>> >
>>> >Library code shouldn't be changing the working directory, context
>>> >manager or not. That belongs to the application.
>>>
>>> Entirely agree.
>>>
>>> I'm concerned that convenient stackable chdir is a bug magnet, and would
>>> creep into library code. Maybe not in the stdlib, but there's no point
>>> writing such a context manager if it isn't going to be used, and
>>> therefore it could get used in library code. Imagine when a popular pypi
>>> module starts using it internally and breaks a multithreaded app
>>> previously relying on it?
>>>
>>
>> I don't think we should worry about it "creeping into library code." The
>> thread-unsafety is not a cause of this context manager. It comes from the
>> preexisting `os.chdir()`. If the library is changing the CWD, it's already
>> thread-unsafe. It's not because of the new context manager. All
>> `os.workdir()` does is make things easier.
>> However, if it's implemented (which I personally support), there should
>> still of course be a warning in the documentation. But I'd like to
>> emphasize that *it is not because of `workdir()` itself, but the
>> underlying `chdir()`!*
>>
>> On 14Sep2021 15:16, Guido van Rossum  wrote:
>> >Here I think we need to drop our perfectionist attitude.
>>
>> I completely agree.
>>
>>> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/J4L3I3QWV65GPKHJ5RZ4NASGX7ZIS774/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-- 
--Guido (mobile)
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/X6IGI33OS7534GF7CCFUKJXTG5OMJAXA/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: os.workdir() context manager

2021-09-14 Thread Finn Mason
BTW, should it be `WorkDir` instead of `workdir` because it's a class, or
would that be too inconsistent?

On Tue, Sep 14, 2021, 6:47 PM Finn Mason  wrote:

>
> On Tue, Sep 14, 2021, 5:36 PM Cameron Simpson  wrote:
>
>> On 15Sep2021 07:50, Chris Angelico  wrote:
>> >On Wed, Sep 15, 2021 at 7:43 AM Cameron Simpson  wrote:
>> >> I know I'm atypical, but I have quite a lot of multithreaded stuff,
>> >> including command line code. So while it'd be ok to avoid this context
>> >> manager for my own code, I fear library modules, either stdlib or pypi,
>> >> quietly using this in their code, making them unuseable in the general
>> >> case. Unrepairably unuseable, for the user.
>> >
>> >Library code shouldn't be changing the working directory, context
>> >manager or not. That belongs to the application.
>>
>> Entirely agree.
>>
>> I'm concerned that convenient stackable chdir is a bug magnet, and would
>> creep into library code. Maybe not in the stdlib, but there's no point
>> writing such a context manager if it isn't going to be used, and
>> therefore it could get used in library code. Imagine when a popular pypi
>> module starts using it internally and breaks a multithreaded app
>> previously relying on it?
>>
>
> I don't think we should worry about it "creeping into library code." The
> thread-unsafety is not a cause of this context manager. It comes from the
> preexisting `os.chdir()`. If the library is changing the CWD, it's already
> thread-unsafe. It's not because of the new context manager. All
> `os.workdir()` does is make things easier.
> However, if it's implemented (which I personally support), there should
> still of course be a warning in the documentation. But I'd like to
> emphasize that *it is not because of `workdir()` itself, but the
> underlying `chdir()`!*
>
> On 14Sep2021 15:16, Guido van Rossum  wrote:
> >Here I think we need to drop our perfectionist attitude.
>
> I completely agree.
>
>>
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/J4L3I3QWV65GPKHJ5RZ4NASGX7ZIS774/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: os.workdir() context manager

2021-09-14 Thread Finn Mason
On Tue, Sep 14, 2021, 5:36 PM Cameron Simpson  wrote:

> On 15Sep2021 07:50, Chris Angelico  wrote:
> >On Wed, Sep 15, 2021 at 7:43 AM Cameron Simpson  wrote:
> >> I know I'm atypical, but I have quite a lot of multithreaded stuff,
> >> including command line code. So while it'd be ok to avoid this context
> >> manager for my own code, I fear library modules, either stdlib or pypi,
> >> quietly using this in their code, making them unuseable in the general
> >> case. Unrepairably unuseable, for the user.
> >
> >Library code shouldn't be changing the working directory, context
> >manager or not. That belongs to the application.
>
> Entirely agree.
>
> I'm concerned that convenient stackable chdir is a bug magnet, and would
> creep into library code. Maybe not in the stdlib, but there's no point
> writing such a context manager if it isn't going to be used, and
> therefore it could get used in library code. Imagine when a popular pypi
> module starts using it internally and breaks a multithreaded app
> previously relying on it?
>

I don't think we should worry about it "creeping into library code." The
thread-unsafety is not a cause of this context manager. It comes from the
preexisting `os.chdir()`. If the library is changing the CWD, it's already
thread-unsafe. It's not because of the new context manager. All
`os.workdir()` does is make things easier.
However, if it's implemented (which I personally support), there should
still of course be a warning in the documentation. But I'd like to
emphasize that *it is not because of `workdir()` itself, but the underlying
`chdir()`!*

On 14Sep2021 15:16, Guido van Rossum  wrote:
>Here I think we need to drop our perfectionist attitude.

I completely agree.

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


[Python-ideas] Re: os.workdir() context manager

2021-09-14 Thread Guido van Rossum
On Tue, Sep 14, 2021 at 4:36 PM Cameron Simpson  wrote:

> On 15Sep2021 07:50, Chris Angelico  wrote:
> >On Wed, Sep 15, 2021 at 7:43 AM Cameron Simpson  wrote:
> >> I know I'm atypical, but I have quite a lot of multithreaded stuff,
> >> including command line code. So while it'd be ok to avoid this context
> >> manager for my own code, I fear library modules, either stdlib or pypi,
> >> quietly using this in their code, making them unuseable in the general
> >> case. Unrepairably unuseable, for the user.
> >
> >Library code shouldn't be changing the working directory, context
> >manager or not. That belongs to the application.
>
> Entirely agree.
>
> I'm concerned that convenient stackable chdir is a bug magnet, and would
> creep into library code. Maybe not in the stdlib, but there's no point
> writing such a context manager if it isn't goingg to be used, and
> therefore it could get used in library code. Imagine when a popular pypi
> module starts using it internally and breaks a multithreaded app
> previously relying on it?
>

I know where I'd file a bug. :-)

"Bug magnet" is an extremely subjective pejorative term. When the *better*
way to do things (os.workdir()) is harder than the *easy* way to do
(os.chdir()), which is the real bug magnet?

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

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


[Python-ideas] Re: os.workdir() context manager

2021-09-14 Thread Chris Angelico
On Wed, Sep 15, 2021 at 9:36 AM Cameron Simpson  wrote:
>
> On 15Sep2021 07:50, Chris Angelico  wrote:
> >On Wed, Sep 15, 2021 at 7:43 AM Cameron Simpson  wrote:
> >> I know I'm atypical, but I have quite a lot of multithreaded stuff,
> >> including command line code. So while it'd be ok to avoid this context
> >> manager for my own code, I fear library modules, either stdlib or pypi,
> >> quietly using this in their code, making them unuseable in the general
> >> case. Unrepairably unuseable, for the user.
> >
> >Library code shouldn't be changing the working directory, context
> >manager or not. That belongs to the application.
>
> Entirely agree.
>
> I'm concerned that convenient stackable chdir is a bug magnet, and would
> creep into library code. Maybe not in the stdlib, but there's no point
> writing such a context manager if it isn't goingg to be used, and
> therefore it could get used in library code. Imagine when a popular pypi
> module starts using it internally and breaks a multithreaded app
> previously relying on it?
>
> >> I think what would be more useful is a context manager which worked on a
> >> threading.local which pushed/popped a reference directory path, and had
> >> an open() method which used that (and friends for other pathname based
> >> functions).
> >
> >Hmm. If it's going to push/pop directories, it should probably work
> >with file descriptors rather than path names, and effectively turn all
> >open calls into openat calls.
>
> Yah. I even thought about that during my sketch. But (a) I've possibly
> never used openat() so I'm unfamiliar with it (other than its existence)
> and (b) I don't think that many other OS calls accept a file descriptor.
> Which still leaves one with the os.path.join() approach, and a mix might
> be inconsistent.
>

I believe that, at the OS level, there are *at() versions of
everything relevant. But the question is more whether it would work at
the Python level. For instance, you can use os.open() with a dir_fd
parameter, but I don't think there's a good way to make the builtin
open() use a reference directory.

Making that happen would probably be a good thing, but a decidedly
nontrivial change.

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


[Python-ideas] Re: os.workdir() context manager

2021-09-14 Thread Cameron Simpson
On 14Sep2021 15:16, Guido van Rossum  wrote:
>Here I think we need to drop our perfectionist attitude. When I saw
>Marc-Andre's proposal my first response was also "but what about threads."
>But really, os.chdir() is the culprit here, and since it's a syscall we
>can't fix it. If we can live with that, we can live with the proposed
>os.workdir(). The docs just need a warning about threads.
[...]
>If we don't offer this in the stdlib, users will just implement this
>themselves, poorly (for example, by not restoring the original when 
>done).

Agreed here. As long as it has a big clear warning about process global 
state.

That is the beauty of libraries, to me: not just reuse, but a correct 
implementation is correct everywhere, and likewise a bugfix fixes all 
the things.

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


[Python-ideas] Re: os.workdir() context manager

2021-09-14 Thread Cameron Simpson
On 15Sep2021 07:50, Chris Angelico  wrote:
>On Wed, Sep 15, 2021 at 7:43 AM Cameron Simpson  wrote:
>> I know I'm atypical, but I have quite a lot of multithreaded stuff,
>> including command line code. So while it'd be ok to avoid this context
>> manager for my own code, I fear library modules, either stdlib or pypi,
>> quietly using this in their code, making them unuseable in the general
>> case. Unrepairably unuseable, for the user.
>
>Library code shouldn't be changing the working directory, context
>manager or not. That belongs to the application.

Entirely agree.

I'm concerned that convenient stackable chdir is a bug magnet, and would 
creep into library code. Maybe not in the stdlib, but there's no point 
writing such a context manager if it isn't goingg to be used, and 
therefore it could get used in library code. Imagine when a popular pypi 
module starts using it internally and breaks a multithreaded app 
previously relying on it?

>> I think what would be more useful is a context manager which worked on a
>> threading.local which pushed/popped a reference directory path, and had
>> an open() method which used that (and friends for other pathname based
>> functions).
>
>Hmm. If it's going to push/pop directories, it should probably work
>with file descriptors rather than path names, and effectively turn all
>open calls into openat calls.

Yah. I even thought about that during my sketch. But (a) I've possibly 
never used openat() so I'm unfamiliar with it (other than its existence) 
and (b) I don't think that many other OS calls accept a file descriptor.  
Which still leaves one with the os.path.join() approach, and a mix might 
be inconsistent.

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


[Python-ideas] Re: Power Assertions: Is it PEP-able?

2021-09-14 Thread Juancarlo Añez
If assertions have an associated block, then `pdb` can be invoked within. I
almost never use debuggers, so I don't remember, but I think a recent
Python version introduced the likes of `debug()` to step into the
pre-configured debugger.

About the "power assertions" proposal in this thread, once everything is in
place to produce the output as proposed, then libraries may come in to
produce different output formats.

My personal preference is for a form of assertions that don't go away, ever.

Regarding the syntax, I think that should be the last part of the design.
If you think about it, a block associated with the assert should execute
when the assertion fails, so maybe it should be something like:

*assert* *cond* *else:* *block*


with an AssertionError raised if *"block"* does not raise.

Another proposal out there that has the same semantics is:

*unless* *cond*: *block*


Yet I find that using a negative keyword makes things ugly. I'd rather
stick to "*assert*", or maybe go for "*invariant*" statement,  to be rid of
the legacy of the meaning of *"assert"* in Python's history.

*invariant* *cond*: *block*


After all, I think it's invariants what I've been after in my recent posts.
It's easy to document that the *"cond"* must be cheap because it will
*_always_* be executed, and that the *"block"* can be as complex as
required by the severity of the failure.

I still think that there's different levels of criticality to failed
assertions, and that an exception hierarchy that has levels can help build
more reliable systems.

On Tue, Sep 14, 2021 at 5:52 PM Finn Mason  wrote:

> I think that this is a great idea. However, pipes only point to one
> character, which can be confusing. (Citation: many tracebacks before 3.10.)
>
> I'm wondering: Could failed assertions step you into `pdb`, if they are
> used for testing purposes? Could there be a way to specify different levels
> of assertions? For example, maybe certain assertions are turned off with -O
> or -OO, others turned off only with -O, and some that never are?
> There are lots of ways `assert` could be improved, and the question is
> how? What is/are the best way(s)?
>
> --
> Finn Mason
>
> On Mon, Sep 13, 2021, 5:36 AM Juancarlo Añez  wrote:
>
>> What about asserts that are not used for testing, but as classic “unless
>>> there’s a bug, this should hold”?
>>
>>
>> To me this relates to the thread about having a structured *assert* that
>> doesn't go away with *-O*.
>>
>> My purpose when addressing *assert* was precisely the *“unless there’s a
>> bug, this should hold”* kind of assertions.
>>
>> In that context, introducing additional yet known costs (as in this
>> "power" idea), providing for different exception types (maybe all
>> descending from AssertError?), and allowing for a block to prepare the
>> exception, are all worth it.
>>
>> Introducing the new syntax for *assert* would imply zero cost for
>> existing assertions.
>>
>> On Sun, Sep 12, 2021 at 10:28 AM Guido van Rossum 
>> wrote:
>>
>>> This is cool.
>>>
>>> AFAIK pytest does something like this. How does your implementation
>>> differ?
>>>
>>> What is your argument for making this part of the language? Why not a
>>> 3rd party library?
>>>
>>> What about asserts that are not used for testing, but as classic “unless
>>> there’s a bug, this should hold”? Those may not want to incur the extra
>>> cost.
>>>
>>> —Guido
>>>
>>> On Sun, Sep 12, 2021 at 07:09  wrote:
>>>
 Hi all,

 I’d like your comments and feedback on an enhancement that introduces
 power assertions to the Python language.

 Proposal
 
 This feature is inspired by a similar feature of the Groovy
 language[1], and is effectively a variant of the `assert` keyword.
 When an assertion expression evaluates to `False`, the output shows not
 only the failure, but also a breakdown of the evaluated expression from the
 inner part to the outer part.

 For example, a procedure like:
 ```python
 class SomeClass:
 def __init__(self):
 self.val = {'d': 'e'}

 def __str__(self):
 return str(self.val)

 sc = SomeClass()

 assert sc.val['d'] == 'f'
 ```

 Will result in the output:

 ```python
 Assertion failed:

 sc.val['d'] == f
 |  ||
 |  eFalse
 |
 {'d': 'e'}
 ```
 See link [2] if the formatting above is screwed up.

 In the output above we can see the value of every part of the
 expression from left to right, mapped to their expression fragment with the
 pipe (`|`).
 The number of rows that are printed depend on the value of each
 fragment of the expression.
 If the value of a fragment is longer than the actual fragment (`{'d':
 'e'}` is longer than `sc`), then the next value (`e`) will be printed on a
 new line which will appear above.
 Values are appended to the same line until it overflows in 

[Python-ideas] Re: os.workdir() context manager

2021-09-14 Thread Guido van Rossum
Here I think we need to drop our perfectionist attitude. When I saw
Marc-Andre's proposal my first response was also "but what about threads."
But really, os.chdir() is the culprit here, and since it's a syscall we
can't fix it. If we can live with that, we can live with the proposed
os.workdir(). The docs just need a warning about threads.

Yes, you could create a thread-safe version of this by overriding open() --
and several hundred other functions that refer to pathnames natively. Such
a project will inevitably have serious backwards compatibility concerns
(any use of pathnames from C extensions will not work right) so it's just
not going to be done.

If we don't offer this in the stdlib, users will just implement this
themselves, poorly (for example, by not restoring the original when done).

On Tue, Sep 14, 2021 at 2:43 PM Cameron Simpson  wrote:

> On 14Sep2021 21:43, M.-A. Lemburg  wrote:
> >- The context manager is not thread safe. There's no thread safe model
> >  for the current work dir. OTOH, scripts usually don't use threads,
> >  so not a big deal.
>
> This is the source of my concerns. Though of course it applies to any
> process global state. It would need this stated up front in big letters
> (as of course does chdir itself). My real concern is that this can leak
> into other functions whose use then makes whatever uses them to become
> inherently and unrepairably not thread safe.
>
> I know I'm atypical, but I have quite a lot of multithreaded stuff,
> including command line code. So while it'd be ok to avoid this context
> manager for my own code, I fear library modules, either stdlib or pypi,
> quietly using this in their code, making them unuseable in the general
> case. Unrepairably unuseable, for the user.
>
> I think what would be more useful is a context manager which worked on a
> threading.local which pushed/popped a reference directory path, and had
> an open() method which used that (and friends for other pathname based
> functions).
>
> In my own code I'd write this like (sketch, untested):
>
> from cs.threads import State as ThreadState
>
> class RefDir(ThreadState)
>
>   def __init__(self, refpath=None):
> if refpath is None:
>   refpath = os.getcwd()
> self.refpath = abspath(refpath)
>
>   def open(self, path, *a, **kw):
> if not isabs(path):
>   path = os.path.join(self.refpath, path)
> return open(path, *a, **kw) # calls the builtin open()
>
>   ... listdir, mkdir, etc etc ...
>
>   # on reflection, __enter__ and __exit__ would make the below even
>   # more convenient
>   @contextmanager
>   def dirpath(newrefpath):
> ''' Push `newrefpath` for the duration of the context manager.
> '''
> with self(refpath=newrefpath):
>   yield self.refpath
>
> and then use it like this:
>
> R = RefDir()
> 
> with R.dirpath('/some/new/place') as newpath:
>   ...
>   with R.open("something.txt") as f:
>   ... work on /some/new/place/something.txt ...
>
> In the above, cs.threads.State is a threading.lcoal subclass which is
> also a context manager whose operation pushes arbitrary attribute
> values.  Great for thread safe execution scoped state. Like this
> example.
>
> All that said, I wrote pretty much exactly what you describe just the
> other week for umask().
>
> Cheers,
> Cameron Simpson 
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/EJETKXD7PAW3XKD5AW4OM45XKDSNX2QJ/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


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

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


[Python-ideas] Re: Power Assertions: Is it PEP-able?

2021-09-14 Thread Finn Mason
I think that this is a great idea. However, pipes only point to one
character, which can be confusing. (Citation: many tracebacks before 3.10.)

I'm wondering: Could failed assertions step you into `pdb`, if they are
used for testing purposes? Could there be a way to specify different levels
of assertions? For example, maybe certain assertions are turned off with -O
or -OO, others turned off only with -O, and some that never are?
There are lots of ways `assert` could be improved, and the question is how?
What is/are the best way(s)?

--
Finn Mason

On Mon, Sep 13, 2021, 5:36 AM Juancarlo Añez  wrote:

> What about asserts that are not used for testing, but as classic “unless
>> there’s a bug, this should hold”?
>
>
> To me this relates to the thread about having a structured *assert* that
> doesn't go away with *-O*.
>
> My purpose when addressing *assert* was precisely the *“unless there’s a
> bug, this should hold”* kind of assertions.
>
> In that context, introducing additional yet known costs (as in this
> "power" idea), providing for different exception types (maybe all
> descending from AssertError?), and allowing for a block to prepare the
> exception, are all worth it.
>
> Introducing the new syntax for *assert* would imply zero cost for
> existing assertions.
>
> On Sun, Sep 12, 2021 at 10:28 AM Guido van Rossum 
> wrote:
>
>> This is cool.
>>
>> AFAIK pytest does something like this. How does your implementation
>> differ?
>>
>> What is your argument for making this part of the language? Why not a 3rd
>> party library?
>>
>> What about asserts that are not used for testing, but as classic “unless
>> there’s a bug, this should hold”? Those may not want to incur the extra
>> cost.
>>
>> —Guido
>>
>> On Sun, Sep 12, 2021 at 07:09  wrote:
>>
>>> Hi all,
>>>
>>> I’d like your comments and feedback on an enhancement that introduces
>>> power assertions to the Python language.
>>>
>>> Proposal
>>> 
>>> This feature is inspired by a similar feature of the Groovy language[1],
>>> and is effectively a variant of the `assert` keyword.
>>> When an assertion expression evaluates to `False`, the output shows not
>>> only the failure, but also a breakdown of the evaluated expression from the
>>> inner part to the outer part.
>>>
>>> For example, a procedure like:
>>> ```python
>>> class SomeClass:
>>> def __init__(self):
>>> self.val = {'d': 'e'}
>>>
>>> def __str__(self):
>>> return str(self.val)
>>>
>>> sc = SomeClass()
>>>
>>> assert sc.val['d'] == 'f'
>>> ```
>>>
>>> Will result in the output:
>>>
>>> ```python
>>> Assertion failed:
>>>
>>> sc.val['d'] == f
>>> |  ||
>>> |  eFalse
>>> |
>>> {'d': 'e'}
>>> ```
>>> See link [2] if the formatting above is screwed up.
>>>
>>> In the output above we can see the value of every part of the expression
>>> from left to right, mapped to their expression fragment with the pipe (`|`).
>>> The number of rows that are printed depend on the value of each fragment
>>> of the expression.
>>> If the value of a fragment is longer than the actual fragment (`{'d':
>>> 'e'}` is longer than `sc`), then the next value (`e`) will be printed on a
>>> new line which will appear above.
>>> Values are appended to the same line until it overflows in length to
>>> horizontal position of the next fragment.
>>>
>>> The information that’s displayed is dictated by the type.
>>> If the type is a constant value, it will be displayed as is.
>>> If the type implements `__str__`, then the return value of that will be
>>> displayed.
>>>
>>> It is important to note that expressions with side effects are affected
>>> by this feature. This is because in order to display this information, we
>>> must store references to the instances and not just the values.
>>>
>>> Rational
>>> 
>>> Every test boils down to the binary statement "Is this true or false?",
>>> whether you use the built-in assert keyword or a more advanced assertion
>>> method provided by a testing framework.
>>> When an assertion fails, the output is binary too — "Expected x, but got
>>> y".
>>>
>>> There are helpful libraries like Hamcrest which give you a more verbose
>>> breakdown of the difference and answer the question "What exactly is the
>>> difference between x and y?".
>>> This is extremely helpful, but it still focuses on the difference
>>> between the values.
>>>
>>> We need to keep in mind that a given state is normally an outcome of a
>>> series of states, that is, one outcome is a result of multiple conditions
>>> and causes.
>>> This is where power assertion comes in. It allows us to better
>>> understand what led to the failure.
>>>
>>> Implementation
>>> 
>>> I’ve already built a fully functional implementation[2] of this feature
>>> as part of my Python testing framework - Nimoy[3].
>>> The current implementation uses AST manipulation to remap the expression
>>> to a data structure[4] at compile time, so that it can then be evaluated
>>> and printed[5] 

[Python-ideas] Re: os.workdir() context manager

2021-09-14 Thread Chris Angelico
On Wed, Sep 15, 2021 at 7:43 AM Cameron Simpson  wrote:
>
> On 14Sep2021 21:43, M.-A. Lemburg  wrote:
> >- The context manager is not thread safe. There's no thread safe model
> >  for the current work dir. OTOH, scripts usually don't use threads,
> >  so not a big deal.
>
> This is the source of my concerns. Though of course it applies to any
> process global state. It would need this stated up front in big letters
> (as of course does chdir itself). My real concern is that this can leak
> into other functions whose use then makes whatever uses them to become
> inherently and unrepairably not thread safe.
>
> I know I'm atypical, but I have quite a lot of multithreaded stuff,
> including command line code. So while it'd be ok to avoid this context
> manager for my own code, I fear library modules, either stdlib or pypi,
> quietly using this in their code, making them unuseable in the general
> case. Unrepairably unuseable, for the user.

Library code shouldn't be changing the working directory, context
manager or not. That belongs to the application.

> I think what would be more useful is a context manager which worked on a
> threading.local which pushed/popped a reference directory path, and had
> an open() method which used that (and friends for other pathname based
> functions).

Hmm. If it's going to push/pop directories, it should probably work
with file descriptors rather than path names, and effectively turn all
open calls into openat calls. I'm currently not sure what the best way
to do that in Python is.

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


[Python-ideas] Re: os.workdir() context manager

2021-09-14 Thread Cameron Simpson
On 14Sep2021 21:43, M.-A. Lemburg  wrote:
>- The context manager is not thread safe. There's no thread safe model
>  for the current work dir. OTOH, scripts usually don't use threads,
>  so not a big deal.

This is the source of my concerns. Though of course it applies to any 
process global state. It would need this stated up front in big letters 
(as of course does chdir itself). My real concern is that this can leak 
into other functions whose use then makes whatever uses them to become 
inherently and unrepairably not thread safe.

I know I'm atypical, but I have quite a lot of multithreaded stuff, 
including command line code. So while it'd be ok to avoid this context 
manager for my own code, I fear library modules, either stdlib or pypi, 
quietly using this in their code, making them unuseable in the general 
case. Unrepairably unuseable, for the user.

I think what would be more useful is a context manager which worked on a 
threading.local which pushed/popped a reference directory path, and had 
an open() method which used that (and friends for other pathname based 
functions).

In my own code I'd write this like (sketch, untested):

from cs.threads import State as ThreadState

class RefDir(ThreadState)

  def __init__(self, refpath=None):
if refpath is None:
  refpath = os.getcwd()
self.refpath = abspath(refpath)

  def open(self, path, *a, **kw):
if not isabs(path):
  path = os.path.join(self.refpath, path)
return open(path, *a, **kw) # calls the builtin open()

  ... listdir, mkdir, etc etc ...

  # on reflection, __enter__ and __exit__ would make the below even 
  # more convenient
  @contextmanager
  def dirpath(newrefpath):
''' Push `newrefpath` for the duration of the context manager.
'''
with self(refpath=newrefpath):
  yield self.refpath

and then use it like this:

R = RefDir()

with R.dirpath('/some/new/place') as newpath:
  ...
  with R.open("something.txt") as f:
  ... work on /some/new/place/something.txt ...

In the above, cs.threads.State is a threading.lcoal subclass which is 
also a context manager whose operation pushes arbitrary attribute 
values.  Great for thread safe execution scoped state. Like this 
example.

All that said, I wrote pretty much exactly what you describe just the 
other week for umask().

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


[Python-ideas] Re: os.workdir() context manager

2021-09-14 Thread Paul Moore
On Tue, 14 Sept 2021 at 20:44, Marc-Andre Lemburg  wrote:
>
> I sometimes write Python scripts which need to work in specific
> work directories.
>
> When putting such code into functions, the outer function typically
> does not expect the current work dir (CWD) to be changed, so wrap the
> code which need the (possibly) modified CWD using a simply context
> manager along the lines of:
>
> class workdir:
> def __init__(self, dir):
> self.dir = dir
> def __enter__(self):
> self.curdir = os.getcwd()
> os.chdir(self.dir)
> def __exit__(self, *exc):
> os.chdir(self.curdir)
> return False
>
> Would there be interest in adding something like this to the os module
> as os.workdir() ?

I've needed (and implemented my own version of) this often enough that
I'd be in favour of it. Of course, as you show, it's not hard to write
it yourself, so I can live with it not getting implemented, too :-)

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


[Python-ideas] os.workdir() context manager

2021-09-14 Thread Marc-Andre Lemburg
Hello all,

I sometimes write Python scripts which need to work in specific
work directories.

When putting such code into functions, the outer function typically
does not expect the current work dir (CWD) to be changed, so wrap the
code which need the (possibly) modified CWD using a simply context
manager along the lines of:

class workdir:
def __init__(self, dir):
self.dir = dir
def __enter__(self):
self.curdir = os.getcwd()
os.chdir(self.dir)
def __exit__(self, *exc):
os.chdir(self.curdir)
return False

Would there be interest in adding something like this to the os module
as os.workdir() ?

Example:

def backup_home_dir(account):
with os.workdir(os.path.join('/home', account)):
# Create a backup of the account dir, rooted at the account's
# home dir
restic.backup(repo, '.')

Notes:
- The context manager is not thread safe. There's no thread safe model
  for the current work dir. OTOH, scripts usually don't use threads,
  so not a big deal.
- The context manager could be made more elaborate, e.g. adding optional
  logging for debugging purposes.
- The same could be added to pathlib's objects as .workdir() method
  returning a context manager.

Thoughts ?

Thanks,
-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Experts (#1, Sep 14 2021)
>>> Python Projects, Coaching and Support ...https://www.egenix.com/
>>> Python Product Development ...https://consulting.egenix.com/


::: We implement business ideas - efficiently in both time and costs :::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
   Registered at Amtsgericht Duesseldorf: HRB 46611
   https://www.egenix.com/company/contact/
 https://www.malemburg.com/

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


[Python-ideas] Re: itertools.compress default selectors

2021-09-14 Thread Chris Angelico
On Wed, Sep 15, 2021 at 4:58 AM Tim Peters  wrote:
> Or perhaps the `compress()` implementation could grow internal
> conditionals to use a different algorithm if the second argument is
> omitted. But that would be a major change to support something that's
> already easily done in more than one more-than-less obvious way.

At which point it'd be basically just turning compress(iter, None)
into filter(None, iter) and we gain nothing. Agreed. So this proposal
has minimal value and enough wrinkles to make it highly unappealing.

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


[Python-ideas] Re: itertools.compress default selectors

2021-09-14 Thread Paul Moore
On Tue, 14 Sept 2021 at 19:58, Tim Peters  wrote:

> Except it's not that simple:

Apologies, Tim, it took me a couple of reads to work out what you were
saying here. I hope you won't mind if I restate the point for the
benefit of anyone else who might have got confused it like I did...

> def gen(hi):
> i = 0
> while i < hi:
> yield i
> i += 1
>
> from itertools import compress
> g = gen(12)
> print(list(filter(None, g)))
> g = gen(12)
> print(list(compress(g, g)))
>
> Which displays:
>
> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
> [0, 2, 4, 6, 8, 10]
>
> The first is obviously intended, but the latter is what you get merely
> by giving the same argument twice to `complress()`.

The key point here is that the proposal that compress(g) should mean
the same as compress(g, g) doesn't actually do what you were
suggesting it would (and what you want), if g is an iterator - and
after all, that's what itertools is supposed to be about, operations
on iterators in general.

To actually get the same behaviour as filter(None, g) in general needs
a much more complicated change than simply saying "the default is to
use the first argument twice".

> `compress()` can't materialize its argument(s) into a list (or tuple)
> first, because it's intended to work fine with infinite sequences. It
> could worm around that like so:under the covers:
>
> from itertools import tee
> g = gen(12)
> print(list(compress(*tee(g
>
> but that's just bizarre ;-) And inefficient.
>
> Or perhaps the `compress()` implementation could grow internal
> conditionals to use a different algorithm if the second argument is
> omitted. But that would be a major change to support something that's
> already easily done in more than one more-than-less obvious way.

At this point, it's no longer a simple change adding a fairly obvious
default value for an argument that's currently mandatory, it's
actually an important and significant (but subtle) change in
behaviour.

Honestly, I think this pretty much kills the proposal. Thanks for
pointing this flaw out Tim, and sorry if I laboured the point you were
making :-)

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


[Python-ideas] Re: itertools.compress default selectors

2021-09-14 Thread Tim Peters
[Chris Angelico ]
> ...
> For it to be accepted, you have to convince people - particularly,
> core devs - that it's of value. At the moment, I'm unconvinced, but on
> the other hand, all you're proposing is a default value for a
> currently-mandatory argument, so the bar isn't TOO high (it's not like
> you're proposing to create a new language keyword or anything!).

Except it's not that simple:

def gen(hi):
i = 0
while i < hi:
yield i
i += 1

from itertools import compress
g = gen(12)
print(list(filter(None, g)))
g = gen(12)
print(list(compress(g, g)))

Which displays:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
[0, 2, 4, 6, 8, 10]

The first is obviously intended, but the latter is what you get merely
by giving the same argument twice to `complress()`.

`compress()` can't materialize its argument(s) into a list (or tuple)
first, because it's intended to work fine with infinite sequences. It
could worm around that like so:under the covers:

from itertools import tee
g = gen(12)
print(list(compress(*tee(g

but that's just bizarre ;-) And inefficient.

Or perhaps the `compress()` implementation could grow internal
conditionals to use a different algorithm if the second argument is
omitted. But that would be a major change to support something that's
already easily done in more than one more-than-less obvious way.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/NASMPTHASUZQTVJPWLL3Q2YVL4DHKCJH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: itertools.compress default selectors

2021-09-14 Thread Chris Angelico
On Wed, Sep 15, 2021 at 4:03 AM m...@dyatkovskiy.com  
wrote:
>
> > The signature is wrong.
> Thanks for remark. Of course proper signature would be:
>
> def jin(a: Iterable[Optional[str]], sep=“ “):
> # …
>
> > Why do you (ab)use compress for that?
> Well, it seems that it is subjective. To me “[None, x, y, z]” -> “[x, y, z]” 
> looks like “compression”. But if community agrees with your side, then, well, 
> it’s OK.

To me, that looks like filtering. The most common sort of filtering is
what the filter() function does - ask a predicate function whether
something's good or bad, and keep the good ones. The filtering done by
itertools.compress() is slightly different - look it up in a
corresponding list of "good" or "bad", and keep the good ones.

What you're looking at is asking a question about each element.
Specifically, you're asking "is this element truthy or falsy?". That
perfectly matches the filter() function.

> Alternatively indeed we can use:
> 2. Use "filter(None, a)”
> 3. (x for x in a if x)
>
> Why not to use #3?
>
> Only having #2 or #3, I would vote for “filter”. It is a builtin, and used to 
> be implemented as intrinsic. In cpython it has a separate “if”  branch for 
> case when first argument is “None” (see “filter_next” function in 
> “bltinmodule.c”)
>

There's no real difference between #2 and #3. If you feel more
comfortable writing comprehensions, write comprehensions. If you feel
more comfortable using builtins, use builtins. Either way, you're
expressing the concept "keep the ones that are true".

> #3 semantically is more complicated and it seems that there are no 
> optimizations at least in cpython (but perhaps I’m wrong?). So, it looks like 
> #3 is slower while parsing and while executing.
>
> #3 is bad choice for code maintenance. It is always better to pass variable 
> once. “(x for x in a if x)” contains micro code dups. Here, you put “x” three 
> times, and then if you decide to use something else you have to edit it in 
> three places. So #3 defeats if you want to reuse or just maintain such code.
>

Yeah, if that bothers you, use filter. Nothing wrong with either IMO.

> And yet, I still have a little hope about original proposal. I proposed to 
> add default value for second argument of “compress”.
>
> So thanks for you attention anyways, and let me know if it is still has a 
> chance to be accepted.

For it to be accepted, you have to convince people - particularly,
core devs - that it's of value. At the moment, I'm unconvinced, but on
the other hand, all you're proposing is a default value for a
currently-mandatory argument, so the bar isn't TOO high (it's not like
you're proposing to create a new language keyword or anything!).

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


[Python-ideas] Re: itertools.compress default selectors

2021-09-14 Thread m...@dyatkovskiy.com
> The signature is wrong. 
Thanks for remark. Of course proper signature would be:

def jin(a: Iterable[Optional[str]], sep=“ “):
# …

> Why do you (ab)use compress for that?
Well, it seems that it is subjective. To me “[None, x, y, z]” -> “[x, y, z]” 
looks like “compression”. But if community agrees with your side, then, well, 
it’s OK.

As another argument to use “compress” was similar case I found on stackoverflow 
for numpy:
https://stackoverflow.com/questions/5927180/how-do-i-remove-all-zero-elements-from-a-numpy-array

So extending “compress” would be useful for math cases as well.

Alternatively indeed we can use:
2. Use "filter(None, a)”
3. (x for x in a if x)

Why not to use #3?

Only having #2 or #3, I would vote for “filter”. It is a builtin, and used to 
be implemented as intrinsic. In cpython it has a separate “if”  branch for case 
when first argument is “None” (see “filter_next” function in “bltinmodule.c”)

There is also a good chance to work with optimized “compress” one day.

#3 semantically is more complicated and it seems that there are no 
optimizations at least in cpython (but perhaps I’m wrong?). So, it looks like 
#3 is slower while parsing and while executing.

#3 is bad choice for code maintenance. It is always better to pass variable 
once. “(x for x in a if x)” contains micro code dups. Here, you put “x” three 
times, and then if you decide to use something else you have to edit it in 
three places. So #3 defeats if you want to reuse or just maintain such code.

Paul confirmed my worries about “jin”, so it seems that it is not an option 
either.

And yet, I still have a little hope about original proposal. I proposed to add 
default value for second argument of “compress”.

So thanks for you attention anyways, and let me know if it is still has a 
chance to be accepted.

Thanks!
Stepan Dyatkovskiy.

> On Sep 14, 2021, at 2:18 PM, Steven D'Aprano  wrote:
> 
> On Tue, Sep 14, 2021 at 11:31:43AM +0400, m...@dyatkovskiy.com wrote:
> 
>> Thus I have collection of options and some of them are empty or None. 
>> In order to get rendered command line options string I use “compress” 
>> in conjunction with “join":
>> 
> opts = " ".join(compress(flags, flags))
> 
> Why do you (ab)use compress for that?
> 
> I understand that `compress(flags, flags)` has the effect of filtering 
> for non-empty flags. But that's an obfuscated way to write it. Either of 
> these would be more understandable:
> 
> * `filter(None, flags)`  # could also use bool instead of None
> 
> * `(flag for flag in flags if flag)`
> 
> especially the last, although heavy users of functional languages may 
> prefer filter. But using compress with the same argument twice is just 
> weird.
> 
> And also fragile. You can't use an iterator for the flags.
> 
 jin(iter(['a', 'b', '', 'c', 'd', 'e', 'f', '', 'g']))
>'a  d'
> 
> 
>> I usually introduce alias for this:
>> 
> def jin(a: str, sep=“ “):
>return sep.join(compress(a, a))
>> 
>> And I found that I use it quite frequently.
> 
> The signature is wrong. `flags` is a list of string options. If you pass 
> an actual string, you expand it with spaces:
> 
> 
 jin('abc def')
>'a b c   d e f'
> 
> 
> -- 
> Steve
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at 
> https://mail.python.org/archives/list/python-ideas@python.org/message/RPY7HJ4VIUL5PXRBBTCFT6AALXBLUUGF/
> Code of Conduct: http://python.org/psf/codeofconduct/

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


[Python-ideas] Re: Addition of a "plus-minus" binary numeric operator

2021-09-14 Thread Ricky Teachey
May I ask what you are actually doing with upper and lower after creating
them? Are you checking to see if another value is between? Something else?
If they are always being used together and you're doing the same things
with them all the time, it starts to smell like you might want to just
write a class.

---
Ricky.

"I've never met a Kentucky man who wasn't either thinking about going home
or actually going home." - Happy Chandler


On Tue, Sep 14, 2021 at 10:11 AM Ir. Robert Vanden Eynde <
robertv...@gmail.com> wrote:

> Add you can call this function plusminus
> Then use the funcoperators module to write :
>
> upper, lower = a +plusminus- b
>
> pip install funcoperators
>
> Le mar. 14 sept. 2021 à 16:02, Paul Moore  a écrit :
>
>> I doubt it, it seems way too specialised to be worth making into a
>> language feature.
>>
>> If you want to, you can write a function:
>>
>> def limits(a, b):
>> return a+b, a-b
>>
>> Paul
>>
>> On Tue, 14 Sept 2021 at 14:55,  wrote:
>> >
>> > Hi all,
>> >
>> > I was wondering on whether there is any interest in introducing a
>> "plus-minus" operator:
>> >
>> > Conceptually very simple; instead of:
>> >
>> > upper, lower = a + b, a - b
>> >
>> > use instead:
>> >
>> > upper, lower = a +- b
>> >
>> > In recent projects I've been working on, I've been having to do the
>> above "plus minus" a lot, and so it would simplify/clean-up/reduce error
>> potential cases where I'm writing the results explicitly.
>> >
>> > It isn't a big thing, but seems like a clean solution, that also takes
>> advantage of python's inherent ability to return and assign tuples.
>> > ___
>> > Python-ideas mailing list -- python-ideas@python.org
>> > To unsubscribe send an email to python-ideas-le...@python.org
>> > https://mail.python.org/mailman3/lists/python-ideas.python.org/
>> > Message archived at
>> https://mail.python.org/archives/list/python-ideas@python.org/message/MCAS5B63Q6ND74GEBP2N3OF3HLISSQMA/
>> > Code of Conduct: http://python.org/psf/codeofconduct/
>> ___
>> Python-ideas mailing list -- python-ideas@python.org
>> To unsubscribe send an email to python-ideas-le...@python.org
>> https://mail.python.org/mailman3/lists/python-ideas.python.org/
>> Message archived at
>> https://mail.python.org/archives/list/python-ideas@python.org/message/XYRRZPCPWF6VJTBX3MAWCIQEWXJC5F3X/
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/527MLDIJ3EHBPGSS2KJ4CBP3RVMR4JBZ/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/PNMWXFP6ETVT425CGOZQW4UPEKAZ6TR6/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Addition of a "plus-minus" binary numeric operator

2021-09-14 Thread Ir. Robert Vanden Eynde
Add you can call this function plusminus
Then use the funcoperators module to write :

upper, lower = a +plusminus- b

pip install funcoperators

Le mar. 14 sept. 2021 à 16:02, Paul Moore  a écrit :

> I doubt it, it seems way too specialised to be worth making into a
> language feature.
>
> If you want to, you can write a function:
>
> def limits(a, b):
> return a+b, a-b
>
> Paul
>
> On Tue, 14 Sept 2021 at 14:55,  wrote:
> >
> > Hi all,
> >
> > I was wondering on whether there is any interest in introducing a
> "plus-minus" operator:
> >
> > Conceptually very simple; instead of:
> >
> > upper, lower = a + b, a - b
> >
> > use instead:
> >
> > upper, lower = a +- b
> >
> > In recent projects I've been working on, I've been having to do the
> above "plus minus" a lot, and so it would simplify/clean-up/reduce error
> potential cases where I'm writing the results explicitly.
> >
> > It isn't a big thing, but seems like a clean solution, that also takes
> advantage of python's inherent ability to return and assign tuples.
> > ___
> > Python-ideas mailing list -- python-ideas@python.org
> > To unsubscribe send an email to python-ideas-le...@python.org
> > https://mail.python.org/mailman3/lists/python-ideas.python.org/
> > Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/MCAS5B63Q6ND74GEBP2N3OF3HLISSQMA/
> > Code of Conduct: http://python.org/psf/codeofconduct/
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/XYRRZPCPWF6VJTBX3MAWCIQEWXJC5F3X/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/527MLDIJ3EHBPGSS2KJ4CBP3RVMR4JBZ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Addition of a "plus-minus" binary numeric operator

2021-09-14 Thread Jonathan Fine
Hi Yahbai

You might wish to reconsider your proposal in light of existing behaviour
>>> 1+-1
0

Consider also your proposed
>>> a, b = 2 +- 1
We know that {a, b} = {1, 3}. But which is which?

In your use case you might be better off introducing a custom type
>>> lims = pm(2, 1)
>>> lims.lo, lims.hi
(1, 3)

I hope this helps you with your code.

best wishes

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


[Python-ideas] Re: Addition of a "plus-minus" binary numeric operator

2021-09-14 Thread Chris Angelico
On Tue, Sep 14, 2021 at 11:58 PM  wrote:
>
> Hi all,
>
> I was wondering on whether there is any interest in introducing a 
> "plus-minus" operator:
>
> Conceptually very simple; instead of:
>
> upper, lower = a + b, a - b
>
> use instead:
>
> upper, lower = a +- b
>
> In recent projects I've been working on, I've been having to do the above 
> "plus minus" a lot, and so it would simplify/clean-up/reduce error potential 
> cases where I'm writing the results explicitly.
>
> It isn't a big thing, but seems like a clean solution, that also takes 
> advantage of python's inherent ability to return and assign tuples.

As an operator, this wouldn't work, since it's ambiguous with adding
negative b to a (ie "a + -b"). But as Paul said, this is perfect for a
very simple function.

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


[Python-ideas] Re: Addition of a "plus-minus" binary numeric operator

2021-09-14 Thread Paul Moore
I doubt it, it seems way too specialised to be worth making into a
language feature.

If you want to, you can write a function:

def limits(a, b):
return a+b, a-b

Paul

On Tue, 14 Sept 2021 at 14:55,  wrote:
>
> Hi all,
>
> I was wondering on whether there is any interest in introducing a 
> "plus-minus" operator:
>
> Conceptually very simple; instead of:
>
> upper, lower = a + b, a - b
>
> use instead:
>
> upper, lower = a +- b
>
> In recent projects I've been working on, I've been having to do the above 
> "plus minus" a lot, and so it would simplify/clean-up/reduce error potential 
> cases where I'm writing the results explicitly.
>
> It isn't a big thing, but seems like a clean solution, that also takes 
> advantage of python's inherent ability to return and assign tuples.
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at 
> https://mail.python.org/archives/list/python-ideas@python.org/message/MCAS5B63Q6ND74GEBP2N3OF3HLISSQMA/
> Code of Conduct: http://python.org/psf/codeofconduct/
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/XYRRZPCPWF6VJTBX3MAWCIQEWXJC5F3X/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Addition of a "plus-minus" binary numeric operator

2021-09-14 Thread yahbai
Hi all,

I was wondering on whether there is any interest in introducing a "plus-minus" 
operator:

Conceptually very simple; instead of:

upper, lower = a + b, a - b

use instead:

upper, lower = a +- b

In recent projects I've been working on, I've been having to do the above "plus 
minus" a lot, and so it would simplify/clean-up/reduce error potential cases 
where I'm writing the results explicitly.

It isn't a big thing, but seems like a clean solution, that also takes 
advantage of python's inherent ability to return and assign tuples.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/MCAS5B63Q6ND74GEBP2N3OF3HLISSQMA/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: classmethod __eq__ comparisons and Any wildcards

2021-09-14 Thread Chris Angelico
On Tue, Sep 14, 2021 at 11:30 PM  wrote:
>
> I think I implemented __eq__ but not __hash__ and it broke the golden rule of 
> x == y => x is y i,.e. hash(x) == hash(y)
>

Not sure what you're referring to there. The rule regarding hashes is
that if x == y, then hash(x) == hash(y). Identity doesn't come into
it, other than in the trivial sense that, for most classes, hash(x) ==
hash(x) (in other words, the hash is stable), and x == x, which
complies with the rule. But if x != x (eg with float("nan")), there's
no problem.

Incidentally, I don't think it's documented, but an object's hash
should never change. Otherwise, you can get bizarre behaviours:

>>> class X:
... def __init__(self, value): self.thing = value
... def __eq__(self, other): return self.thing == other.thing
... def __hash__(self): return hash(self.thing)
...
>>> stuff = {X(5): "hello", X(7): "world"}
>>> stuff[X(5)]
'hello'

Well and good. But if we mutate the key...

>>> list(stuff)[0].thing = 2
>>> for key in stuff:
... print(key, stuff[key])
...
Traceback (most recent call last):
  File "", line 2, in 
KeyError: <__main__.X object at 0x7f1420409180>
>>>

... we can iterate over the keys in the dictionary, use that exact
object to subscript the dictionary, and it isn't found. That key/value
pair has been placed in the bucket for 5, and won't be found in 2's
bucket.

If equality can change, __hash__ should be omitted.

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


[Python-ideas] Re: classmethod __eq__ comparisons and Any wildcards

2021-09-14 Thread johnmelendowski
As pointed out, you want metaclass for this. A warning, I've overwritten many 
of the dunders on classes for fun and I actually broke the ability to repr my 
class in certain situations by overriding __eq__ and/or __hash__ something deep 
in ipython/python with the repr. I forget the exact situation, I think I 
implemented __eq__ but not __hash__ and it broke the golden rule of x == y => x 
is y i,.e. hash(x) == hash(y) 

Great way to really learn the data model but you will be in for a bit of pain 
trying to debug these things.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/AVQDN2XIMOXQ6CJLYPVZCNZGBDLXMEHN/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: itertools.compress default selectors

2021-09-14 Thread Steven D'Aprano
On Tue, Sep 14, 2021 at 11:31:43AM +0400, m...@dyatkovskiy.com wrote:

> Thus I have collection of options and some of them are empty or None. 
> In order to get rendered command line options string I use “compress” 
> in conjunction with “join":
> 
> >>> opts = " ".join(compress(flags, flags))

Why do you (ab)use compress for that?

I understand that `compress(flags, flags)` has the effect of filtering 
for non-empty flags. But that's an obfuscated way to write it. Either of 
these would be more understandable:

* `filter(None, flags)`  # could also use bool instead of None

* `(flag for flag in flags if flag)`

especially the last, although heavy users of functional languages may 
prefer filter. But using compress with the same argument twice is just 
weird.

And also fragile. You can't use an iterator for the flags.

>>> jin(iter(['a', 'b', '', 'c', 'd', 'e', 'f', '', 'g']))
'a  d'


> I usually introduce alias for this:
> 
> >>> def jin(a: str, sep=“ “):
> >>> return sep.join(compress(a, a))
> 
> And I found that I use it quite frequently.

The signature is wrong. `flags` is a list of string options. If you pass 
an actual string, you expand it with spaces:


>>> jin('abc def')
'a b c   d e f'


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


[Python-ideas] Re: itertools.compress default selectors

2021-09-14 Thread Paul Moore
On Tue, 14 Sept 2021 at 08:38, m...@dyatkovskiy.com  
wrote:
> Main motivation was a use case where we gather command line options, and some 
> of them are… optional.
[...]
> And yet I’m solid that we need some compact and nice way for rendering 
> strings with command options. That would be a thing.

Frankly, I'd just use something like your "jin" function

def make_option_string(options):
return " ".join(opt for opt in options if opt)

Note that I gave it a more readable name that reflects the actual use
case. This is deliberate, as I think the main advantage here is
readability, and using a name that reflects the use case, rather than
a "generic" name, helps readability. That's also why I don't see this
as being a useful candidate for the stdlib - it would have to have a
"generic" name in that case, which defeats the (for me) main benefit.

I find the "sep.join(x for x in it if x)" construction short and
readable enough that I'd be unlikely to use a dedicated function for
it, even if one existed. And while "x for x in it if x" is annoyingly
repetitive, it's not so bad that I'd go hunting for a function to
replace it.

So for me, I *don't* think we need a dedicated function for this.

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


[Python-ideas] Re: itertools.compress default selectors

2021-09-14 Thread m...@dyatkovskiy.com
OK, If I might tell some story... :)

Main motivation was a use case where we gather command line options, and some 
of them are… optional.

Below is a realistic example. Namely options for LLVM Clang:

>>> flags = [“-O3”, “-fomit-frame-pointer”, maybe_pgo(context)]

Here “maybe_pgo” returns either “None” if we don’t use profile guided 
optimization and it returns “-fprofile-generate” otherwise.

Thus I have collection of options and some of them are empty or None. In order 
to get rendered command line options string I use “compress” in conjunction 
with “join":

>>> opts = " ".join(compress(flags, flags))

I usually introduce alias for this:

>>> def jin(a: str, sep=“ “):
>>> return sep.join(compress(a, a))

And I found that I use it quite frequently.

(“jin” is an analog of “join" but without “emptiness”, so we omitted “o” :) )

Initially I also used this:

 it = (x for x in it if x)

But when you about to build sophisticated options string it leads to quite 
scattered code. Whilst with an alias I make pretty readable one-liners:

>>> opts = “ “.join(compress([“-O3”, “-fomit-stackpointer”, 
>>> maybe_linker_pgo(context)]))

or in case with “str.jin”:

>>> opts = " ".jin([“-O3”, “-fomit-stackpointer”, maybe_linker_pgo(context)])

I considered to propose “str.jin” static method, and pretty much wondered about 
it. But then decided that for stdlib and might be too much and stopped on 
“compress”. Also it still allows to build options collection in a nice way if 
you surround all options lists with a “compress” call:

>>> flags = compress([“-O3”, “-fomit-stackpointer”, *maybe_even_more(context)])
>>> ldflags = compress([“-fglobal-merge”, maybe_opt_level(context)]
>>> opts = " “.join(flags + ldflags)

What confuses me with “compress” is a weird dispersion of similar 
functionality: “filter” (builtin), “itertools.compress” and 
“itertools.filterfalse”. All of them pursues similar goals and in fact might be 
redesigned as a single method. Or methods family with same prefix (“filter”?). 
And perhaps it was discussed already.

So wouldn’t it be wasted effort to work on “compress” right now? Perhaps “jin” 
would be better a solution indeed?

And yet I’m solid that we need some compact and nice way for rendering strings 
with command options. That would be a thing.

Thanks!
Stepan Dyatkovskiy


> On Sep 14, 2021, at 2:19 AM, Tim Peters  wrote:
> 
> FYI, itertools.compress() is very useful in conjunction with
> itertools.cycle() to pick out elements following a periodic pattern of
> indices. For example,
> 
> # Elements at even indices.
 list(compress(range(20), cycle([1, 0])))
> [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
> 
> # Or at odd ones.
 list(compress(range(20), cycle([0, 1])))
> [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
> 
> # Pick every third.
 list(compress(range(20), cycle([0, 0, 1])))
> [2, 5, 8, 11, 14, 17]
> 
> # Omit every third.
 list(compress(range(20), cycle([1, 1, 0])))
> [0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19]
> 
> For arguments that are re-iteraerable, there are several ways to get
> the proposed semantics, including just passing the argument twice to
> compress():
> 
 a = [None, "", "-filove-python",  "CFLAGS=-O3"]
 " ".join(compress(a, a))
> '-filove-python CFLAGS=-O3'
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at 
> https://mail.python.org/archives/list/python-ideas@python.org/message/XGCVW3LNEU2FNMB7JYTIQENK4KGHV4LZ/
> Code of Conduct: http://python.org/psf/codeofconduct/

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