From 5858dc0042a8b159df2127b4a63c818a6959ff62 Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Mon, 4 Jan 2021 15:35:04 +0900 Subject: [PATCH] Imported Upstream version 1.12.0 --- .gitignore | 1 + .travis.yml | 2 +- CHANGES | 9 ++++++ CONTRIBUTORS | 3 +- LICENSE | 2 +- README.rst | 17 +++++++---- documentation/conf.py | 2 +- documentation/index.rst | 29 ++++++++++++++---- setup.cfg | 3 ++ setup.py | 8 +++-- six.py | 65 ++++++++++++++++++++++++++++++++++++++-- test_six.py | 80 ++++++++++++++++++++++++++++++++++++++++++++++++- tox.ini | 6 +--- 13 files changed, 202 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index 7b027c2..d4b534b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.pyc +build dist MANIFEST documentation/_build diff --git a/.travis.yml b/.travis.yml index f86390e..45713fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 b399882..164f0b5 100644 --- 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 ------ diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 5979045..35596c4 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -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 f3068bf..365d107 100644 --- 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 diff --git a/README.rst b/README.rst index c17d8d7..a99e6f5 100644 --- a/README.rst +++ b/README.rst @@ -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. diff --git a/documentation/conf.py b/documentation/conf.py index ad925c1..e039301 100644 --- a/documentation/conf.py +++ b/documentation/conf.py @@ -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 diff --git a/documentation/index.rst b/documentation/index.rst index dd0dc6e..99192a2 100644 --- a/documentation/index.rst +++ b/documentation/index.rst @@ -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 `_. Its bug +Six can be downloaded on `PyPI `_. Its bug tracker and code hosting is on `GitHub `_. 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 diff --git a/setup.cfg b/setup.cfg index 70ce163..317e016 100644 --- 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 = diff --git a/setup.py b/setup.py index ca44e10..2596479 100644 --- 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 6bf4fd3..89b2188 100644 --- 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 " -__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. diff --git a/test_six.py b/test_six.py index 43e7426..897e232 100644 --- a/test_six.py +++ b/test_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 @@ -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..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 d581326..f7df78c 100644 --- 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 - -- 2.7.4