[Python-ideas] Re: !$? operators for gratuitous overloading

2020-02-03 Thread Andrew Barnert via Python-ideas
On Feb 3, 2020, at 21:14, Random832  wrote:
> 
> If we are going to have a general binary operator mechanism, maybe it should 
> be something more haskell-like,

That’s exactly what I suggested—but more to argue that we don’t want a general 
binary operator mechanism at all. (The right way to do it would be like 
Haskell, we don’t want anything like whet Haskell does, therefore we shouldn’t 
do it.)

> with an open-ended set of binary operator names [`identifier` as haskell, 
> perhaps? and/or maybe the unicode math ops section, with stuff like circled 
> plus] and a way to define precedence before the point of use for the parser.

Well, in Haskell, it’s any _string_ of symbol characters, not just any one 
symbol character. And I think you’d want that even if you open it up to all of 
Unicode Sm. Not just because most of the non-ASCII characters are hard to type 
in most environments, but because for an awful lot of operations there’s no 
obvious single character. For example, what Unicode character would be as good 
as >> for rshift even to read, much less to type? How could you distinguish |<, 
<|, |>, >|, and the other map insert/update operators by using single 
characters for each? And so on.

And operator strings don’t work in Python, where things like 2+-3 are perfectly 
valid sequences of two operators (and 2-=3 is valid and not even an operator). 
Also, without sectioning, it would be hard to refer to operators—Python has the 
operator module for all the builtin ones, and operator.add looks just as nice 
as (+), but that doesn’t help if you need a Python equivalent to (|<>) or a 
non-ASCII character.

Even the backticked names thing, while I don’t think it has any syntactic 
ambiguity, I don’t think it would be readable in Python, because you don’t read 
Python in terms of curried functions. For example, in Haskell, if I write odd 
`dropwhile` xs, that makes sense, because you think of it as the partially 
applied function (dropwhile odd) being applied to xs, but in Python nobody 
would think of it as partial(dropwhile, odd)(xs). So it would at best look 
backward and at worst incomprehensible.

But anyway, even if there weren’t any problems with either one, I think the 
odds of convincing the Python community to add it would be pretty close to nil.

That being said, somewhere or other I have a hacky import hook that I could dig 
up if you want it that lets you do something like this. (Hacky not just in the 
way that it’s implemented, but also in what it does and doesn’t allow—basically 
an operator is any string of Sm characters that happens to generate a single 
ERRORTOKEN when tokenized as normal Python, IIRC.) I can’t imagine using it in 
real life code, but it was fun to implement.

> Perhaps it would also be useful to provide a utility function for performing 
> the __op__/__rop__/NotImplemented/most-derived-class binary operator 
> execution rules on an arbitrary pair of method names, without *any* 
> syntactical support [in order to, say, allow evaluation of custom ASTs for 
> non-python languages on python objects]

That part is not too hard to write, and doesn’t change from version to version, 
and if we don’t add custom operators (or encourage people to do so with import 
hooks) I think it will come up very rarely. So I think it’s probably not needed 
in the stdlib.

(If you’ve got an idea for the opposite problem, though, a tool to make it 
easier to implement __op__ and __rop__ pairs on your types without having to go 
through the whole mess seen in fractions.Fraction, that would be pretty handy 
in the stdlib…)

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


[Python-ideas] Re: addition of "nameof" operator

2020-02-03 Thread Bruce Leban
On Mon, Feb 3, 2020 at 3:58 AM Richard Damon 
wrote:

>
> IF Python had a proper refactoring tool (see my other message where I
> question the ability to do that) then the nameof operator would clearly
> help keep logging/debug strings in line with the program definitions.
>
> A statement like print("bar", foo.bar) would be very hard to notice that
> the "bar" match the foo.bar, while
>
> print(nameof(foo.bar), foo.bar) makes the connection explicit.
>

What you're actually asking for is a way for a refactoring tool to
recognize that the string "bar" is a reference to the bar in foo.bar.
You're NOT asking for the Python compiler to recognize that. There are lots
of ways to do this. And Ricky Teachey's examples show that this is pretty
ugly.

On Mon, Feb 3, 2020 at 9:38 AM Ricky Teachey  wrote:

