diff options
-rw-r--r-- | Doc/library/sys.rst | 34 | ||||
-rw-r--r-- | Doc/whatsnew/3.3.rst | 20 | ||||
-rw-r--r-- | Include/unicodeobject.h | 2 | ||||
-rw-r--r-- | Lib/packaging/run.py | 5 | ||||
-rw-r--r-- | Lib/packaging/tests/test_uninstall.py | 78 | ||||
-rw-r--r-- | Lib/packaging/tests/test_version.py | 20 | ||||
-rw-r--r-- | Lib/packaging/version.py | 2 | ||||
-rw-r--r-- | Lib/sysconfig.cfg | 2 | ||||
-rwxr-xr-x | Lib/test/regrtest.py | 24 | ||||
-rw-r--r-- | Lib/test/support.py | 3 | ||||
-rw-r--r-- | Lib/test/test_minidom.py | 2 | ||||
-rw-r--r-- | Misc/NEWS | 2 |
12 files changed, 119 insertions, 75 deletions
diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 43f65e2..0a8ac8b 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -121,6 +121,15 @@ always available. Use ``'backslashreplace'`` error handler on :exc:`UnicodeEncodeError`. +.. data:: dont_write_bytecode + + If this is true, Python won't try to write ``.pyc`` or ``.pyo`` files on the + import of source modules. This value is initially set to ``True`` or + ``False`` depending on the :option:`-B` command line option and the + :envvar:`PYTHONDONTWRITEBYTECODE` environment variable, but you can set it + yourself to control bytecode file generation. + + .. function:: excepthook(type, value, traceback) This function prints out a given traceback and exception to ``sys.stderr``. @@ -185,10 +194,10 @@ always available. Python files are installed; by default, this is also ``'/usr/local'``. This can be set at build time with the ``--exec-prefix`` argument to the :program:`configure` script. Specifically, all configuration files (e.g. the - :file:`pyconfig.h` header file) are installed in the directory ``exec_prefix + - '/lib/pythonversion/config'``, and shared library modules are installed in - ``exec_prefix + '/lib/pythonversion/lib-dynload'``, where *version* is equal to - ``version[:3]``. + :file:`pyconfig.h` header file) are installed in the directory + :file:`{exec_prefix}/lib/python{X.Y}/config', and shared library modules are + installed in :file:`{exec_prefix}/lib/python{X.Y}/lib-dynload`, where *X.Y* + is the version number of Python, for example ``3.2``. .. data:: executable @@ -629,7 +638,7 @@ always available. i.e. ``1114111`` (``0x10FFFF`` in hexadecimal). .. versionchanged:: 3.3 - Before :pep:`393`, :data:`sys.maxunicode` used to return either ``0xFFFF`` + Before :pep:`393`, ``sys.maxunicode`` used to be either ``0xFFFF`` or ``0x10FFFF``, depending on the configuration option that specified whether Unicode characters were stored as UCS-2 or UCS-4. @@ -750,10 +759,10 @@ always available. independent Python files are installed; by default, this is the string ``'/usr/local'``. This can be set at build time with the ``--prefix`` argument to the :program:`configure` script. The main collection of Python - library modules is installed in the directory ``prefix + '/lib/pythonversion'`` + library modules is installed in the directory :file:`{prefix}/lib/python{X.Y}`` while the platform independent header files (all except :file:`pyconfig.h`) are - stored in ``prefix + '/include/pythonversion'``, where *version* is equal to - ``version[:3]``. + stored in :file:`{prefix}/include/python{X.Y}``, where *X.Y* is the version + number of Python, for example ``3.2``. .. data:: ps1 @@ -771,15 +780,6 @@ always available. implement a dynamic prompt. -.. data:: dont_write_bytecode - - If this is true, Python won't try to write ``.pyc`` or ``.pyo`` files on the - import of source modules. This value is initially set to ``True`` or ``False`` - depending on the ``-B`` command line option and the ``PYTHONDONTWRITEBYTECODE`` - environment variable, but you can set it yourself to control bytecode file - generation. - - .. function:: setcheckinterval(interval) Set the interpreter's "check interval". This integer value determines how often diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst index c2cf524..a3abc11 100644 --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -6,8 +6,7 @@ :Release: |release| :Date: |today| -.. $Id$ - Rules for maintenance: +.. Rules for maintenance: * Anyone can add text to this document. Do not spend very much time on the wording of your changes, because your text will probably @@ -40,25 +39,25 @@ * It's helpful to add the bug/patch number as a comment: - % Patch 12345 XXX Describe the transmogrify() function added to the socket module. - (Contributed by P.Y. Developer.) + (Contributed by P.Y. Developer in :issue:`12345`.) - This saves the maintainer the effort of going through the SVN log + This saves the maintainer the effort of going through the Mercurial log when researching a change. This article explains the new features in Python 3.3, compared to 3.2. -PEP XXX: Stub -============= - - PEP 393: Flexible String Representation ======================================= -XXX Give a short introduction about :pep:`393`. +[Abstract copied from the PEP: The Unicode string type is changed to support +multiple internal representations, depending on the character with the largest +Unicode ordinal (1, 2, or 4 bytes). This allows a space-efficient +representation in common cases, but gives access to full UCS-4 on all systems. +For compatibility with existing APIs, several representations may exist in +parallel; over time, this compatibility should be phased out.] PEP 393 is fully backward compatible. The legacy API should remain available at least five years. Applications using the legacy API will not @@ -109,6 +108,7 @@ XXX Add list of changes introduced by :pep:`393` here: XXX mention new and deprecated functions and macros + Other Language Changes ====================== diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index 3c691c1..75dec86 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -206,7 +206,7 @@ extern "C" { immediately follow the structure. utf8_length and wstr_length can be found in the length field; the utf8 pointer is equal to the data pointer. */ typedef struct { - /* There a 4 forms of Unicode strings: + /* There are 4 forms of Unicode strings: - compact ascii: diff --git a/Lib/packaging/run.py b/Lib/packaging/run.py index 5affb17..59ad6ee 100644 --- a/Lib/packaging/run.py +++ b/Lib/packaging/run.py @@ -283,10 +283,11 @@ def _run(dispatcher, args, **kw): dist.parse_config_files() for cmd in dispatcher.commands: + # FIXME need to catch MetadataMissingError here (from the check command + # e.g.)--or catch any exception, print an error message and exit with 1 dist.run_command(cmd, dispatcher.command_options[cmd]) - # XXX this is crappy - return dist + return 0 @action_help("""\ diff --git a/Lib/packaging/tests/test_uninstall.py b/Lib/packaging/tests/test_uninstall.py index c7702de..8f094f4 100644 --- a/Lib/packaging/tests/test_uninstall.py +++ b/Lib/packaging/tests/test_uninstall.py @@ -1,15 +1,12 @@ -"""Tests for the uninstall command.""" +"""Tests for the packaging.uninstall module.""" import os import sys -from io import StringIO -import stat +import logging import packaging.util -from packaging.database import disable_cache, enable_cache -from packaging.run import main from packaging.errors import PackagingError from packaging.install import remove -from packaging.command.install_dist import install_dist +from packaging.database import disable_cache, enable_cache from packaging.tests import unittest, support @@ -47,16 +44,12 @@ class UninstallTestCase(support.TempdirManager, packaging.util._path_created.clear() super(UninstallTestCase, self).tearDown() - def run_setup(self, *args): - # run setup with args - args = ['run'] + list(args) - dist = main(args) - return dist - def get_path(self, dist, name): - cmd = install_dist(dist) - cmd.prefix = self.root_dir - cmd.finalize_options() + # the dist argument must contain an install_dist command correctly + # initialized with a prefix option and finalized befored this method + # can be called successfully; practically, this means that you should + # call self.install_dist before self.get_path + cmd = dist.get_command_obj('install_dist') return getattr(cmd, 'install_' + name) def make_dist(self, name='Foo', **kw): @@ -83,43 +76,56 @@ class UninstallTestCase(support.TempdirManager, if not dirname: dirname = self.make_dist(name, **kw) os.chdir(dirname) - old_out = sys.stderr - sys.stderr = StringIO() - dist = self.run_setup('install_dist', '--prefix=' + self.root_dir) - install_lib = self.get_path(dist, 'purelib') - return dist, install_lib - def test_uninstall_unknow_distribution(self): + dist = support.TestDistribution() + # for some unfathomable reason, the tests will fail horribly if the + # parse_config_files method is not called, even if it doesn't do + # anything useful; trying to build and use a command object manually + # also fails + dist.parse_config_files() + dist.finalize_options() + dist.run_command('install_dist', + {'prefix': ('command line', self.root_dir)}) + + site_packages = self.get_path(dist, 'purelib') + return dist, site_packages + + def test_uninstall_unknown_distribution(self): + dist, site_packages = self.install_dist('Foospam') self.assertRaises(PackagingError, remove, 'Foo', - paths=[self.root_dir]) + paths=[site_packages]) def test_uninstall(self): - dist, install_lib = self.install_dist() - self.assertIsFile(install_lib, 'foo', '__init__.py') - self.assertIsFile(install_lib, 'foo', 'sub', '__init__.py') - self.assertIsFile(install_lib, 'Foo-0.1.dist-info', 'RECORD') - self.assertTrue(remove('Foo', paths=[install_lib])) - self.assertIsNotFile(install_lib, 'foo', 'sub', '__init__.py') - self.assertIsNotFile(install_lib, 'Foo-0.1.dist-info', 'RECORD') - - def test_remove_issue(self): + dist, site_packages = self.install_dist() + self.assertIsFile(site_packages, 'foo', '__init__.py') + self.assertIsFile(site_packages, 'foo', 'sub', '__init__.py') + self.assertIsFile(site_packages, 'Foo-0.1.dist-info', 'RECORD') + self.assertTrue(remove('Foo', paths=[site_packages])) + self.assertIsNotFile(site_packages, 'foo', 'sub', '__init__.py') + self.assertIsNotFile(site_packages, 'Foo-0.1.dist-info', 'RECORD') + + def test_uninstall_error_handling(self): # makes sure if there are OSErrors (like permission denied) - # remove() stops and display a clean error - dist, install_lib = self.install_dist('Meh') + # remove() stops and displays a clean error + dist, site_packages = self.install_dist('Meh') # breaking os.rename old = os.rename def _rename(source, target): - raise OSError + raise OSError(42, 'impossible operation') os.rename = _rename try: - self.assertFalse(remove('Meh', paths=[install_lib])) + self.assertFalse(remove('Meh', paths=[site_packages])) finally: os.rename = old - self.assertTrue(remove('Meh', paths=[install_lib])) + logs = [log for log in self.get_logs(logging.INFO) + if log.startswith('Error:')] + self.assertEqual(logs, ['Error: [Errno 42] impossible operation']) + + self.assertTrue(remove('Meh', paths=[site_packages])) def test_suite(): diff --git a/Lib/packaging/tests/test_version.py b/Lib/packaging/tests/test_version.py index f94c800..2c86111 100644 --- a/Lib/packaging/tests/test_version.py +++ b/Lib/packaging/tests/test_version.py @@ -101,7 +101,17 @@ class VersionTestCase(unittest.TestCase): True >>> V('1.2.0') >= V('1.2.3') False - >>> (V('1.0') > V('1.0b2')) + >>> V('1.2.0rc1') >= V('1.2.0') + False + >>> V('1.0') > V('1.0b2') + True + >>> V('1.0') > V('1.0c2') + True + >>> V('1.0') > V('1.0rc2') + True + >>> V('1.0rc2') > V('1.0rc1') + True + >>> V('1.0c4') > V('1.0c1') True >>> (V('1.0') > V('1.0c2') > V('1.0c1') > V('1.0b2') > V('1.0b1') ... > V('1.0a2') > V('1.0a1')) @@ -129,6 +139,8 @@ class VersionTestCase(unittest.TestCase): ... < V('1.0.dev18') ... < V('1.0.dev456') ... < V('1.0.dev1234') + ... < V('1.0rc1') + ... < V('1.0rc2') ... < V('1.0') ... < V('1.0.post456.dev623') # development version of a post release ... < V('1.0.post456')) @@ -236,9 +248,9 @@ class VersionWhiteBoxTestCase(unittest.TestCase): def test_parse_numdots(self): # For code coverage completeness, as pad_zeros_length can't be set or # influenced from the public interface - self.assertEqual(V('1.0')._parse_numdots('1.0', '1.0', - pad_zeros_length=3), - [1, 0, 0]) + self.assertEqual( + V('1.0')._parse_numdots('1.0', '1.0', pad_zeros_length=3), + [1, 0, 0]) def test_suite(): diff --git a/Lib/packaging/version.py b/Lib/packaging/version.py index 0eaf80b..7d812bb 100644 --- a/Lib/packaging/version.py +++ b/Lib/packaging/version.py @@ -253,7 +253,7 @@ def suggest_normalized_version(s): # if we have something like "b-2" or "a.2" at the end of the # version, that is pobably beta, alpha, etc # let's remove the dash or dot - rs = re.sub(r"([abc|rc])[\-\.](\d+)$", r"\1\2", rs) + rs = re.sub(r"([abc]|rc)[\-\.](\d+)$", r"\1\2", rs) # 1.0-dev-r371 -> 1.0.dev371 # 0.1-dev-r79 -> 0.1.dev79 diff --git a/Lib/sysconfig.cfg b/Lib/sysconfig.cfg index 573b12e..565c0eb 100644 --- a/Lib/sysconfig.cfg +++ b/Lib/sysconfig.cfg @@ -31,7 +31,7 @@ man = {datadir}/man # be used directly in [resource_locations]. confdir = /etc datadir = /usr/share -libdir = /usr/lib ; or /usr/lib64 on a multilib system +libdir = /usr/lib statedir = /var # User resource directory local = ~/.local/{distribution.name} diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py index e46f935..59bdb01 100755 --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -173,6 +173,7 @@ import io import json import logging import os +import packaging.database import platform import random import re @@ -967,6 +968,7 @@ class saved_test_environment: 'sys.warnoptions', 'threading._dangling', 'multiprocessing.process._dangling', 'sysconfig._CONFIG_VARS', 'sysconfig._SCHEMES', + 'packaging.database_caches', ) def get_sys_argv(self): @@ -1054,6 +1056,28 @@ class saved_test_environment: # Can't easily revert the logging state pass + def get_packaging_database_caches(self): + # caching system used by the PEP 376 implementation + # we have one boolean and four dictionaries, initially empty + switch = packaging.database._cache_enabled + saved = [] + for name in ('_cache_name', '_cache_name_egg', + '_cache_path', '_cache_path_egg'): + cache = getattr(packaging.database, name) + saved.append((id(cache), cache, cache.copy())) + return switch, saved + def restore_packaging_database_caches(self, saved): + switch, saved_caches = saved + packaging.database._cache_enabled = switch + for offset, name in enumerate(('_cache_name', '_cache_name_egg', + '_cache_path', '_cache_path_egg')): + _, cache, items = saved_caches[offset] + # put back the same object in place + setattr(packaging.database, name, cache) + # now restore its items + cache.clear() + cache.update(items) + def get_sys_warnoptions(self): return id(sys.warnoptions), sys.warnoptions, sys.warnoptions[:] def restore_sys_warnoptions(self, saved_options): diff --git a/Lib/test/support.py b/Lib/test/support.py index 619bf4c..556e82f4 100644 --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -187,8 +187,7 @@ def get_attribute(obj, name): try: attribute = getattr(obj, name) except AttributeError: - raise unittest.SkipTest("module %s has no attribute %s" % ( - repr(obj), name)) + raise unittest.SkipTest("object %r has no attribute %r" % (obj, name)) else: return attribute diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py index 0a60136..2621f72 100644 --- a/Lib/test/test_minidom.py +++ b/Lib/test/test_minidom.py @@ -467,7 +467,7 @@ class MinidomTest(unittest.TestCase): dom.unlink() self.confirm(domstr == str.replace("\n", "\r\n")) - def test_toPrettyXML_perserves_content_of_text_node(self): + def test_toprettyxml_preserves_content_of_text_node(self): str = '<A>B</A>' dom = parseString(str) dom2 = parseString(dom.toprettyxml()) @@ -1261,6 +1261,8 @@ Library Build ----- +- PEP 393: the configure option --with-wide-unicode is removed. + - Issue #12852: Set _XOPEN_SOURCE to 700, instead of 600, to get POSIX 2008 functions on OpenBSD (e.g. fdopendir). |