[Python-Dev] Re: GDB not breaking at the right place

2021-05-21 Thread Guido van Rossum
Huh, you're right, I forgot that Py_LOCAL_AGGRESSIVE is specific to MSVC
(maybe it wasn't always).

I can think of nothing else apart from a gcc or gdb bug. Oh, hm, maybe
computed gotos play havoc with the labels???

On Fri, May 21, 2021 at 2:01 PM Skip Montanaro 
wrote:

>
>
> On Fri, May 21, 2021 at 2:48 PM Guido van Rossum  wrote:
>
>> I suspect that you're running into the issue where compiler optimizations
>> are *forced* on for ceval.c.
>>
>> There's a comment near the top about this. Just comment out this line:
>>
>> #define PY_LOCAL_AGGRESSIVE
>>
>> We tried to define that macro conditionally, but something broke because
>> the C stack frame for _PyEval_EvalFrameDefault became enormous without
>> optimization, and some tests failed. (Maybe it was Victor's refleak test?
>> The git history will tell you more if you're really interested.)
>>
>> This is a nasty trap (I fell in myself, so that makes it nasty :-), but
>> the proper fix would be convoluted -- we'd need a way to enable or disable
>> this separately so the specific test can run but developers trying to step
>> through ceval.c will be able to see the unoptimized code.
>>
>
> Thanks, Guido, however that doesn't seem to help. I grepped around for
> PY_LOCAL_AGGRESSIVE in the source. It seems to be specific to MSVC. Here's
> the definition in Include/pyport.h with a slight change to the indentation
> to demonstrate its scope better:
>
> #if defined(_MSC_VER)
> #  if defined(PY_LOCAL_AGGRESSIVE)
>  /* enable more aggressive optimization for MSVC */
>  /* active in both release and debug builds - see bpo-43271 */
> #pragma optimize("gt", on)
> #  endif
>/* ignore warnings if the compiler decides not to inline a function */
> #  pragma warning(disable: 4710)
>/* fastest possible local call under MSVC */
> #  define Py_LOCAL(type) static type __fastcall
> #  define Py_LOCAL_INLINE(type) static __inline type __fastcall
> #else
> #  define Py_LOCAL(type) static type
> #  define Py_LOCAL_INLINE(type) static inline type
> #endif
>
> I can move the actual point where GDB breaks by replacing -Og with -O0,
> but it still breaks at the wrong place, just a different wrong place. If I
> set a breakpoint by line number, it stops at the proper place.
>
> Skip
>
>

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

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


[Python-Dev] Re: GDB not breaking at the right place

2021-05-21 Thread Skip Montanaro
On Fri, May 21, 2021 at 2:48 PM Guido van Rossum  wrote:

> I suspect that you're running into the issue where compiler optimizations
> are *forced* on for ceval.c.
>
> There's a comment near the top about this. Just comment out this line:
>
> #define PY_LOCAL_AGGRESSIVE
>
> We tried to define that macro conditionally, but something broke because
> the C stack frame for _PyEval_EvalFrameDefault became enormous without
> optimization, and some tests failed. (Maybe it was Victor's refleak test?
> The git history will tell you more if you're really interested.)
>
> This is a nasty trap (I fell in myself, so that makes it nasty :-), but
> the proper fix would be convoluted -- we'd need a way to enable or disable
> this separately so the specific test can run but developers trying to step
> through ceval.c will be able to see the unoptimized code.
>

Thanks, Guido, however that doesn't seem to help. I grepped around for
PY_LOCAL_AGGRESSIVE in the source. It seems to be specific to MSVC. Here's
the definition in Include/pyport.h with a slight change to the indentation
to demonstrate its scope better:

#if defined(_MSC_VER)
#  if defined(PY_LOCAL_AGGRESSIVE)
 /* enable more aggressive optimization for MSVC */
 /* active in both release and debug builds - see bpo-43271 */
#pragma optimize("gt", on)
#  endif
   /* ignore warnings if the compiler decides not to inline a function */
#  pragma warning(disable: 4710)
   /* fastest possible local call under MSVC */
#  define Py_LOCAL(type) static type __fastcall
#  define Py_LOCAL_INLINE(type) static __inline type __fastcall
#else
#  define Py_LOCAL(type) static type
#  define Py_LOCAL_INLINE(type) static inline type
#endif

I can move the actual point where GDB breaks by replacing -Og with -O0, but
it still breaks at the wrong place, just a different wrong place. If I set
a breakpoint by line number, it stops at the proper place.

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


[Python-Dev] Re: GDB not breaking at the right place

2021-05-21 Thread Guido van Rossum
I suspect that you're running into the issue where compiler optimizations
are *forced* on for ceval.c.

There's a comment near the top about this. Just comment out this line:

#define PY_LOCAL_AGGRESSIVE

We tried to define that macro conditionally, but something broke because
the C stack frame for _PyEval_EvalFrameDefault became enormous without
optimization, and some tests failed. (Maybe it was Victor's refleak test?
The git history will tell you more if you're really interested.)

This is a nasty trap (I fell in myself, so that makes it nasty :-), but the
proper fix would be convoluted -- we'd need a way to enable or disable this
separately so the specific test can run but developers trying to step
through ceval.c will be able to see the unoptimized code.

On Fri, May 21, 2021 at 12:40 PM Skip Montanaro 
wrote:

> I'm having a hard time debugging some virtual machine code because GDB
> won't break where it's supposed to. Here's my breakpoint #2:
>
> 2   breakpoint keep y   0x556914fd
> ceval_reg.h:_PyEval_EvalFrameDefault:TARGET_JUMP_IF_FALSE_REG
> breakpoint already hit 1 time
> p/x oparg
> p (oparg >> 16) & 0xff | (oparg >> 8) & 0xff
> p oparg & 0xff
> p *fastlocals@4
>
> but when it breaks, it's not at the beginning of the case (that is, where
> the TARGET_JUMP_IF_FALSE_REG label is defined), but inside the SETLOCAL
> macro of the COMPAR_OP_REG case! (That is, it's not anywhere close to the
> correct place.)
>
> case TARGET(COMPARE_OP_REG): {
> int dst = REGARG4(oparg);
> int src1 = REGARG3(oparg);
> int src2 = REGARG2(oparg);
> int cmpop = REGARG1(oparg);
> assert(cmpop <= Py_GE);
> PyObject *left = GETLOCAL(src1);
> PyObject *right = GETLOCAL(src2);
> PyObject *res = PyObject_RichCompare(left, right, cmpop);
> *SETLOCAL(dst, res);*
> if (res == NULL)
> goto error;
> DISPATCH();
> }
>
> It actually breaks in the Py_XDECREF which is part of the SETLOCAL macro:
>
> #define SETLOCAL(i, value)  do { PyObject *tmp = GETLOCAL(i); \
>  GETLOCAL(i) = value; \
>  *Py_XDECREF(tmp)*; } while (0)
>
> (actually, in the Py_DECREF underneath the Py_XDECREF macro). I've
> configured like so:
>
> ./configure --with-pydebug --with-tracerefs --with-assertions
>
> Python/ceval.c is compiled with this GCC command:
>
> gcc -pthread -c -Wno-unused-result -Wsign-compare -g -Og -Wall-std=c99
> -Wextra -Wno-unused-result -Wno-unused-parameter
> -Wno-missing-field-initializers -Wstrict-prototypes
> -Werror=implicit-function-declaration -fvisibility=hidden
>  -I./Include/internal  -I. -I./Include-DPy_BUILD_CORE -o Python/ceval.o
> Python/ceval.c
>
> I don't know if this is a GCC problem, a GDB problem, or a Skip problem. Is
> there more I can do to help the tool chain break at the correct place? It
> seems that if I break at a hard line number, GDB does the right thing, but
> I'd kind of prefer to use the symbolic label instead. I rather like the
> notion of breaking at a label name, but if GCC/GDB can't figure things out,
> I guess I'll have to live with line numbers.
>
> Thanks,
>
> Skip
>
> ___
> Python-Dev mailing list -- python-dev@python.org
> To unsubscribe send an email to python-dev-le...@python.org
> https://mail.python.org/mailman3/lists/python-dev.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-dev@python.org/message/EOTDLRRUR6J6KMM6ZKBDJDAZLBEY6BBP/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


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

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


[Python-Dev] GDB not breaking at the right place

2021-05-21 Thread Skip Montanaro
I'm having a hard time debugging some virtual machine code because GDB
won't break where it's supposed to. Here's my breakpoint #2:

2   breakpoint keep y   0x556914fd
ceval_reg.h:_PyEval_EvalFrameDefault:TARGET_JUMP_IF_FALSE_REG
breakpoint already hit 1 time
p/x oparg
p (oparg >> 16) & 0xff | (oparg >> 8) & 0xff
p oparg & 0xff
p *fastlocals@4

but when it breaks, it's not at the beginning of the case (that is, where
the TARGET_JUMP_IF_FALSE_REG label is defined), but inside the SETLOCAL
macro of the COMPAR_OP_REG case! (That is, it's not anywhere close to the
correct place.)

case TARGET(COMPARE_OP_REG): {
int dst = REGARG4(oparg);
int src1 = REGARG3(oparg);
int src2 = REGARG2(oparg);
int cmpop = REGARG1(oparg);
assert(cmpop <= Py_GE);
PyObject *left = GETLOCAL(src1);
PyObject *right = GETLOCAL(src2);
PyObject *res = PyObject_RichCompare(left, right, cmpop);
*SETLOCAL(dst, res);*
if (res == NULL)
goto error;
DISPATCH();
}

It actually breaks in the Py_XDECREF which is part of the SETLOCAL macro:

#define SETLOCAL(i, value)  do { PyObject *tmp = GETLOCAL(i); \
 GETLOCAL(i) = value; \
 *Py_XDECREF(tmp)*; } while (0)

