diff options
| -rw-r--r-- | distutils2/_backport/__init__.py | 6 | ||||
| -rw-r--r-- | distutils2/_backport/misc.py | 141 | ||||
| -rw-r--r-- | distutils2/_backport/tests/test_shutil.py | 2 | ||||
| -rw-r--r-- | distutils2/command/build_scripts.py | 2 | ||||
| -rw-r--r-- | distutils2/compat.py | 143 | ||||
| -rw-r--r-- | distutils2/create.py | 6 | ||||
| -rw-r--r-- | distutils2/markers.py | 2 | ||||
| -rw-r--r-- | distutils2/pypi/simple.py | 6 | ||||
| -rw-r--r-- | distutils2/tests/pypi_server.py | 2 | ||||
| -rw-r--r-- | distutils2/tests/test_markers.py | 2 |
10 files changed, 155 insertions, 157 deletions
diff --git a/distutils2/_backport/__init__.py b/distutils2/_backport/__init__.py index ce6f11b..3d67498 100644 --- 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/_backport/misc.py b/distutils2/_backport/misc.py new file mode 100644 index 0000000..1759c94 --- /dev/null +++ b/distutils2/_backport/misc.py @@ -0,0 +1,141 @@ +"""Backports for individual classes and functions.""" + +import os +import re +import sys +import codecs + +__all__ = ['any', 'detect_encoding', 'fsencode', 'python_implementation', + 'wraps'] + + +try: + any = 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(): + """Return a string identifying the 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/_backport/tests/test_shutil.py b/distutils2/_backport/tests/test_shutil.py index fc883ad..b058d67 100644 --- a/distutils2/_backport/tests/test_shutil.py +++ b/distutils2/_backport/tests/test_shutil.py @@ -6,13 +6,13 @@ from os.path import splitdrive 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 index 300f692..901a679 100644 --- a/distutils2/command/build_scripts.py +++ b/distutils2/command/build_scripts.py @@ -7,8 +7,8 @@ from distutils2.command.cmd import Command 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 index 7c82142..bcd4f0f 100644 --- 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 @@ class Mixin2to3(_KLASS): 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 index d0c9477..5ad4563 100644 --- a/distutils2/create.py +++ b/distutils2/create.py @@ -31,13 +31,9 @@ from distutils2 import logger # 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 index 0281179..ac7df79 100644 --- a/distutils2/markers.py +++ b/distutils2/markers.py @@ -6,7 +6,7 @@ import platform 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 index 50b2c9c..46c9d1c 100644 --- a/distutils2/pypi/simple.py +++ b/distutils2/pypi/simple.py @@ -16,10 +16,9 @@ import os from fnmatch import translate from distutils2 import logger -from distutils2.compat import wraps -from distutils2.metadata import Metadata -from distutils2.version import get_version_predicate from distutils2 import __version__ as distutils2_version +from distutils2.version import get_version_predicate +from distutils2.metadata import Metadata from distutils2.pypi.base import BaseClient from distutils2.pypi.dist import (ReleasesList, EXTENSIONS, get_infos_from_url, MD5_HASH) @@ -27,6 +26,7 @@ from distutils2.pypi.errors import (PackagingPyPIError, DownloadError, 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 index 0dfde1f..ad4ce14 100644 --- a/distutils2/tests/pypi_server.py +++ b/distutils2/tests/pypi_server.py @@ -38,7 +38,7 @@ from SimpleHTTPServer import SimpleHTTPRequestHandler 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 index 67e9e9b..89697d0 100644 --- 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 |
