Add a developer mode to Python: -X dev command line option

Hi,
The discussion on DeprecationWarning reminded me my old idea of a "development mode" for CPython: -X dev. Since Brett likes it, I post it on python-dev. Last year, I posted this idea to python-ideas but my idea was rejected:
https://mail.python.org/pipermail/python-ideas/2016-March/039314.html
In short: python3.7 -X dev script.py behaves as: PYTHONMALLOC=debug python3.7 -Wd -b -X faulthandler script.py
The idea of -X dev is to enable "debug checks". Some of these checks are already enabled by default if CPython is compiled in debug mode. These checks help to debug bugs earlier.
The problem is that outside CPython development, Python developers use a Python binary from their Linux distributor or a binary installed from python.org: a binary compiled in release mode. Well, some Linux distributions provide a debug build, but the ABI is incompatible, and so is hard to use in practice.
Running the tests of your code in -X dev mode should help you to catch subtle bugs and prevent regressions if you upgrade Python.
The -X dev mode doesn't raise hard exceptions, but usually only emits warnings. It allows you to fix bugs one by one in your own code, without having to fix bugs in third party code.
If you control your whole code base, you may want to enable -X dev=strict which raises hard exceptions, to make sure that you are really safe.
My "-X dev" idea is not incompatible with Nick's PEP 565 "Show DeprecationWarning in __main__" and it's different: it's an opt-in option, while Nick wants to change the default behaviour.
---
Full copy of my email sent last year to python-ideas.
When I develop on CPython, I'm always building Python in debug mode using ./configure --with-pydebug. This mode enables a *lot* of extra checks which helps me to detect bugs earlier. The debug mode makes Python much slower and so is not the default. "python3" in Linux distributions is a binary compiled in release mode. When they also provide a binary compiled in debug mode, you will probably have issues to use your existing C extensions, since they all of them are compiled in release mode which is not compatible (you must recompile C extensions in debug mode).
I propose to add a "development mode" to Python, to get a few checks to detect bugs earlier: a new -X dev command line option. Example:
python3.6 -X dev script.py
Checks enabled by this flag must:
* Not flood the stdout/stderr (ex: don't write one message per second) * Have a low overhead in term of CPU and memory (ex: max 10%)
I propose to enable:
* Show DeprecationWarning and ResourceWarning warnings: python -Wd * Show BytesWarning warning: python -b * Enable Python assertions (assert) and set __debug__ to True: remove (or just ignore) -O or -OO command line arguments * faulthandler to get a Python traceback on segfault and fatal errors: python -X faulthandler * Debug hooks on Python memory allocators: PYTHONMALLOC=debug
For example, I consider that enabling tracemalloc is too expensive (CPU & memory) and must not be enabled in -X dev.
I wrote a proof-of-concept: if -X dev is used, executable Python once again with more parameters. Basically, replace: python3.6 -X dev ... with PYTHONMALLOC=debug python3.6 -Wd -b -X faulthandler ...
The list of checks can be extended later. For example, we may enable the debug mode of asyncio: PYTHONASYNCIODEBUG=1.
The scope of the "developer mode" is unclear to me. Many modules (ex: asyncio) already have a debug mode. Would it be a bad idea to enable *all* debug modes of *all* modules? For example, http.client has a debug level: do you expect debug traces of the HTTP client when you develop your application?
IMHO the scope must be well defined: don't modify modules of the stdlib, only enable more debug flags in the Python core (warnings, unicode, memory allocators, etc.).
Maybe we even a need -X dev=strict which would be stricter:
* use -Werror instead of -Wd: raise an exception when a warning is emitted * use -bb instead of -b: get BytesWarning exceptions * Replace "inconsistent use of tabs and spaces in indentation" warning with an error in the Python parser * etc.
Again, this list can be extended later.
Or maybe we need multiple level to control the quantity of debug traces, warnings, ... written into stdout/stderr?
In my experience, the problem with converting warnings to errors is that you don't control the code of your whole application. It's common that third party modules raise DeprecationWarning, ResourceWarning, etc. Even some modules of the Python stdlib raise DeprecatingWarning! For example, I recall that distutils raises a DeprecationWarning on Python 3.4 when importing the imp module.
"Similar" idea in other programming languages:
* Perl: http://perldoc.perl.org/strict.html * PHP: https://secure.php.net/manual/fr/function.error-reporting.php
Victor

On Mon, 13 Nov 2017 17:08:06 +0100 Victor Stinner victor.stinner@gmail.com wrote:
Hi,
The discussion on DeprecationWarning reminded me my old idea of a "development mode" for CPython: -X dev. Since Brett likes it, I post it on python-dev. Last year, I posted this idea to python-ideas but my idea was rejected:
https://mail.python.org/pipermail/python-ideas/2016-March/039314.html
In short: python3.7 -X dev script.py behaves as: PYTHONMALLOC=debug python3.7 -Wd -b -X faulthandler script.py
I would personally not add `-b` in those options. I think it was useful while porting stuff to 3.x, but not so much these days.
Regards
Antoine.

2017-11-13 17:40 GMT+01:00 Antoine Pitrou solipsis@pitrou.net:
I would personally not add `-b` in those options. I think it was useful while porting stuff to 3.x, but not so much these days.
You should consider youself as lucky if you completed to port all your code to Python 3. It's not my case yet :-) (I'm thinking to code that I have to port, not only code that I wrote myself.)
I confirm that I usually use -b while I'm porting code from Python 2 to Python 3. So, usually I know that I will get Python 3 compatibility issues. Sometimes, you may still get Python 3 compatibility issues while the project is already tagged as "compatible with Python 3", just because you get into a code path which wasn't properyl tested before.
Well, I don't have a strong opinion on -b.
Victor

