mirror of
https://github.com/python/cpython.git
synced 2025-08-31 05:58:33 +00:00
Branch merge
This commit is contained in:
commit
0bbacc621c
52 changed files with 256 additions and 294 deletions
|
@ -14,6 +14,7 @@ platform
|
||||||
pybuilddir.txt
|
pybuilddir.txt
|
||||||
pyconfig.h
|
pyconfig.h
|
||||||
libpython*.a
|
libpython*.a
|
||||||
|
libpython*.so*
|
||||||
python.exe
|
python.exe
|
||||||
python-gdb.py
|
python-gdb.py
|
||||||
reflog.txt
|
reflog.txt
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -37,6 +37,7 @@ build/
|
||||||
config.log
|
config.log
|
||||||
config.status
|
config.status
|
||||||
libpython*.a
|
libpython*.a
|
||||||
|
libpython*.so*
|
||||||
pybuilddir.txt
|
pybuilddir.txt
|
||||||
pyconfig.h
|
pyconfig.h
|
||||||
python
|
python
|
||||||
|
|
|
@ -41,14 +41,13 @@ PCbuild/amd64/
|
||||||
|
|
||||||
syntax: glob
|
syntax: glob
|
||||||
libpython*.a
|
libpython*.a
|
||||||
|
libpython*.so*
|
||||||
*.swp
|
*.swp
|
||||||
*.o
|
*.o
|
||||||
*.pyc
|
*.pyc
|
||||||
*.pyo
|
*.pyo
|
||||||
*.pyd
|
*.pyd
|
||||||
*.cover
|
*.cover
|
||||||
*.orig
|
|
||||||
*.rej
|
|
||||||
*~
|
*~
|
||||||
Lib/lib2to3/*.pickle
|
Lib/lib2to3/*.pickle
|
||||||
Lib/test/data/*
|
Lib/test/data/*
|
||||||
|
|
|
@ -203,6 +203,7 @@ docs@python.org), and we'll be glad to correct the problem.
|
||||||
* Kalle Svensson
|
* Kalle Svensson
|
||||||
* Jim Tittsler
|
* Jim Tittsler
|
||||||
* David Turner
|
* David Turner
|
||||||
|
* Sandro Tosi
|
||||||
* Ville Vainio
|
* Ville Vainio
|
||||||
* Nadeem Vawda
|
* Nadeem Vawda
|
||||||
* Martijn Vries
|
* Martijn Vries
|
||||||
|
|
|
@ -72,8 +72,8 @@ setup script). Indirectly provides the :class:`distutils.dist.Distribution` and
|
||||||
| | be built | :class:`distutils.core.Extension` |
|
| | be built | :class:`distutils.core.Extension` |
|
||||||
+--------------------+--------------------------------+-------------------------------------------------------------+
|
+--------------------+--------------------------------+-------------------------------------------------------------+
|
||||||
| *classifiers* | A list of categories for the | The list of available |
|
| *classifiers* | A list of categories for the | The list of available |
|
||||||
| | package | categorizations is at |
|
| | package | categorizations is available on `PyPI |
|
||||||
| | | http://pypi.python.org/pypi?:action=list_classifiers. |
|
| | | <http://pypi.python.org/pypi?:action=list_classifiers>`_. |
|
||||||
+--------------------+--------------------------------+-------------------------------------------------------------+
|
+--------------------+--------------------------------+-------------------------------------------------------------+
|
||||||
| *distclass* | the :class:`Distribution` | A subclass of |
|
| *distclass* | the :class:`Distribution` | A subclass of |
|
||||||
| | class to use | :class:`distutils.core.Distribution` |
|
| | class to use | :class:`distutils.core.Distribution` |
|
||||||
|
|
|
@ -72,7 +72,7 @@ In that case, you would download the installer appropriate to your platform and
|
||||||
do the obvious thing with it: run it if it's an executable installer, ``rpm
|
do the obvious thing with it: run it if it's an executable installer, ``rpm
|
||||||
--install`` it if it's an RPM, etc. You don't need to run Python or a setup
|
--install`` it if it's an RPM, etc. You don't need to run Python or a setup
|
||||||
script, you don't need to compile anything---you might not even need to read any
|
script, you don't need to compile anything---you might not even need to read any
|
||||||
instructions (although it's always a good idea to do so anyways).
|
instructions (although it's always a good idea to do so anyway).
|
||||||
|
|
||||||
Of course, things will not always be that easy. You might be interested in a
|
Of course, things will not always be that easy. You might be interested in a
|
||||||
module distribution that doesn't have an easy-to-use installer for your
|
module distribution that doesn't have an easy-to-use installer for your
|
||||||
|
|
|
@ -431,7 +431,8 @@ Glossary
|
||||||
|
|
||||||
mapping
|
mapping
|
||||||
A container object that supports arbitrary key lookups and implements the
|
A container object that supports arbitrary key lookups and implements the
|
||||||
methods specified in the :class:`Mapping` or :class:`MutableMapping`
|
methods specified in the :class:`~collections.Mapping` or
|
||||||
|
:class:`~collections.MutableMapping`
|
||||||
:ref:`abstract base classes <collections-abstract-base-classes>`. Examples
|
:ref:`abstract base classes <collections-abstract-base-classes>`. Examples
|
||||||
include :class:`dict`, :class:`collections.defaultdict`,
|
include :class:`dict`, :class:`collections.defaultdict`,
|
||||||
:class:`collections.OrderedDict` and :class:`collections.Counter`.
|
:class:`collections.OrderedDict` and :class:`collections.Counter`.
|
||||||
|
|
|
@ -14,7 +14,7 @@ the standard audio interface for Linux and recent versions of FreeBSD.
|
||||||
ALSA is in the standard kernel as of 2.5.x. Presumably if you
|
ALSA is in the standard kernel as of 2.5.x. Presumably if you
|
||||||
use ALSA, you'll have to make sure its OSS compatibility layer
|
use ALSA, you'll have to make sure its OSS compatibility layer
|
||||||
is active to use ossaudiodev, but you're gonna need it for the vast
|
is active to use ossaudiodev, but you're gonna need it for the vast
|
||||||
majority of Linux audio apps anyways.
|
majority of Linux audio apps anyway.
|
||||||
|
|
||||||
Sounds like things are also complicated for other BSDs. In response
|
Sounds like things are also complicated for other BSDs. In response
|
||||||
to my python-dev query, Thomas Wouters said:
|
to my python-dev query, Thomas Wouters said:
|
||||||
|
|
|
@ -67,8 +67,8 @@ module distribution being built/packaged/distributed/installed.
|
||||||
| | be built | :class:`packaging.compiler.extension.Extension` |
|
| | be built | :class:`packaging.compiler.extension.Extension` |
|
||||||
+--------------------+--------------------------------+-------------------------------------------------------------+
|
+--------------------+--------------------------------+-------------------------------------------------------------+
|
||||||
| *classifiers* | A list of categories for the | The list of available |
|
| *classifiers* | A list of categories for the | The list of available |
|
||||||
| | distribution | categorizations is at |
|
| | distribution | categorizations is available on `PyPI |
|
||||||
| | | http://pypi.python.org/pypi?:action=list_classifiers. |
|
| | | <http://pypi.python.org/pypi?:action=list_classifiers>`_. |
|
||||||
+--------------------+--------------------------------+-------------------------------------------------------------+
|
+--------------------+--------------------------------+-------------------------------------------------------------+
|
||||||
| *distclass* | the :class:`Distribution` | A subclass of |
|
| *distclass* | the :class:`Distribution` | A subclass of |
|
||||||
| | class to use | :class:`packaging.dist.Distribution` |
|
| | class to use | :class:`packaging.dist.Distribution` |
|
||||||
|
|
|
@ -39,7 +39,7 @@ The Python standard library provides two different profilers:
|
||||||
2. :mod:`profile`, a pure Python module whose interface is imitated by
|
2. :mod:`profile`, a pure Python module whose interface is imitated by
|
||||||
:mod:`cProfile`. Adds significant overhead to profiled programs. If you're
|
:mod:`cProfile`. Adds significant overhead to profiled programs. If you're
|
||||||
trying to extend the profiler in some way, the task might be easier with this
|
trying to extend the profiler in some way, the task might be easier with this
|
||||||
module. Copyright © 1994, by InfoSeek Corporation.
|
module.
|
||||||
|
|
||||||
The :mod:`profile` and :mod:`cProfile` modules export the same interface, so
|
The :mod:`profile` and :mod:`cProfile` modules export the same interface, so
|
||||||
they are mostly interchangeable; :mod:`cProfile` has a much lower overhead but
|
they are mostly interchangeable; :mod:`cProfile` has a much lower overhead but
|
||||||
|
@ -592,27 +592,3 @@ The resulting profiler will then call :func:`your_time_func`.
|
||||||
functions should be used with care and should be as fast as possible. For the
|
functions should be used with care and should be as fast as possible. For the
|
||||||
best results with a custom timer, it might be necessary to hard-code it in the C
|
best results with a custom timer, it might be necessary to hard-code it in the C
|
||||||
source of the internal :mod:`_lsprof` module.
|
source of the internal :mod:`_lsprof` module.
|
||||||
|
|
||||||
|
|
||||||
Copyright and License Notices
|
|
||||||
=============================
|
|
||||||
|
|
||||||
Copyright © 1994, by InfoSeek Corporation, all rights reserved.
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this Python software and its
|
|
||||||
associated documentation for any purpose (subject to the restriction in the
|
|
||||||
following sentence) without fee is hereby granted, provided that the above
|
|
||||||
copyright notice appears in all copies, and that both that copyright notice and
|
|
||||||
this permission notice appear in supporting documentation, and that the name of
|
|
||||||
InfoSeek not be used in advertising or publicity pertaining to distribution of
|
|
||||||
the software without specific, written prior permission. This permission is
|
|
||||||
explicitly restricted to the copying and modification of the software to remain
|
|
||||||
in Python, compiled Python, or other languages (such as C) wherein the modified
|
|
||||||
or derived code is exclusively imported into a Python module.
|
|
||||||
|
|
||||||
INFOSEEK CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT
|
|
||||||
SHALL INFOSEEK CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
|
||||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
|
||||||
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
||||||
OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
|
|
|
@ -34,6 +34,22 @@ The :mod:`shlex` module defines the following functions:
|
||||||
passing ``None`` for *s* will read the string to split from standard
|
passing ``None`` for *s* will read the string to split from standard
|
||||||
input.
|
input.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: quote(s)
|
||||||
|
|
||||||
|
Return a shell-escaped version of the string *s*. The returned value is a
|
||||||
|
string that can safely be used as one token in a shell command line.
|
||||||
|
Examples::
|
||||||
|
|
||||||
|
>>> filename = 'somefile; rm -rf /home'
|
||||||
|
>>> command = 'ls -l {}'.format(quote(filename))
|
||||||
|
>>> print(command)
|
||||||
|
ls -l 'somefile; rm -rf /home'
|
||||||
|
>>> remote_command = 'ssh home {}'.format(quote(command))
|
||||||
|
>>> print(remote_command)
|
||||||
|
ssh home 'ls -l '"'"'somefile; rm -rf /home'"'"''
|
||||||
|
|
||||||
|
|
||||||
The :mod:`shlex` module defines the following class:
|
The :mod:`shlex` module defines the following class:
|
||||||
|
|
||||||
|
|
||||||
|
@ -282,5 +298,4 @@ parsing rules.
|
||||||
|
|
||||||
* EOF is signaled with a :const:`None` value;
|
* EOF is signaled with a :const:`None` value;
|
||||||
|
|
||||||
* Quoted empty strings (``''``) are allowed;
|
* Quoted empty strings (``''``) are allowed.
|
||||||
|
|
||||||
|
|
|
@ -159,12 +159,18 @@ Directory and files operations
|
||||||
|
|
||||||
.. function:: move(src, dst)
|
.. function:: move(src, dst)
|
||||||
|
|
||||||
Recursively move a file or directory to another location.
|
Recursively move a file or directory (*src*) to another location (*dst*).
|
||||||
|
|
||||||
Uses :func:`os.rename` to perform the move. If it fails, for reasons such as
|
If the destination is a directory or a symlink to a directory, then *src* is
|
||||||
when *src* and *dst* are on different filesystems or in case of windows where
|
moved inside that directory.
|
||||||
rename is not supported when *dst* exists, fallback to copying *src* (with
|
|
||||||
:func:`copy2`) to the *dst* and then remove *src*.
|
The destination directory must not already exist. If the destination already
|
||||||
|
exists but is not a directory, it may be overwritten depending on
|
||||||
|
:func:`os.rename` semantics.
|
||||||
|
|
||||||
|
If the destination is on the current filesystem, then :func:`os.rename` is
|
||||||
|
used. Otherwise, *src* is copied (using :func:`copy2`) to *dst* and then
|
||||||
|
removed.
|
||||||
|
|
||||||
.. function:: disk_usage(path)
|
.. function:: disk_usage(path)
|
||||||
|
|
||||||
|
@ -177,9 +183,9 @@ Directory and files operations
|
||||||
|
|
||||||
.. exception:: Error
|
.. exception:: Error
|
||||||
|
|
||||||
This exception collects exceptions that raised during a multi-file operation. For
|
This exception collects exceptions that are raised during a multi-file
|
||||||
:func:`copytree`, the exception argument is a list of 3-tuples (*srcname*,
|
operation. For :func:`copytree`, the exception argument is a list of 3-tuples
|
||||||
*dstname*, *exception*).
|
(*srcname*, *dstname*, *exception*).
|
||||||
|
|
||||||
|
|
||||||
.. _shutil-example:
|
.. _shutil-example:
|
||||||
|
@ -277,7 +283,7 @@ Archiving operations
|
||||||
|
|
||||||
.. function:: get_archive_formats()
|
.. function:: get_archive_formats()
|
||||||
|
|
||||||
Returns a list of supported formats for archiving.
|
Return a list of supported formats for archiving.
|
||||||
Each element of the returned sequence is a tuple ``(name, description)``
|
Each element of the returned sequence is a tuple ``(name, description)``
|
||||||
|
|
||||||
By default :mod:`shutil` provides these formats:
|
By default :mod:`shutil` provides these formats:
|
||||||
|
@ -295,7 +301,7 @@ Archiving operations
|
||||||
|
|
||||||
.. function:: register_archive_format(name, function, [extra_args, [description]])
|
.. function:: register_archive_format(name, function, [extra_args, [description]])
|
||||||
|
|
||||||
Registers an archiver for the format *name*. *function* is a callable that
|
Register an archiver for the format *name*. *function* is a callable that
|
||||||
will be used to invoke the archiver.
|
will be used to invoke the archiver.
|
||||||
|
|
||||||
If given, *extra_args* is a sequence of ``(name, value)`` pairs that will be
|
If given, *extra_args* is a sequence of ``(name, value)`` pairs that will be
|
||||||
|
|
|
@ -92,7 +92,8 @@ This module defines one class called :class:`Popen`:
|
||||||
>>> call("cat " + filename, shell=True) # Uh-oh. This will end badly...
|
>>> call("cat " + filename, shell=True) # Uh-oh. This will end badly...
|
||||||
|
|
||||||
*shell=False* does not suffer from this vulnerability; the above Note may be
|
*shell=False* does not suffer from this vulnerability; the above Note may be
|
||||||
helpful in getting code using *shell=False* to work.
|
helpful in getting code using *shell=False* to work. See also
|
||||||
|
:func:`shlex.quote` for a function useful to quote filenames and commands.
|
||||||
|
|
||||||
On Windows: the :class:`Popen` class uses CreateProcess() to execute the
|
On Windows: the :class:`Popen` class uses CreateProcess() to execute the
|
||||||
child program, which operates on strings. If *args* is a sequence, it will
|
child program, which operates on strings. If *args* is a sequence, it will
|
||||||
|
@ -871,3 +872,7 @@ runtime):
|
||||||
described in rule 3.
|
described in rule 3.
|
||||||
|
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:mod:`shlex`
|
||||||
|
Module which provides function to parse and escape command lines.
|
||||||
|
|
|
@ -494,36 +494,6 @@ The :mod:`http.cookies` module contains the following notice::
|
||||||
PERFORMANCE OF THIS SOFTWARE.
|
PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
Profiling
|
|
||||||
---------
|
|
||||||
|
|
||||||
The :mod:`profile` and :mod:`pstats` modules contain the following notice::
|
|
||||||
|
|
||||||
Copyright 1994, by InfoSeek Corporation, all rights reserved.
|
|
||||||
Written by James Roskind
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this Python software
|
|
||||||
and its associated documentation for any purpose (subject to the
|
|
||||||
restriction in the following sentence) without fee is hereby granted,
|
|
||||||
provided that the above copyright notice appears in all copies, and
|
|
||||||
that both that copyright notice and this permission notice appear in
|
|
||||||
supporting documentation, and that the name of InfoSeek not be used in
|
|
||||||
advertising or publicity pertaining to distribution of the software
|
|
||||||
without specific, written prior permission. This permission is
|
|
||||||
explicitly restricted to the copying and modification of the software
|
|
||||||
to remain in Python, compiled Python, or other languages (such as C)
|
|
||||||
wherein the modified or derived code is exclusively imported into a
|
|
||||||
Python module.
|
|
||||||
|
|
||||||
INFOSEEK CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
|
||||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
FITNESS. IN NO EVENT SHALL INFOSEEK CORPORATION BE LIABLE FOR ANY
|
|
||||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
|
||||||
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
|
||||||
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
||||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
|
|
||||||
|
|
||||||
Execution tracing
|
Execution tracing
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ c-api/sequence,,:i2,o[i1:i2]
|
||||||
c-api/sequence,,:i2,o[i1:i2] = v
|
c-api/sequence,,:i2,o[i1:i2] = v
|
||||||
c-api/sequence,,:i2,del o[i1:i2]
|
c-api/sequence,,:i2,del o[i1:i2]
|
||||||
c-api/unicode,,:end,str[start:end]
|
c-api/unicode,,:end,str[start:end]
|
||||||
distutils/apiref,,:action,http://pypi.python.org/pypi?:action=list_classifiers
|
|
||||||
distutils/setupscript,,::,
|
distutils/setupscript,,::,
|
||||||
extending/embedding,,:numargs,"if(!PyArg_ParseTuple(args, "":numargs""))"
|
extending/embedding,,:numargs,"if(!PyArg_ParseTuple(args, "":numargs""))"
|
||||||
extending/extending,,:set,"if (PyArg_ParseTuple(args, ""O:set_callback"", &temp)) {"
|
extending/extending,,:set,"if (PyArg_ParseTuple(args, ""O:set_callback"", &temp)) {"
|
||||||
|
@ -495,7 +494,6 @@ library/pprint,209,::,"'Programming Language :: Python :: 2.6',"
|
||||||
library/pprint,209,::,"'Programming Language :: Python :: 2.7',"
|
library/pprint,209,::,"'Programming Language :: Python :: 2.7',"
|
||||||
library/pprint,209,::,"'Topic :: Software Development :: Libraries',"
|
library/pprint,209,::,"'Topic :: Software Development :: Libraries',"
|
||||||
library/pprint,209,::,"'Topic :: Software Development :: Libraries :: Python Modules'],"
|
library/pprint,209,::,"'Topic :: Software Development :: Libraries :: Python Modules'],"
|
||||||
library/packaging.dist,,:action,http://pypi.python.org/pypi?:action=list_classifiers
|
|
||||||
packaging/examples,,`,This is the description of the ``foobar`` project.
|
packaging/examples,,`,This is the description of the ``foobar`` project.
|
||||||
packaging/setupcfg,,::,Development Status :: 3 - Alpha
|
packaging/setupcfg,,::,Development Status :: 3 - Alpha
|
||||||
packaging/setupcfg,,::,License :: OSI Approved :: Mozilla Public License 1.1 (MPL 1.1)
|
packaging/setupcfg,,::,License :: OSI Approved :: Mozilla Public License 1.1 (MPL 1.1)
|
||||||
|
|
|
|
@ -598,24 +598,24 @@ occurs within the definition of a class.
|
||||||
Name mangling is helpful for letting subclasses override methods without
|
Name mangling is helpful for letting subclasses override methods without
|
||||||
breaking intraclass method calls. For example::
|
breaking intraclass method calls. For example::
|
||||||
|
|
||||||
class Mapping:
|
class Mapping:
|
||||||
def __init__(self, iterable):
|
def __init__(self, iterable):
|
||||||
self.items_list = []
|
self.items_list = []
|
||||||
self.__update(iterable)
|
self.__update(iterable)
|
||||||
|
|
||||||
def update(self, iterable):
|
def update(self, iterable):
|
||||||
for item in iterable:
|
for item in iterable:
|
||||||
self.items_list.append(item)
|
self.items_list.append(item)
|
||||||
|
|
||||||
__update = update # private copy of original update() method
|
__update = update # private copy of original update() method
|
||||||
|
|
||||||
class MappingSubclass(Mapping):
|
class MappingSubclass(Mapping):
|
||||||
|
|
||||||
def update(self, keys, values):
|
def update(self, keys, values):
|
||||||
# provides new signature for update()
|
# provides new signature for update()
|
||||||
# but does not break __init__()
|
# but does not break __init__()
|
||||||
for item in zip(keys, values):
|
for item in zip(keys, values):
|
||||||
self.items_list.append(item)
|
self.items_list.append(item)
|
||||||
|
|
||||||
Note that the mangling rules are designed mostly to avoid accidents; it still is
|
Note that the mangling rules are designed mostly to avoid accidents; it still is
|
||||||
possible to access or modify a variable that is considered private. This can
|
possible to access or modify a variable that is considered private. This can
|
||||||
|
|
|
@ -94,8 +94,8 @@ versions.
|
||||||
curses
|
curses
|
||||||
------
|
------
|
||||||
|
|
||||||
The :class:`curses.window` class has a new :class:`~curses.window.get_wch`
|
The :class:`curses.window` class has a new :meth:`~curses.window.get_wch` method
|
||||||
method to a wide character. Patch by Iñigo Serna.
|
to get a wide character. Patch by Iñigo Serna.
|
||||||
|
|
||||||
(:issue:`6755`)
|
(:issue:`6755`)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
"""Find modules used by a script, using introspection."""
|
"""Find modules used by a script, using introspection."""
|
||||||
|
|
||||||
from __future__ import generators
|
|
||||||
import dis
|
import dis
|
||||||
import imp
|
import imp
|
||||||
import marshal
|
import marshal
|
||||||
|
@ -9,8 +8,6 @@ import sys
|
||||||
import types
|
import types
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
READ_MODE = "rU"
|
|
||||||
|
|
||||||
# XXX Clean up once str8's cstor matches bytes.
|
# XXX Clean up once str8's cstor matches bytes.
|
||||||
LOAD_CONST = bytes([dis.opname.index('LOAD_CONST')])
|
LOAD_CONST = bytes([dis.opname.index('LOAD_CONST')])
|
||||||
IMPORT_NAME = bytes([dis.opname.index('IMPORT_NAME')])
|
IMPORT_NAME = bytes([dis.opname.index('IMPORT_NAME')])
|
||||||
|
@ -29,8 +26,7 @@ packagePathMap = {}
|
||||||
|
|
||||||
# A Public interface
|
# A Public interface
|
||||||
def AddPackagePath(packagename, path):
|
def AddPackagePath(packagename, path):
|
||||||
paths = packagePathMap.get(packagename, [])
|
paths = packagePathMap.setdefault(packagename, []).append(path)
|
||||||
paths.append(path)
|
|
||||||
packagePathMap[packagename] = paths
|
packagePathMap[packagename] = paths
|
||||||
|
|
||||||
replacePackageMap = {}
|
replacePackageMap = {}
|
||||||
|
@ -106,14 +102,14 @@ class ModuleFinder:
|
||||||
|
|
||||||
def run_script(self, pathname):
|
def run_script(self, pathname):
|
||||||
self.msg(2, "run_script", pathname)
|
self.msg(2, "run_script", pathname)
|
||||||
with open(pathname, READ_MODE) as fp:
|
with open(pathname) as fp:
|
||||||
stuff = ("", "r", imp.PY_SOURCE)
|
stuff = ("", "r", imp.PY_SOURCE)
|
||||||
self.load_module('__main__', fp, pathname, stuff)
|
self.load_module('__main__', fp, pathname, stuff)
|
||||||
|
|
||||||
def load_file(self, pathname):
|
def load_file(self, pathname):
|
||||||
dir, name = os.path.split(pathname)
|
dir, name = os.path.split(pathname)
|
||||||
name, ext = os.path.splitext(name)
|
name, ext = os.path.splitext(name)
|
||||||
with open(pathname, READ_MODE) as fp:
|
with open(pathname) as fp:
|
||||||
stuff = (ext, "r", imp.PY_SOURCE)
|
stuff = (ext, "r", imp.PY_SOURCE)
|
||||||
self.load_module(name, fp, pathname, stuff)
|
self.load_module(name, fp, pathname, stuff)
|
||||||
|
|
||||||
|
@ -270,7 +266,8 @@ class ModuleFinder:
|
||||||
try:
|
try:
|
||||||
m = self.load_module(fqname, fp, pathname, stuff)
|
m = self.load_module(fqname, fp, pathname, stuff)
|
||||||
finally:
|
finally:
|
||||||
if fp: fp.close()
|
if fp:
|
||||||
|
fp.close()
|
||||||
if parent:
|
if parent:
|
||||||
setattr(parent, partname, m)
|
setattr(parent, partname, m)
|
||||||
self.msgout(3, "import_module ->", m)
|
self.msgout(3, "import_module ->", m)
|
||||||
|
@ -662,4 +659,4 @@ if __name__ == '__main__':
|
||||||
try:
|
try:
|
||||||
mf = test()
|
mf = test()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("\n[interrupt]")
|
print("\n[interrupted]")
|
||||||
|
|
|
@ -51,7 +51,7 @@ import itertools
|
||||||
from multiprocessing import TimeoutError, cpu_count
|
from multiprocessing import TimeoutError, cpu_count
|
||||||
from multiprocessing.dummy.connection import Pipe
|
from multiprocessing.dummy.connection import Pipe
|
||||||
from threading import Lock, RLock, Semaphore, BoundedSemaphore
|
from threading import Lock, RLock, Semaphore, BoundedSemaphore
|
||||||
from threading import Event
|
from threading import Event, Condition
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -84,17 +84,6 @@ class DummyProcess(threading.Thread):
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
class Condition(threading._Condition):
|
|
||||||
# XXX
|
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
notify_all = threading._Condition.notify_all.__func__
|
|
||||||
else:
|
|
||||||
notify_all = threading._Condition.notify_all
|
|
||||||
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
Process = DummyProcess
|
Process = DummyProcess
|
||||||
current_process = threading.current_thread
|
current_process = threading.current_thread
|
||||||
current_process()._children = weakref.WeakKeyDictionary()
|
current_process()._children = weakref.WeakKeyDictionary()
|
||||||
|
|
|
@ -57,7 +57,8 @@ class Command:
|
||||||
from packaging.dist import Distribution
|
from packaging.dist import Distribution
|
||||||
|
|
||||||
if not isinstance(dist, Distribution):
|
if not isinstance(dist, Distribution):
|
||||||
raise TypeError("dist must be a Distribution instance")
|
raise TypeError("dist must be an instance of Distribution, not %r"
|
||||||
|
% type(dist))
|
||||||
if self.__class__ is Command:
|
if self.__class__ is Command:
|
||||||
raise RuntimeError("Command is an abstract class")
|
raise RuntimeError("Command is an abstract class")
|
||||||
|
|
||||||
|
|
|
@ -351,7 +351,7 @@ class EggInfoDistribution:
|
||||||
except IOError:
|
except IOError:
|
||||||
requires = None
|
requires = None
|
||||||
self.metadata = Metadata(path=path)
|
self.metadata = Metadata(path=path)
|
||||||
self.name = self.metadata['name']
|
self.name = self.metadata['Name']
|
||||||
self.version = self.metadata['Version']
|
self.version = self.metadata['Version']
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -72,7 +72,7 @@ class DependencyGraph:
|
||||||
self.missing[distribution].append(requirement)
|
self.missing[distribution].append(requirement)
|
||||||
|
|
||||||
def _repr_dist(self, dist):
|
def _repr_dist(self, dist):
|
||||||
return '%r %s' % (dist.name, dist.metadata['Version'])
|
return '%r %s' % (dist.name, dist.version)
|
||||||
|
|
||||||
def repr_node(self, dist, level=1):
|
def repr_node(self, dist, level=1):
|
||||||
"""Prints only a subgraph"""
|
"""Prints only a subgraph"""
|
||||||
|
@ -145,7 +145,7 @@ def generate_graph(dists):
|
||||||
graph.add_distribution(dist)
|
graph.add_distribution(dist)
|
||||||
provides = (dist.metadata['Provides-Dist'] +
|
provides = (dist.metadata['Provides-Dist'] +
|
||||||
dist.metadata['Provides'] +
|
dist.metadata['Provides'] +
|
||||||
['%s (%s)' % (dist.name, dist.metadata['Version'])])
|
['%s (%s)' % (dist.name, dist.version)])
|
||||||
|
|
||||||
for p in provides:
|
for p in provides:
|
||||||
comps = p.strip().rsplit(" ", 1)
|
comps = p.strip().rsplit(" ", 1)
|
||||||
|
|
|
@ -85,7 +85,7 @@ def _run_packaging_install(path):
|
||||||
dist.parse_config_files()
|
dist.parse_config_files()
|
||||||
try:
|
try:
|
||||||
dist.run_command('install_dist')
|
dist.run_command('install_dist')
|
||||||
name = dist.metadata['name']
|
name = dist.metadata['Name']
|
||||||
return database.get_distribution(name) is not None
|
return database.get_distribution(name) is not None
|
||||||
except (IOError, os.error, PackagingError, CCompilerError) as msg:
|
except (IOError, os.error, PackagingError, CCompilerError) as msg:
|
||||||
raise ValueError("Failed to install, " + str(msg))
|
raise ValueError("Failed to install, " + str(msg))
|
||||||
|
@ -118,10 +118,10 @@ def install_local_project(path):
|
||||||
"""
|
"""
|
||||||
path = os.path.abspath(path)
|
path = os.path.abspath(path)
|
||||||
if os.path.isdir(path):
|
if os.path.isdir(path):
|
||||||
logger.info('Installing from source directory: %s', path)
|
logger.info('Installing from source directory: %r', path)
|
||||||
return _run_install_from_dir(path)
|
return _run_install_from_dir(path)
|
||||||
elif _is_archive_file(path):
|
elif _is_archive_file(path):
|
||||||
logger.info('Installing from archive: %s', path)
|
logger.info('Installing from archive: %r', path)
|
||||||
_unpacked_dir = tempfile.mkdtemp()
|
_unpacked_dir = tempfile.mkdtemp()
|
||||||
try:
|
try:
|
||||||
shutil.unpack_archive(path, _unpacked_dir)
|
shutil.unpack_archive(path, _unpacked_dir)
|
||||||
|
@ -129,7 +129,7 @@ def install_local_project(path):
|
||||||
finally:
|
finally:
|
||||||
shutil.rmtree(_unpacked_dir)
|
shutil.rmtree(_unpacked_dir)
|
||||||
else:
|
else:
|
||||||
logger.warning('No projects to install.')
|
logger.warning('No project to install.')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ def install_dists(dists, path, paths=None):
|
||||||
|
|
||||||
# reverting
|
# reverting
|
||||||
for installed_dist in installed_dists:
|
for installed_dist in installed_dists:
|
||||||
logger.info('Reverting %s', installed_dist)
|
logger.info('Reverting %r', installed_dist)
|
||||||
remove(installed_dist.name, paths)
|
remove(installed_dist.name, paths)
|
||||||
raise e
|
raise e
|
||||||
return installed_dists
|
return installed_dists
|
||||||
|
@ -314,12 +314,12 @@ def get_infos(requirements, index=None, installed=None, prefer_final=True):
|
||||||
if predicate.name.lower() != installed_project.name.lower():
|
if predicate.name.lower() != installed_project.name.lower():
|
||||||
continue
|
continue
|
||||||
found = True
|
found = True
|
||||||
logger.info('Found %s %s', installed_project.name,
|
logger.info('Found %r %s', installed_project.name,
|
||||||
installed_project.metadata['version'])
|
installed_project.version)
|
||||||
|
|
||||||
# if we already have something installed, check it matches the
|
# if we already have something installed, check it matches the
|
||||||
# requirements
|
# requirements
|
||||||
if predicate.match(installed_project.metadata['version']):
|
if predicate.match(installed_project.version):
|
||||||
return infos
|
return infos
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -336,7 +336,7 @@ def get_infos(requirements, index=None, installed=None, prefer_final=True):
|
||||||
try:
|
try:
|
||||||
release = index.get_release(requirements)
|
release = index.get_release(requirements)
|
||||||
except (ReleaseNotFound, ProjectNotFound):
|
except (ReleaseNotFound, ProjectNotFound):
|
||||||
raise InstallationException('Release not found: "%s"' % requirements)
|
raise InstallationException('Release not found: %r' % requirements)
|
||||||
|
|
||||||
if release is None:
|
if release is None:
|
||||||
logger.info('Could not find a matching project')
|
logger.info('Could not find a matching project')
|
||||||
|
@ -386,7 +386,7 @@ def remove(project_name, paths=None, auto_confirm=True):
|
||||||
"""
|
"""
|
||||||
dist = get_distribution(project_name, use_egg_info=True, paths=paths)
|
dist = get_distribution(project_name, use_egg_info=True, paths=paths)
|
||||||
if dist is None:
|
if dist is None:
|
||||||
raise PackagingError('Distribution "%s" not found' % project_name)
|
raise PackagingError('Distribution %r not found' % project_name)
|
||||||
files = dist.list_installed_files(local=True)
|
files = dist.list_installed_files(local=True)
|
||||||
rmdirs = []
|
rmdirs = []
|
||||||
rmfiles = []
|
rmfiles = []
|
||||||
|
@ -423,7 +423,7 @@ def remove(project_name, paths=None, auto_confirm=True):
|
||||||
|
|
||||||
if not success:
|
if not success:
|
||||||
logger.info('%r cannot be removed.', project_name)
|
logger.info('%r cannot be removed.', project_name)
|
||||||
logger.info('Error: %s' % str(error))
|
logger.info('Error: %s', error)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
logger.info('Removing %r: ', project_name)
|
logger.info('Removing %r: ', project_name)
|
||||||
|
@ -523,7 +523,7 @@ def install(project):
|
||||||
|
|
||||||
except InstallationConflict as e:
|
except InstallationConflict as e:
|
||||||
if logger.isEnabledFor(logging.INFO):
|
if logger.isEnabledFor(logging.INFO):
|
||||||
projects = ['%r %s' % (p.name, p.version) for p in e.args[0]]
|
projects = ('%r %s' % (p.name, p.version) for p in e.args[0])
|
||||||
logger.info('%r conflicts with %s', project, ','.join(projects))
|
logger.info('%r conflicts with %s', project, ','.join(projects))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -214,7 +214,7 @@ def _create(distpatcher, args, **kw):
|
||||||
@action_help(generate_usage)
|
@action_help(generate_usage)
|
||||||
def _generate(distpatcher, args, **kw):
|
def _generate(distpatcher, args, **kw):
|
||||||
generate_setup_py()
|
generate_setup_py()
|
||||||
print('The setup.py was generated')
|
logger.info('The setup.py was generated')
|
||||||
|
|
||||||
|
|
||||||
@action_help(graph_usage)
|
@action_help(graph_usage)
|
||||||
|
@ -222,7 +222,8 @@ def _graph(dispatcher, args, **kw):
|
||||||
name = args[1]
|
name = args[1]
|
||||||
dist = get_distribution(name, use_egg_info=True)
|
dist = get_distribution(name, use_egg_info=True)
|
||||||
if dist is None:
|
if dist is None:
|
||||||
print('Distribution not found.')
|
logger.warning('Distribution not found.')
|
||||||
|
return 1
|
||||||
else:
|
else:
|
||||||
dists = get_distributions(use_egg_info=True)
|
dists = get_distributions(use_egg_info=True)
|
||||||
graph = generate_graph(dists)
|
graph = generate_graph(dists)
|
||||||
|
@ -234,8 +235,7 @@ def _install(dispatcher, args, **kw):
|
||||||
# first check if we are in a source directory
|
# first check if we are in a source directory
|
||||||
if len(args) < 2:
|
if len(args) < 2:
|
||||||
# are we inside a project dir?
|
# are we inside a project dir?
|
||||||
listing = os.listdir(os.getcwd())
|
if os.path.isfile('setup.cfg') or os.path.isfile('setup.py'):
|
||||||
if 'setup.py' in listing or 'setup.cfg' in listing:
|
|
||||||
args.insert(1, os.getcwd())
|
args.insert(1, os.getcwd())
|
||||||
else:
|
else:
|
||||||
logger.warning('No project to install.')
|
logger.warning('No project to install.')
|
||||||
|
@ -244,16 +244,10 @@ def _install(dispatcher, args, **kw):
|
||||||
target = args[1]
|
target = args[1]
|
||||||
# installing from a source dir or archive file?
|
# installing from a source dir or archive file?
|
||||||
if os.path.isdir(target) or _is_archive_file(target):
|
if os.path.isdir(target) or _is_archive_file(target):
|
||||||
if install_local_project(target):
|
return not install_local_project(target)
|
||||||
return 0
|
|
||||||
else:
|
|
||||||
return 1
|
|
||||||
else:
|
else:
|
||||||
# download from PyPI
|
# download from PyPI
|
||||||
if install(target):
|
return not install(target)
|
||||||
return 0
|
|
||||||
else:
|
|
||||||
return 1
|
|
||||||
|
|
||||||
|
|
||||||
@action_help(metadata_usage)
|
@action_help(metadata_usage)
|
||||||
|
@ -263,12 +257,15 @@ def _metadata(dispatcher, args, **kw):
|
||||||
name = opts['args'][0]
|
name = opts['args'][0]
|
||||||
dist = get_distribution(name, use_egg_info=True)
|
dist = get_distribution(name, use_egg_info=True)
|
||||||
if dist is None:
|
if dist is None:
|
||||||
logger.warning('%s not installed', name)
|
logger.warning('%r not installed', name)
|
||||||
return
|
return 1
|
||||||
else:
|
elif os.path.isfile('setup.cfg'):
|
||||||
logger.info('searching local dir for metadata')
|
logger.info('searching local dir for metadata')
|
||||||
dist = Distribution()
|
dist = Distribution() # XXX use config module
|
||||||
dist.parse_config_files()
|
dist.parse_config_files()
|
||||||
|
else:
|
||||||
|
logger.warning('no argument given and no local setup.cfg found')
|
||||||
|
return 1
|
||||||
|
|
||||||
metadata = dist.metadata
|
metadata = dist.metadata
|
||||||
|
|
||||||
|
@ -299,11 +296,15 @@ def _remove(distpatcher, args, **kw):
|
||||||
else:
|
else:
|
||||||
auto_confirm = False
|
auto_confirm = False
|
||||||
|
|
||||||
|
retcode = 0
|
||||||
for dist in set(opts['args']):
|
for dist in set(opts['args']):
|
||||||
try:
|
try:
|
||||||
remove(dist, auto_confirm=auto_confirm)
|
remove(dist, auto_confirm=auto_confirm)
|
||||||
except PackagingError:
|
except PackagingError:
|
||||||
logger.warning('%s not installed', dist)
|
logger.warning('%r not installed', dist)
|
||||||
|
retcode = 1
|
||||||
|
|
||||||
|
return retcode
|
||||||
|
|
||||||
|
|
||||||
@action_help(run_usage)
|
@action_help(run_usage)
|
||||||
|
@ -339,14 +340,8 @@ def _run(dispatcher, args, **kw):
|
||||||
# XXX still need to be extracted from Distribution
|
# XXX still need to be extracted from Distribution
|
||||||
dist.parse_config_files()
|
dist.parse_config_files()
|
||||||
|
|
||||||
try:
|
for cmd in dispatcher.commands:
|
||||||
for cmd in dispatcher.commands:
|
dist.run_command(cmd, dispatcher.command_options[cmd])
|
||||||
dist.run_command(cmd, dispatcher.command_options[cmd])
|
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
raise SystemExit("interrupted")
|
|
||||||
except (IOError, os.error, PackagingError, CCompilerError) as msg:
|
|
||||||
raise SystemExit("error: " + str(msg))
|
|
||||||
|
|
||||||
# XXX this is crappy
|
# XXX this is crappy
|
||||||
return dist
|
return dist
|
||||||
|
@ -358,19 +353,24 @@ def _list(dispatcher, args, **kw):
|
||||||
dists = get_distributions(use_egg_info=True)
|
dists = get_distributions(use_egg_info=True)
|
||||||
if 'all' in opts or opts['args'] == []:
|
if 'all' in opts or opts['args'] == []:
|
||||||
results = dists
|
results = dists
|
||||||
|
listall = True
|
||||||
else:
|
else:
|
||||||
results = [d for d in dists if d.name.lower() in opts['args']]
|
results = (d for d in dists if d.name.lower() in opts['args'])
|
||||||
|
listall = False
|
||||||
|
|
||||||
number = 0
|
number = 0
|
||||||
for dist in results:
|
for dist in results:
|
||||||
print('%s %s at %s' % (dist.name, dist.metadata['version'], dist.path))
|
print('%r %s (from %r)' % (dist.name, dist.version, dist.path))
|
||||||
number += 1
|
number += 1
|
||||||
|
|
||||||
print()
|
|
||||||
if number == 0:
|
if number == 0:
|
||||||
print('Nothing seems to be installed.')
|
if listall:
|
||||||
|
logger.info('Nothing seems to be installed.')
|
||||||
|
else:
|
||||||
|
logger.warning('No matching distribution found.')
|
||||||
|
return 1
|
||||||
else:
|
else:
|
||||||
print('Found %d projects installed.' % number)
|
logger.info('Found %d projects installed.', number)
|
||||||
|
|
||||||
|
|
||||||
@action_help(search_usage)
|
@action_help(search_usage)
|
||||||
|
@ -382,7 +382,8 @@ def _search(dispatcher, args, **kw):
|
||||||
"""
|
"""
|
||||||
#opts = _parse_args(args[1:], '', ['simple', 'xmlrpc'])
|
#opts = _parse_args(args[1:], '', ['simple', 'xmlrpc'])
|
||||||
# 1. what kind of index is requested ? (xmlrpc / simple)
|
# 1. what kind of index is requested ? (xmlrpc / simple)
|
||||||
raise NotImplementedError
|
logger.error('not implemented')
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
actions = [
|
actions = [
|
||||||
|
@ -662,6 +663,7 @@ class Dispatcher:
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
if self.action is None:
|
if self.action is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
for action, desc, func in actions:
|
for action, desc, func in actions:
|
||||||
if action == self.action:
|
if action == self.action:
|
||||||
return func(self, self.args)
|
return func(self, self.args)
|
||||||
|
@ -676,6 +678,12 @@ def main(args=None):
|
||||||
if dispatcher.action is None:
|
if dispatcher.action is None:
|
||||||
return
|
return
|
||||||
return dispatcher()
|
return dispatcher()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
logger.info('interrupted')
|
||||||
|
return 1
|
||||||
|
except (IOError, os.error, PackagingError, CCompilerError) as exc:
|
||||||
|
logger.exception(exc)
|
||||||
|
return 1
|
||||||
finally:
|
finally:
|
||||||
logger.setLevel(old_level)
|
logger.setLevel(old_level)
|
||||||
logger.handlers[:] = old_handlers
|
logger.handlers[:] = old_handlers
|
||||||
|
|
|
@ -302,7 +302,7 @@ class TestDatabase(support.LoggingCatcher,
|
||||||
self.assertIsInstance(dist, Distribution)
|
self.assertIsInstance(dist, Distribution)
|
||||||
if (dist.name in dict(fake_dists) and
|
if (dist.name in dict(fake_dists) and
|
||||||
dist.path.startswith(self.fake_dists_path)):
|
dist.path.startswith(self.fake_dists_path)):
|
||||||
found_dists.append((dist.name, dist.metadata['version'], ))
|
found_dists.append((dist.name, dist.version))
|
||||||
else:
|
else:
|
||||||
# check that it doesn't find anything more than this
|
# check that it doesn't find anything more than this
|
||||||
self.assertFalse(dist.path.startswith(self.fake_dists_path))
|
self.assertFalse(dist.path.startswith(self.fake_dists_path))
|
||||||
|
@ -323,7 +323,7 @@ class TestDatabase(support.LoggingCatcher,
|
||||||
self.assertIsInstance(dist, (Distribution, EggInfoDistribution))
|
self.assertIsInstance(dist, (Distribution, EggInfoDistribution))
|
||||||
if (dist.name in dict(fake_dists) and
|
if (dist.name in dict(fake_dists) and
|
||||||
dist.path.startswith(self.fake_dists_path)):
|
dist.path.startswith(self.fake_dists_path)):
|
||||||
found_dists.append((dist.name, dist.metadata['version']))
|
found_dists.append((dist.name, dist.version))
|
||||||
else:
|
else:
|
||||||
self.assertFalse(dist.path.startswith(self.fake_dists_path))
|
self.assertFalse(dist.path.startswith(self.fake_dists_path))
|
||||||
|
|
||||||
|
@ -489,17 +489,17 @@ class TestDatabase(support.LoggingCatcher,
|
||||||
|
|
||||||
checkLists([], _yield_distributions(False, False, sys.path))
|
checkLists([], _yield_distributions(False, False, sys.path))
|
||||||
|
|
||||||
found = [(dist.name, dist.metadata['Version'])
|
found = [(dist.name, dist.version)
|
||||||
for dist in _yield_distributions(False, True, sys.path)
|
for dist in _yield_distributions(False, True, sys.path)
|
||||||
if dist.path.startswith(self.fake_dists_path)]
|
if dist.path.startswith(self.fake_dists_path)]
|
||||||
checkLists(eggs, found)
|
checkLists(eggs, found)
|
||||||
|
|
||||||
found = [(dist.name, dist.metadata['Version'])
|
found = [(dist.name, dist.version)
|
||||||
for dist in _yield_distributions(True, False, sys.path)
|
for dist in _yield_distributions(True, False, sys.path)
|
||||||
if dist.path.startswith(self.fake_dists_path)]
|
if dist.path.startswith(self.fake_dists_path)]
|
||||||
checkLists(dists, found)
|
checkLists(dists, found)
|
||||||
|
|
||||||
found = [(dist.name, dist.metadata['Version'])
|
found = [(dist.name, dist.version)
|
||||||
for dist in _yield_distributions(True, True, sys.path)
|
for dist in _yield_distributions(True, True, sys.path)
|
||||||
if dist.path.startswith(self.fake_dists_path)]
|
if dist.path.startswith(self.fake_dists_path)]
|
||||||
checkLists(dists + eggs, found)
|
checkLists(dists + eggs, found)
|
||||||
|
|
|
@ -29,7 +29,7 @@ class InstalledDist:
|
||||||
self.metadata['Requires-Dist'] = deps
|
self.metadata['Requires-Dist'] = deps
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<InstalledDist %s>' % self.metadata['Name']
|
return '<InstalledDist %r>' % self.metadata['Name']
|
||||||
|
|
||||||
|
|
||||||
class ToInstallDist:
|
class ToInstallDist:
|
||||||
|
|
23
Lib/pipes.py
23
Lib/pipes.py
|
@ -62,7 +62,9 @@ For an example, see the function test() at the end of the file.
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import string
|
# we import the quote function rather than the module for backward compat
|
||||||
|
# (quote used to be an undocumented but used function in pipes)
|
||||||
|
from shlex import quote
|
||||||
|
|
||||||
__all__ = ["Template"]
|
__all__ = ["Template"]
|
||||||
|
|
||||||
|
@ -245,22 +247,3 @@ def makepipeline(infile, steps, outfile):
|
||||||
cmdlist = trapcmd + '\n' + cmdlist + '\n' + rmcmd
|
cmdlist = trapcmd + '\n' + cmdlist + '\n' + rmcmd
|
||||||
#
|
#
|
||||||
return cmdlist
|
return cmdlist
|
||||||
|
|
||||||
|
|
||||||
# Reliably quote a string as a single argument for /bin/sh
|
|
||||||
|
|
||||||
# Safe unquoted
|
|
||||||
_safechars = frozenset(string.ascii_letters + string.digits + '@%_-+=:,./')
|
|
||||||
|
|
||||||
def quote(file):
|
|
||||||
"""Return a shell-escaped version of the file string."""
|
|
||||||
for c in file:
|
|
||||||
if c not in _safechars:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
if not file:
|
|
||||||
return "''"
|
|
||||||
return file
|
|
||||||
# use single quotes, and put single quotes into double quotes
|
|
||||||
# the string $'b is then quoted as '$'"'"'b'
|
|
||||||
return "'" + file.replace("'", "'\"'\"'") + "'"
|
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
"""Class for printing reports on profiled python code."""
|
"""Class for printing reports on profiled python code."""
|
||||||
|
|
||||||
# Class for printing reports on profiled python code. rev 1.0 4/1/94
|
|
||||||
#
|
|
||||||
# Written by James Roskind
|
# Written by James Roskind
|
||||||
# Based on prior profile module by Sjoerd Mullender...
|
# Based on prior profile module by Sjoerd Mullender...
|
||||||
# which was hacked somewhat by: Guido van Rossum
|
# which was hacked somewhat by: Guido van Rossum
|
||||||
|
|
||||||
"""Class for profiling Python code."""
|
|
||||||
|
|
||||||
# Copyright Disney Enterprises, Inc. All Rights Reserved.
|
# Copyright Disney Enterprises, Inc. All Rights Reserved.
|
||||||
# Licensed to PSF under a Contributor Agreement
|
# Licensed to PSF under a Contributor Agreement
|
||||||
#
|
#
|
||||||
|
|
20
Lib/shlex.py
20
Lib/shlex.py
|
@ -6,13 +6,14 @@
|
||||||
# Posix compliance, split(), string arguments, and
|
# Posix compliance, split(), string arguments, and
|
||||||
# iterator interface by Gustavo Niemeyer, April 2003.
|
# iterator interface by Gustavo Niemeyer, April 2003.
|
||||||
|
|
||||||
import os.path
|
import os
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
__all__ = ["shlex", "split"]
|
__all__ = ["shlex", "split", "quote"]
|
||||||
|
|
||||||
class shlex:
|
class shlex:
|
||||||
"A lexical analyzer class for simple shell-like syntaxes."
|
"A lexical analyzer class for simple shell-like syntaxes."
|
||||||
|
@ -274,6 +275,21 @@ def split(s, comments=False, posix=True):
|
||||||
lex.commenters = ''
|
lex.commenters = ''
|
||||||
return list(lex)
|
return list(lex)
|
||||||
|
|
||||||
|
|
||||||
|
_find_unsafe = re.compile(r'[^\w\d@%_\-\+=:,\./]').search
|
||||||
|
|
||||||
|
def quote(s):
|
||||||
|
"""Return a shell-escaped version of the string *s*."""
|
||||||
|
if not s:
|
||||||
|
return "''"
|
||||||
|
if _find_unsafe(s) is None:
|
||||||
|
return s
|
||||||
|
|
||||||
|
# use single quotes, and put single quotes into double quotes
|
||||||
|
# the string $'b is then quoted as '$'"'"'b'
|
||||||
|
return "'" + s.replace("'", "'\"'\"'") + "'"
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
if len(sys.argv) == 1:
|
if len(sys.argv) == 1:
|
||||||
lexer = shlex()
|
lexer = shlex()
|
||||||
|
|
|
@ -4,17 +4,10 @@ Tests common to list and UserList.UserList
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
from functools import cmp_to_key
|
||||||
|
|
||||||
from test import support, seq_tests
|
from test import support, seq_tests
|
||||||
|
|
||||||
def CmpToKey(mycmp):
|
|
||||||
'Convert a cmp= function into a key= function'
|
|
||||||
class K(object):
|
|
||||||
def __init__(self, obj):
|
|
||||||
self.obj = obj
|
|
||||||
def __lt__(self, other):
|
|
||||||
return mycmp(self.obj, other.obj) == -1
|
|
||||||
return K
|
|
||||||
|
|
||||||
class CommonTest(seq_tests.CommonTest):
|
class CommonTest(seq_tests.CommonTest):
|
||||||
|
|
||||||
|
@ -484,7 +477,7 @@ class CommonTest(seq_tests.CommonTest):
|
||||||
return 1
|
return 1
|
||||||
else: # a > b
|
else: # a > b
|
||||||
return -1
|
return -1
|
||||||
u.sort(key=CmpToKey(revcmp))
|
u.sort(key=cmp_to_key(revcmp))
|
||||||
self.assertEqual(u, self.type2test([2,1,0,-1,-2]))
|
self.assertEqual(u, self.type2test([2,1,0,-1,-2]))
|
||||||
|
|
||||||
# The following dumps core in unpatched Python 1.5:
|
# The following dumps core in unpatched Python 1.5:
|
||||||
|
@ -497,7 +490,7 @@ class CommonTest(seq_tests.CommonTest):
|
||||||
else: # xmod > ymod
|
else: # xmod > ymod
|
||||||
return 1
|
return 1
|
||||||
z = self.type2test(range(12))
|
z = self.type2test(range(12))
|
||||||
z.sort(key=CmpToKey(myComparison))
|
z.sort(key=cmp_to_key(myComparison))
|
||||||
|
|
||||||
self.assertRaises(TypeError, z.sort, 2)
|
self.assertRaises(TypeError, z.sort, 2)
|
||||||
|
|
||||||
|
@ -509,7 +502,8 @@ class CommonTest(seq_tests.CommonTest):
|
||||||
return -1
|
return -1
|
||||||
else: # x > y
|
else: # x > y
|
||||||
return 1
|
return 1
|
||||||
self.assertRaises(ValueError, z.sort, key=CmpToKey(selfmodifyingComparison))
|
self.assertRaises(ValueError, z.sort,
|
||||||
|
key=cmp_to_key(selfmodifyingComparison))
|
||||||
|
|
||||||
self.assertRaises(TypeError, z.sort, 42, 42, 42, 42)
|
self.assertRaises(TypeError, z.sort, 42, 42, 42, 42)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import __future__
|
|
||||||
import os
|
import os
|
||||||
|
import errno
|
||||||
|
import shutil
|
||||||
import unittest
|
import unittest
|
||||||
import distutils.dir_util
|
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from test import support
|
from test import support
|
||||||
|
@ -9,7 +9,7 @@ from test import support
|
||||||
import modulefinder
|
import modulefinder
|
||||||
|
|
||||||
TEST_DIR = tempfile.mkdtemp()
|
TEST_DIR = tempfile.mkdtemp()
|
||||||
TEST_PATH = [TEST_DIR, os.path.dirname(__future__.__file__)]
|
TEST_PATH = [TEST_DIR, os.path.dirname(tempfile.__file__)]
|
||||||
|
|
||||||
# Each test description is a list of 5 items:
|
# Each test description is a list of 5 items:
|
||||||
#
|
#
|
||||||
|
@ -196,12 +196,17 @@ a/module.py
|
||||||
from . import bar
|
from . import bar
|
||||||
"""]
|
"""]
|
||||||
|
|
||||||
|
|
||||||
def open_file(path):
|
def open_file(path):
|
||||||
##print "#", os.path.abspath(path)
|
|
||||||
dirname = os.path.dirname(path)
|
dirname = os.path.dirname(path)
|
||||||
distutils.dir_util.mkpath(dirname)
|
try:
|
||||||
|
os.makedirs(dirname)
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno != errno.EEXIST:
|
||||||
|
raise
|
||||||
return open(path, "w")
|
return open(path, "w")
|
||||||
|
|
||||||
|
|
||||||
def create_package(source):
|
def create_package(source):
|
||||||
ofi = None
|
ofi = None
|
||||||
try:
|
try:
|
||||||
|
@ -216,6 +221,7 @@ def create_package(source):
|
||||||
if ofi:
|
if ofi:
|
||||||
ofi.close()
|
ofi.close()
|
||||||
|
|
||||||
|
|
||||||
class ModuleFinderTest(unittest.TestCase):
|
class ModuleFinderTest(unittest.TestCase):
|
||||||
def _do_test(self, info, report=False):
|
def _do_test(self, info, report=False):
|
||||||
import_this, modules, missing, maybe_missing, source = info
|
import_this, modules, missing, maybe_missing, source = info
|
||||||
|
@ -234,19 +240,17 @@ class ModuleFinderTest(unittest.TestCase):
|
||||||
## import traceback; traceback.print_exc()
|
## import traceback; traceback.print_exc()
|
||||||
## sys.path = opath
|
## sys.path = opath
|
||||||
## return
|
## return
|
||||||
modules = set(modules)
|
modules = sorted(set(modules))
|
||||||
found = set(mf.modules.keys())
|
found = sorted(mf.modules)
|
||||||
more = list(found - modules)
|
|
||||||
less = list(modules - found)
|
|
||||||
# check if we found what we expected, not more, not less
|
# check if we found what we expected, not more, not less
|
||||||
self.assertEqual((more, less), ([], []))
|
self.assertEqual(found, modules)
|
||||||
|
|
||||||
# check for missing and maybe missing modules
|
# check for missing and maybe missing modules
|
||||||
bad, maybe = mf.any_missing_maybe()
|
bad, maybe = mf.any_missing_maybe()
|
||||||
self.assertEqual(bad, missing)
|
self.assertEqual(bad, missing)
|
||||||
self.assertEqual(maybe, maybe_missing)
|
self.assertEqual(maybe, maybe_missing)
|
||||||
finally:
|
finally:
|
||||||
distutils.dir_util.remove_tree(TEST_DIR)
|
shutil.rmtree(TEST_DIR)
|
||||||
|
|
||||||
def test_package(self):
|
def test_package(self):
|
||||||
self._do_test(package_test)
|
self._do_test(package_test)
|
||||||
|
@ -254,25 +258,23 @@ class ModuleFinderTest(unittest.TestCase):
|
||||||
def test_maybe(self):
|
def test_maybe(self):
|
||||||
self._do_test(maybe_test)
|
self._do_test(maybe_test)
|
||||||
|
|
||||||
if getattr(__future__, "absolute_import", None):
|
def test_maybe_new(self):
|
||||||
|
self._do_test(maybe_test_new)
|
||||||
|
|
||||||
def test_maybe_new(self):
|
def test_absolute_imports(self):
|
||||||
self._do_test(maybe_test_new)
|
self._do_test(absolute_import_test)
|
||||||
|
|
||||||
def test_absolute_imports(self):
|
def test_relative_imports(self):
|
||||||
self._do_test(absolute_import_test)
|
self._do_test(relative_import_test)
|
||||||
|
|
||||||
def test_relative_imports(self):
|
def test_relative_imports_2(self):
|
||||||
self._do_test(relative_import_test)
|
self._do_test(relative_import_test_2)
|
||||||
|
|
||||||
def test_relative_imports_2(self):
|
def test_relative_imports_3(self):
|
||||||
self._do_test(relative_import_test_2)
|
self._do_test(relative_import_test_3)
|
||||||
|
|
||||||
def test_relative_imports_3(self):
|
|
||||||
self._do_test(relative_import_test_3)
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
distutils.log.set_threshold(distutils.log.WARN)
|
|
||||||
support.run_unittest(ModuleFinderTest)
|
support.run_unittest(ModuleFinderTest)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -79,20 +79,6 @@ class SimplePipeTests(unittest.TestCase):
|
||||||
with open(TESTFN) as f:
|
with open(TESTFN) as f:
|
||||||
self.assertEqual(f.read(), d)
|
self.assertEqual(f.read(), d)
|
||||||
|
|
||||||
def testQuoting(self):
|
|
||||||
safeunquoted = string.ascii_letters + string.digits + '@%_-+=:,./'
|
|
||||||
unsafe = '"`$\\!'
|
|
||||||
|
|
||||||
self.assertEqual(pipes.quote(''), "''")
|
|
||||||
self.assertEqual(pipes.quote(safeunquoted), safeunquoted)
|
|
||||||
self.assertEqual(pipes.quote('test file name'), "'test file name'")
|
|
||||||
for u in unsafe:
|
|
||||||
self.assertEqual(pipes.quote('test%sname' % u),
|
|
||||||
"'test%sname'" % u)
|
|
||||||
for u in unsafe:
|
|
||||||
self.assertEqual(pipes.quote("test%s'name'" % u),
|
|
||||||
"'test%s'\"'\"'name'\"'\"''" % u)
|
|
||||||
|
|
||||||
def testRepr(self):
|
def testRepr(self):
|
||||||
t = pipes.Template()
|
t = pipes.Template()
|
||||||
self.assertEqual(repr(t), "<Template instance, steps=[]>")
|
self.assertEqual(repr(t), "<Template instance, steps=[]>")
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import unittest
|
import io
|
||||||
import os, sys, io
|
|
||||||
import shlex
|
import shlex
|
||||||
|
import string
|
||||||
|
import unittest
|
||||||
|
|
||||||
from test import support
|
from test import support
|
||||||
|
|
||||||
|
@ -173,6 +174,21 @@ class ShlexTest(unittest.TestCase):
|
||||||
"%s: %s != %s" %
|
"%s: %s != %s" %
|
||||||
(self.data[i][0], l, self.data[i][1:]))
|
(self.data[i][0], l, self.data[i][1:]))
|
||||||
|
|
||||||
|
def testQuote(self):
|
||||||
|
safeunquoted = string.ascii_letters + string.digits + '@%_-+=:,./'
|
||||||
|
unsafe = '"`$\\!'
|
||||||
|
|
||||||
|
self.assertEqual(shlex.quote(''), "''")
|
||||||
|
self.assertEqual(shlex.quote(safeunquoted), safeunquoted)
|
||||||
|
self.assertEqual(shlex.quote('test file name'), "'test file name'")
|
||||||
|
for u in unsafe:
|
||||||
|
self.assertEqual(shlex.quote('test%sname' % u),
|
||||||
|
"'test%sname'" % u)
|
||||||
|
for u in unsafe:
|
||||||
|
self.assertEqual(shlex.quote("test%s'name'" % u),
|
||||||
|
"'test%s'\"'\"'name'\"'\"''" % u)
|
||||||
|
|
||||||
|
|
||||||
# Allow this test to be used with old shlex.py
|
# Allow this test to be used with old shlex.py
|
||||||
if not getattr(shlex, "split", None):
|
if not getattr(shlex, "split", None):
|
||||||
for methname in dir(ShlexTest):
|
for methname in dir(ShlexTest):
|
||||||
|
|
|
@ -2,18 +2,11 @@ from test import support
|
||||||
import random
|
import random
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
|
from functools import cmp_to_key
|
||||||
|
|
||||||
verbose = support.verbose
|
verbose = support.verbose
|
||||||
nerrors = 0
|
nerrors = 0
|
||||||
|
|
||||||
def CmpToKey(mycmp):
|
|
||||||
'Convert a cmp= function into a key= function'
|
|
||||||
class K(object):
|
|
||||||
def __init__(self, obj):
|
|
||||||
self.obj = obj
|
|
||||||
def __lt__(self, other):
|
|
||||||
return mycmp(self.obj, other.obj) == -1
|
|
||||||
return K
|
|
||||||
|
|
||||||
def check(tag, expected, raw, compare=None):
|
def check(tag, expected, raw, compare=None):
|
||||||
global nerrors
|
global nerrors
|
||||||
|
@ -23,7 +16,7 @@ def check(tag, expected, raw, compare=None):
|
||||||
|
|
||||||
orig = raw[:] # save input in case of error
|
orig = raw[:] # save input in case of error
|
||||||
if compare:
|
if compare:
|
||||||
raw.sort(key=CmpToKey(compare))
|
raw.sort(key=cmp_to_key(compare))
|
||||||
else:
|
else:
|
||||||
raw.sort()
|
raw.sort()
|
||||||
|
|
||||||
|
@ -108,7 +101,7 @@ class TestBase(unittest.TestCase):
|
||||||
print(" Checking against an insane comparison function.")
|
print(" Checking against an insane comparison function.")
|
||||||
print(" If the implementation isn't careful, this may segfault.")
|
print(" If the implementation isn't careful, this may segfault.")
|
||||||
s = x[:]
|
s = x[:]
|
||||||
s.sort(key=CmpToKey(lambda a, b: int(random.random() * 3) - 1))
|
s.sort(key=cmp_to_key(lambda a, b: int(random.random() * 3) - 1))
|
||||||
check("an insane function left some permutation", x, s)
|
check("an insane function left some permutation", x, s)
|
||||||
|
|
||||||
if len(x) >= 2:
|
if len(x) >= 2:
|
||||||
|
@ -165,12 +158,12 @@ class TestBugs(unittest.TestCase):
|
||||||
L.pop()
|
L.pop()
|
||||||
return (x > y) - (x < y)
|
return (x > y) - (x < y)
|
||||||
L = [1,2]
|
L = [1,2]
|
||||||
self.assertRaises(ValueError, L.sort, key=CmpToKey(mutating_cmp))
|
self.assertRaises(ValueError, L.sort, key=cmp_to_key(mutating_cmp))
|
||||||
def mutating_cmp(x, y):
|
def mutating_cmp(x, y):
|
||||||
L.append(3)
|
L.append(3)
|
||||||
del L[:]
|
del L[:]
|
||||||
return (x > y) - (x < y)
|
return (x > y) - (x < y)
|
||||||
self.assertRaises(ValueError, L.sort, key=CmpToKey(mutating_cmp))
|
self.assertRaises(ValueError, L.sort, key=cmp_to_key(mutating_cmp))
|
||||||
memorywaster = [memorywaster]
|
memorywaster = [memorywaster]
|
||||||
|
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
|
@ -185,7 +178,7 @@ class TestDecorateSortUndecorate(unittest.TestCase):
|
||||||
def my_cmp(x, y):
|
def my_cmp(x, y):
|
||||||
xlower, ylower = x.lower(), y.lower()
|
xlower, ylower = x.lower(), y.lower()
|
||||||
return (xlower > ylower) - (xlower < ylower)
|
return (xlower > ylower) - (xlower < ylower)
|
||||||
copy.sort(key=CmpToKey(my_cmp))
|
copy.sort(key=cmp_to_key(my_cmp))
|
||||||
|
|
||||||
def test_baddecorator(self):
|
def test_baddecorator(self):
|
||||||
data = 'The quick Brown fox Jumped over The lazy Dog'.split()
|
data = 'The quick Brown fox Jumped over The lazy Dog'.split()
|
||||||
|
@ -261,8 +254,8 @@ class TestDecorateSortUndecorate(unittest.TestCase):
|
||||||
def my_cmp_reversed(x, y):
|
def my_cmp_reversed(x, y):
|
||||||
x0, y0 = x[0], y[0]
|
x0, y0 = x[0], y[0]
|
||||||
return (y0 > x0) - (y0 < x0)
|
return (y0 > x0) - (y0 < x0)
|
||||||
data.sort(key=CmpToKey(my_cmp), reverse=True)
|
data.sort(key=cmp_to_key(my_cmp), reverse=True)
|
||||||
copy1.sort(key=CmpToKey(my_cmp_reversed))
|
copy1.sort(key=cmp_to_key(my_cmp_reversed))
|
||||||
self.assertEqual(data, copy1)
|
self.assertEqual(data, copy1)
|
||||||
copy2.sort(key=lambda x: x[0], reverse=True)
|
copy2.sort(key=lambda x: x[0], reverse=True)
|
||||||
self.assertEqual(data, copy2)
|
self.assertEqual(data, copy2)
|
||||||
|
|
|
@ -172,10 +172,7 @@ class _RLock(_Verbose):
|
||||||
_PyRLock = _RLock
|
_PyRLock = _RLock
|
||||||
|
|
||||||
|
|
||||||
def Condition(*args, **kwargs):
|
class Condition(_Verbose):
|
||||||
return _Condition(*args, **kwargs)
|
|
||||||
|
|
||||||
class _Condition(_Verbose):
|
|
||||||
|
|
||||||
def __init__(self, lock=None, verbose=None):
|
def __init__(self, lock=None, verbose=None):
|
||||||
_Verbose.__init__(self, verbose)
|
_Verbose.__init__(self, verbose)
|
||||||
|
@ -308,10 +305,7 @@ class _Condition(_Verbose):
|
||||||
notifyAll = notify_all
|
notifyAll = notify_all
|
||||||
|
|
||||||
|
|
||||||
def Semaphore(*args, **kwargs):
|
class Semaphore(_Verbose):
|
||||||
return _Semaphore(*args, **kwargs)
|
|
||||||
|
|
||||||
class _Semaphore(_Verbose):
|
|
||||||
|
|
||||||
# After Tim Peters' semaphore class, but not quite the same (no maximum)
|
# After Tim Peters' semaphore class, but not quite the same (no maximum)
|
||||||
|
|
||||||
|
@ -366,25 +360,19 @@ class _Semaphore(_Verbose):
|
||||||
self.release()
|
self.release()
|
||||||
|
|
||||||
|
|
||||||
def BoundedSemaphore(*args, **kwargs):
|
class BoundedSemaphore(Semaphore):
|
||||||
return _BoundedSemaphore(*args, **kwargs)
|
|
||||||
|
|
||||||
class _BoundedSemaphore(_Semaphore):
|
|
||||||
"""Semaphore that checks that # releases is <= # acquires"""
|
"""Semaphore that checks that # releases is <= # acquires"""
|
||||||
def __init__(self, value=1, verbose=None):
|
def __init__(self, value=1, verbose=None):
|
||||||
_Semaphore.__init__(self, value, verbose)
|
Semaphore.__init__(self, value, verbose)
|
||||||
self._initial_value = value
|
self._initial_value = value
|
||||||
|
|
||||||
def release(self):
|
def release(self):
|
||||||
if self._value >= self._initial_value:
|
if self._value >= self._initial_value:
|
||||||
raise ValueError("Semaphore released too many times")
|
raise ValueError("Semaphore released too many times")
|
||||||
return _Semaphore.release(self)
|
return Semaphore.release(self)
|
||||||
|
|
||||||
|
|
||||||
def Event(*args, **kwargs):
|
class Event(_Verbose):
|
||||||
return _Event(*args, **kwargs)
|
|
||||||
|
|
||||||
class _Event(_Verbose):
|
|
||||||
|
|
||||||
# After Tim Peters' event class (without is_posted())
|
# After Tim Peters' event class (without is_posted())
|
||||||
|
|
||||||
|
@ -918,10 +906,7 @@ class Thread(_Verbose):
|
||||||
|
|
||||||
# The timer class was contributed by Itamar Shtull-Trauring
|
# The timer class was contributed by Itamar Shtull-Trauring
|
||||||
|
|
||||||
def Timer(*args, **kwargs):
|
class Timer(Thread):
|
||||||
return _Timer(*args, **kwargs)
|
|
||||||
|
|
||||||
class _Timer(Thread):
|
|
||||||
"""Call a function after a specified number of seconds:
|
"""Call a function after a specified number of seconds:
|
||||||
|
|
||||||
t = Timer(30.0, f, args=[], kwargs={})
|
t = Timer(30.0, f, args=[], kwargs={})
|
||||||
|
|
10
Misc/NEWS
10
Misc/NEWS
|
@ -244,6 +244,16 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #10968: Remove indirection in threading. The public names (Thread,
|
||||||
|
Condition, etc.) used to be factory functions returning instances of hidden
|
||||||
|
classes (_Thread, _Condition, etc.), because (if Guido recalls correctly) this
|
||||||
|
code pre-dates the ability to subclass extension types. It is now possible to
|
||||||
|
inherit from Thread and other classes, without having to import the private
|
||||||
|
underscored names like multiprocessing did.
|
||||||
|
|
||||||
|
- Issue #9723: Add shlex.quote functions, to escape filenames and command
|
||||||
|
lines.
|
||||||
|
|
||||||
- Issue #12603: Fix pydoc.synopsis() on files with non-negative st_mtime.
|
- Issue #12603: Fix pydoc.synopsis() on files with non-negative st_mtime.
|
||||||
|
|
||||||
- Issue #12514: Use try/finally to assure the timeit module restores garbage
|
- Issue #12514: Use try/finally to assure the timeit module restores garbage
|
||||||
|
|
|
@ -57,7 +57,7 @@ typedef struct {
|
||||||
int error; /* see WFERR_* values */
|
int error; /* see WFERR_* values */
|
||||||
int depth;
|
int depth;
|
||||||
/* If fp == NULL, the following are valid: */
|
/* If fp == NULL, the following are valid: */
|
||||||
PyObject * readable; /* Stream-like object being read from */
|
PyObject *readable; /* Stream-like object being read from */
|
||||||
PyObject *str;
|
PyObject *str;
|
||||||
PyObject *current_filename;
|
PyObject *current_filename;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
@ -467,7 +467,7 @@ typedef WFILE RFILE; /* Same struct with different invariants */
|
||||||
static int
|
static int
|
||||||
r_string(char *s, int n, RFILE *p)
|
r_string(char *s, int n, RFILE *p)
|
||||||
{
|
{
|
||||||
char * ptr;
|
char *ptr;
|
||||||
int read, left;
|
int read, left;
|
||||||
|
|
||||||
if (!p->readable) {
|
if (!p->readable) {
|
||||||
|
@ -566,7 +566,7 @@ r_long(RFILE *p)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
r_long64(RFILE *p)
|
r_long64(RFILE *p)
|
||||||
{
|
{
|
||||||
PyObject * result = NULL;
|
PyObject *result = NULL;
|
||||||
long lo4 = r_long(p);
|
long lo4 = r_long(p);
|
||||||
long hi4 = r_long(p);
|
long hi4 = r_long(p);
|
||||||
|
|
||||||
|
|
1
Tools/scripts/abitype.py
Normal file → Executable file
1
Tools/scripts/abitype.py
Normal file → Executable file
|
@ -1,3 +1,4 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
# This script converts a C file to use the PEP 384 type definition API
|
# This script converts a C file to use the PEP 384 type definition API
|
||||||
# Usage: abitype.py < old_code > new_code
|
# Usage: abitype.py < old_code > new_code
|
||||||
import re, sys
|
import re, sys
|
||||||
|
|
0
Tools/scripts/cleanfuture.py
Normal file → Executable file
0
Tools/scripts/cleanfuture.py
Normal file → Executable file
0
Tools/scripts/combinerefs.py
Normal file → Executable file
0
Tools/scripts/combinerefs.py
Normal file → Executable file
0
Tools/scripts/db2pickle.py
Normal file → Executable file
0
Tools/scripts/db2pickle.py
Normal file → Executable file
1
Tools/scripts/diff.py
Normal file → Executable file
1
Tools/scripts/diff.py
Normal file → Executable file
|
@ -1,3 +1,4 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
""" Command line interface to difflib.py providing diffs in four formats:
|
""" Command line interface to difflib.py providing diffs in four formats:
|
||||||
|
|
||||||
* ndiff: lists every line and highlights interline changes.
|
* ndiff: lists every line and highlights interline changes.
|
||||||
|
|
0
Tools/scripts/find_recursionlimit.py
Normal file → Executable file
0
Tools/scripts/find_recursionlimit.py
Normal file → Executable file
0
Tools/scripts/get-remote-certificate.py
Normal file → Executable file
0
Tools/scripts/get-remote-certificate.py
Normal file → Executable file
25
Tools/scripts/mailerdaemon.py
Normal file → Executable file
25
Tools/scripts/mailerdaemon.py
Normal file → Executable file
|
@ -1,4 +1,5 @@
|
||||||
"""mailerdaemon - classes to parse mailer-daemon messages"""
|
#!/usr/bin/env python3
|
||||||
|
"""Classes to parse mailer-daemon messages."""
|
||||||
|
|
||||||
import calendar
|
import calendar
|
||||||
import email.message
|
import email.message
|
||||||
|
@ -6,7 +7,10 @@ import re
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
Unparseable = 'mailerdaemon.Unparseable'
|
|
||||||
|
class Unparseable(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ErrorMessage(email.message.Message):
|
class ErrorMessage(email.message.Message):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -18,8 +22,10 @@ class ErrorMessage(email.message.Message):
|
||||||
if not sub:
|
if not sub:
|
||||||
return 0
|
return 0
|
||||||
sub = sub.lower()
|
sub = sub.lower()
|
||||||
if sub.startswith('waiting mail'): return 1
|
if sub.startswith('waiting mail'):
|
||||||
if 'warning' in sub: return 1
|
return 1
|
||||||
|
if 'warning' in sub:
|
||||||
|
return 1
|
||||||
self.sub = sub
|
self.sub = sub
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
@ -145,14 +151,17 @@ def emparse_list(fp, sub):
|
||||||
errors.append(' '.join((email.strip()+': '+reason).split()))
|
errors.append(' '.join((email.strip()+': '+reason).split()))
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
EMPARSERS = [emparse_list, ]
|
EMPARSERS = [emparse_list]
|
||||||
|
|
||||||
def sort_numeric(a, b):
|
def sort_numeric(a, b):
|
||||||
a = int(a)
|
a = int(a)
|
||||||
b = int(b)
|
b = int(b)
|
||||||
if a < b: return -1
|
if a < b:
|
||||||
elif a > b: return 1
|
return -1
|
||||||
else: return 0
|
elif a > b:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
def parsedir(dir, modify):
|
def parsedir(dir, modify):
|
||||||
os.chdir(dir)
|
os.chdir(dir)
|
||||||
|
|
1
Tools/scripts/make_ctype.py
Normal file → Executable file
1
Tools/scripts/make_ctype.py
Normal file → Executable file
|
@ -1,3 +1,4 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
"""Script that generates the ctype.h-replacement in stringobject.c."""
|
"""Script that generates the ctype.h-replacement in stringobject.c."""
|
||||||
|
|
||||||
NAMES = ("LOWER", "UPPER", "ALPHA", "DIGIT", "XDIGIT", "ALNUM", "SPACE")
|
NAMES = ("LOWER", "UPPER", "ALPHA", "DIGIT", "XDIGIT", "ALNUM", "SPACE")
|
||||||
|
|
0
Tools/scripts/md5sum.py
Normal file → Executable file
0
Tools/scripts/md5sum.py
Normal file → Executable file
1
Tools/scripts/patchcheck.py
Normal file → Executable file
1
Tools/scripts/patchcheck.py
Normal file → Executable file
|
@ -1,3 +1,4 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import shutil
|
import shutil
|
||||||
|
|
0
Tools/scripts/pickle2db.py
Normal file → Executable file
0
Tools/scripts/pickle2db.py
Normal file → Executable file
0
Tools/scripts/pysource.py
Normal file → Executable file
0
Tools/scripts/pysource.py
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
# Make a reST file compliant to our pre-commit hook.
|
# Make a reST file compliant to our pre-commit hook.
|
||||||
# Currently just remove trailing whitespace.
|
# Currently just remove trailing whitespace.
|
||||||
|
|
0
Tools/scripts/svneol.py
Normal file → Executable file
0
Tools/scripts/svneol.py
Normal file → Executable file
Loading…
Add table
Add a link
Reference in a new issue