[Python-checkins] distutils2: Better separate compat and _backport.

eric.araujo python-checkins at python.org
Wed Nov 23 16:45:59 CET 2011


http://hg.python.org/distutils2/rev/a382d149a0f0
changeset:   1262:a382d149a0f0
parent:      1259:c898ebb74f28
user:        Éric Araujo <merwok at netwok.org>
date:        Wed Nov 23 13:31:27 2011 +0100
summary:
  Better separate compat and _backport.

This moves individual backported functions from compat into a new
_backport.misc module.  compat regains its original purpose of
containing 2to3 support code (i.e. compat for projects using distutils2,
not internal compat for d2 code) and all backports now live under the
private _backport subnamespace.

Also fix the definition of “any” to bind it to the builtin in 2.5+
(fsencode and detect_encoding not changed, they never exist in
2.x).

files:
  distutils2/_backport/__init__.py          |    6 +-
  distutils2/compat.py                      |   63 +---
  distutils2/_backport/tests/test_shutil.py |    2 +-
  distutils2/command/build_scripts.py       |    2 +-
  distutils2/compat.py                      |  143 +---------
  distutils2/create.py                      |    6 +-
  distutils2/markers.py                     |    2 +-
  distutils2/pypi/simple.py                 |    6 +-
  distutils2/tests/pypi_server.py           |    2 +-
  distutils2/tests/test_markers.py          |    2 +-
  10 files changed, 20 insertions(+), 214 deletions(-)


diff --git a/distutils2/_backport/__init__.py b/distutils2/_backport/__init__.py
--- a/distutils2/_backport/__init__.py
+++ b/distutils2/_backport/__init__.py
@@ -1,4 +1,6 @@
-"""Modules copied from Python 3 standard libraries.
+"""Modules copied from Python 3 standard libraries, for internal use only.
 
-Individual classes and objects like the any function are in compat.
+Individual classes and functions are found in d2._backport.misc.  Intended
+usage is to always import things missing from 2.4 from that module: the
+built-in/stdlib objects will be used if found.
 """
diff --git a/distutils2/compat.py b/distutils2/_backport/misc.py
copy from distutils2/compat.py
copy to distutils2/_backport/misc.py
--- a/distutils2/compat.py
+++ b/distutils2/_backport/misc.py
@@ -1,69 +1,16 @@
-"""Compatibility helpers.
-
-This module provides individual classes or objects backported from
-Python 3.2, for internal use only.  Whole modules are in _backport.
-"""
+"""Backports for individual classes and functions."""
 
 import os
 import re
 import sys
 import codecs
-from distutils2 import logger
 
+__all__ = ['any', 'detect_encoding', 'fsencode', 'python_implementation',
+           'wraps']
 
-# XXX Having two classes with the same name is not a good thing.
-# XXX 2to3-related code should move from util to this module
 
 try:
-    from distutils2.util import Mixin2to3 as _Mixin2to3
-    _CONVERT = True
-    _KLASS = _Mixin2to3
-except ImportError:
-    _CONVERT = False
-    _KLASS = object
-
-__all__ = ['Mixin2to3']
-
-
-class Mixin2to3(_KLASS):
-    """ The base class which can be used for refactoring. When run under
-    Python 3.0, the run_2to3 method provided by Mixin2to3 is overridden.
-    When run on Python 2.x, it merely creates a class which overrides run_2to3,
-    yet does nothing in particular with it.
-    """
-    if _CONVERT:
-
-        def _run_2to3(self, files, doctests=[], fixers=[]):
-            """ Takes a list of files and doctests, and performs conversion
-            on those.
-              - First, the files which contain the code(`files`) are converted.
-              - Second, the doctests in `files` are converted.
-              - Thirdly, the doctests in `doctests` are converted.
-            """
-            if fixers:
-                self.fixer_names = fixers
-
-            logger.info('converting Python code')
-            _KLASS.run_2to3(self, files)
-
-            logger.info('converting doctests in Python files')
-            _KLASS.run_2to3(self, files, doctests_only=True)
-
-            if doctests != []:
-                logger.info('converting doctest in text files')
-                _KLASS.run_2to3(self, doctests, doctests_only=True)
-    else:
-        # If run on Python 2.x, there is nothing to do.
-
-        def _run_2to3(self, files, doctests=[], fixers=[]):
-            pass
-
-
-# The rest of this file does not exist in packaging
-# functions are sorted alphabetically and are not included in __all__
-
-try:
-    any
+    any = any
 except NameError:
     def any(seq):
         for elem in seq:
@@ -179,10 +126,12 @@
             return func
         return wrapped
 
+
 try:
     from platform import python_implementation
 except ImportError:
     def python_implementation():
+        """Return a string identifying the Python implementation."""
         if 'PyPy' in sys.version:
             return 'PyPy'
         if os.name == 'java':
diff --git a/distutils2/_backport/tests/test_shutil.py b/distutils2/_backport/tests/test_shutil.py
--- a/distutils2/_backport/tests/test_shutil.py
+++ b/distutils2/_backport/tests/test_shutil.py
@@ -6,13 +6,13 @@
 from StringIO import StringIO
 
 from distutils.spawn import find_executable, spawn
-from distutils2.compat import wraps
 from distutils2._backport import shutil, tarfile
 from distutils2._backport.shutil import (
     _make_tarball, _make_zipfile, make_archive, unpack_archive,
     register_archive_format, unregister_archive_format, get_archive_formats,
     register_unpack_format, unregister_unpack_format, get_unpack_formats,
     Error, RegistryError)
+from distutils2._backport.misc import wraps
 
 from distutils2.tests import unittest, support
 from test.test_support import TESTFN
diff --git a/distutils2/command/build_scripts.py b/distutils2/command/build_scripts.py
--- a/distutils2/command/build_scripts.py
+++ b/distutils2/command/build_scripts.py
@@ -7,8 +7,8 @@
 from distutils2.util import convert_path, newer
 from distutils2 import logger
 from distutils2.compat import Mixin2to3
-from distutils2.compat import detect_encoding, fsencode
 from distutils2._backport import sysconfig
+from distutils2._backport.misc import detect_encoding, fsencode
 
 
 # check if Python is called on the first line with this expression
diff --git a/distutils2/compat.py b/distutils2/compat.py
--- a/distutils2/compat.py
+++ b/distutils2/compat.py
@@ -1,13 +1,5 @@
-"""Compatibility helpers.
+"""Support for build-time 2to3 conversion."""
 
