2003-01-23 12:26:42 -05:00
|
|
|
|
PEP: 304
|
2003-01-28 23:23:26 -05:00
|
|
|
|
Title: Controlling Generation of Bytecode Files
|
2003-01-23 12:26:42 -05:00
|
|
|
|
Version: $Revision$
|
|
|
|
|
Last-Modified: $Date$
|
|
|
|
|
Author: Skip Montanaro
|
2006-04-27 04:47:55 -04:00
|
|
|
|
Status: Withdrawn
|
2003-01-28 22:56:47 -05:00
|
|
|
|
Type: Standards Track
|
2003-01-23 12:26:42 -05:00
|
|
|
|
Content-Type: text/x-rst
|
|
|
|
|
Created: 22-Jan-2003
|
2005-06-22 18:56:06 -04:00
|
|
|
|
Post-History: 27-Jan-2003, 31-Jan-2003, 17-Jun-2005
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
2018-06-16 01:05:26 -04:00
|
|
|
|
Historical Note
|
|
|
|
|
===============
|
|
|
|
|
|
|
|
|
|
While this original PEP was withdrawn, a variant of this feature
|
|
|
|
|
was eventually implemented for Python 3.8 in https://bugs.python.org/issue33499
|
|
|
|
|
|
|
|
|
|
Several of the issues and concerns originally raised in this PEP were resolved
|
|
|
|
|
by other changes in the intervening years:
|
|
|
|
|
|
|
|
|
|
- the introduction of isolated mode to handle potential security concerns
|
|
|
|
|
- the switch to ``importlib``, a fully import-hook based import system implementation
|
2022-01-21 06:03:51 -05:00
|
|
|
|
- :pep:`3147`'s change in the bytecode cache layout to use ``__pycache__``
|
2018-06-16 01:05:26 -04:00
|
|
|
|
subdirectories, including the ``source_to_cache(path)`` and
|
|
|
|
|
``cache_to_source(path)`` APIs that allow the interpreter to automatically
|
|
|
|
|
handle the redirection to a separate cache directory
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
Abstract
|
|
|
|
|
========
|
|
|
|
|
|
|
|
|
|
This PEP outlines a mechanism for controlling the generation and
|
|
|
|
|
location of compiled Python bytecode files. This idea originally
|
|
|
|
|
arose as a patch request [1]_ and evolved into a discussion thread on
|
|
|
|
|
the python-dev mailing list [2]_. The introduction of an environment
|
|
|
|
|
variable will allow people installing Python or Python-based
|
2003-01-29 14:28:10 -05:00
|
|
|
|
third-party packages to control whether or not bytecode files should
|
|
|
|
|
be generated at installation time, and if so, where they should be
|
2003-01-29 17:49:04 -05:00
|
|
|
|
written. It will also allow users to control whether or not bytecode
|
|
|
|
|
files should be generated at application run-time, and if so, where
|
|
|
|
|
they should be written.
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Proposal
|
|
|
|
|
========
|
|
|
|
|
|
|
|
|
|
Add a new environment variable, PYTHONBYTECODEBASE, to the mix of
|
2003-01-31 12:28:11 -05:00
|
|
|
|
environment variables which Python understands. PYTHONBYTECODEBASE is
|
|
|
|
|
interpreted as follows:
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
2003-01-31 12:28:11 -05:00
|
|
|
|
- If not defined, Python bytecode is generated in exactly the same way
|
|
|
|
|
as is currently done. sys.bytecodebase is set to the root directory
|
2005-06-18 09:04:03 -04:00
|
|
|
|
(either / on Unix and Mac OSX or the root directory of the startup
|
|
|
|
|
(installation???) drive -- typically ``C:\`` -- on Windows).
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
2003-01-31 12:28:11 -05:00
|
|
|
|
- If defined and it refers to an existing directory to which the user
|
|
|
|
|
has write permission, sys.bytecodebase is set to that directory and
|
|
|
|
|
bytecode files are written into a directory structure rooted at that
|
|
|
|
|
location.
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
2003-01-31 12:28:11 -05:00
|
|
|
|
- If defined but empty, sys.bytecodebase is set to None and generation
|
|
|
|
|
of bytecode files is suppressed altogether.
|
|
|
|
|
|
2003-05-29 09:46:46 -04:00
|
|
|
|
- If defined and one of the following is true:
|
2003-01-31 12:28:11 -05:00
|
|
|
|
|
|
|
|
|
* it does not refer to a directory,
|
|
|
|
|
|
|
|
|
|
* it refers to a directory, but not one for which the user has write
|
|
|
|
|
permission
|
|
|
|
|
|
|
|
|
|
a warning is displayed, sys.bytecodebase is set to None and
|
2003-01-23 12:26:42 -05:00
|
|
|
|
generation of bytecode files is suppressed altogether.
|
|
|
|
|
|
2003-01-31 12:28:11 -05:00
|
|
|
|
After startup initialization, all runtime references are to
|
|
|
|
|
sys.bytecodebase, not the PYTHONBYTECODEBASE environment variable.
|
|
|
|
|
sys.path is not modified.
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
2003-01-31 12:28:11 -05:00
|
|
|
|
From the above, we see sys.bytecodebase can only take on two valid
|
|
|
|
|
types of values: None or a string referring to a valid directory on
|
|
|
|
|
the system.
|
|
|
|
|
|
|
|
|
|
During import, this extension works as follows:
|
|
|
|
|
|
|
|
|
|
- The normal search for a module is conducted. The search order is
|
|
|
|
|
roughly: dynamically loaded extension module, Python source file,
|
|
|
|
|
Python bytecode file. The only time this mechanism comes into play
|
|
|
|
|
is if a Python source file is found.
|
|
|
|
|
|
|
|
|
|
- Once we've found a source module, an attempt to read a byte-compiled
|
|
|
|
|
file in the same directory is made. (This is the same as before.)
|
|
|
|
|
|
|
|
|
|
- If no byte-compiled file is found, an attempt to read a
|
|
|
|
|
byte-compiled file from the augmented directory is made.
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
2019-07-03 14:20:45 -04:00
|
|
|
|
- If bytecode generation is required, the generated bytecode is written
|
2005-06-18 09:04:03 -04:00
|
|
|
|
to the augmented directory if possible.
|
|
|
|
|
|
2003-01-29 14:28:10 -05:00
|
|
|
|
Note that this PEP is explicitly *not* about providing
|
|
|
|
|
module-by-module or directory-by-directory control over the
|
|
|
|
|
disposition of bytecode files.
|
|
|
|
|
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
Glossary
|
|
|
|
|
--------
|
|
|
|
|
|
|
|
|
|
- "bytecode base" refers to the current setting of
|
2003-01-29 13:49:47 -05:00
|
|
|
|
sys.bytecodebase.
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
- "augmented directory" refers to the directory formed from the
|
|
|
|
|
bytecode base and the directory name of the source file.
|
|
|
|
|
|
|
|
|
|
- PYTHONBYTECODEBASE refers to the environment variable when necessary
|
|
|
|
|
to distinguish it from "bytecode base".
|
|
|
|
|
|
2003-01-23 13:45:09 -05:00
|
|
|
|
|
2003-01-23 12:26:42 -05:00
|
|
|
|
Locating bytecode files
|
|
|
|
|
-----------------------
|
|
|
|
|
|
|
|
|
|
When the interpreter is searching for a module, it will use sys.path
|
|
|
|
|
as usual. However, when a possible bytecode file is considered, an
|
|
|
|
|
extra probe for a bytecode file may be made. First, a check is made
|
|
|
|
|
for the bytecode file using the directory in sys.path which holds the
|
|
|
|
|
source file (the current behavior). If a valid bytecode file is not
|
|
|
|
|
found there (either one does not exist or exists but is out-of-date)
|
|
|
|
|
and the bytecode base is not None, a second probe is made using the
|
|
|
|
|
directory in sys.path prefixed appropriately by the bytecode base.
|
|
|
|
|
|
2003-01-23 13:45:09 -05:00
|
|
|
|
|
2003-01-23 12:26:42 -05:00
|
|
|
|
Writing bytecode files
|
|
|
|
|
----------------------
|
|
|
|
|
|
|
|
|
|
When the bytecode base is not None, a new bytecode file is written to
|
|
|
|
|
the appropriate augmented directory, never directly to a directory in
|
|
|
|
|
sys.path.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Defining augmented directories
|
|
|
|
|
------------------------------
|
|
|
|
|
|
|
|
|
|
Conceptually, the augmented directory for a bytecode file is the
|
|
|
|
|
directory in which the source file exists prefixed by the bytecode
|
2003-01-23 13:45:09 -05:00
|
|
|
|
base. In a Unix environment this would be::
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
2003-01-29 13:49:47 -05:00
|
|
|
|
pcb = os.path.abspath(sys.bytecodebase)
|
2003-01-23 12:26:42 -05:00
|
|
|
|
if sourcefile[0] == os.sep: sourcefile = sourcefile[1:]
|
|
|
|
|
augdir = os.path.join(pcb, os.path.dirname(sourcefile))
|
|
|
|
|
|
|
|
|
|
On Windows, which does not have a single-rooted directory tree, the
|
|
|
|
|
drive letter of the directory containing the source file is treated as
|
|
|
|
|
a directory component after removing the trailing colon. The
|
2003-01-23 13:45:09 -05:00
|
|
|
|
augmented directory is thus derived as ::
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
2003-01-29 13:49:47 -05:00
|
|
|
|
pcb = os.path.abspath(sys.bytecodebase)
|
2003-01-23 12:26:42 -05:00
|
|
|
|
drive, base = os.path.splitdrive(os.path.dirname(sourcefile))
|
|
|
|
|
drive = drive[:-1]
|
|
|
|
|
if base[0] == "\\": base = base[1:]
|
|
|
|
|
augdir = os.path.join(pcb, drive, base)
|
|
|
|
|
|
2003-01-29 14:28:10 -05:00
|
|
|
|
|
2003-01-23 12:26:42 -05:00
|
|
|
|
Fixing the location of the bytecode base
|
|
|
|
|
----------------------------------------
|
|
|
|
|
|
|
|
|
|
During program startup, the value of the PYTHONBYTECODEBASE
|
|
|
|
|
environment variable is made absolute, checked for validity and added
|
2003-01-23 13:45:09 -05:00
|
|
|
|
to the sys module, effectively::
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
pcb = os.path.abspath(os.environ["PYTHONBYTECODEBASE"])
|
2005-06-18 09:04:03 -04:00
|
|
|
|
probe = os.path.join(pcb, "foo")
|
2003-01-23 12:26:42 -05:00
|
|
|
|
try:
|
|
|
|
|
open(probe, "w")
|
|
|
|
|
except IOError:
|
2003-01-29 13:49:47 -05:00
|
|
|
|
sys.bytecodebase = None
|
2005-06-18 09:04:03 -04:00
|
|
|
|
else:
|
|
|
|
|
os.unlink(probe)
|
|
|
|
|
sys.bytecodebase = pcb
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
This allows the user to specify the bytecode base as a relative path,
|
2005-06-18 09:04:03 -04:00
|
|
|
|
but not have it subject to changes to the current working directory
|
|
|
|
|
during program execution. (I can't imagine you'd want it to move
|
|
|
|
|
around during program execution.)
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
2005-06-18 09:04:03 -04:00
|
|
|
|
There is nothing special about sys.bytecodebase. The user may change
|
|
|
|
|
it at runtime if desired, but normally it will not be modified.
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Rationale
|
|
|
|
|
=========
|
|
|
|
|
|
|
|
|
|
In many environments it is not possible for non-root users to write
|
|
|
|
|
into directories containing Python source files. Most of the time,
|
|
|
|
|
this is not a problem as Python source is generally byte compiled
|
|
|
|
|
during installation. However, there are situations where bytecode
|
|
|
|
|
files are either missing or need to be updated. If the directory
|
|
|
|
|
containing the source file is not writable by the current user a
|
|
|
|
|
performance penalty is incurred each time a program importing the
|
|
|
|
|
module is run. [3]_ Warning messages may also be generated in certain
|
|
|
|
|
circumstances. If the directory is writable, nearly simultaneous
|
2016-05-03 05:03:16 -04:00
|
|
|
|
attempts to write the bytecode file by two separate processes
|
2003-01-23 12:26:42 -05:00
|
|
|
|
may occur, resulting in file corruption. [4]_
|
|
|
|
|
|
2003-01-23 13:51:09 -05:00
|
|
|
|
In environments with RAM disks available, it may be desirable for
|
2003-01-23 12:26:42 -05:00
|
|
|
|
performance reasons to write bytecode files to a directory on such a
|
|
|
|
|
disk. Similarly, in environments where Python source code resides on
|
|
|
|
|
network file systems, it may be desirable to cache bytecode files on
|
|
|
|
|
local disks.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Alternatives
|
|
|
|
|
============
|
|
|
|
|
|
|
|
|
|
The only other alternative proposed so far [1]_ seems to be to add a
|
|
|
|
|
-R flag to the interpreter to disable writing bytecode files
|
|
|
|
|
altogether. This proposal subsumes that. Adding a command-line
|
|
|
|
|
option is certainly possible, but is probably not sufficient, as the
|
|
|
|
|
interpreter's command line is not readily available during
|
2005-06-18 09:04:03 -04:00
|
|
|
|
installation (early during program startup???).
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Issues
|
|
|
|
|
======
|
|
|
|
|
|
|
|
|
|
- Interpretation of a module's __file__ attribute. I believe the
|
|
|
|
|
__file__ attribute of a module should reflect the true location of
|
|
|
|
|
the bytecode file. If people want to locate a module's source code,
|
|
|
|
|
they should use imp.find_module(module).
|
|
|
|
|
|
|
|
|
|
- Security - What if root has PYTHONBYTECODEBASE set? Yes, this can
|
|
|
|
|
present a security risk, but so can many other things the root user
|
|
|
|
|
does. The root user should probably not set PYTHONBYTECODEBASE
|
2005-06-18 09:04:03 -04:00
|
|
|
|
except possibly during installation. Still, perhaps this problem
|
|
|
|
|
can be minimized. When running as root the interpreter should check
|
|
|
|
|
to see if PYTHONBYTECODEBASE refers to a directory which is writable
|
|
|
|
|
by anyone other than root. If so, it could raise an exception or
|
|
|
|
|
warning and set sys.bytecodebase to None. Or, see the next item.
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
- More security - What if PYTHONBYTECODEBASE refers to a general
|
|
|
|
|
directory (say, /tmp)? In this case, perhaps loading of a
|
|
|
|
|
preexisting bytecode file should occur only if the file is owned by
|
|
|
|
|
the current user or root. (Does this matter on Windows?)
|
|
|
|
|
|
2003-01-27 17:33:41 -05:00
|
|
|
|
- The interaction of this PEP with import hooks has not been
|
|
|
|
|
considered yet. In fact, the best way to implement this idea might
|
2022-01-21 06:03:51 -05:00
|
|
|
|
be as an import hook. See :pep:`302`.
|
2003-01-27 17:33:41 -05:00
|
|
|
|
|
2022-01-21 06:03:51 -05:00
|
|
|
|
- In the current (pre-:pep:`304`) environment, it is safe to delete a
|
2003-01-31 12:28:11 -05:00
|
|
|
|
source file after the corresponding bytecode file has been created,
|
2022-01-21 06:03:51 -05:00
|
|
|
|
since they reside in the same directory. With :pep:`304` as currently
|
2003-01-31 12:28:11 -05:00
|
|
|
|
defined, this is not the case. A bytecode file in the augmented
|
|
|
|
|
directory is only considered when the source file is present and it
|
|
|
|
|
thus never considered when looking for module files ending in
|
|
|
|
|
".pyc". I think this behavior may have to change.
|
|
|
|
|
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
Examples
|
|
|
|
|
========
|
|
|
|
|
|
|
|
|
|
In the examples which follow, the urllib source code resides in
|
|
|
|
|
/usr/lib/python2.3/urllib.py and /usr/lib/python2.3 is in sys.path but
|
|
|
|
|
is not writable by the current user.
|
|
|
|
|
|
|
|
|
|
- The bytecode base is /tmp. /usr/lib/python2.3/urllib.pyc exists and
|
|
|
|
|
is valid. When urllib is imported, the contents of
|
|
|
|
|
/usr/lib/python2.3/urllib.pyc are used. The augmented directory is
|
|
|
|
|
not consulted. No other bytecode file is generated.
|
|
|
|
|
|
|
|
|
|
- The bytecode base is /tmp. /usr/lib/python2.3/urllib.pyc exists,
|
|
|
|
|
but is out-of-date. When urllib is imported, the generated bytecode
|
2003-01-29 13:49:47 -05:00
|
|
|
|
file is written to urllib.pyc in the augmented directory which has
|
|
|
|
|
the value /tmp/usr/lib/python2.3. Intermediate directories will be
|
|
|
|
|
created as needed.
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
- The bytecode base is None. No urllib.pyc file is found. When
|
|
|
|
|
urllib is imported, no bytecode file is written.
|
|
|
|
|
|
|
|
|
|
- The bytecode base is /tmp. No urllib.pyc file is found. When
|
|
|
|
|
urllib is imported, the generated bytecode file is written to the
|
2003-01-29 13:49:47 -05:00
|
|
|
|
augmented directory which has the value /tmp/usr/lib/python2.3.
|
|
|
|
|
Intermediate directories will be created as needed.
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
- At startup, PYTHONBYTECODEBASE is /tmp/foobar, which does not exist.
|
2003-01-29 13:49:47 -05:00
|
|
|
|
A warning is emitted, sys.bytecodebase is set to None and no
|
2003-01-23 12:26:42 -05:00
|
|
|
|
bytecode files are written during program execution unless
|
2003-01-29 13:49:47 -05:00
|
|
|
|
sys.bytecodebase is later changed to refer to a valid,
|
2003-01-23 12:26:42 -05:00
|
|
|
|
writable directory.
|
|
|
|
|
|
|
|
|
|
- At startup, PYTHONBYTECODEBASE is set to /, which exists, but is not
|
|
|
|
|
writable by the current user. A warning is emitted,
|
2003-01-29 13:49:47 -05:00
|
|
|
|
sys.bytecodebase is set to None and no bytecode files are
|
|
|
|
|
written during program execution unless sys.bytecodebase is
|
2003-01-23 12:26:42 -05:00
|
|
|
|
later changed to refer to a valid, writable directory. Note that
|
|
|
|
|
even though the augmented directory constructed for a particular
|
|
|
|
|
bytecode file may be writable by the current user, what counts is
|
|
|
|
|
that the bytecode base directory itself is writable.
|
|
|
|
|
|
|
|
|
|
- At startup PYTHONBYTECODEBASE is set to the empty string.
|
2003-01-29 13:49:47 -05:00
|
|
|
|
sys.bytecodebase is set to None. No warning is generated, however.
|
|
|
|
|
If no urllib.pyc file is found when urllib is imported, no bytecode
|
|
|
|
|
file is written.
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
In the Windows examples which follow, the urllib source code resides
|
2003-01-23 13:45:09 -05:00
|
|
|
|
in ``C:\PYTHON22\urllib.py``. ``C:\PYTHON22`` is in sys.path but is
|
2003-01-23 12:26:42 -05:00
|
|
|
|
not writable by the current user.
|
|
|
|
|
|
|
|
|
|
- The bytecode base is set to ``C:\TEMP``. ``C:\PYTHON22\urllib.pyc``
|
|
|
|
|
exists and is valid. When urllib is imported, the contents of
|
|
|
|
|
``C:\PYTHON22\urllib.pyc`` are used. The augmented directory is not
|
|
|
|
|
consulted.
|
|
|
|
|
|
|
|
|
|
- The bytecode base is set to ``C:\TEMP``. ``C:\PYTHON22\urllib.pyc``
|
|
|
|
|
exists, but is out-of-date. When urllib is imported, a new bytecode
|
2003-01-29 13:49:47 -05:00
|
|
|
|
file is written to the augmented directory which has the value
|
|
|
|
|
``C:\TEMP\C\PYTHON22``. Intermediate directories will be created as
|
|
|
|
|
needed.
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
2003-01-23 13:51:09 -05:00
|
|
|
|
- At startup PYTHONBYTECODEBASE is set to ``TEMP`` and the current
|
2003-01-23 12:26:42 -05:00
|
|
|
|
working directory at application startup is ``H:\NET``. The
|
|
|
|
|
potential bytecode base is thus ``H:\NET\TEMP``. If this directory
|
2003-01-29 13:49:47 -05:00
|
|
|
|
exists and is writable by the current user, sys.bytecodebase will be
|
|
|
|
|
set to that value. If not, a warning will be emitted and
|
|
|
|
|
sys.bytecodebase will be set to None.
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
- The bytecode base is ``C:\TEMP``. No urllib.pyc file is found.
|
|
|
|
|
When urllib is imported, the generated bytecode file is written to
|
2003-01-29 13:49:47 -05:00
|
|
|
|
the augmented directory which has the value ``C:\TEMP\C\PYTHON22``.
|
|
|
|
|
Intermediate directories will be created as needed.
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
2003-01-23 13:45:09 -05:00
|
|
|
|
|
2003-01-29 17:49:04 -05:00
|
|
|
|
Implementation
|
|
|
|
|
==============
|
|
|
|
|
|
|
|
|
|
See the patch on Sourceforge. [6]_
|
|
|
|
|
|
2003-01-23 12:26:42 -05:00
|
|
|
|
References
|
|
|
|
|
==========
|
|
|
|
|
|
|
|
|
|
.. [1] patch 602345, Option for not writing py.[co] files, Klose
|
2018-07-21 19:57:17 -04:00
|
|
|
|
(https://bugs.python.org/issue602345)
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
.. [2] python-dev thread, Disable writing .py[co], Norwitz
|
2017-06-11 15:02:39 -04:00
|
|
|
|
(https://mail.python.org/pipermail/python-dev/2003-January/032270.html)
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
.. [3] Debian bug report, Mailman is writing to /usr in cron, Wegner
|
|
|
|
|
(http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=96111)
|
|
|
|
|
|
|
|
|
|
.. [4] python-dev thread, Parallel pyc construction, Dubois
|
2017-06-11 15:02:39 -04:00
|
|
|
|
(https://mail.python.org/pipermail/python-dev/2003-January/032060.html)
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
2003-01-29 17:49:04 -05:00
|
|
|
|
.. [6] patch 677103, PYTHONBYTECODEBASE patch (PEP 304), Montanaro
|
2018-07-21 19:57:17 -04:00
|
|
|
|
(https://bugs.python.org/issue677103)
|
2003-01-29 17:49:04 -05:00
|
|
|
|
|
2003-01-23 12:26:42 -05:00
|
|
|
|
|
|
|
|
|
Copyright
|
|
|
|
|
=========
|
|
|
|
|
|
|
|
|
|
This document has been placed in the public domain.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
..
|
|
|
|
|
Local Variables:
|
|
|
|
|
mode: indented-text
|
|
|
|
|
indent-tabs-mode: nil
|
|
|
|
|
sentence-end-double-space: t
|
|
|
|
|
fill-column: 70
|
|
|
|
|
End:
|