(actually, in the Py_DECREF underneath the Py_XDECREF macro). I've
configured like so:

./configure --with-pydebug --with-tracerefs --with-assertions

Python/ceval.c is compiled with this GCC command:

gcc -pthread -c -Wno-unused-result -Wsign-compare -g -Og -Wall-std=c99
-Wextra -Wno-unused-result -Wno-unused-parameter
-Wno-missing-field-initializers -Wstrict-prototypes
-Werror=implicit-function-declaration -fvisibility=hidden
 -I./Include/internal  -I. -I./Include-DPy_BUILD_CORE -o Python/ceval.o
Python/ceval.c

I don't know if this is a GCC problem, a GDB problem, or a Skip problem. Is
there more I can do to help the tool chain break at the correct place? It
seems that if I break at a hard line number, GDB does the right thing, but
I'd kind of prefer to use the symbolic label instead. I rather like the
notion of breaking at a label name, but if GCC/GDB can't figure things out,
I guess I'll have to live with line numbers.

Thanks,

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


[Python-Dev] Summary of Python tracker Issues

2021-05-21 Thread Python tracker

ACTIVITY SUMMARY (2021-05-14 - 2021-05-21)
Python tracker at https://bugs.python.org/

To view or respond to any of the issues listed below, click on the issue.
Do NOT respond to this message.