Le 13/11/2017 à 17:46, Victor Stinner a écrit :
2017-11-13 17:40 GMT+01:00 Antoine Pitrou solipsis@pitrou.net:
I would personally not add `-b` in those options. I think it was useful while porting stuff to 3.x, but not so much these days.
You should consider youself as lucky if you completed to port all your code to Python 3. It's not my case yet :-) (I'm thinking to code that I have to port, not only code that I wrote myself.)
The main issue I have with `-b` is actually that you can get spurious warnings about properly working code. You can also get warnings in well-tested third-party libraries, e.g.:
distributed/tests/test_client.py::test_get_versions /home/antoine/miniconda3/envs/dask36/lib/python3.6/site-packages/pandas/core/dtypes/common.py:20: BytesWarning: Comparison between bytes and string for t in ['O', 'int8', 'uint8', 'int16', 'uint16', /home/antoine/miniconda3/envs/dask36/lib/python3.6/site-packages/pandas/io/packers.py:231: BytesWarning: Comparison between bytes and string 7: np.dtype('int64'),
distributed/tests/test_client.py::test_serialize_collections_of_futures_sync /home/antoine/miniconda3/envs/dask36/lib/python3.6/site-packages/numpy/core/numeric.py:583: BytesWarning: Comparison between bytes and string return array(a, dtype, copy=False, order=order, subok=True)
distributed/tests/test_client.py::test_serialize_collections_of_futures /home/antoine/miniconda3/envs/dask36/lib/python3.6/site-packages/numpy/core/numeric.py:583: BytesWarning: Comparison between bytes and string return array(a, dtype, copy=False, order=order, subok=True)
(this is an excerpt of the warnings I got by running our test suite with "python -b")
Regards
Antoine.

2017-11-13 17:51 GMT+01:00 Antoine Pitrou antoine@python.org:
The main issue I have with `-b` is actually that you can get spurious warnings about properly working code. You can also get warnings in well-tested third-party libraries, e.g.:
distributed/tests/test_client.py::test_get_versions /home/antoine/miniconda3/envs/dask36/lib/python3.6/site-packages/pandas/core/dtypes/common.py:20: BytesWarning: Comparison between bytes and string for t in ['O', 'int8', 'uint8', 'int16', 'uint16', /home/antoine/miniconda3/envs/dask36/lib/python3.6/site-packages/pandas/io/packers.py:231: BytesWarning: Comparison between bytes and string 7: np.dtype('int64'),
Oh right, that's a very good reason to not include -b option in the -X dev mode ;-)
Usually, I mostly care of ResourceWarning and DeprecationWarning warnings.
PYTHONMALLOC=debug and -X faulthandler just comes "for free", they don't change the behaviour as -b, and should help to debug crashes.
---
By the way, My worst memory of BytesWarning is when implemented/fixed (I don't call) os.get_exec_path():
# {b'PATH': ...}.get('PATH') and {'PATH': ...}.get(b'PATH') emit a # BytesWarning when using python -b or python -bb: ignore the warning with warnings.catch_warnings(): warnings.simplefilter("ignore", BytesWarning) ...
I really dislike this code since warnings.catch_warnings() is process-wide and so impact other threads :-(
(Maybe Yury's PEP "context variables" would help here? ;-))
Victor

On Mon, 13 Nov 2017 18:19:07 +0100 Victor Stinner victor.stinner@gmail.com wrote:
I really dislike this code since warnings.catch_warnings() is process-wide and so impact other threads :-(
(Maybe Yury's PEP "context variables" would help here? ;-))
They can't really help unless we break the catch_warnings() API to make it affect some kind of thread-local warning settings (which don't exist currently).
Regards
Antoine.

13.11.17 18:40, Antoine Pitrou пише:
On Mon, 13 Nov 2017 17:08:06 +0100 Victor Stinner victor.stinner@gmail.com wrote:
In short: python3.7 -X dev script.py behaves as: PYTHONMALLOC=debug python3.7 -Wd -b -X faulthandler script.py
I would personally not add `-b` in those options. I think it was useful while porting stuff to 3.x, but not so much these days.
I concur with Antoine.

On 14 November 2017 at 02:08, Victor Stinner victor.stinner@gmail.com wrote:
My "-X dev" idea is not incompatible with Nick's PEP 565 "Show DeprecationWarning in __main__" and it's different: it's an opt-in option, while Nick wants to change the default behaviour.
I'm +1 on a `-X dev` mode, since it enables a lot of things that are useful for making an application more robust (extension module debugging, explicit scope-controlled resource management) that I wouldn't want turned at the REPL by default. It also implicitly adjusts over time as we add more debugging capabilities.
I don't consider it a replacement for tweaking how we handle DeprecationWarning by default, though :)
Cheers, Nick.

Hi,
Since Brett and Nick like the idea and nobody complained against it, I implemented the -X dev option: https://bugs.python.org/issue32043 (Right now, it's a pull request.)
I removed the -b option.
Victor
2017-11-14 3:57 GMT+01:00 Nick Coghlan ncoghlan@gmail.com:
On 14 November 2017 at 02:08, Victor Stinner victor.stinner@gmail.com wrote:
My "-X dev" idea is not incompatible with Nick's PEP 565 "Show DeprecationWarning in __main__" and it's different: it's an opt-in option, while Nick wants to change the default behaviour.
I'm +1 on a `-X dev` mode, since it enables a lot of things that are useful for making an application more robust (extension module debugging, explicit scope-controlled resource management) that I wouldn't want turned at the REPL by default. It also implicitly adjusts over time as we add more debugging capabilities.
I don't consider it a replacement for tweaking how we handle DeprecationWarning by default, though :)
Cheers, Nick.
-- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Ok, I merged my PR adding -X dev: you can now test in Python 3.7 ;-)
The list of checks can be extended later. For example, we may enable the debug mode of asyncio: PYTHONASYNCIODEBUG=1.
I opened https://bugs.python.org/issue32047 to propose enable asyncio debug mode using the Python developer mode.
What do you think? Is it ok to include asyncio in the global "developer mode"?
Victor

On Thu, 16 Nov 2017 12:53:24 +0100 Victor Stinner victor.stinner@gmail.com wrote:
Ok, I merged my PR adding -X dev: you can now test in Python 3.7 ;-)
The list of checks can be extended later. For example, we may enable the debug mode of asyncio: PYTHONASYNCIODEBUG=1.
I opened https://bugs.python.org/issue32047 to propose enable asyncio debug mode using the Python developer mode.
What do you think? Is it ok to include asyncio in the global "developer mode"?
I'd rather not. Those are two orthogonal things. In particular, asyncio debug mode is quite expensive.
Regards
Antoine.

2017-11-16 13:09 GMT+01:00 Antoine Pitrou solipsis@pitrou.net:
What do you think? Is it ok to include asyncio in the global "developer mode"?
I'd rather not. Those are two orthogonal things. In particular, asyncio debug mode is quite expensive.
Is it really an issue? When you develop an application, the performance of the application shouldn't be an issue no? From my point of view, it's the purpose of the opt-in developer mode: enable "expensive" checks at runtime. But you are right that the cost of the checks should be evaluated.
About asyncio debug mode, if it's too expensive to be used to develop an application, maybe there is an issue with additional checks? Should we remove some of them to be able to use asyncio debug mode in more cases?
Victor

Le 16/11/2017 à 13:38, Victor Stinner a écrit :
2017-11-16 13:09 GMT+01:00 Antoine Pitrou solipsis@pitrou.net:
What do you think? Is it ok to include asyncio in the global "developer mode"?
I'd rather not. Those are two orthogonal things. In particular, asyncio debug mode is quite expensive.
Is it really an issue? When you develop an application, the performance of the application shouldn't be an issue no?
When you develop an application, you can run functional tests which have timing requirements (or simply be too annoying to run if runtimes are multiplied by 2 or more). In that case it is good to enable "cheap" debug checks (those that have less than a 20% cost) while leaving the expensive ones disabled.
About asyncio debug mode, if it's too expensive to be used to develop an application, maybe there is an issue with additional checks? Should we remove some of them to be able to use asyncio debug mode in more cases?
Well, I'm sure some people like them, otherwise they wouldn't have been added to the codebase in the first place :-) For example, knowing where a Future was created can make debug logs much more informative.
(see https://bugs.python.org/issue31970)
Regards
Antoine.

2017-11-16 13:43 GMT+01:00 Antoine Pitrou antoine@python.org:
About asyncio debug mode, if it's too expensive to be used to develop an application, maybe there is an issue with additional checks? Should we remove some of them to be able to use asyncio debug mode in more cases?
Well, I'm sure some people like them, otherwise they wouldn't have been added to the codebase in the first place :-) For example, knowing where a Future was created can make debug logs much more informative.
The most expensive part of asyncio debug mode is the code to extracts the current stack when a coroutine or a handle is created.
Would it make sense to modify asyncio debug mode to skip the traceback by default, but add a second debug level which extracts the traceback?
Victor

On Thu, Nov 16, 2017 at 7:56 AM, Victor Stinner victor.stinner@gmail.com wrote:
2017-11-16 13:43 GMT+01:00 Antoine Pitrou antoine@python.org:
About asyncio debug mode, if it's too expensive to be used to develop an application, maybe there is an issue with additional checks? Should we remove some of them to be able to use asyncio debug mode in more cases?
Well, I'm sure some people like them, otherwise they wouldn't have been added to the codebase in the first place :-) For example, knowing where a Future was created can make debug logs much more informative.
The most expensive part of asyncio debug mode is the code to extracts the current stack when a coroutine or a handle is created.
Probably the most expensive part of asyncio debug mode is all coroutines wrapped with CoroWrapper. This makes every "await" and coroutine instantiation much slower (think 2-3x).
Would it make sense to modify asyncio debug mode to skip the traceback by default, but add a second debug level which extracts the traceback?
Let's keep it simple. I'm big -1 on adding different "debug levels", they are always confusing.
Overall I don't see an issue with enabling asyncio debug mode when python is executed with "-X dev". If the purpose of the flag is to make Python super verbose and it will not be recommended to use it in production -- then why not.
Yury

On Nov 16, 2017, at 09:47, Yury Selivanov yselivanov.ml@gmail.com wrote:
Let's keep it simple. I'm big -1 on adding different "debug levels", they are always confusing.
Oh, this one’s easy.
-X dev == some debugging -X deve == a little more -X devel == give it to me! -X develo == now you’re talking (literally) -X develop == thank you sir, may I have another? -X develope == here comes the flood -X developer == needle inna haystack!
Cheers, -Barry

On 11/16/2017 7:39 AM, Barry Warsaw wrote:
On Nov 16, 2017, at 09:47, Yury Selivanov yselivanov.ml@gmail.com wrote:
Let's keep it simple. I'm big -1 on adding different "debug levels", they are always confusing.
Oh, this one’s easy.
-X dev == some debugging -X deve == a little more -X devel == give it to me!
This is the "devel level", where you solve those bugs from hell...
-X develo == now you’re talking (literally) -X develop == thank you sir, may I have another? -X develope == here comes the flood -X developer == needle inna haystack!
Cheers, -Barry
Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/v%2Bpython%40g.nevcal.com

2017-11-16 15:47 GMT+01:00 Yury Selivanov yselivanov.ml@gmail.com:
Overall I don't see an issue with enabling asyncio debug mode when python is executed with "-X dev".
Cool!
If the purpose of the flag is to make Python super verbose and it will not be recommended to use it in production -- then why not.
Running an application in debug mode or "developer mode" was never recommanded by anyone. Who runs Django in debug mode on production? :-) (Nobody, I hope.)
I'm working on the -X dev documentation to clarify its purpose.
No, the developer mode must not flood stdout with debug messages. It should only emit warnings if a potential or real bug is detected. For example, I don't want to enable the debug mode of ftplib in the developer mode, since this option logs each FTP command to stdout. It's a different use case.
About performance, IMHO the purpose of the developer mode is to enable additional checks to ease debug, checks were are too expensive to be enabled by default. This definition fits well with the asyncio debug mode.
Victor

My draft addition to the -X dev doc: """ The developer mode is different from the "debug mode" of some modules of the standard library which enables a lot of debug logs. The developer mode should only log a warning if a potential bug is detected.
The developer mode has a limited effect. Many modules of the standard library have their own "debug mode" which is not enabled in the developer mode. See also the :data:`__debug__` flag disabled by the :option:`-O` option, and :data:`sys.flags.debug` enabled by the :option:`-d` option. """
You forgot the infamous -d option!
Honestly, I never used __debug__ nor sys.flags.debug.
I like adding yet another option to confuse people a little bit more!
Victor
2017-11-16 17:52 GMT+01:00 Antoine Pitrou antoine@python.org:
Le 16/11/2017 à 17:42, Victor Stinner a écrit :
Running an application in debug mode or "developer mode" was never recommanded by anyone.
I don't know. Almost everyone runs Python with __debug__ set to True :-)
Regards
Antoine. _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/victor.stinner%40gmail.co...

On Nov 16, 2017, at 06:53, Victor Stinner victor.stinner@gmail.com wrote:
What do you think? Is it ok to include asyncio in the global "developer mode"?
I’m +1 on that, and the performance hit doesn’t bother me for a developer mode.
-Barry

On Thu, 16 Nov 2017 03:57:49 +0100 Victor Stinner victor.stinner@gmail.com wrote:
Hi,
Since Brett and Nick like the idea and nobody complained against it, I implemented the -X dev option: https://bugs.python.org/issue32043 (Right now, it's a pull request.)
Could you measure and perhaps document the expected effect on performance and memory consumption? (it can be a very rough ballpart estimate)
Regards
Antoine.

2017-11-16 13:11 GMT+01:00 Antoine Pitrou solipsis@pitrou.net:
Could you measure and perhaps document the expected effect on performance and memory consumption? (it can be a very rough ballpart estimate)
Currently "python3 -X dev script.py" behaves as "PYTHONMALLOC=debug python3 -W default -X faulthandler script.py".
faulthandler has a negligible cost on performance/memory.
For -W default, I guess that your question is the cost on emitting a warning: overhead when a warning is displayed, and overhead when the warning is filtered. Right?
IMHO the most expensive check is PYTHONMALLOC=debug which increases a lot the memory usage.
You can measure the difference using tracemalloc and PYTHONMALLOC:
haypo@selma$ PYTHONMALLOC=debug ./python -X tracemalloc -i -m test test_os (...)
import tracemalloc; tracemalloc.get_traced_memory()
(10719623, 10981725)
haypo@selma$ PYTHONMALLOC=debug ./python -X tracemalloc -i -m test test_os (...)
import tracemalloc; tracemalloc.get_traced_memory()
(10724064, 16577338)
For example, on test_os, PYTHONMALLOC=debug increases the peak memory usage from 10.5 MiB to 15.8 MiB: +50%.
PYTHONMALLOC=debug adds 4 * sizeof(size_t) bytes to each allocated memory block. For example, an empty tuple uses 64 bytes, but PYTHONMALLOC=debug allocates 96 bytes (+ 32 bytes) in 64-bit mode.
Victor

Hi Victor,
Thanks for the answer!
Le 16/11/2017 à 13:48, Victor Stinner a écrit :
faulthandler has a negligible cost on performance/memory.
For -W default, I guess that your question is the cost on emitting a warning: overhead when a warning is displayed, and overhead when the warning is filtered. Right?
-Wdefault means -Wonce or -Walways? If the former, I don't expect many warnings to be emitted.
For example, on test_os, PYTHONMALLOC=debug increases the peak memory usage from 10.5 MiB to 15.8 MiB: +50%.
I see. For my use cases, this would be acceptable :-)
But I think this should be documented, for example:
"""Currently, developer mode adds negligible CPU time overhead, but can increase memory consumption significantly if many small objects are allocated. This is subject to change in the future."""
Regards
Antoine.