> To restate the motivation: the hope is that there is a potentially large
> benefit of being able to more easily refactor code with something like a
> nameof().
>
> 
>
> class FunctionLogger:
> # NOTE: this docstring will result in a runtime error, so can't even use 
> nameof() here to help ourselves
> f"""Records use of a function.
> The optional `{nameof(FunctionLogger.log)}` parameter is to be a callable 
> that accepts a string.
> It is logging.info by default.
> """
> *...*logging.exception(f"failed to log {func_name!r} call; is 
> {cls_name}.{log_param_name} set correctly?")
>
> *Bottom line: refactoring remains a chore. The win is minimal. Do nothing
> option is preferred.*
>
> Here is a much more readable alternative which has the advantage that it
is already supported by Python. I'm going to show a harder example where I
want to reference foo.bar and allow both foo and bar to be refactored.
Here's the original proposal:

f"The field {nameof(foo)}.{nameof(foo.bar)} can be refactored."

Here's my alternative:

f"""The field {"foo.bar"} can be refactored."""


Since there's no real reason that you'd use {} around a literal string, we
have our refactoring tool recognize that syntax as a variable reference. It
has no net effect on the running code. If we don't want foo to be
refactored, we write instead:

f"""The field foo.{"bar"} can be refactored."""


And if we just want the string to reference "bar" but want to make sure
it's foo.bar not something_else.bar, we could write this:

f"""The field {"foo" and "bar"} can be refactored."""


--- Bruce



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


[Python-ideas] Re: !$? operators for gratuitous overloading

2020-02-03 Thread Random832
On Sun, Feb 2, 2020, at 11:41, MRAB wrote:
> On 2020-02-02 15:00, Karl Ramm wrote:
> > We have all shared in the observation that all but the most carefully
> > considered operator overloading tends to reduce code readability.  There
> > also many programmers that feel that they need it to make there code terse
> > (or perhaps shiny) enough.
> > 
> > I propose adding ! and $ as (normally unimplemented) binary operators and ?
> > as a unary operator so as to explicitly to give people the rope they want
> > but clearly tagged "here there be shenanigans".
> > 
> In the past there have been suggestions to add None-coalescing 
> operators 
> such as "?." and "??", comparable to the null-coalescing operators of 
> C#, so I'm -1 on just adding "!", "$" and "?" without a solid use-case, 
> in case we find a better use for them later in the future.

Before the nameof discussion got shut down, I was going to propose $nameof as a 
way to avoid collision with a function called "nameof", and I still think it's 
viable as a general way to make an open-ended set of keywords that don't 
collide with identifiers [frozenset literals?]... so I'm also -1 on cutting 
down the number of reserved ASCII characters without a very good concrete use 
case.

If we are going to have a general binary operator mechanism, maybe it should be 
something more haskell-like, with an open-ended set of binary operator names 
[`identifier` as haskell, perhaps? and/or maybe the unicode math ops section, 
with stuff like circled plus] and a way to define precedence before the point 
of use for the parser.

Perhaps it would also be useful to provide a utility function for performing 
the __op__/__rop__/NotImplemented/most-derived-class binary operator execution 
rules on an arbitrary pair of method names, without *any* syntactical support 
[in order to, say, allow evaluation of custom ASTs for non-python languages on 
python objects]
___
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/GISGMZLBZ3FRT77QWJ3EXUGJTGJC2MEG/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: allow full expressions in decorators

2020-02-03 Thread Guido van Rossum
I’ve always resisted changing this, but it keeps coming up, and in other
cases we don’t restrict the grammar (except when there are real
ambiguities). So maybe the SC can accept a PRP for this?

On Mon, Feb 3, 2020 at 15:47 Ben Avrahami  wrote:

> Hi all, decorators are a very powerful feature in python, but it's syntax
> is strangely restrictive.
>
> decorator ::=  "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE
>
> for 99% of cases this is not a hindrance, but sometimes we'd rather be
> able to use full expression syntax. consider the following example (using
> PyQt):
>
> # make 10 buttons
> buttons = [QPushButton(f'button #{i}') for i in range(10)]
> # for now we only want to bind an event to the first button
> @buttons[0].clicked.connect
> def foo():
> ... # do whatever
>
> in cases such as this, it would be useful to have any expression
> acceptable as a decorator.
>
> In addition to other use cases such as chained function calling
> (@buttons_dict.get("foo"). clicked.connect), the restrictiveness of the
> decorator syntax seems like a strange oversight. Arbitrary expressions are
> already allowed in decorator lines as arguments, so allowing them as the
> called decorator shouldn't be too difficult.
>
> Any thoughts on this?
> ___
> 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/WOWD4P323DYDIGUQVWMESDWUG6QOW4MP/
> 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/FKE7ZFGUDCU5WVOE2QTD5XGMCNCOMETV/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] allow full expressions in decorators

2020-02-03 Thread Ben Avrahami
Hi all, decorators are a very powerful feature in python, but it's syntax
is strangely restrictive.

decorator ::=  "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE

for 99% of cases this is not a hindrance, but sometimes we'd rather be able
to use full expression syntax. consider the following example (using PyQt):

# make 10 buttons
buttons = [QPushButton(f'button #{i}') for i in range(10)]
# for now we only want to bind an event to the first button
@buttons[0].clicked.connect
def foo():
... # do whatever

in cases such as this, it would be useful to have any expression acceptable
as a decorator.

In addition to other use cases such as chained function calling
(@buttons_dict.get("foo"). clicked.connect), the restrictiveness of the
decorator syntax seems like a strange oversight. Arbitrary expressions are
already allowed in decorator lines as arguments, so allowing them as the
called decorator shouldn't be too difficult.

Any thoughts on this?
___
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/WOWD4P323DYDIGUQVWMESDWUG6QOW4MP/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: concurrent.futures cancel pending at Executor.shutdown

