kislyuk / eight

Python 2 to the power of 3
https://eight.readthedocs.org/
Apache License 2.0
47 stars 6 forks source link

eight: Python 2 to the power of 3

Eight is a Python module that provides a minimalist compatibility layer between Python 3 and 2. Eight lets you write code for Python 3.3+ while providing limited compatibility with Python 2.7 with no code changes. Eight is inspired by six <https://pythonhosted.org/six/>, nine <https://github.com/nandoflorestan/nine>, and python-future <https://github.com/PythonCharmers/python-future>_, but provides better internationalization (i18n) support, is more lightweight, easier to use, and unambiguously biased toward Python 3 code: if you remove eight from your code, it will continue to function exactly as it did with eight on Python 3.

To write code for Python 3 that is portable to Python 2, you may also want to read Armin Ronacher's excellent Python 3 porting guide <http://lucumr.pocoo.org/2013/5/21/porting-to-python-3-redux/>, as well as the official porting guide <http://docs.python.org/3/howto/pyporting.html>.

Writing from eight import * in your code is a no-op in Python 3. In Python 2, it binds a bunch of Python 3 names to their Python 2 equivalents. Also, if you need to import a module or module member that was renamed in Python 3, writing from eight import <module> will do the right thing (equivalent to import <module> on Python 3 and ``import

as `` on Python 2). Finally, eight can optionally wrap your standard streams and environment variable I/O to use text, not bytes (see below). Installation ------------ :: pip install eight Synopsis -------- .. code-block:: python from eight import * from eight import queue from eight.collections import UserList, deque If you use ``print``, division, non-ASCII literals, or relative imports, you should also add this `future import `_ at the top of each source file: .. code-block:: python from __future__ import (print_function, division, unicode_literals, absolute_import) Wrapping stdio -------------- Eight provides wrappers for ``sys.stdin``, ``sys.stdout``, and ``sys.stderr`` to make them (and methods that use them) behave like they do on Python 3. Specifically, in Python 3 these streams accept text data, and their ``.buffer`` attributes refer to the underlying streams that accept bytes. Eight uses the `io `_ module to do the same for you, but subclasses the TextIOWrapper class for ``sys.stdout`` and ``sys.stderr`` to coerce non-unicode input to unicode on Python 2 (otherwise, because of the Python 2 semantics, things like exception printing cease to work). To enable stdio wrapping, use the following: .. code-block:: python import eight eight.wrap_stdio() To revert the effects of this on any of the streams, use the detach method, e.g. ``sys.stdin = sys.stdin.detach()`` (but remember to condition this on ``eight.USING_PYTHON2``). See the `io module documentation `_ for more information. Decoding command-line arguments ------------------------------- Eight provides a utility function to decode the contents of ``sys.argv`` on Python 2 (as Python 3 does). It uses ``sys.stdin.encoding`` as the encoding to do so: .. code-block:: python import eight eight.decode_command_line_args() The call to ``decode_command_line_args()`` replaces ``sys.argv`` with its decoded contents and returns the new contents. On Python 3, the call is a no-op (it returns ``sys.argv`` and leaves it intact). Wrapping environment variable getters and setters ------------------------------------------------- Eight provides utility wrappers to help bring Python 2 environment variable access and assignment in line with Python 3: encode the input to ``os.putenv`` (which is used for statements like ``os.environ[x] = y``) and decode the output of ``os.getenv`` (used for ``x = os.environ[y]``). Use ``wrap_os_environ_io()`` to monkey-patch these wrappers into the ``os`` module: .. code-block:: python import eight eight.wrap_os_environ_io() On Python 3, the call is a no-op. Selecting from the buffet ------------------------- You can see what ``from eight import *`` will do by running `IPython `_ and typing ``import eight``, then ``eight.``. Here is a full list of what's available: * ``ascii`` * ``bytes`` * ``chr`` * ``filter`` * ``hex`` * ``input`` * ``int`` * ``map`` * ``oct`` * ``open`` * ``range`` * ``round`` * ``str`` * ``super`` * ``zip`` You can import these symbols by listing them explicitly. If for any reason you see an issue with importing them all (which is recommended), you can of course import a subset. In addition to names imported by ``from eight import *``, the following modules are available and should be imported by name using ``from eight import `` when needed: * ``queue`` (old name: ``Queue``) * ``builtins`` (old name: ``__builtin__``) * ``copyreg`` (old name: ``copy_reg``) * ``configparser`` (old name: ``ConfigParser``) * ``reprlib`` (old name: ``repr``) * ``winreg`` (old name: ``_winreg``) * ``_thread`` (old name: ``thread``) * ``_dummy_thread`` (old name: ``dummy_thread``) The following modules have attributes which resided elsewhere in Python 2: TODO Acknowledgments --------------- `Python-future `_ for doing a bunch of heavy lifting on backports of Python 3 features. Links ----- * `Project home page (GitHub) `_ * `Documentation (Read the Docs) `_ * `Package distribution (PyPI) `_ Bugs ~~~~ Please report bugs, issues, feature requests, etc. on `GitHub `_. License ------- Licensed under the terms of the `Apache License, Version 2.0 `_. .. image:: https://img.shields.io/travis/kislyuk/eight.svg :target: https://travis-ci.org/kislyuk/eight .. image:: https://codecov.io/github/kislyuk/eight/coverage.svg?branch=master :target: https://codecov.io/github/kislyuk/eight?branch=master .. image:: https://img.shields.io/pypi/v/eight.svg :target: https://pypi.python.org/pypi/eight .. image:: https://img.shields.io/pypi/l/eight.svg :target: https://pypi.python.org/pypi/eight .. image:: https://readthedocs.org/projects/eight/badge/?version=latest :target: https://eight.readthedocs.io/