Imported Upstream version 1.12.0 upstream/1.12.0
authorDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 4 Jan 2021 06:35:50 +0000 (15:35 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 4 Jan 2021 06:35:50 +0000 (15:35 +0900)
13 files changed:
.gitignore
.travis.yml
CHANGES
CONTRIBUTORS
LICENSE
README.rst
documentation/conf.py
documentation/index.rst
setup.cfg
setup.py
six.py
test_six.py
tox.ini

index 7b027c262a968a98d1ecba70a040587607f57e6f..d4b534be53efbd69504f2f2e158917f5c7e45f05 100644 (file)
@@ -1,4 +1,5 @@
 *.pyc
+build
 dist
 MANIFEST
 documentation/_build
index f86390e5f4cba8d316dd866a01feead49313d9c2..45713fcf9485c0af1ae70ac997eb0dccb5f8980e 100644 (file)
@@ -15,7 +15,7 @@ python:
 - pypy2.7-5.8.0
 - pypy3.5-5.8.0
 install:
-- pip install --upgrade --force-reinstall "setuptools; python_version != '3.2'" "setuptools < 30; python_version == '3.2'"
+- pip install --upgrade --force-reinstall "setuptools; python_version != '3.2' and python_version != '3.3'" "setuptools < 30; python_version == '3.2'" "setuptools < 40; python_version == '3.3'"
 - pip uninstall --yes six || true
 - pip install --upgrade --force-reinstall --ignore-installed -e .
 - pip install pytest
diff --git a/CHANGES b/CHANGES
index b399882561ec295d8defcadbe1b9b995b1eb9e11..164f0b5d58f27898e24fe80003ff5f2c99c34656 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,15 @@ Changelog for six
 
 This file lists the changes in each six version.
 
+1.12.0
+------
+
+- Issue #259, pull request #260: `six.add_metaclass` now preserves
+  `__qualname__` from the original class.
+
+- Pull request #204: Add `six.ensure_binary`, `six.ensure_text`, and
+  `six.ensure_str`.
+
 1.11.0
 ------
 
index 5979045aaf3a18deb60be7621744d6c64fb20ec4..35596c4bcafc1447159bd35368f677a5765f6448 100644 (file)
@@ -19,6 +19,7 @@ Joshua Harlow
 Anselm Kruis
 Alexander Lukanin
 James Mills
+Jordan Moldow
 Berker Peksag
 Sridhar Ratnakumar
 Erik Rose
@@ -27,6 +28,6 @@ Peter Ruibal
 Miroslav Shubernetskiy
 Anthony Sottile
 Lucas Wiman
-Jordan Moldow
+Jingxin Zhu
 
 If you think you belong on this list, please let me know! --Benjamin
diff --git a/LICENSE b/LICENSE
index f3068bfd9e0cd86de6b2ce5f5fa7faf38c68e5ce..365d10741bfac1d8317daa669d1d35a59cd05553 100644 (file)
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2010-2017 Benjamin Peterson
+Copyright (c) 2010-2018 Benjamin Peterson
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of
 this software and associated documentation files (the "Software"), to deal in
index c17d8d732af859de2c46abad0064434a84dc160a..a99e6f5585a918b8a68ceabace2fb6e34e92183b 100644 (file)
@@ -1,11 +1,18 @@
-.. image:: http://img.shields.io/pypi/v/six.svg
-   :target: https://pypi.python.org/pypi/six
+.. image:: https://img.shields.io/pypi/v/six.svg
+   :target: https://pypi.org/project/six/
+   :alt: six on PyPI
 
 .. image:: https://travis-ci.org/benjaminp/six.svg?branch=master
-    :target: https://travis-ci.org/benjaminp/six
+   :target: https://travis-ci.org/benjaminp/six
+   :alt: six on TravisCI
 
-.. image:: http://img.shields.io/badge/license-MIT-green.svg
+.. image:: https://readthedocs.org/projects/six/badge/?version=latest
+   :target: https://six.readthedocs.io/
+   :alt: six's documentation on Read the Docs
+
+.. image:: https://img.shields.io/badge/license-MIT-green.svg
    :target: https://github.com/benjaminp/six/blob/master/LICENSE
+   :alt: MIT License badge
 
 Six is a Python 2 and 3 compatibility library.  It provides utility functions
 for smoothing over the differences between the Python versions with the goal of
@@ -16,7 +23,7 @@ Six supports every Python version since 2.6.  It is contained in only one Python
 file, so it can be easily copied into your project. (The copyright and license
 notice must be retained.)
 
-Online documentation is at http://six.rtfd.org.
+Online documentation is at https://six.readthedocs.io/.
 
 Bugs can be reported to https://github.com/benjaminp/six.  The code can also
 be found there.
index ad925c1c1d1e83614937072bbe94e6c3056d188d..e0393016fc87db2c2c227fdd1e9a7cf971dce22e 100644 (file)
@@ -33,7 +33,7 @@ master_doc = "index"
 
 # General information about the project.
 project = u"six"
-copyright = u"2010-2017, Benjamin Peterson"
+copyright = u"2010-2018, Benjamin Peterson"
 
 sys.path.append(os.path.abspath(os.path.join(".", "..")))
 from six import __version__ as six_version
index dd0dc6e3bde8c458dc4f11331ef7be12ed67aba8..99192a21ed6d8f940fb0ea4b6022978ca30f1274 100644 (file)
@@ -13,7 +13,7 @@ Python 3.  It is intended to support codebases that work on both Python 2 and 3
 without modification.  six consists of only one Python file, so it is painless
 to copy into a project.
 
-Six can be downloaded on `PyPi <https://pypi.python.org/pypi/six/>`_.  Its bug
+Six can be downloaded on `PyPI <https://pypi.org/project/six/>`_.  Its bug
 tracker and code hosting is on `GitHub <https://github.com/benjaminp/six>`_.
 
 The name, "six", comes from the fact that 2*3 equals 6.  Why not addition?
@@ -50,8 +50,9 @@ Six provides constants that may differ between Python versions.  Ones ending
 
 .. data:: class_types
 
-   Possible class types.  In Python 2, this encompasses old-style and new-style
-   classes.  In Python 3, this is just new-styles.
+   Possible class types.  In Python 2, this encompasses old-style
+   :data:`py2:types.ClassType` and new-style ``type`` classes.  In Python 3,
+   this is just ``type``.
 
 
 .. data:: integer_types
@@ -371,7 +372,7 @@ string data in all Python versions.
 .. function:: b(data)
 
    A "fake" bytes literal.  *data* should always be a normal string literal.  In
-   Python 2, :func:`b` returns a 8-bit string.  In Python 3, *data* is encoded
+   Python 2, :func:`b` returns an 8-bit string.  In Python 3, *data* is encoded
    with the latin-1 encoding to bytes.
 
 
@@ -433,6 +434,24 @@ string data in all Python versions.
    a bytes object iterator in Python 3.
 
 
+.. function:: ensure_binary(s, encoding='utf-8', errors='strict')
+
+   Coerce *s* to :data:`binary_type`. *encoding*, *errors* are the same as
+   :meth:`py3:str.encode`
+
+
+.. function:: ensure_str(s, encoding='utf-8', errors='strict')
+
+   Coerce *s* to ``str``. ``encoding``, ``errors`` are the same
+   :meth:`py3:str.encode`
+
+
+.. function:: ensure_text(s, encoding='utf-8', errors='strict')
+
+   Coerce *s* to :data:`text_type`. *encoding*, *errors* are the same as
+   :meth:`py3:str.encode`
+
+
 .. data:: StringIO
 
    This is a fake file object for textual data.  It's an alias for
@@ -503,7 +522,7 @@ Python 2 or 3, write::
    from six.moves import html_parser
 
 Similarly, to get the function to reload modules, which was moved from the
-builtin module to the ``imp`` module, use::
+builtin module to the ``importlib`` module, use::
 
    from six.moves import reload_module
 
index 70ce163deff5159c3a2e89ed02a9ec45dfe9367c..317e016c8cc04d097b3b69639710357deb1c972b 100644 (file)
--- a/setup.cfg
+++ b/setup.cfg
@@ -5,6 +5,9 @@ universal = 1
 max-line-length = 100
 ignore = F821
 
+[metadata]
+license_file = LICENSE
+
 [tool:pytest]
 minversion=2.2.0
 pep8ignore =
index ca44e100e427ecf5424bacb84d5eb6f5c712f231..25964793bce7794c20e0366268db607416881583 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2010-2017 Benjamin Peterson
+# Copyright (c) 2010-2018 Benjamin Peterson
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal
@@ -31,6 +31,7 @@ except ImportError:
 import six
 
 six_classifiers = [
+    "Development Status :: 5 - Production/Stable",
     "Programming Language :: Python :: 2",
     "Programming Language :: Python :: 3",
     "Intended Audience :: Developers",
@@ -46,11 +47,12 @@ setup(name="six",
       version=six.__version__,
       author="Benjamin Peterson",
       author_email="benjamin@python.org",
-      url="http://pypi.python.org/pypi/six/",
+      url="https://github.com/benjaminp/six",
       tests_require=["pytest"],
       py_modules=["six"],
       description="Python 2 and 3 compatibility utilities",
       long_description=six_long_description,
       license="MIT",
-      classifiers=six_classifiers
+      classifiers=six_classifiers,
+      python_requires=">=2.6, !=3.0.*, !=3.1.*",
       )
diff --git a/six.py b/six.py
index 6bf4fd381046207a4794aee17be6d22db237f30a..89b2188fd63f6f95f1c4500f476a8e6adeaabdd0 100644 (file)
--- a/six.py
+++ b/six.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2010-2017 Benjamin Peterson
+# Copyright (c) 2010-2018 Benjamin Peterson
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal
@@ -29,7 +29,7 @@ import sys
 import types
 
 __author__ = "Benjamin Peterson <benjamin@python.org>"
-__version__ = "1.11.0"
+__version__ = "1.12.0"
 
 
 # Useful for very coarse version differentiation.
@@ -844,10 +844,71 @@ def add_metaclass(metaclass):
                 orig_vars.pop(slots_var)
         orig_vars.pop('__dict__', None)
         orig_vars.pop('__weakref__', None)
+        if hasattr(cls, '__qualname__'):
+            orig_vars['__qualname__'] = cls.__qualname__
         return metaclass(cls.__name__, cls.__bases__, orig_vars)
     return wrapper
 
 
+def ensure_binary(s, encoding='utf-8', errors='strict'):
+    """Coerce **s** to six.binary_type.
+
+    For Python 2:
+      - `unicode` -> encoded to `str`
+      - `str` -> `str`
+
+    For Python 3:
+      - `str` -> encoded to `bytes`
+      - `bytes` -> `bytes`
+    """
+    if isinstance(s, text_type):
+        return s.encode(encoding, errors)
+    elif isinstance(s, binary_type):
+        return s
+    else:
+        raise TypeError("not expecting type '%s'" % type(s))
+
+
+def ensure_str(s, encoding='utf-8', errors='strict'):
+    """Coerce *s* to `str`.
+
+    For Python 2:
+      - `unicode` -> encoded to `str`
+      - `str` -> `str`
+
+    For Python 3:
+      - `str` -> `str`
+      - `bytes` -> decoded to `str`
+    """
+    if not isinstance(s, (text_type, binary_type)):
+        raise TypeError("not expecting type '%s'" % type(s))
+    if PY2 and isinstance(s, text_type):
+        s = s.encode(encoding, errors)
+    elif PY3 and isinstance(s, binary_type):
+        s = s.decode(encoding, errors)
+    return s
+
+
+def ensure_text(s, encoding='utf-8', errors='strict'):
+    """Coerce *s* to six.text_type.
+
+    For Python 2:
+      - `unicode` -> `unicode`
+      - `str` -> `unicode`
+
+    For Python 3:
+      - `str` -> `str`
+      - `bytes` -> decoded to `str`
+    """
+    if isinstance(s, binary_type):
+        return s.decode(encoding, errors)
+    elif isinstance(s, text_type):
+        return s
+    else:
+        raise TypeError("not expecting type '%s'" % type(s))
+
+
+
 def python_2_unicode_compatible(klass):
     """
     A decorator that defines __unicode__ and __str__ methods under Python 2.
index 43e7426dea1241bbd371d2f24f63f510427a519f..897e2322f7e7a99ec37cedbc79f123e9c0179a28 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2010-2017 Benjamin Peterson
+# Copyright (c) 2010-2018 Benjamin Peterson
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal
@@ -875,6 +875,26 @@ def test_add_metaclass():
     assert type(MySlotsWeakref) is Meta
 
 
+@py.test.mark.skipif("sys.version_info[:2] < (3, 3)")
+def test_add_metaclass_nested():
+    # Regression test for https://github.com/benjaminp/six/issues/259
+    class Meta(type):
+        pass
+
+    class A:
+        class B: pass
+
+    expected = 'test_add_metaclass_nested.<locals>.A.B'
+
+    assert A.B.__qualname__ == expected
+
+    class A:
+        @six.add_metaclass(Meta)
+        class B: pass
+
+    assert A.B.__qualname__ == expected
+
+
 @py.test.mark.skipif("sys.version_info[:2] < (2, 7) or sys.version_info[:2] in ((3, 0), (3, 1))")
 def test_assertCountEqual():
     class TestAssertCountEqual(unittest.TestCase):
@@ -932,3 +952,61 @@ def test_python_2_unicode_compatible():
         assert str(my_test) == six.u("hello")
 
     assert getattr(six.moves.builtins, 'bytes', str)(my_test) == six.b("hello")
+
+
+class EnsureTests:
+
+    # grinning face emoji
+    UNICODE_EMOJI = six.u("\U0001F600")
+    BINARY_EMOJI = b"\xf0\x9f\x98\x80"
+
+    def test_ensure_binary_raise_type_error(self):
+        with py.test.raises(TypeError):
+            six.ensure_str(8)
+
+    def test_errors_and_encoding(self):
+        six.ensure_binary(self.UNICODE_EMOJI, encoding='latin-1', errors='ignore')
+        with py.test.raises(UnicodeEncodeError):
+            six.ensure_binary(self.UNICODE_EMOJI, encoding='latin-1', errors='strict')
+
+    def test_ensure_binary_raise(self):
+        converted_unicode = six.ensure_binary(self.UNICODE_EMOJI, encoding='utf-8', errors='strict')
+        converted_binary = six.ensure_binary(self.BINARY_EMOJI, encoding="utf-8", errors='strict')
+        if six.PY2:
+            # PY2: unicode -> str
+            assert converted_unicode == self.BINARY_EMOJI and isinstance(converted_unicode, str)
+            # PY2: str -> str
+            assert converted_binary == self.BINARY_EMOJI and isinstance(converted_binary, str)
+        else:
+            # PY3: str -> bytes
+            assert converted_unicode == self.BINARY_EMOJI and isinstance(converted_unicode, bytes)
+            # PY3: bytes -> bytes
+            assert converted_binary == self.BINARY_EMOJI and isinstance(converted_binary, bytes)
+
+    def test_ensure_str(self):
+        converted_unicode = six.ensure_str(self.UNICODE_EMOJI, encoding='utf-8', errors='strict')
+        converted_binary = six.ensure_str(self.BINARY_EMOJI, encoding="utf-8", errors='strict')
+        if six.PY2:
+            # PY2: unicode -> str
+            assert converted_unicode == self.BINARY_EMOJI and isinstance(converted_unicode, str)
+            # PY2: str -> str
+            assert converted_binary == self.BINARY_EMOJI and isinstance(converted_binary, str)
+        else:
+            # PY3: str -> str
+            assert converted_unicode == self.UNICODE_EMOJI and isinstance(converted_unicode, str)
+            # PY3: bytes -> str
+            assert converted_binary == self.UNICODE_EMOJI and isinstance(converted_unicode, str)
+
+    def test_ensure_text(self):
+        converted_unicode = six.ensure_text(self.UNICODE_EMOJI, encoding='utf-8', errors='strict')
+        converted_binary = six.ensure_text(self.BINARY_EMOJI, encoding="utf-8", errors='strict')
+        if six.PY2:
+            # PY2: unicode -> unicode
+            assert converted_unicode == self.UNICODE_EMOJI and isinstance(converted_unicode, unicode)
+            # PY2: str -> unicode
+            assert converted_binary == self.UNICODE_EMOJI and isinstance(converted_unicode, unicode)
+        else:
+            # PY3: str -> str
+            assert converted_unicode == self.UNICODE_EMOJI and isinstance(converted_unicode, str)
+            # PY3: bytes -> str
+            assert converted_binary == self.UNICODE_EMOJI and isinstance(converted_unicode, str)
diff --git a/tox.ini b/tox.ini
index d581326da9464020a27a67af2d58a9e7a66342a3..f7df78c5dcfd12602e14b4c710862c60f2941fda 100644 (file)
--- a/tox.ini
+++ b/tox.ini
@@ -1,15 +1,11 @@
 [tox]
 envlist=py26,py27,py31,py32,py33,py34,pypy,flake8
-indexserver=
-    default = https://pypi.python.org/simple
-    testrun = http://pypi.testrun.org
 
 [testenv]
 deps= pytest
-commands= py.test -rfsxX {posargs}
+commands= python -m pytest -rfsxX {posargs}
 
 [testenv:flake8]
 basepython=python
 deps=flake8
 commands= flake8 six.py
-