2017-11-16 13:54 GMT+01:00 Antoine Pitrou antoine@python.org:
-Wdefault means -Wonce or -Walways? If the former, I don't expect many warnings to be emitted.
It's kind of funny that passing "-W default" changes the "default" behaviour. "-W default" is documented as:
"Explicitly request the default behavior (printing each warning once per source line)."
https://docs.python.org/dev/using/cmdline.html#cmdoption-w
Default warnings filters in release mode:
$ python3 -c 'import pprint, warnings; pprint.pprint(warnings.filters)' [('ignore', None, <class 'DeprecationWarning'>, None, 0), ('ignore', None, <class 'PendingDeprecationWarning'>, None, 0), ('ignore', None, <class 'ImportWarning'>, None, 0), ('ignore', None, <class 'BytesWarning'>, None, 0), ('ignore', None, <class 'ResourceWarning'>, None, 0)]
-Wd adds the a warnings filter with the "default" action matching all warnings (any kind, any message, any line number) if I understand correctly:
$ python3 -Wd -c 'import pprint, warnings; pprint.pprint(warnings.filters)' [('default', re.compile('', re.IGNORECASE), <class 'Warning'>, re.compile(''), 0), ('ignore', None, <class 'DeprecationWarning'>, None, 0), ('ignore', None, <class 'PendingDeprecationWarning'>, None, 0), ('ignore', None, <class 'ImportWarning'>, None, 0), ('ignore', None, <class 'BytesWarning'>, None, 0), ('ignore', None, <class 'ResourceWarning'>, None, 0)]
"default" and "once" actions are different:
default: "print the first occurrence of matching warnings for **each location where the warning is issued**" once: "print only the first occurrence of matching warnings, **regardless of location**"
For example, on test_os, PYTHONMALLOC=debug increases the peak memory usage from 10.5 MiB to 15.8 MiB: +50%.
I see. For my use cases, this would be acceptable :-)
But I think this should be documented, for example:
"""Currently, developer mode adds negligible CPU time overhead, but can increase memory consumption significantly if many small objects are allocated. This is subject to change in the future."""
+50% memory is inacceptable to develop on embedded devices, or more generally with low level. But in that case, you are can enable options enabled by -X dev manually, without PYTHONMALLOC=debug :-)
Ok, I will document that, I like your proposed paragraph.
Victor