Issues counts and deltas:
  open7452 (+23)
  closed 48492 (+51)
  total  55944 (+74)

Open issues with patches: 2965 


Issues opened (57)
==

#39950: Add pathlib.Path.hardlink_to()
https://bugs.python.org/issue39950  reopened by barneygale

#42834: [subinterpreters] Convert "global" static variable caches in _
https://bugs.python.org/issue42834  reopened by kj

#44126: Support cross-compiling of cpython modules using setuptools
https://bugs.python.org/issue44126  reopened by jmoguill2

#44135: issubclass documentation doesn't explain tuple semantic
https://bugs.python.org/issue44135  opened by joaozinho

#44136: Remove pathlib flavours
https://bugs.python.org/issue44136  opened by barneygale

#44138: multiprocessing documentation should note behavior when proces
https://bugs.python.org/issue44138  opened by kushal-kumaran

#44140: WeakKeyDictionary should support lookup by id instead of hash
https://bugs.python.org/issue44140  opened by conchylicultor

#44142: ast.unparse: visually better code generation
https://bugs.python.org/issue44142  opened by BTaskaya

#44145: hmac.update is not releasing the GIL when openssl's hmac is us
https://bugs.python.org/issue44145  opened by gregory.p.smith

#44147: [WinError 193] %1 is not a valid Win32 application
https://bugs.python.org/issue44147  opened by bassel27

#44149: difflib.get_close_matches: Add `key` argument
https://bugs.python.org/issue44149  opened by mustafaquraish

#44151: Improve parameter names and return value ordering for linear_r
https://bugs.python.org/issue44151  opened by rhettinger

#44153: Signaling an asyncio subprocess might raise ProcessLookupError
https://bugs.python.org/issue44153  opened by syntaxcoloring

#44155: Race condition when using multiprocessing BaseManager and Pool
https://bugs.python.org/issue44155  opened by chenzhuowansui

#44156: [subinterpreters] Replace static string caches with subinterpr
https://bugs.python.org/issue44156  opened by kj

#44157: redirect_* should also redirect C-level streams
https://bugs.python.org/issue44157  opened by xmorel