-This module provides individual classes or objects backported from
-Python 3.2, for internal use only.  Whole modules are in _backport.
-"""
-
-import os
-import re
-import sys
-import codecs
 from distutils2 import logger
 
 
@@ -57,136 +49,3 @@
 
         def _run_2to3(self, files, doctests=[], fixers=[]):
             pass
-
-
-# The rest of this file does not exist in packaging
-# functions are sorted alphabetically and are not included in __all__
-
-try:
-    any
-except NameError:
-    def any(seq):
-        for elem in seq:
-            if elem:
-                return True
-        return False
-
-
-_cookie_re = re.compile("coding[:=]\s*([-\w.]+)")
-
-
-def _get_normal_name(orig_enc):
-    """Imitates get_normal_name in tokenizer.c."""
-    # Only care about the first 12 characters.
-    enc = orig_enc[:12].lower().replace("_", "-")
-    if enc == "utf-8" or enc.startswith("utf-8-"):
-        return "utf-8"
-    if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \
-       enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")):
-        return "iso-8859-1"
-    return orig_enc
-
-
-def detect_encoding(readline):
-    """
-    The detect_encoding() function is used to detect the encoding that should
-    be used to decode a Python source file.  It requires one argment, readline,
-    in the same way as the tokenize() generator.
-
-    It will call readline a maximum of twice, and return the encoding used
-    (as a string) and a list of any lines (left as bytes) it has read in.
-
-    It detects the encoding from the presence of a utf-8 bom or an encoding
-    cookie as specified in pep-0263.  If both a bom and a cookie are present,
-    but disagree, a SyntaxError will be raised.  If the encoding cookie is an
-    invalid charset, raise a SyntaxError.  Note that if a utf-8 bom is found,
-    'utf-8-sig' is returned.
-
-    If no encoding is specified, then the default of 'utf-8' will be returned.
-    """
-    bom_found = False
-    encoding = None
-    default = 'utf-8'
-
-    def read_or_stop():
-        try:
-            return readline()
-        except StopIteration:
-            return ''
-
-    def find_cookie(line):
-        try:
-            line_string = line.decode('ascii')
-        except UnicodeDecodeError:
-            return None
-
-        matches = _cookie_re.findall(line_string)
-        if not matches:
-            return None
-        encoding = _get_normal_name(matches[0])
-        try:
-            codec = codecs.lookup(encoding)
-        except LookupError:
-            # This behaviour mimics the Python interpreter
-            raise SyntaxError("unknown encoding: " + encoding)
-
-        if bom_found:
-            if codec.name != 'utf-8':
-                # This behaviour mimics the Python interpreter
-                raise SyntaxError('encoding problem: utf-8')
-            encoding += '-sig'
-        return encoding
-
-    first = read_or_stop()
-    if first.startswith(codecs.BOM_UTF8):
-        bom_found = True
-        first = first[3:]
-        default = 'utf-8-sig'
-    if not first:
-        return default, []
-
-    encoding = find_cookie(first)
-    if encoding:
-        return encoding, [first]
-
-    second = read_or_stop()
-    if not second:
-        return default, [first]
-
-    encoding = find_cookie(second)
-    if encoding:
-        return encoding, [first, second]
-
-    return default, [first, second]
-
-
-def fsencode(filename):
-    if isinstance(filename, str):
-        return filename
-    elif isinstance(filename, unicode):
-        return filename.encode(sys.getfilesystemencoding())
-    else:
-        raise TypeError("expect bytes or str, not %s" %
-                        type(filename).__name__)
-
-
-try:
-    from functools import wraps
-except ImportError:
-    def wraps(func=None):
-        """No-op replacement for functools.wraps"""
-        def wrapped(func):
-            return func
-        return wrapped
-
-try:
-    from platform import python_implementation
-except ImportError:
-    def python_implementation():
-        if 'PyPy' in sys.version:
-            return 'PyPy'
-        if os.name == 'java':
-            return 'Jython'
-        if sys.version.startswith('IronPython'):
-            return 'IronPython'
-        return 'CPython'
diff --git a/distutils2/create.py b/distutils2/create.py
--- a/distutils2/create.py
+++ b/distutils2/create.py
@@ -31,13 +31,9 @@
 # importing this with an underscore as it should be replaced by the
 # dict form or another structures for all purposes
 from distutils2._trove import all_classifiers as _CLASSIFIERS_LIST
-from distutils2.compat import detect_encoding
 from distutils2.version import is_valid_version
 from distutils2._backport import shutil, sysconfig
-try:
-    any
-except NameError:
-    from distutils2.compat import any
+from distutils2._backport.misc import any, detect_encoding
 try:
     from hashlib import md5
 except ImportError:
diff --git a/distutils2/markers.py b/distutils2/markers.py
--- a/distutils2/markers.py
+++ b/distutils2/markers.py
@@ -6,7 +6,7 @@
 from tokenize import generate_tokens, NAME, OP, STRING, ENDMARKER
 from StringIO import StringIO as BytesIO
 
-from distutils2.compat import python_implementation
+from distutils2._backport.misc import python_implementation
 
 __all__ = ['interpret']
 
diff --git a/distutils2/pypi/simple.py b/distutils2/pypi/simple.py
--- a/distutils2/pypi/simple.py
+++ b/distutils2/pypi/simple.py
@@ -16,10 +16,9 @@
 
 from fnmatch import translate
 from distutils2 import logger
-from distutils2.compat import wraps
+from distutils2 import __version__ as distutils2_version
+from distutils2.version import get_version_predicate
 from distutils2.metadata import Metadata
-from distutils2.version import get_version_predicate
-from distutils2 import __version__ as distutils2_version
 from distutils2.pypi.base import BaseClient
 from distutils2.pypi.dist import (ReleasesList, EXTENSIONS,
                                   get_infos_from_url, MD5_HASH)
@@ -27,6 +26,7 @@
                                     UnableToDownload, CantParseArchiveName,
                                     ReleaseNotFound, ProjectNotFound)
 from distutils2.pypi.mirrors import get_mirrors
+from distutils2._backport.misc import wraps
 
 __all__ = ['Crawler', 'DEFAULT_SIMPLE_INDEX_URL']
 
diff --git a/distutils2/tests/pypi_server.py b/distutils2/tests/pypi_server.py
--- a/distutils2/tests/pypi_server.py
+++ b/distutils2/tests/pypi_server.py
@@ -38,7 +38,7 @@
 from SimpleXMLRPCServer import SimpleXMLRPCServer
 
 from distutils2.tests import unittest
-from distutils2.compat import wraps
+from distutils2._backport.misc import wraps
 
 
 PYPI_DEFAULT_STATIC_PATH = os.path.join(
diff --git a/distutils2/tests/test_markers.py b/distutils2/tests/test_markers.py
--- a/distutils2/tests/test_markers.py
+++ b/distutils2/tests/test_markers.py
@@ -2,8 +2,8 @@
 import os
 import sys
 import platform
-from distutils2.compat import python_implementation
 from distutils2.markers import interpret
+from distutils2._backport.misc import python_implementation
 
 from distutils2.tests import unittest
 from distutils2.tests.support import LoggingCatcher

-- 
Repository URL: http://hg.python.org/distutils2


More information about the Python-checkins mailing list