2020-02-03 Thread Miguel Ángel Prosper
Sincerely I would have to agree that it's seems a bit excessive the 
`cancel_on_error`, unless it enabled by default and implemented in the abstract 
class it should probably not be included, that was just an idea to keep 
backwards compatibility.

I will personally simply add subclass of my prefered executor with the 
following for my particular use case:

def __exit__(self, exc_type, exc_val, exc_tb):
self.shutdown(wait=True, cancel_futures=exc_val is not None)
return False

Again, I think aborting futures on uncaught exceptions make sense, but it would 
break backwards compatibility.
___
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/3XDUZPZS3VCGX2PJMZHILI2L65V7BEGS/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: addition of "nameof" operator

2020-02-03 Thread Andrew Barnert via Python-ideas
On Feb 3, 2020, at 10:25, Andrew Barnert  wrote:
> 
> This is the same as Smalltalk, ObjC, Ruby, f-script, and all of the other 
> languages that use the same dynamic type/data model as Python. And Smalltalk 
> was the first language to have practical refactoring tools (although I don’t 
> think they were called that until Ralph Johnson’s refactoring object browser 
> in the early 90s).
> 
> One difference between Python and most of the other Smalltalk-model languages 
> is that they use symbols or selectors or some other string-like type to name 
> methods, while Python uses plain old strings. If you have print(:bar, 
> foo.bar) obviously bar is the name of an attribute rather than normal text. 
> Dropping selectors from the language turns out to cause a lot fewer problems 
> than any Smalltalk devotee would have believed, just a few very small 
> problems—like the one nameof is trying to fix.
> 
> Meanwhile, unlike Smalltalk and most other languages with the same model, 
> Python has optional static typing. The other major Smalltalk-model language 
> that added optional static types is ObjectiveC—and one of the reasons was to 
> improve the navigation and refactoring tools. For example, if you have a 
> function that takes a `foo: Any` param (spelled `id foo` in ObjC) and there 
> are three unrelated types that all have a `bar` method, the tool will tell 
> you that it’s ambiguous which one you meant by `nameof bar` (spelled 
> `@sel(bar)`), and it can suggest that you either specify a type for `foo`, or 
> create an implicit ABC (a `@protocol` in ObjC terms) to own the method. If 
> you do the first, renaming Foo.bar to baz will change the selector; if you do 
> the latter, it will warn you that Foo.bar makes Foo conform to the Barable 
> protocol that you defined and there are selectors in your program that depend 
> on it being Barable, so do you want to break that or do you want to rename 
> Barable.bar and all of the classes that implement it instead? If you do 
> neither, it doesn’t guess, it tells you that there are two ambiguous uses of 
> the selectors and lets you see the two uses of the selector or the three 
> classes that define it, so you can proceed manually.
> 
> Of course this means that an IDE, object browser, or standalone refactoring 
> tool has to build a mapping from selector names to a list of implicit uses, 
> explicit uses, and definitions (including knowing which definitions are 
> inherited, and which are relied on by protocols)  for the whole program. But 
> that’s exactly what they do. That’s why RJBrowser takes a while to start up, 
> and why Xcode is constantly running clang on bits of your code in the 
> background as you edit.
> 
> Couldn’t a Python tool just also keep track of every string and substring 
> that has at least one match as a use or definition of an attribute? Yes. But 
> I think it’s obvious why this is a lot more work and at least a little less 
> useful. And that may be part of the reason Python has always had fewer 
> refactoring tools available than Smalltalk, ObjC, etc., which is why nameof 
> could be a useful addition.

All that being said, I’m not sure _how_ useful it would be in practice. Python 
has a chicken-and-egg problem that C#, ObjC, etc. don’t.

If the C#/ObjC devs add a new feature to their language, the Visual 
Studio/Xcode team next door adds a nameof-driven renaming feature to the 
refactoring tools in the IDE that 90% of C#/ObjC programmers use, and then then 
everyone who wants that feature starts using nameof.

If the Python devs add nameof, PyCharm, PyDev, etc. may not take advantage of 
it, and they may already have an often-good-enough heuristic-guessing feature 
for people who don’t use it. If not many people start using it, there will be 
even less motivation for PyCharm to take advantage of it, etc.

If a new feature has an obvious large benefit (and/or is fun enough to 
implement), like optional static typing, you can jump past that hurdle. If a 
new feature has other uses even without IDE support, like @dataclass, you can 
spiral over it. But nameof is neither; it might just be a dead-on-arrival 
feature that’s only ever used by a handful of large teams who build their own 
internal tools. (And that large internal-tool-building team could just define a 
builtin `def nameof(x: str): return x` to use while debugging and write an 
install-time or import-time transformer that just replaces every `nameof(x)` 
with `x` to eliminate the deployed runtime cost.)

Add in the fact that most people use the newest version of C# or ObjC for any 
new project, while Python developers often stay a version or 3 behind, and a 
breaking change like this would probably need a __future__ and/or deprecation 
schedule on top of that, and the problem looks even worse.