#44158: Clarify documentation for redirected stdout/stderr when using 
https://bugs.python.org/issue44158  opened by tanty

#44159: mimetypes -  "strict" on Windows
https://bugs.python.org/issue44159  opened by Norman Lorrain

#44163: IDLE ValueError in HyperParser
https://bugs.python.org/issue44163  opened by rhettinger

#44164: Document what are resources in importlib.resources
https://bugs.python.org/issue44164  opened by FFY00

#44165: [sqlite3] sqlite3_prepare_v2 micro optimisation: pass string s
https://bugs.python.org/issue44165  opened by erlendaasland

#44166: Make IndexError messages for list more informative
https://bugs.python.org/issue44166  opened by miguendes

#44167: ipaddress.IPv6Address.is_private makes redundant checks
https://bugs.python.org/issue44167  opened by mjpieters

#44170: ShareableList cannot safely handle multibyte utf-8 characters
https://bugs.python.org/issue44170  opened by huwcbjones

#44172: curses module may call delwin() on original window before subw
https://bugs.python.org/issue44172  opened by michaelforney

#44173: Stored (uncompressed) ZipExtFile in zipfile can be seekable at
https://bugs.python.org/issue44173  opened by juniorjpdj

#44174: Unclear meaning of _Private__names in enum docs.
https://bugs.python.org/issue44174  opened by gregory.p.smith

#44175: What do "cased" and "uncased" mean?
https://bugs.python.org/issue44175  opened by otakutyrant

#44176: asyncio.as_completed() raises TypeError when the first supplie
https://bugs.python.org/issue44176  opened by alexdelorenzo

#44178: Add an interpreter-level critical section construct
https://bugs.python.org/issue44178  opened by xmorel

#44180: SyntaxError misidentified in 3.10.0b1 when = used instead of :
https://bugs.python.org/issue44180  opened by aroberge

#44181: SyntaxError in Python 3.10.0b1: wrong token for missing comma
https://bugs.python.org/issue44181  opened by aroberge

#44182: python-config.sh vs python-config.py inconsistency
https://bugs.python.org/issue44182  opened by millert

#44183: Can't install certificates if GUI tools are not installed on m
https://bugs.python.org/issue44183  opened by thetechconspiracy

#44184: crash on windows invoking flake8
https://bugs.python.org/issue44184  opened by Anthony Sottile

#44185: mock_open file handle __exit__ does not call close
https://bugs.python.org/issue44185  opened by williamsjoblom

#44186: TimedRotatingFileHandler overwrite log
https://bugs.python.org/issue44186  opened by aeg

#44187: Implement infrastructure for quickening and specializing
https://bugs.python.org/issue44187  opened by Mark.Shannon

#44188: ThreadPoolExecutor unbalanced semaphore count
https://bugs.python.org/issue44188  opened by 

[Python-Dev] Re: The repr of a sentinel

2021-05-21 Thread Steve Dower

On 5/21/2021 9:36 AM, Petr Viktorin wrote:

On 21. 05. 21 3:23, Eric V. Smith wrote:

On 5/20/2021 3:24 PM, Ronald Oussoren via Python-Dev wrote:

One example of this is the definition of dataclasses.field:

