cpython (merge default -> default): Branch merge
http://hg.python.org/cpython/rev/1eaafbf35ed1 changeset: 71575:1eaafbf35ed1 parent: 71548:7df53f5788a4 parent: 71574:77254e92159f user: Éric Araujo <merwok@netwok.org> date: Fri Jul 29 14:30:03 2011 +0200 summary: Branch merge files: .bzrignore | 1 + .gitignore | 1 + .hgignore | 3 +- Doc/ACKS.txt | 1 + Doc/distutils/apiref.rst | 4 +- Doc/distutils/install.rst | 2 +- Doc/glossary.rst | 3 +- Doc/library/ossaudiodev.rst | 2 +- Doc/library/packaging.dist.rst | 4 +- Doc/library/profile.rst | 26 +---- Doc/library/shlex.rst | 19 ++- Doc/library/shutil.rst | 26 ++- Doc/library/subprocess.rst | 7 +- Doc/license.rst | 29 ---- Doc/tools/sphinxext/susp-ignored.csv | 2 - Doc/tutorial/classes.rst | 28 ++-- Doc/whatsnew/3.3.rst | 4 +- Lib/modulefinder.py | 15 +- Lib/multiprocessing/dummy/__init__.py | 13 +-- Lib/packaging/command/cmd.py | 3 +- Lib/packaging/database.py | 2 +- Lib/packaging/depgraph.py | 4 +- Lib/packaging/install.py | 24 ++-- Lib/packaging/run.py | 72 ++++++----- Lib/packaging/tests/test_database.py | 10 +- Lib/packaging/tests/test_install.py | 2 +- Lib/pipes.py | 23 +--- Lib/pstats.py | 4 - Lib/shlex.py | 20 +++- Lib/test/list_tests.py | 16 +- Lib/test/test_modulefinder.py | 48 ++++--- Lib/test/test_pipes.py | 14 -- Lib/test/test_shlex.py | 20 +++- Lib/test/test_sort.py | 23 +-- Lib/threading.py | 29 +--- Misc/NEWS | 10 + Python/marshal.c | 6 +- Tools/scripts/abitype.py | 1 + Tools/scripts/cleanfuture.py | Bin Tools/scripts/combinerefs.py | Bin Tools/scripts/db2pickle.py | Bin Tools/scripts/diff.py | 1 + Tools/scripts/find_recursionlimit.py | Bin Tools/scripts/get-remote-certificate.py | Bin Tools/scripts/mailerdaemon.py | 25 ++- Tools/scripts/make_ctype.py | 1 + Tools/scripts/md5sum.py | Bin Tools/scripts/patchcheck.py | 1 + Tools/scripts/pickle2db.py | Bin Tools/scripts/pysource.py | Bin Tools/scripts/reindent-rst.py | 2 +- Tools/scripts/svneol.py | Bin 52 files changed, 257 insertions(+), 294 deletions(-) diff --git a/.bzrignore b/.bzrignore --- a/.bzrignore +++ b/.bzrignore @@ -14,6 +14,7 @@ pybuilddir.txt pyconfig.h libpython*.a +libpython*.so* python.exe python-gdb.py reflog.txt diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ config.log config.status libpython*.a +libpython*.so* pybuilddir.txt pyconfig.h python diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -41,14 +41,13 @@ syntax: glob libpython*.a +libpython*.so* *.swp *.o *.pyc *.pyo *.pyd *.cover -*.orig -*.rej *~ Lib/lib2to3/*.pickle Lib/test/data/* diff --git a/Doc/ACKS.txt b/Doc/ACKS.txt --- a/Doc/ACKS.txt +++ b/Doc/ACKS.txt @@ -203,6 +203,7 @@ * Kalle Svensson * Jim Tittsler * David Turner + * Sandro Tosi * Ville Vainio * Nadeem Vawda * Martijn Vries diff --git a/Doc/distutils/apiref.rst b/Doc/distutils/apiref.rst --- a/Doc/distutils/apiref.rst +++ b/Doc/distutils/apiref.rst @@ -72,8 +72,8 @@ | | be built | :class:`distutils.core.Extension` | +--------------------+--------------------------------+-------------------------------------------------------------+ | *classifiers* | A list of categories for the | The list of available | - | | package | categorizations is at | - | | | http://pypi.python.org/pypi?:action=list_classifiers. | + | | package | categorizations is available on `PyPI | + | | | <http://pypi.python.org/pypi?:action=list_classifiers>`_. | +--------------------+--------------------------------+-------------------------------------------------------------+ | *distclass* | the :class:`Distribution` | A subclass of | | | class to use | :class:`distutils.core.Distribution` | diff --git a/Doc/distutils/install.rst b/Doc/distutils/install.rst --- a/Doc/distutils/install.rst +++ b/Doc/distutils/install.rst @@ -72,7 +72,7 @@ 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 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 module distribution that doesn't have an easy-to-use installer for your diff --git a/Doc/glossary.rst b/Doc/glossary.rst --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -431,7 +431,8 @@ mapping 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 include :class:`dict`, :class:`collections.defaultdict`, :class:`collections.OrderedDict` and :class:`collections.Counter`. diff --git a/Doc/library/ossaudiodev.rst b/Doc/library/ossaudiodev.rst --- a/Doc/library/ossaudiodev.rst +++ b/Doc/library/ossaudiodev.rst @@ -14,7 +14,7 @@ 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 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 to my python-dev query, Thomas Wouters said: diff --git a/Doc/library/packaging.dist.rst b/Doc/library/packaging.dist.rst --- a/Doc/library/packaging.dist.rst +++ b/Doc/library/packaging.dist.rst @@ -67,8 +67,8 @@ | | be built | :class:`packaging.compiler.extension.Extension` | +--------------------+--------------------------------+-------------------------------------------------------------+ | *classifiers* | A list of categories for the | The list of available | - | | distribution | categorizations is at | - | | | http://pypi.python.org/pypi?:action=list_classifiers. | + | | distribution | categorizations is available on `PyPI | + | | | <http://pypi.python.org/pypi?:action=list_classifiers>`_. | +--------------------+--------------------------------+-------------------------------------------------------------+ | *distclass* | the :class:`Distribution` | A subclass of | | | class to use | :class:`packaging.dist.Distribution` | diff --git a/Doc/library/profile.rst b/Doc/library/profile.rst --- a/Doc/library/profile.rst +++ b/Doc/library/profile.rst @@ -39,7 +39,7 @@ 2. :mod:`profile`, a pure Python module whose interface is imitated by :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 - module. Copyright © 1994, by InfoSeek Corporation. + module. The :mod:`profile` and :mod:`cProfile` modules export the same interface, so they are mostly interchangeable; :mod:`cProfile` has a much lower overhead but @@ -592,27 +592,3 @@ 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 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. diff --git a/Doc/library/shlex.rst b/Doc/library/shlex.rst --- a/Doc/library/shlex.rst +++ b/Doc/library/shlex.rst @@ -34,6 +34,22 @@ passing ``None`` for *s* will read the string to split from standard 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: @@ -282,5 +298,4 @@ * EOF is signaled with a :const:`None` value; -* Quoted empty strings (``''``) are allowed; - +* Quoted empty strings (``''``) are allowed. diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst --- a/Doc/library/shutil.rst +++ b/Doc/library/shutil.rst @@ -159,12 +159,18 @@ .. 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 - when *src* and *dst* are on different filesystems or in case of windows where - rename is not supported when *dst* exists, fallback to copying *src* (with - :func:`copy2`) to the *dst* and then remove *src*. + If the destination is a directory or a symlink to a directory, then *src* is + moved inside that directory. + + 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) @@ -177,9 +183,9 @@ .. exception:: Error - This exception collects exceptions that raised during a multi-file operation. For - :func:`copytree`, the exception argument is a list of 3-tuples (*srcname*, - *dstname*, *exception*). + This exception collects exceptions that are raised during a multi-file + operation. For :func:`copytree`, the exception argument is a list of 3-tuples + (*srcname*, *dstname*, *exception*). .. _shutil-example: @@ -277,7 +283,7 @@ .. 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)`` By default :mod:`shutil` provides these formats: @@ -295,7 +301,7 @@ .. 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. If given, *extra_args* is a sequence of ``(name, value)`` pairs that will be diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -92,7 +92,8 @@ >>> call("cat " + filename, shell=True) # Uh-oh. This will end badly... *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 child program, which operates on strings. If *args* is a sequence, it will @@ -871,3 +872,7 @@ described in rule 3. +.. seealso:: + + :mod:`shlex` + Module which provides function to parse and escape command lines. diff --git a/Doc/license.rst b/Doc/license.rst --- a/Doc/license.rst +++ b/Doc/license.rst @@ -494,36 +494,6 @@ 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 ----------------- diff --git a/Doc/tools/sphinxext/susp-ignored.csv b/Doc/tools/sphinxext/susp-ignored.csv --- a/Doc/tools/sphinxext/susp-ignored.csv +++ b/Doc/tools/sphinxext/susp-ignored.csv @@ -5,7 +5,6 @@ c-api/sequence,,:i2,o[i1:i2] = v c-api/sequence,,:i2,del o[i1:i2] c-api/unicode,,:end,str[start:end] -distutils/apiref,,:action,http://pypi.python.org/pypi?:action=list_classifiers distutils/setupscript,,::, extending/embedding,,:numargs,"if(!PyArg_ParseTuple(args, "":numargs""))" extending/extending,,:set,"if (PyArg_ParseTuple(args, ""O:set_callback"", &temp)) {" @@ -495,7 +494,6 @@ library/pprint,209,::,"'Programming Language :: Python :: 2.7'," library/pprint,209,::,"'Topic :: Software Development :: Libraries'," 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/setupcfg,,::,Development Status :: 3 - Alpha packaging/setupcfg,,::,License :: OSI Approved :: Mozilla Public License 1.1 (MPL 1.1) diff --git a/Doc/tutorial/classes.rst b/Doc/tutorial/classes.rst --- a/Doc/tutorial/classes.rst +++ b/Doc/tutorial/classes.rst @@ -598,24 +598,24 @@ Name mangling is helpful for letting subclasses override methods without breaking intraclass method calls. For example:: - class Mapping: - def __init__(self, iterable): - self.items_list = [] - self.__update(iterable) + class Mapping: + def __init__(self, iterable): + self.items_list = [] + self.__update(iterable) - def update(self, iterable): - for item in iterable: - self.items_list.append(item) + def update(self, iterable): + for item in iterable: + 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): - # provides new signature for update() - # but does not break __init__() - for item in zip(keys, values): - self.items_list.append(item) + def update(self, keys, values): + # provides new signature for update() + # but does not break __init__() + for item in zip(keys, values): + self.items_list.append(item) 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 diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -94,8 +94,8 @@ curses ------ -The :class:`curses.window` class has a new :class:`~curses.window.get_wch` -method to a wide character. Patch by Iñigo Serna. +The :class:`curses.window` class has a new :meth:`~curses.window.get_wch` method +to get a wide character. Patch by Iñigo Serna. (:issue:`6755`) diff --git a/Lib/modulefinder.py b/Lib/modulefinder.py --- a/Lib/modulefinder.py +++ b/Lib/modulefinder.py @@ -1,6 +1,5 @@ """Find modules used by a script, using introspection.""" -from __future__ import generators import dis import imp import marshal @@ -9,8 +8,6 @@ import types import struct -READ_MODE = "rU" - # XXX Clean up once str8's cstor matches bytes. LOAD_CONST = bytes([dis.opname.index('LOAD_CONST')]) IMPORT_NAME = bytes([dis.opname.index('IMPORT_NAME')]) @@ -29,8 +26,7 @@ # A Public interface def AddPackagePath(packagename, path): - paths = packagePathMap.get(packagename, []) - paths.append(path) + paths = packagePathMap.setdefault(packagename, []).append(path) packagePathMap[packagename] = paths replacePackageMap = {} @@ -106,14 +102,14 @@ def run_script(self, pathname): self.msg(2, "run_script", pathname) - with open(pathname, READ_MODE) as fp: + with open(pathname) as fp: stuff = ("", "r", imp.PY_SOURCE) self.load_module('__main__', fp, pathname, stuff) def load_file(self, pathname): dir, name = os.path.split(pathname) name, ext = os.path.splitext(name) - with open(pathname, READ_MODE) as fp: + with open(pathname) as fp: stuff = (ext, "r", imp.PY_SOURCE) self.load_module(name, fp, pathname, stuff) @@ -270,7 +266,8 @@ try: m = self.load_module(fqname, fp, pathname, stuff) finally: - if fp: fp.close() + if fp: + fp.close() if parent: setattr(parent, partname, m) self.msgout(3, "import_module ->", m) @@ -662,4 +659,4 @@ try: mf = test() except KeyboardInterrupt: - print("\n[interrupt]") + print("\n[interrupted]") diff --git a/Lib/multiprocessing/dummy/__init__.py b/Lib/multiprocessing/dummy/__init__.py --- a/Lib/multiprocessing/dummy/__init__.py +++ b/Lib/multiprocessing/dummy/__init__.py @@ -51,7 +51,7 @@ from multiprocessing import TimeoutError, cpu_count from multiprocessing.dummy.connection import Pipe from threading import Lock, RLock, Semaphore, BoundedSemaphore -from threading import Event +from threading import Event, Condition from queue import Queue # @@ -84,17 +84,6 @@ # # -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 current_process = threading.current_thread current_process()._children = weakref.WeakKeyDictionary() diff --git a/Lib/packaging/command/cmd.py b/Lib/packaging/command/cmd.py --- a/Lib/packaging/command/cmd.py +++ b/Lib/packaging/command/cmd.py @@ -57,7 +57,8 @@ from packaging.dist import 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: raise RuntimeError("Command is an abstract class") diff --git a/Lib/packaging/database.py b/Lib/packaging/database.py --- a/Lib/packaging/database.py +++ b/Lib/packaging/database.py @@ -351,7 +351,7 @@ except IOError: requires = None self.metadata = Metadata(path=path) - self.name = self.metadata['name'] + self.name = self.metadata['Name'] self.version = self.metadata['Version'] else: diff --git a/Lib/packaging/depgraph.py b/Lib/packaging/depgraph.py --- a/Lib/packaging/depgraph.py +++ b/Lib/packaging/depgraph.py @@ -72,7 +72,7 @@ self.missing[distribution].append(requirement) 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): """Prints only a subgraph""" @@ -145,7 +145,7 @@ graph.add_distribution(dist) provides = (dist.metadata['Provides-Dist'] + dist.metadata['Provides'] + - ['%s (%s)' % (dist.name, dist.metadata['Version'])]) + ['%s (%s)' % (dist.name, dist.version)]) for p in provides: comps = p.strip().rsplit(" ", 1) diff --git a/Lib/packaging/install.py b/Lib/packaging/install.py --- a/Lib/packaging/install.py +++ b/Lib/packaging/install.py @@ -85,7 +85,7 @@ dist.parse_config_files() try: dist.run_command('install_dist') - name = dist.metadata['name'] + name = dist.metadata['Name'] return database.get_distribution(name) is not None except (IOError, os.error, PackagingError, CCompilerError) as msg: raise ValueError("Failed to install, " + str(msg)) @@ -118,10 +118,10 @@ """ path = os.path.abspath(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) elif _is_archive_file(path): - logger.info('Installing from archive: %s', path) + logger.info('Installing from archive: %r', path) _unpacked_dir = tempfile.mkdtemp() try: shutil.unpack_archive(path, _unpacked_dir) @@ -129,7 +129,7 @@ finally: shutil.rmtree(_unpacked_dir) else: - logger.warning('No projects to install.') + logger.warning('No project to install.') return False @@ -191,7 +191,7 @@ # reverting for installed_dist in installed_dists: - logger.info('Reverting %s', installed_dist) + logger.info('Reverting %r', installed_dist) remove(installed_dist.name, paths) raise e return installed_dists @@ -314,12 +314,12 @@ if predicate.name.lower() != installed_project.name.lower(): continue found = True - logger.info('Found %s %s', installed_project.name, - installed_project.metadata['version']) + logger.info('Found %r %s', installed_project.name, + installed_project.version) # if we already have something installed, check it matches the # requirements - if predicate.match(installed_project.metadata['version']): + if predicate.match(installed_project.version): return infos break @@ -336,7 +336,7 @@ try: release = index.get_release(requirements) except (ReleaseNotFound, ProjectNotFound): - raise InstallationException('Release not found: "%s"' % requirements) + raise InstallationException('Release not found: %r' % requirements) if release is None: logger.info('Could not find a matching project') @@ -386,7 +386,7 @@ """ dist = get_distribution(project_name, use_egg_info=True, paths=paths) 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) rmdirs = [] rmfiles = [] @@ -423,7 +423,7 @@ if not success: logger.info('%r cannot be removed.', project_name) - logger.info('Error: %s' % str(error)) + logger.info('Error: %s', error) return False logger.info('Removing %r: ', project_name) @@ -523,7 +523,7 @@ except InstallationConflict as e: 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)) return True diff --git a/Lib/packaging/run.py b/Lib/packaging/run.py --- a/Lib/packaging/run.py +++ b/Lib/packaging/run.py @@ -214,7 +214,7 @@ @action_help(generate_usage) def _generate(distpatcher, args, **kw): generate_setup_py() - print('The setup.py was generated') + logger.info('The setup.py was generated') @action_help(graph_usage) @@ -222,7 +222,8 @@ name = args[1] dist = get_distribution(name, use_egg_info=True) if dist is None: - print('Distribution not found.') + logger.warning('Distribution not found.') + return 1 else: dists = get_distributions(use_egg_info=True) graph = generate_graph(dists) @@ -234,8 +235,7 @@ # first check if we are in a source directory if len(args) < 2: # are we inside a project dir? - listing = os.listdir(os.getcwd()) - if 'setup.py' in listing or 'setup.cfg' in listing: + if os.path.isfile('setup.cfg') or os.path.isfile('setup.py'): args.insert(1, os.getcwd()) else: logger.warning('No project to install.') @@ -244,16 +244,10 @@ target = args[1] # installing from a source dir or archive file? if os.path.isdir(target) or _is_archive_file(target): - if install_local_project(target): - return 0 - else: - return 1 + return not install_local_project(target) else: # download from PyPI - if install(target): - return 0 - else: - return 1 + return not install(target) @action_help(metadata_usage) @@ -263,12 +257,15 @@ name = opts['args'][0] dist = get_distribution(name, use_egg_info=True) if dist is None: - logger.warning('%s not installed', name) - return + logger.warning('%r not installed', name) + return 1 + elif os.path.isfile('setup.cfg'): + logger.info('searching local dir for metadata') + dist = Distribution() # XXX use config module + dist.parse_config_files() else: - logger.info('searching local dir for metadata') - dist = Distribution() - dist.parse_config_files() + logger.warning('no argument given and no local setup.cfg found') + return 1 metadata = dist.metadata @@ -299,11 +296,15 @@ else: auto_confirm = False + retcode = 0 for dist in set(opts['args']): try: remove(dist, auto_confirm=auto_confirm) except PackagingError: - logger.warning('%s not installed', dist) + logger.warning('%r not installed', dist) + retcode = 1 + + return retcode @action_help(run_usage) @@ -339,14 +340,8 @@ # XXX still need to be extracted from Distribution dist.parse_config_files() - try: - for cmd in dispatcher.commands: - 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)) + for cmd in dispatcher.commands: + dist.run_command(cmd, dispatcher.command_options[cmd]) # XXX this is crappy return dist @@ -358,19 +353,24 @@ dists = get_distributions(use_egg_info=True) if 'all' in opts or opts['args'] == []: results = dists + listall = True 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 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 - print() 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: - print('Found %d projects installed.' % number) + logger.info('Found %d projects installed.', number) @action_help(search_usage) @@ -382,7 +382,8 @@ """ #opts = _parse_args(args[1:], '', ['simple', 'xmlrpc']) # 1. what kind of index is requested ? (xmlrpc / simple) - raise NotImplementedError + logger.error('not implemented') + return 1 actions = [ @@ -662,6 +663,7 @@ def __call__(self): if self.action is None: return + for action, desc, func in actions: if action == self.action: return func(self, self.args) @@ -676,6 +678,12 @@ if dispatcher.action is None: return return dispatcher() + except KeyboardInterrupt: + logger.info('interrupted') + return 1 + except (IOError, os.error, PackagingError, CCompilerError) as exc: + logger.exception(exc) + return 1 finally: logger.setLevel(old_level) logger.handlers[:] = old_handlers diff --git a/Lib/packaging/tests/test_database.py b/Lib/packaging/tests/test_database.py --- a/Lib/packaging/tests/test_database.py +++ b/Lib/packaging/tests/test_database.py @@ -302,7 +302,7 @@ self.assertIsInstance(dist, Distribution) if (dist.name in dict(fake_dists) and dist.path.startswith(self.fake_dists_path)): - found_dists.append((dist.name, dist.metadata['version'], )) + found_dists.append((dist.name, dist.version)) else: # check that it doesn't find anything more than this self.assertFalse(dist.path.startswith(self.fake_dists_path)) @@ -323,7 +323,7 @@ self.assertIsInstance(dist, (Distribution, EggInfoDistribution)) if (dist.name in dict(fake_dists) and dist.path.startswith(self.fake_dists_path)): - found_dists.append((dist.name, dist.metadata['version'])) + found_dists.append((dist.name, dist.version)) else: self.assertFalse(dist.path.startswith(self.fake_dists_path)) @@ -489,17 +489,17 @@ 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) if dist.path.startswith(self.fake_dists_path)] checkLists(eggs, found) - found = [(dist.name, dist.metadata['Version']) + found = [(dist.name, dist.version) for dist in _yield_distributions(True, False, sys.path) if dist.path.startswith(self.fake_dists_path)] checkLists(dists, found) - found = [(dist.name, dist.metadata['Version']) + found = [(dist.name, dist.version) for dist in _yield_distributions(True, True, sys.path) if dist.path.startswith(self.fake_dists_path)] checkLists(dists + eggs, found) diff --git a/Lib/packaging/tests/test_install.py b/Lib/packaging/tests/test_install.py --- a/Lib/packaging/tests/test_install.py +++ b/Lib/packaging/tests/test_install.py @@ -29,7 +29,7 @@ self.metadata['Requires-Dist'] = deps def __repr__(self): - return '<InstalledDist %s>' % self.metadata['Name'] + return '<InstalledDist %r>' % self.metadata['Name'] class ToInstallDist: diff --git a/Lib/pipes.py b/Lib/pipes.py --- a/Lib/pipes.py +++ b/Lib/pipes.py @@ -62,7 +62,9 @@ import re import os 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"] @@ -245,22 +247,3 @@ cmdlist = trapcmd + '\n' + cmdlist + '\n' + rmcmd # 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("'", "'\"'\"'") + "'" diff --git a/Lib/pstats.py b/Lib/pstats.py --- a/Lib/pstats.py +++ b/Lib/pstats.py @@ -1,13 +1,9 @@ """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 # Based on prior profile module by Sjoerd Mullender... # which was hacked somewhat by: Guido van Rossum -"""Class for profiling Python code.""" - # Copyright Disney Enterprises, Inc. All Rights Reserved. # Licensed to PSF under a Contributor Agreement # diff --git a/Lib/shlex.py b/Lib/shlex.py --- a/Lib/shlex.py +++ b/Lib/shlex.py @@ -6,13 +6,14 @@ # Posix compliance, split(), string arguments, and # iterator interface by Gustavo Niemeyer, April 2003. -import os.path +import os +import re import sys from collections import deque from io import StringIO -__all__ = ["shlex", "split"] +__all__ = ["shlex", "split", "quote"] class shlex: "A lexical analyzer class for simple shell-like syntaxes." @@ -274,6 +275,21 @@ lex.commenters = '' 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 len(sys.argv) == 1: lexer = shlex() diff --git a/Lib/test/list_tests.py b/Lib/test/list_tests.py --- a/Lib/test/list_tests.py +++ b/Lib/test/list_tests.py @@ -4,17 +4,10 @@ import sys import os +from functools import cmp_to_key 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): @@ -484,7 +477,7 @@ return 1 else: # a > b return -1 - u.sort(key=CmpToKey(revcmp)) + u.sort(key=cmp_to_key(revcmp)) self.assertEqual(u, self.type2test([2,1,0,-1,-2])) # The following dumps core in unpatched Python 1.5: @@ -497,7 +490,7 @@ else: # xmod > ymod return 1 z = self.type2test(range(12)) - z.sort(key=CmpToKey(myComparison)) + z.sort(key=cmp_to_key(myComparison)) self.assertRaises(TypeError, z.sort, 2) @@ -509,7 +502,8 @@ return -1 else: # x > y 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) diff --git a/Lib/test/test_modulefinder.py b/Lib/test/test_modulefinder.py --- a/Lib/test/test_modulefinder.py +++ b/Lib/test/test_modulefinder.py @@ -1,7 +1,7 @@ -import __future__ import os +import errno +import shutil import unittest -import distutils.dir_util import tempfile from test import support @@ -9,7 +9,7 @@ import modulefinder 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: # @@ -196,12 +196,17 @@ from . import bar """] + def open_file(path): - ##print "#", os.path.abspath(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") + def create_package(source): ofi = None try: @@ -216,6 +221,7 @@ if ofi: ofi.close() + class ModuleFinderTest(unittest.TestCase): def _do_test(self, info, report=False): import_this, modules, missing, maybe_missing, source = info @@ -234,19 +240,17 @@ ## import traceback; traceback.print_exc() ## sys.path = opath ## return - modules = set(modules) - found = set(mf.modules.keys()) - more = list(found - modules) - less = list(modules - found) + modules = sorted(set(modules)) + found = sorted(mf.modules) # 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 bad, maybe = mf.any_missing_maybe() self.assertEqual(bad, missing) self.assertEqual(maybe, maybe_missing) finally: - distutils.dir_util.remove_tree(TEST_DIR) + shutil.rmtree(TEST_DIR) def test_package(self): self._do_test(package_test) @@ -254,25 +258,23 @@ def test_maybe(self): 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): - self._do_test(maybe_test_new) + def test_absolute_imports(self): + self._do_test(absolute_import_test) - def test_absolute_imports(self): - self._do_test(absolute_import_test) + def test_relative_imports(self): + self._do_test(relative_import_test) - def test_relative_imports(self): - self._do_test(relative_import_test) + def test_relative_imports_2(self): + self._do_test(relative_import_test_2) - def test_relative_imports_2(self): - self._do_test(relative_import_test_2) + def test_relative_imports_3(self): + self._do_test(relative_import_test_3) - def test_relative_imports_3(self): - self._do_test(relative_import_test_3) def test_main(): - distutils.log.set_threshold(distutils.log.WARN) support.run_unittest(ModuleFinderTest) if __name__ == "__main__": diff --git a/Lib/test/test_pipes.py b/Lib/test/test_pipes.py --- a/Lib/test/test_pipes.py +++ b/Lib/test/test_pipes.py @@ -79,20 +79,6 @@ with open(TESTFN) as f: 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): t = pipes.Template() self.assertEqual(repr(t), "<Template instance, steps=[]>") diff --git a/Lib/test/test_shlex.py b/Lib/test/test_shlex.py --- a/Lib/test/test_shlex.py +++ b/Lib/test/test_shlex.py @@ -1,6 +1,7 @@ +import io +import shlex +import string import unittest -import os, sys, io -import shlex from test import support @@ -173,6 +174,21 @@ "%s: %s != %s" % (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 if not getattr(shlex, "split", None): for methname in dir(ShlexTest): diff --git a/Lib/test/test_sort.py b/Lib/test/test_sort.py --- a/Lib/test/test_sort.py +++ b/Lib/test/test_sort.py @@ -2,18 +2,11 @@ import random import sys import unittest +from functools import cmp_to_key verbose = support.verbose 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): global nerrors @@ -23,7 +16,7 @@ orig = raw[:] # save input in case of error if compare: - raw.sort(key=CmpToKey(compare)) + raw.sort(key=cmp_to_key(compare)) else: raw.sort() @@ -108,7 +101,7 @@ print(" Checking against an insane comparison function.") print(" If the implementation isn't careful, this may segfault.") 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) if len(x) >= 2: @@ -165,12 +158,12 @@ L.pop() return (x > y) - (x < y) 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): L.append(3) del L[:] 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] #============================================================================== @@ -185,7 +178,7 @@ def my_cmp(x, y): xlower, ylower = x.lower(), y.lower() return (xlower > ylower) - (xlower < ylower) - copy.sort(key=CmpToKey(my_cmp)) + copy.sort(key=cmp_to_key(my_cmp)) def test_baddecorator(self): data = 'The quick Brown fox Jumped over The lazy Dog'.split() @@ -261,8 +254,8 @@ def my_cmp_reversed(x, y): x0, y0 = x[0], y[0] return (y0 > x0) - (y0 < x0) - data.sort(key=CmpToKey(my_cmp), reverse=True) - copy1.sort(key=CmpToKey(my_cmp_reversed)) + data.sort(key=cmp_to_key(my_cmp), reverse=True) + copy1.sort(key=cmp_to_key(my_cmp_reversed)) self.assertEqual(data, copy1) copy2.sort(key=lambda x: x[0], reverse=True) self.assertEqual(data, copy2) diff --git a/Lib/threading.py b/Lib/threading.py --- a/Lib/threading.py +++ b/Lib/threading.py @@ -172,10 +172,7 @@ _PyRLock = _RLock -def Condition(*args, **kwargs): - return _Condition(*args, **kwargs) - -class _Condition(_Verbose): +class Condition(_Verbose): def __init__(self, lock=None, verbose=None): _Verbose.__init__(self, verbose) @@ -308,10 +305,7 @@ notifyAll = notify_all -def Semaphore(*args, **kwargs): - return _Semaphore(*args, **kwargs) - -class _Semaphore(_Verbose): +class Semaphore(_Verbose): # After Tim Peters' semaphore class, but not quite the same (no maximum) @@ -366,25 +360,19 @@ self.release() -def BoundedSemaphore(*args, **kwargs): - return _BoundedSemaphore(*args, **kwargs) - -class _BoundedSemaphore(_Semaphore): +class BoundedSemaphore(Semaphore): """Semaphore that checks that # releases is <= # acquires""" def __init__(self, value=1, verbose=None): - _Semaphore.__init__(self, value, verbose) + Semaphore.__init__(self, value, verbose) self._initial_value = value def release(self): if self._value >= self._initial_value: raise ValueError("Semaphore released too many times") - return _Semaphore.release(self) + return Semaphore.release(self) -def Event(*args, **kwargs): - return _Event(*args, **kwargs) - -class _Event(_Verbose): +class Event(_Verbose): # After Tim Peters' event class (without is_posted()) @@ -918,10 +906,7 @@ # The timer class was contributed by Itamar Shtull-Trauring -def Timer(*args, **kwargs): - return _Timer(*args, **kwargs) - -class _Timer(Thread): +class Timer(Thread): """Call a function after a specified number of seconds: t = Timer(30.0, f, args=[], kwargs={}) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -244,6 +244,16 @@ 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 #12514: Use try/finally to assure the timeit module restores garbage diff --git a/Python/marshal.c b/Python/marshal.c --- a/Python/marshal.c +++ b/Python/marshal.c @@ -57,7 +57,7 @@ int error; /* see WFERR_* values */ int depth; /* 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 *current_filename; char *ptr; @@ -467,7 +467,7 @@ static int r_string(char *s, int n, RFILE *p) { - char * ptr; + char *ptr; int read, left; if (!p->readable) { @@ -566,7 +566,7 @@ static PyObject * r_long64(RFILE *p) { - PyObject * result = NULL; + PyObject *result = NULL; long lo4 = r_long(p); long hi4 = r_long(p); diff --git a/Tools/scripts/abitype.py b/Tools/scripts/abitype.py old mode 100644 new mode 100755 --- a/Tools/scripts/abitype.py +++ b/Tools/scripts/abitype.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 # This script converts a C file to use the PEP 384 type definition API # Usage: abitype.py < old_code > new_code import re, sys diff --git a/Tools/scripts/cleanfuture.py b/Tools/scripts/cleanfuture.py old mode 100644 new mode 100755 diff --git a/Tools/scripts/combinerefs.py b/Tools/scripts/combinerefs.py old mode 100644 new mode 100755 diff --git a/Tools/scripts/db2pickle.py b/Tools/scripts/db2pickle.py old mode 100644 new mode 100755 diff --git a/Tools/scripts/diff.py b/Tools/scripts/diff.py old mode 100644 new mode 100755 --- a/Tools/scripts/diff.py +++ b/Tools/scripts/diff.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 """ Command line interface to difflib.py providing diffs in four formats: * ndiff: lists every line and highlights interline changes. diff --git a/Tools/scripts/find_recursionlimit.py b/Tools/scripts/find_recursionlimit.py old mode 100644 new mode 100755 diff --git a/Tools/scripts/get-remote-certificate.py b/Tools/scripts/get-remote-certificate.py old mode 100644 new mode 100755 diff --git a/Tools/scripts/mailerdaemon.py b/Tools/scripts/mailerdaemon.py old mode 100644 new mode 100755 --- a/Tools/scripts/mailerdaemon.py +++ b/Tools/scripts/mailerdaemon.py @@ -1,4 +1,5 @@ -"""mailerdaemon - classes to parse mailer-daemon messages""" +#!/usr/bin/env python3 +"""Classes to parse mailer-daemon messages.""" import calendar import email.message @@ -6,7 +7,10 @@ import os import sys -Unparseable = 'mailerdaemon.Unparseable' + +class Unparseable(Exception): + pass + class ErrorMessage(email.message.Message): def __init__(self): @@ -18,8 +22,10 @@ if not sub: return 0 sub = sub.lower() - if sub.startswith('waiting mail'): return 1 - if 'warning' in sub: return 1 + if sub.startswith('waiting mail'): + return 1 + if 'warning' in sub: + return 1 self.sub = sub return 0 @@ -145,14 +151,17 @@ errors.append(' '.join((email.strip()+': '+reason).split())) return errors -EMPARSERS = [emparse_list, ] +EMPARSERS = [emparse_list] def sort_numeric(a, b): a = int(a) b = int(b) - if a < b: return -1 - elif a > b: return 1 - else: return 0 + if a < b: + return -1 + elif a > b: + return 1 + else: + return 0 def parsedir(dir, modify): os.chdir(dir) diff --git a/Tools/scripts/make_ctype.py b/Tools/scripts/make_ctype.py old mode 100644 new mode 100755 --- a/Tools/scripts/make_ctype.py +++ b/Tools/scripts/make_ctype.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 """Script that generates the ctype.h-replacement in stringobject.c.""" NAMES = ("LOWER", "UPPER", "ALPHA", "DIGIT", "XDIGIT", "ALNUM", "SPACE") diff --git a/Tools/scripts/md5sum.py b/Tools/scripts/md5sum.py old mode 100644 new mode 100755 diff --git a/Tools/scripts/patchcheck.py b/Tools/scripts/patchcheck.py old mode 100644 new mode 100755 --- a/Tools/scripts/patchcheck.py +++ b/Tools/scripts/patchcheck.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import re import sys import shutil diff --git a/Tools/scripts/pickle2db.py b/Tools/scripts/pickle2db.py old mode 100644 new mode 100755 diff --git a/Tools/scripts/pysource.py b/Tools/scripts/pysource.py old mode 100644 new mode 100755 diff --git a/Tools/scripts/reindent-rst.py b/Tools/scripts/reindent-rst.py --- a/Tools/scripts/reindent-rst.py +++ b/Tools/scripts/reindent-rst.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Make a reST file compliant to our pre-commit hook. # Currently just remove trailing whitespace. diff --git a/Tools/scripts/svneol.py b/Tools/scripts/svneol.py old mode 100644 new mode 100755 -- Repository URL: http://hg.python.org/cpython
participants (1)
-
eric.araujo