On 16 November 2017 at 22:54, Antoine Pitrou antoine@python.org wrote:
Hi Victor,
Thanks for the answer!
Le 16/11/2017 à 13:48, Victor Stinner a écrit :
faulthandler has a negligible cost on performance/memory.
For -W default, I guess that your question is the cost on emitting a warning: overhead when a warning is displayed, and overhead when the warning is filtered. Right?
-Wdefault means -Wonce or -Walways? If the former, I don't expect many warnings to be emitted.
Confusingly, neither of these: default, once, module, and always are all different settings.
once: once per process (regardless of location) module: once per module (regardless of line) default: once per location (line+module combination) always: every time
Still, even with once-per-location behaviour, the warning overhead should be minimal.
Cheers, Nick.

On Nov 15, 2017, at 21:57, Victor Stinner victor.stinner@gmail.com wrote:
Since Brett and Nick like the idea and nobody complained against it, I implemented the -X dev option:
Cool! What would you think about printing a summary of the settings under the standard banner when you run the REPL under -X dev? I’d rather not have to look it up in some obscure docs page whenever I use it. If not that, then what about having a -msettings module or some such that prints it out?
-Barry
participants (8)
-
Antoine Pitrou
-
Antoine Pitrou
-
Barry Warsaw
-
Glenn Linderman
-
Nick Coghlan
-
Serhiy Storchaka
-
Victor Stinner
-
Yury Selivanov