So, someone who wants this feature has to not only resolve all the confusion 
over what exactly is being proposed and how it helps, but also make the case 
that Python tools and Python

[Python-ideas] Re: addition of "nameof" operator

2020-02-03 Thread Andrew Barnert via Python-ideas
On Feb 3, 2020, at 03:59, Richard Damon  wrote:
> 
> On 2/3/20 12:02 AM, Bruce Leban wrote:
>> People keep mentioning refactoring. It's a red herring.
>> 
>> No refactoring tool needs a nameof operator added to the language in order 
>> to do its job. And certainly an operator that requires running the program 
>> in order to use it is not going to be helpful. Refactoring tools analyze the 
>> program; they don't run it.
>> 
>> And f-strings are another red herring. There is nothing magical about 
>> expressions inside f-strings compared to those outside.
>> 
>> Ignoring the red herrings, I see no utility in a nameof operator and no way 
>> for it to actually do anything useful.
>> 
>> --- Bruce
> 
> IF Python had a proper refactoring tool (see my other message where I 
> question the ability to do that) then the nameof operator would clearly help 
> keep logging/debug strings in line with the program definitions.
> 
> A statement like print("bar", foo.bar) would be very hard to notice that the 
> "bar" match the foo.bar, while
> 
> print(nameof(foo.bar), foo.bar) makes the connection explicit.
> 
> This is where such an operation could help with refactoring, having an actual 
> Python attribute reference that the refactoring operation could see, so it 
> knows that the string is based on that attribute and not something else.
> 
> As I mentioned elsewhere, the issue is that in Python, if we change the 
> attribute bar in class Foo, then we have the problem that we often can't tell 
> if in foo.bar if foo is of type Foo, so we should apply the change. This 
> isn't a problem is statically typed languages, as there we can determine the 
> type of foo, and see if the change applies (at least in most cases).

This is the same as Smalltalk, ObjC, Ruby, f-script, and all of the other 
languages that use the same dynamic type/data model as Python. And Smalltalk 
was the first language to have practical refactoring tools (although I don’t 
think they were called that until Ralph Johnson’s refactoring object browser in 
the early 90s).

One difference between Python and most of the other Smalltalk-model languages 
is that they use symbols or selectors or some other string-like type to name 
methods, while Python uses plain old strings. If you have print(:bar, foo.bar) 
obviously bar is the name of an attribute rather than normal text. Dropping 
selectors from the language turns out to cause a lot fewer problems than any 
Smalltalk devotee would have believed, just a few very small problems—like the 
one nameof is trying to fix.

Meanwhile, unlike Smalltalk and most other languages with the same model, 
Python has optional static typing. The other major Smalltalk-model language 
that added optional static types is ObjectiveC—and one of the reasons was to 
improve the navigation and refactoring tools. For example, if you have a 
function that takes a `foo: Any` param (spelled `id foo` in ObjC) and there are 
three unrelated types that all have a `bar` method, the tool will tell you that 
it’s ambiguous which one you meant by `nameof bar` (spelled `@sel(bar)`), and 
it can suggest that you either specify a type for `foo`, or create an implicit 
ABC (a `@protocol` in ObjC terms) to own the method. If you do the first, 
renaming Foo.bar to baz will change the selector; if you do the latter, it will 
warn you that Foo.bar makes Foo conform to the Barable protocol that you 
defined and there are selectors in your program that depend on it being 
Barable, so do you want to break that or do you want to rename Barable.bar and 
all of the classes that implement it instead? If you do neither, it doesn’t 
guess, it tells you that there are two ambiguous uses of the selectors and lets 
you see the two uses of the selector or the three classes that define it, so 
you can proceed manually.

Of course this means that an IDE, object browser, or standalone refactoring 
tool has to build a mapping from selector names to a list of implicit uses, 
explicit uses, and definitions (including knowing which definitions are 
inherited, and which are relied on by protocols)  for the whole program. But 
that’s exactly what they do. That’s why RJBrowser takes a while to start up, 
and why Xcode is constantly running clang on bits of your code in the 
background as you edit.

Couldn’t a Python tool just also keep track of every string and substring that 
has at least one match as a use or definition of an attribute? Yes. But I think 
it’s obvious why this is a lot more work and at least a little less useful. And 
that may be part of the reason Python has always had fewer refactoring tools 
available than Smalltalk, ObjC, etc., which is why nameof could be a useful 
addition.

___
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/a

[Python-ideas] Re: addition of "nameof" operator

2020-02-03 Thread Ricky Teachey
To restate the motivation: the hope is that there is a potentially large
benefit of being able to more easily refactor code with something like a
nameof().

I am going to make the claim that:

   1. this benefit is actually minimal and does not address a lot of other
   existing refactoring problems/chores, and
   2. comes at the cost of a possible loss of readability, and therefore
   isn't worth the trade

Consider the following typical code (I hope it is nice; I feel like I can
certainly read it):