|dataclasses.||field|(/*/, /default=MISSING/, 
/default_factory=MISSING/, /repr=True/, /hash=None/, /init=True/, 
/compare=True/, /metadata=None/)


Completely agree. I'm opposed to Ellipsis as a sentinel for this 
reason, at least for dataclasses. I can easily see wanting to store an 
Ellipsis in a field of a dataclass that's describing a function's 
parameters. And I can even see it being the default= value. Not so 
much default_factory=, but they may as well be the same.


And this argument also works for any other single value.
Including the original None.

(It just might not be obvious at first, before that single value starts 
being used in lots of different contexts.)


I think it's a fairly obvious case, and a legitimate one to acknowledge 
(the array one less so - we're talking about a "missing parameter" 
sentinel, so you ought to be testing for it immediately and replacing 
with your preferred/secret default value, not using it for indexing 
without even checking it).


In the example above, it's fairly easy to pass "lambda: ..." as the 
default_factory to work around it, and besides, the existence of rare 
edge cases doesn't mean you have to force everyone into acting like 
they're a rare edge case.


All the other situations where we want arguments with unspecified 
default values can use ..., and the few cases where ... is a valid value 
(semantically, for the API, not syntactically) can spend the time 
figuring out a different API design.


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


[Python-Dev] Re: python-iterators mailing list on SourceForge

2021-05-21 Thread Julien Palard via Python-Dev
Le 5/11/21 à 8:39 PM, Guido van Rossum a écrit :
> I doubt that anyone has the keys to the python project on sourceforge
> any more... :-( We've abandoned that platform nearly two decades ago.

That's right…

Sourceforge staff mentionned there's the list of current admins here:

=> https://sourceforge.net/p/python/_members/

so if someone see its login there, you can try logging in and unhide the
mailing list, else I'll try to have sourceforge unhide it by hand.

--
[Julien Palard](https://mdk.fr)

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


[Python-Dev] Re: The repr of a sentinel

2021-05-21 Thread Luciano Ramalho
I was attracted to Python in 1998 because it seemed designed to make
the simple cases simple, and the hard cases possible.

My personal takeaway from this discussion: I will continue to advocate
for the use of Ellipsis as a sentinel in the *many* cases where it is
suitable.

For the hard cases, I will read the upcoming 46-page "PEP 973:
Parameterized Sentinel Factory Factory API" ;-)

Cheers,

Luciano


-- 
Luciano Ramalho
|  Author of Fluent Python (O'Reilly, 2015)
| http://shop.oreilly.com/product/0636920032519.do
|  Technical Principal at ThoughtWorks
|  Twitter: @ramalhoorg
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/3RXJFB4B5KWBG3F226KUE7ZM53URDLXP/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: PEP 659: Specializing Adaptive Interpreter

2021-05-21 Thread Stephen J. Turnbull
Christopher Barker writes:

 > I find this whole conversation confusing -- does anyone really think a
 > substantial performance boost to cPython is not a "good thing"?

 > [PyPy, Numba, Cython] are why Python is very useful today -- but
 > none of them make the case that making cPython run faster isn't a
 > worthy goal.

I don't understand why you think anybody, except maybe some crank who
caused the editors of Science or whatever it was to seriously
embarrass themselves, opposes the goal of making cPython run faster.

All I want is some sanity when advocating changes to Python.  For
performance work, tell us how much faster cPython is going to be,
explain where you got your numbers, and let us decide how we'll use
the cycles saved.  There's been a lot of nonsense peddled in support
of this proposal by the proponent and thirds parties, when all anybody
needs is

Mark says he can make cPython noticably faster
 and
   we believe him!

More important, Microsoft does.

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


[Python-Dev] Re: The repr of a sentinel

2021-05-21 Thread Petr Viktorin

On 21. 05. 21 3:23, Eric V. Smith wrote:

On 5/20/2021 3:24 PM, Ronald Oussoren via Python-Dev wrote:



On 20 May 2021, at 19:10, Luciano Ramalho > wrote:


I'd like to learn about use cases where `...` (a.k.a. `Ellipsis`) is
not a good sentinel. It's a pickable singleton testable with `is`,
readily available, and extremely unlikely to appear in a data stream.
Its repr is "Ellipsis".

If you don't like the name for this purpose, you can always define a
constant (that won't fix the `repr`, obviously, but helps with source
code readability).

SENTINEL = ...

I can't think of any case where I'd rather have my own custom
sentinel, or need a special API for sentinels. Probably my fault, of
course. Please enlighten me!


One use case for a sentinel that is not a predefined (builtin) 
singleton is APIs where an arbitrary user specified value can be used.


One example of this is the definition of dataclasses.field:

|dataclasses.||field|(/*/, /default=MISSING/, 
/default_factory=MISSING/, /repr=True/, /hash=None/, /init=True/, 
/compare=True/, /metadata=None/)


Here the “default” and “default_factory” can be an arbitrary value, 
and any builtin singleton could be used. Hence the use of a custom 
module-private sentinel that cannot clash with values used by users of 
the module (unless those users poke at private details of the module, 
but then all bets are off anyway).


That’s why I don’t particularly like the proposal of using Ellipsis as 
the sanctioned sentinel value. It would be weird at best that the 
default for a dataclass field can be any value, except for the builtin 
Ellipsis value.


Completely agree. I'm opposed to Ellipsis as a sentinel for this reason, 
at least for dataclasses. I can easily see wanting to store an Ellipsis 
in a field of a dataclass that's describing a function's parameters. And 
I can even see it being the default= value. Not so much 
default_factory=, but they may as well be the same.



And this argument also works for any other single value.
Including the original None.

(It just might not be obvious at first, before that single value starts 
being used in lots of different contexts.)

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