import logging
import functools

class FunctionLogger:
"""Records use of a function.
The optional `log` parameter is to be a callable that accepts a string.
It is logging.info by default.
"""
log = logging.info
def __init__(self, log=None):
if log is not None:
self.log = log
def __call__(self, func):func_name = func.__name__
@functools.wraps(func)def wrapper(*args, **kwargs):
try:self.log(f"called {func_name!r}")
  except:cls_name = type(self).__name__
logging.exception(f"failed to log {func_name!r} call; is
{cls_name}.log set correctly?")finally:
return func(*args, **kwargs)return wrapper

Let's think through: what refactoring must occur to change the "log"
parameter to something else? And, how readable does the code remain
afterward?

At least some of the code could certainly benefit from being more
easily refactored (by an IDE) with nameof(), but how much?

import logging
import functools

class FunctionLogger:
# NOTE: this docstring will result in a runtime error, so can't
even use nameof() here to help ourselves
f"""Records use of a function.
The optional `{nameof(FunctionLogger.log)}` parameter is to be a
callable that accepts a string.
It is logging.info by default.
"""
log = logging.info  # no need for nameof() here, but see below *
def __init__(self, log=None):  # IDE will refactor the init
signature SEPARATELY (see below *)
if log is not None:  # no help from nameof() in __init__ body
# IDE will get this one just fine anyway; shouldn't use
nameof() in this situation
# using it actually hurts readability
setattr(self, nameof(self.log), log)
def __call__(self, func):
func_name = nameof(func)  # it's different, but NOT an
improvement over func.__name__
@functools.wraps(func)
def wrapper(*args, **kwargs):
try:
self.log(f"called {func_name!r}")
except:
cls_name = nameof(type(self))  # different, but NOT an
improvement over type(self).__name__
log_param_name = nameof(self.log)  # ok, HERE is a
place we are definitely going to benefit from nameof()
#  readability of next line might actually be slightly
improved...? But perhaps it's also worse...?
# but the IDE will refactor next line automatically,
which is handy.logging.exception(f"failed to log
{func_name!r} call; is {cls_name}.{log_param_name} set correctly?")
finally:return func(*args, **kwargs)
return wrapper

* For the class level member and init signature/body: the IDE won't know to
include the class member and the init signature/body in a refactor of a
member-level variable, and this problem isn't helped by nameof(). Multiple
refactoring chores have to be completed to change the parameter name: 1.
the init signature, 2. the class level variable, 3. object level variable,
4. the class docstring, 5. all of the f strings. Using a nameof() only
totally prevents one of them (the f strings; it can't help with the
docstring).

So I guess there is SOME benefit here. But I think it comes at the cost of
some potential loss of readability, and there are some major places in
which nameof() doesn't bring any help at all (looking at you, class
docstring).

And there is a ready alternative: use a global if you think you might
rename your parameters later (see code at bottom). This rolls TWO of the
refactoring chores into one (the f strings and the docstring).

*Bottom line: refactoring remains a chore. The win is minimal. Do nothing
option is preferred.*

import logging
import functools

_FOO = "foo"  # haven't decided on .foo member name yet...


class FunctionLogger:
# with a global, this docstring will work!
f"""Records use of a function.
The optional `{_FOO}` parameter is to be a callable that accepts a string.
It is logging.info by default.
"""
log = logging.info

def __init__(self, log=None):
if log is not None:
self.log = log

def __call__(self, func):
func_name = func.__name__

@functools.wraps(func)
def wrapper(*args, **kwargs):
try:
self.log(f"called {func_name!r}")
except:
cls_name = type(self).__name__
# employ the global below for the e

[Python-ideas] Re: concurrent.futures cancel pending at Executor.shutdown

2020-02-03 Thread Brian Quinlan
Thanks for all your hard work on the `cancel_futures` feature!

As you said, there is a complexity cost (both in terms of the API and the
implementation) whenever a new feature is added. The current
ProcessPoolExecutor implementation, in particular, is complex enough that I
can't easily easily reason about it's behavior and there are some
long-standing bugs that have been difficult to resolve. I was actually
hoping that we wouldn't touch the API for a while so I could do some
stability work.

I'm -0 on the `cancel_on_error` feature but maybe it would help to hear
about a concrete use case that can't be easily accomplished using the
current API?

Cheers,
Brian


On Mon, Feb 3, 2020 at 12:36 AM Kyle Stanley  wrote:

> Miguel Ángel Prosper wrote:
> > Thank you so much for the work, I was very confused on how to even start
> implementing it in the ProcessPoolExecutor, but you finished everything
> super quick!
>
> No problem! The ProcessPoolExecutor implementation wasn't immediately
> clear to me either, but after some experimentation (and some great
> suggestions from Brian Quinlain to improve it) I was able to get it
> functioning as intended. Thank you for the proposal, I think it will be a
> good addition for the Executor API.
>
> Miguel Ángel Prosper wrote:
> > I'm suppose that this might be better in another thread but... Could it
> be possible to changing the context manager of the executor to cancel
> futures on uncaught exceptions?
>
> Hmm, it should be possible. Do you specifically mean cancelling the
> pending futures once a single one of the submitted functions raises an
> exception, or cancelling the pending futures when the Executor itself
> raises an exception (I.E. BrokenProcessPool)? I would assume the prior,
> since that seems more useful to me.
>
> Miguel Ángel Prosper wrote:
> > If not I could also be added as an optional parameter to the executor
> constructor, "cancel_on_error" set to False to not changing anything.
>
> Assuming we did implement something like this, I'd say it should be done
> as an optional parameter for the constructor (as stated above) rather than
> as the default option when an exception occurs, because it would
> significantly different from the current behavior. At the moment, the
> executor doesn't mind when exceptions are raised from submitted functions;
> it simply sets the exception to the future (via ``future.set_exception()``)
> and moves on to the next.
>
> So, cancelling the pending futures after one raises an exception would be
> a significant behavioral change; one that could easily result in breaking
> existing code. As a result, I think it should be an optional parameter if
> anything.
>
> As far as whether or not it should be implemented, I'm not 100% certain.
> While I'm not against the idea of it, I think it would be reasonable to
> wait until the new parameter is released in Python 3.9 and see what users
> think of it prior to adding a similar parameter to the executor constructor
> as well. The cost of adding a new feature demanded by users is relatively
> minimal, but once it's added we're stuck with maintaining it.
>
> If the idea is approved, I'd be happy to help with implementing it. I just
> want to make sure that we actually want it in the first place.
>
> What do you think, Guido? I've also CC'd Brian Quinlain and Antoine
> Pitrou, in case they have any feedback but didn't see the original thread.
>
> On Mon, Feb 3, 2020 at 2:27 AM Miguel Ángel Prosper <
> miguelangel.pros...@gmail.com> wrote:
>
>> Thank you so much for the work, I was very confused on how to even start
>> implementing it in the ProcessPoolExecutor, but you finished everything
>> super quick!
>>
>> I'm suppose that this might be better in another thread but... Could it
>> be possible to changing the context manager of the executor to cancel
>> futures on uncaught exceptions? If not I could also be added as an optional
>> parameter to the executor constructor, "cancel_on_error" set to False to
>> not changing anything. Personally I was thinking of using the executor like
>> that; currently I have to either place everything in a try except block,
>> handle it and then reraise it or subclass each executor.
>> ___
>> 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/R5VMWP75K35KF3DJN2F5MBZXD5UOQIV3/
>> 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/5OK7BUEUACAHB7ZYHOPTXODVWCZWS5YB/
Code

[Python-ideas] Re: concurrent.futures cancel pending at Executor.shutdown

2020-02-03 Thread Miguel Ángel Prosper
> But, it would potentially risk adding an underutilized parameter to the 
> executor constructor (which contributes to feature bloat).

That's true, personally I would always enable cancel_on_error (making it 
redundant and implementing it in the abstract class), but that's just my use 
case. You can always add that functionality later with your own subclass.

Personally I think it make sense to do it by default but that's just me and it 
also changes current behaviour.
___
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/MMS3OGNA6XNKT63DYWVB4DZFHESLKOXM/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Annotated string literals

2020-02-03 Thread Antoine Rozo
Why don't you define a LOCALIZE function (x → x) like in your C example?

Le lun. 3 févr. 2020 à 13:01, Soni L.  a écrit :
>
>
>
> On 2020-02-02 11:29 p.m., Eric V. Smith wrote:
> > On 2/2/2020 8:28 PM, Soni L. wrote:
> >> It'd be cool to attach metadata to string literals that doesn't end
> >> up in the resulting string object. This metadata could be used by all
> >> sorts of tools, everything from localization to refactoring.
> >>
> >> In C, some localization libraries use macros for it, such as:
> >>
> >> #define LOCALIZE(s) s
> >>
> >> and it acts like an annotation, and then you do:
> >>
> >> printf("%s", get_localized(locale, LOCALIZE("This string gets
> >> extracted and used in language files")));
> >>
> >> And I think Python could do better and have special string literals
> >> explicitly for this purpose.
> >>
> >> It could even be something with fstrings, like: f"{#localize}This
> >> string gets extracted and used in language files"
> >>
> >> Ofc, there's nothing preventing one from using something like
> >> f"{(lambda _:'')('localize')}This string gets extracted and used in
> >> language files" today, but I feel like having some sort of dedicated
> >> syntax for it would be an improvement.
> >
> > You might want to look at PEP 501.
> >
> > Eric
>
> Oh. No, I want it to return plain strings.
>
> e.g. you should be able to replace an existing
>
> MY_STRING = "This string gets extracted and used in language files"
>
> with
>
> MY_STRING = [uhh idk what would go here tbh]
>
> and maintain full backwards-compatibility.
>
> It's for external tools to consume, not for python code to consume.
>
> >
> > ___
> > 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/GEBY52WVQBFB7J27MRJPZZPJMWUZZJWO/
> > 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/HY6N3CA2FEJL5EGY5QWJHBLP5KVETTD3/
> Code of Conduct: http://python.org/psf/codeofconduct/



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


[Python-ideas] Re: Annotated string literals

2020-02-03 Thread Soni L.




On 2020-02-02 11:29 p.m., Eric V. Smith wrote:

On 2/2/2020 8:28 PM, Soni L. wrote:
It'd be cool to attach metadata to string literals that doesn't end 
up in the resulting string object. This metadata could be used by all 
sorts of tools, everything from localization to refactoring.


In C, some localization libraries use macros for it, such as:

#define LOCALIZE(s) s

and it acts like an annotation, and then you do:

printf("%s", get_localized(locale, LOCALIZE("This string gets 
extracted and used in language files")));


And I think Python could do better and have special string literals 
explicitly for this purpose.


It could even be something with fstrings, like: f"{#localize}This 
string gets extracted and used in language files"


Ofc, there's nothing preventing one from using something like 
f"{(lambda _:'')('localize')}This string gets extracted and used in 
language files" today, but I feel like having some sort of dedicated 
syntax for it would be an improvement.


You might want to look at PEP 501.

Eric


Oh. No, I want it to return plain strings.

e.g. you should be able to replace an existing

MY_STRING = "This string gets extracted and used in language files"

with

MY_STRING = [uhh idk what would go here tbh]

and maintain full backwards-compatibility.

It's for external tools to consume, not for python code to consume.



___
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/GEBY52WVQBFB7J27MRJPZZPJMWUZZJWO/

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


[Python-ideas] Re: addition of "nameof" operator

2020-02-03 Thread Richard Damon

On 2/3/20 12:02 AM, Bruce Leban wrote:

People keep mentioning refactoring. It's a red herring.

No refactoring tool needs a nameof operator added to the language in 
order to do its job. And certainly an operator that requires running 
the program in order to use it is not going to be helpful. Refactoring 
tools analyze the program; they don't run it.


And f-strings are another red herring. There is nothing magical about 
expressions inside f-strings compared to those outside.


Ignoring the red herrings, I see no utility in a nameof operator and 
no way for it to actually do anything useful.


--- Bruce


IF Python had a proper refactoring tool (see my other message where I 
question the ability to do that) then the nameof operator would clearly 
help keep logging/debug strings in line with the program definitions.


A statement like print("bar", foo.bar) would be very hard to notice that 
the "bar" match the foo.bar, while


print(nameof(foo.bar), foo.bar) makes the connection explicit.

This is where such an operation could help with refactoring, having an 
actual Python attribute reference that the refactoring operation could 
see, so it knows that the string is based on that attribute and not 
something else.


As I mentioned elsewhere, the issue is that in Python, if we change the 
attribute bar in class Foo, then we have the problem that we often can't 
tell if in foo.bar if foo is of type Foo, so we should apply the change. 
This isn't a problem is statically typed languages, as there we can 
determine the type of foo, and see if the change applies (at least in 
most cases).


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


[Python-ideas] Re: concurrent.futures cancel pending at Executor.shutdown

2020-02-03 Thread Kyle Stanley
> Then if Executor.__exit__ detects an exception it would call shutdown
with cancel_futures set to True.

Oh, I see. That should be rather simple:

```
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_val is not None and self._cancel_on_error:
self.shutdown(wait=True, cancel_futures=True)
else:
self.shutdown(wait=True)
return False
```

(I believe the above would have to be specified as an override for each of
ThreadPoolExecutor and ProcessPoolExecutor if *cancel_on_error* were
supplied as a parameter to the executor constructor. They both currently
use the ``__exit__`` specified in the abstract Executor class, which
wouldn't have access to *cancel_on_error*.)

My previous consideration about waiting for user input of
*cancel_futures *after
the release of 3.9*, *before adding *cancel_on_error* to the constructor
still applies to some degree though. If it directly uses
executor.shutdown() with cancel_futures set to True, the maintenance would
be rather minimal. But, it would potentially risk adding an underutilized
parameter to the executor constructor (which contributes to feature bloat).

On Mon, Feb 3, 2020 at 4:03 AM Miguel Ángel Prosper <
miguelangel.pros...@gmail.com> wrote:

> > Hmm, it should be possible. Do you specifically mean cancelling the
> pending
> > futures once a single one of the submitted functions raises an exception,
> > or cancelling the pending futures when the Executor itself raises an
> > exception (I.E. BrokenProcessPool)? I would assume the prior, since that
> > seems more useful to me.
>
> I was referring to any exception within the context manager of the
> executor, not the futures or just the executor's exceptions, something such
> as the following:
>
> with ThreadPoolExecutor(cancel_on_error=True) as executor:
> # Code here
> raise Exception
>
>  Then if Executor.__exit__ detects an exception it would call shutdown
> with cancel_futures set to True.
> ___
> 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/OAMG4JUFK54FTAASHQG5WNAA7BU7KRS7/
> 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/GCKG347LGTROINXHYUVTN3IN4QTLGYRK/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: concurrent.futures cancel pending at Executor.shutdown

2020-02-03 Thread Miguel Ángel Prosper
> Hmm, it should be possible. Do you specifically mean cancelling the pending
> futures once a single one of the submitted functions raises an exception,
> or cancelling the pending futures when the Executor itself raises an
> exception (I.E. BrokenProcessPool)? I would assume the prior, since that
> seems more useful to me.

I was referring to any exception within the context manager of the executor, 
not the futures or just the executor's exceptions, something such as the 
following:

with ThreadPoolExecutor(cancel_on_error=True) as executor:
# Code here
raise Exception

 Then if Executor.__exit__ detects an exception it would call shutdown with 
cancel_futures set to True.
___
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/OAMG4JUFK54FTAASHQG5WNAA7BU7KRS7/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: concurrent.futures cancel pending at Executor.shutdown

2020-02-03 Thread Kyle Stanley
Miguel Ángel Prosper wrote:
> Thank you so much for the work, I was very confused on how to even start
implementing it in the ProcessPoolExecutor, but you finished everything
super quick!

No problem! The ProcessPoolExecutor implementation wasn't immediately clear
to me either, but after some experimentation (and some great suggestions
from Brian Quinlain to improve it) I was able to get it functioning as
intended. Thank you for the proposal, I think it will be a good addition
for the Executor API.

Miguel Ángel Prosper wrote:
> I'm suppose that this might be better in another thread but... Could it
be possible to changing the context manager of the executor to cancel
futures on uncaught exceptions?

Hmm, it should be possible. Do you specifically mean cancelling the pending
futures once a single one of the submitted functions raises an exception,
or cancelling the pending futures when the Executor itself raises an
exception (I.E. BrokenProcessPool)? I would assume the prior, since that
seems more useful to me.

Miguel Ángel Prosper wrote:
> If not I could also be added as an optional parameter to the executor
constructor, "cancel_on_error" set to False to not changing anything.

Assuming we did implement something like this, I'd say it should be done as
an optional parameter for the constructor (as stated above) rather than as
the default option when an exception occurs, because it would significantly
different from the current behavior. At the moment, the executor doesn't
mind when exceptions are raised from submitted functions; it simply sets
the exception to the future (via ``future.set_exception()``) and moves on
to the next.

So, cancelling the pending futures after one raises an exception would be a
significant behavioral change; one that could easily result in breaking
existing code. As a result, I think it should be an optional parameter if
anything.

As far as whether or not it should be implemented, I'm not 100% certain.
While I'm not against the idea of it, I think it would be reasonable to
wait until the new parameter is released in Python 3.9 and see what users
think of it prior to adding a similar parameter to the executor constructor
as well. The cost of adding a new feature demanded by users is relatively
minimal, but once it's added we're stuck with maintaining it.

If the idea is approved, I'd be happy to help with implementing it. I just
want to make sure that we actually want it in the first place.

What do you think, Guido? I've also CC'd Brian Quinlain and Antoine Pitrou,
in case they have any feedback but didn't see the original thread.

On Mon, Feb 3, 2020 at 2:27 AM Miguel Ángel Prosper <
miguelangel.pros...@gmail.com> wrote:

> Thank you so much for the work, I was very confused on how to even start
> implementing it in the ProcessPoolExecutor, but you finished everything
> super quick!
>
> I'm suppose that this might be better in another thread but... Could it be
> possible to changing the context manager of the executor to cancel futures
> on uncaught exceptions? If not I could also be added as an optional
> parameter to the executor constructor, "cancel_on_error" set to False to
> not changing anything. Personally I was thinking of using the executor like
> that; currently I have to either place everything in a try except block,
> handle it and then reraise it or subclass each executor.
> ___
> 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/R5VMWP75K35KF3DJN2F5MBZXD5UOQIV3/
> 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/PMIV2XIYGHULEBZVDG2Q5PBQJJXYB2LD/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] concurrent.futures deinitializer for Executor

2020-02-03 Thread Miguel Ángel Prosper
Hi, I thought maybe a callback before the worker of a Executor finishes would 
be helpful. It would allow the setup and teardown resources (such as file, 
databases, connections, ...) across workers. My particular use case is for 
closing down requests.Session objects, that currently its very complicated to 
cleanup properly. There are many other use cases, a generic format would be 
something like the following:

import threading
from concurrent.futures import ThreadPoolExecutor

worker_local = threading.local()

def session_initializer():
# Initialize costly resources for a particular worker
worker_local.resources = ...

def session_deinitializer():
# Deinitialize worker resources carefully
worker_local.resources ...

with ThreadPoolExecutor(initializer=session_initializer, 
deinitializer=session_deinitializer) as executor:
executor.submit(task)
...
___
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/BOKCVLL4B7COBVXFS5BPTTFTRFU3JKJD/
Code of Conduct: http://python.org/psf/codeofconduct/