diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 00000000..f8a20eda --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,8 @@ +# Contributing + +## Build documentation locally + +Using tox: +```shell +$ tox -e docs +``` diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 00000000..e4f0e0b3 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,13 @@ +# Security Policy + +## Supported Versions + +Security updates are applied only to the latest release. + +## Reporting a Vulnerability + +If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released. + +Please disclose it at [security advisory](https://github.com/PythonCharmers/python-future/security/advisories/new). + +This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..bcefff65 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,46 @@ +name: CI + +on: + pull_request: + push: + +concurrency: + group: ${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + test: + strategy: + fail-fast: false + matrix: + versions: + # - python: "2.6" + - python: "2.7" + - python: "3.3" + - python: "3.4" + - python: "3.5" + - python: "3.6" + - python: "3.7" + - python: "3.8" + - python: "3.9" + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - if: ${{ matrix.versions.python != '2.6' }} + run: | + docker build \ + . \ + --build-arg PYTHON_VERSION=${{ matrix.versions.python }} \ + -t jmadler/python-future-builder:${{ matrix.versions.python }} + - if: ${{ matrix.versions.python == '2.6' }} + run: | + docker build \ + . \ + -f 2.6.Dockerfile \ + -t jmadler/python-future-builder:${{ matrix.versions.python }} + - run: | + docker run \ + -e PYTHON_VERSION=${{ matrix.versions.python }} \ + jmadler/python-future-builder:${{ matrix.versions.python }} \ + /root/python-future/test.sh diff --git a/.gitignore b/.gitignore index 52146838..1b8eaeb5 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,12 @@ develop-eggs .installed.cfg lib lib64 +MANIFEST +MANIFEST.in + +# Backup files +*.bak +*.backup # Installer logs pip-log.txt @@ -38,3 +44,8 @@ nosetests.xml .project .pydevproject +# PyCharm / IntelliJ +.idea + +# Generated test file +mytempfile.py diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml new file mode 100644 index 00000000..dd8d0d65 --- /dev/null +++ b/.pre-commit-hooks.yaml @@ -0,0 +1,15 @@ +- id: futurize + name: futurize + description: Futurize your Py2 code to ensure it is runnable on Py3. + language: python + types: [python] + entry: futurize -w -n --no-diffs + args: [--stage1] + +- id: pasteurize + name: pasteurize + description: Pasteurize your Py3 code to ensure it is runnable on Py2. + language: python + language_version: python3 + types: [python] + entry: pasteurize -w -n --no-diffs diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 7b0fa4ce..00000000 --- a/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: python -python: - - "3.3" - - "2.7" - - "2.6" -# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors -# These packages only exist on Ubuntu 13.04 and newer: -# before_install: -# - sudo apt-get install -qq libpython2.7-testsuite libpython3.3-testsuite -# No dependencies currently unless using Python 2.6. -install: - - if [[ $TRAVIS_PYTHON_VERSION == 2.6* ]]; then pip install -r requirements_py26.txt --use-mirrors; fi -# command to run tests, e.g. python setup.py test -script: python setup.py test diff --git a/2.6.Dockerfile b/2.6.Dockerfile new file mode 100644 index 00000000..efaf3809 --- /dev/null +++ b/2.6.Dockerfile @@ -0,0 +1,26 @@ +FROM mrupgrade/deadsnakes:2.6 + +RUN mkdir -p ~/.pip/ && echo '[global] \n\ +trusted-host = pypi.python.org\n\ + pypi.org\n\ + files.pythonhosted.org\n\ +' >> ~/.pip/pip.conf + +RUN apt-get update && \ + apt-get install -y curl + +RUN mkdir -p /root/pip && \ + cd /root/pip && \ + curl -O https://files.pythonhosted.org/packages/8a/e9/8468cd68b582b06ef554be0b96b59f59779627131aad48f8a5bce4b13450/wheel-0.29.0-py2.py3-none-any.whl && \ + curl -O https://files.pythonhosted.org/packages/31/77/3781f65cafe55480b56914def99022a5d2965a4bb269655c89ef2f1de3cd/importlib-1.0.4.zip && \ + curl -O https://files.pythonhosted.org/packages/ef/41/d8a61f1b2ba308e96b36106e95024977e30129355fd12087f23e4b9852a1/pytest-3.2.5-py2.py3-none-any.whl && \ + curl -O https://files.pythonhosted.org/packages/f2/94/3af39d34be01a24a6e65433d19e107099374224905f1e0cc6bbe1fd22a2f/argparse-1.4.0-py2.py3-none-any.whl && \ + curl -O https://files.pythonhosted.org/packages/72/20/7f0f433060a962200b7272b8c12ba90ef5b903e218174301d0abfd523813/unittest2-1.1.0-py2.py3-none-any.whl && \ + curl -O https://files.pythonhosted.org/packages/53/67/9620edf7803ab867b175e4fd23c7b8bd8eba11cb761514dcd2e726ef07da/py-1.4.34-py2.py3-none-any.whl && \ + curl -O https://files.pythonhosted.org/packages/53/25/ef88e8e45db141faa9598fbf7ad0062df8f50f881a36ed6a0073e1572126/ordereddict-1.1.tar.gz && \ + curl -O https://files.pythonhosted.org/packages/17/0a/6ac05a3723017a967193456a2efa0aa9ac4b51456891af1e2353bb9de21e/traceback2-1.4.0-py2.py3-none-any.whl && \ + curl -O https://files.pythonhosted.org/packages/65/26/32b8464df2a97e6dd1b656ed26b2c194606c16fe163c695a992b36c11cdf/six-1.13.0-py2.py3-none-any.whl && \ + curl -O https://files.pythonhosted.org/packages/c7/a3/c5da2a44c85bfbb6eebcfc1dde24933f8704441b98fdde6528f4831757a6/linecache2-1.0.0-py2.py3-none-any.whl + +WORKDIR /root/python-future +ADD . /root/python-future \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..c859757f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +ARG PYTHON_VERSION +FROM python:${PYTHON_VERSION}-slim + +ENV LC_ALL=C.UTF-8 + +WORKDIR /root/python-future +ADD . /root/python-future diff --git a/LICENSE.txt b/LICENSE.txt index 4d2ea1c8..275cafd3 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2013 Python Charmers Pty Ltd, Australia +Copyright (c) 2013-2024 Python Charmers, Australia Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/MANIFEST.in b/MANIFEST.in index d050d284..d0e9f3d1 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,9 +1,27 @@ -include README.rst -include futurize.py -include discover_tests.py -include LICENSE.txt -include ChangeLog.txt -include docs/*.py -include docs/*.txt -include docs/*.rst - +include *.sh +include *.txt +include *.rst +include *.py +include .travis.yml +include pytest.ini +recursive-include docs LICENSE +recursive-include docs README +recursive-include docs *.conf +recursive-include docs *.css_t +recursive-include docs *.html +recursive-include docs *.ico +recursive-include docs *.inc +recursive-include docs *.ipynb +recursive-include docs *.png +recursive-include docs *.py +recursive-include docs *.rst +recursive-include docs *.sh +recursive-include docs *.tiff +recursive-include docs *.txt +recursive-include docs Makefile +recursive-include src *.py +recursive-include src *.pem +recursive-include tests *.au +recursive-include tests *.gif +recursive-include tests *.py +recursive-include tests *.txt diff --git a/README.rst b/README.rst index 164e2de1..a3aceb7d 100644 --- a/README.rst +++ b/README.rst @@ -1,56 +1,91 @@ -future: an easier, safer, cleaner upgrade path to Python 3 -========================================================== +.. _overview: +Overview: Easy, clean, reliable Python 2/3 compatibility +======================================================== -Overview -======== +.. image:: https://github.com/PythonCharmers/python-future/actions/workflows/ci.yml/badge.svg?branch=master + :target: https://github.com/PythonCharmers/python-future/actions/workflows/ci.yml?query=branch%3Amaster -``future`` is the missing compatibility layer between Python 3 and Python -2. It allows you to maintain a single, clean Python 3.x-compatible -codebase with minimal cruft and run it easily on Python 2 without further -modification. +``python-future`` is the missing compatibility layer between Python 2 and +Python 3. It allows you to use a single, clean Python 3.x-compatible +codebase to support both Python 2 and Python 3 with minimal overhead. -``future`` comes with ``futurize``, a script that helps you to transition -to supporting both Python 2 and 3 in a single codebase, module by module. +It provides ``future`` and ``past`` packages with backports and forward +ports of features from Python 3 and 2. It also comes with ``futurize`` and +``pasteurize``, customized 2to3-based scripts that helps you to convert +either Py2 or Py3 code easily to support both Python 2 and 3 in a single +clean Py3-style codebase, module by module. +The ``python-future`` project has been downloaded over 1.7 billion times. + +.. _status + +Status +------ + +The ``python-future`` project was created in 2013 to attempt to save Python from +the schism of version incompatibility that was threatening to tear apart the +language (as Perl 6 contributed to the death of Perl). + +That time is now past. Thanks to a huge porting effort across the Python +community, Python 3 eventually thrived. Python 2 reached its end of life in +2020 and the ``python-future`` package should no longer be necessary. Use it to +help with porting legacy code to Python 3 but don't depend on it for new code. + +.. _features: Features -------- -- provides backports and remappings for 15 builtins with different - semantics on Py3 versus Py2 -- provides backports and remappings from the Py3 standard library -- 300+ unit tests -- ``futurize`` script based on ``2to3``, ``3to2`` and parts of - ``python-modernize`` for automatic conversion from either Py2 or Py3 to a - clean single-source codebase compatible with Python 2.6+ and Python 3.3+. -- a consistent set of utility functions and decorators selected from - Py2/3 compatibility interfaces from projects like ``six``, ``IPython``, - ``Jinja2``, ``Django``, and ``Pandas``. +- ``future.builtins`` package (also available as ``builtins`` on Py2) provides + backports and remappings for 20 builtins with different semantics on Py3 + versus Py2 + +- support for directly importing 30 standard library modules under + their Python 3 names on Py2 + +- support for importing the other 14 refactored standard library modules + under their Py3 names relatively cleanly via + ``future.standard_library`` and ``future.moves`` + +- ``past.builtins`` package provides forward-ports of 19 Python 2 types and + builtin functions. These can aid with per-module code migrations. + +- ``past.translation`` package supports transparent translation of Python 2 + modules to Python 3 upon import. [This feature is currently in alpha.] + +- 1000+ unit tests, including many from the Py3.3 source tree. + +- ``futurize`` and ``pasteurize`` scripts based on ``2to3`` and parts of + ``3to2`` and ``python-modernize``, for automatic conversion from either Py2 + or Py3 to a clean single-source codebase compatible with Python 2.6+ and + Python 3.3+. +- a curated set of utility functions and decorators in ``future.utils`` and + ``past.utils`` selected from Py2/3 compatibility interfaces from projects + like ``six``, ``IPython``, ``Jinja2``, ``Django``, and ``Pandas``. + +- support for the ``surrogateescape`` error handler when encoding and + decoding the backported ``str`` and ``bytes`` objects. [This feature is + currently in alpha.] + +- support for pre-commit hooks + +.. _code-examples: Code examples ------------- -``future`` is designed to be imported at the top of each Python module -together with Python's built-in ``__future__`` module like this:: +Replacements for Py2's built-in functions and types are designed to be imported +at the top of each Python module together with Python's built-in ``__future__`` +statements. For example, this code behaves identically on Python 2.6/2.7 after +these imports as it does on Python 3.3+: - from __future__ import (absolute_import, division, - print_function, unicode_literals) - from future import standard_library - from future.builtins import * - -followed by standard Python 3 code. The imports have no effect on Python -3 but allow the code to run mostly unchanged on Python 3 and Python 2.6/2.7. - -For example, this code behaves the same way on Python 2.6/2.7 after these -imports as it normally does on Python 3:: - - # Support for renamed standard library modules via import hooks - from http.client import HttpConnection - from itertools import filterfalse - import html.parser - import queue +.. code-block:: python + + from __future__ import absolute_import, division, print_function + from builtins import (bytes, str, open, super, range, + zip, round, input, int, pow, object) # Backported Py3 bytes object b = bytes(b'ABCD') @@ -65,15 +100,15 @@ imports as it normally does on Python 3:: assert s != bytes(b'ABCD') assert isinstance(s.encode('utf-8'), bytes) assert isinstance(b.decode('utf-8'), str) - assert repr(s) == 'ABCD' # consistent repr with Py3 (no u prefix) + assert repr(s) == "'ABCD'" # consistent repr with Py3 (no u prefix) # These raise TypeErrors: # bytes(b'B') in s # s.find(bytes(b'A')) # Extra arguments for the open() function f = open('japanese.txt', encoding='utf-8', errors='replace') - - # New simpler super() function: + + # New zero-argument super() function: class VerboseList(list): def append(self, item): print('Adding an item') @@ -82,52 +117,223 @@ imports as it normally does on Python 3:: # New iterable range object with slicing support for i in range(10**15)[:10]: pass - + # Other iterators: map, zip, filter my_iter = zip(range(3), ['a', 'b', 'c']) assert my_iter != list(my_iter) - + # The round() function behaves as it does in Python 3, using # "Banker's Rounding" to the nearest even last digit: assert round(0.1250, 2) == 0.12 - + # input() replaces Py2's raw_input() (with no eval()): name = input('What is your name? ') print('Hello ' + name) + # pow() supports fractional exponents of negative numbers like in Py3: + z = pow(-1, 0.5) + # Compatible output from isinstance() across Py2/3: assert isinstance(2**64, int) # long integers assert isinstance(u'blah', str) - assert isinstance('blah', str) # with unicode_literals in effect - assert isinstance(b'bytestring', bytes) + assert isinstance('blah', str) # only if unicode_literals is in effect + # Py3-style iterators written as new-style classes (subclasses of + # future.types.newobject) are automatically backward compatible with Py2: + class Upper(object): + def __init__(self, iterable): + self._iter = iter(iterable) + def __next__(self): # note the Py3 interface + return next(self._iter).upper() + def __iter__(self): + return self + assert list(Upper('hello')) == list('HELLO') -Documentation -------------- -See http://python-future.org +There is also support for renamed standard library modules. The recommended +interface works like this: + +.. code-block:: python + + # Many Py3 module names are supported directly on both Py2.x and 3.x: + from http.client import HttpConnection + import html.parser + import queue + import xmlrpc.client + + # Refactored modules with clashing names on Py2 and Py3 are supported + # as follows: + from future import standard_library + standard_library.install_aliases() + + # Then, for example: + from itertools import filterfalse, zip_longest + from urllib.request import urlopen + from collections import ChainMap + from collections import UserDict, UserList, UserString + from subprocess import getoutput, getstatusoutput + from collections import Counter, OrderedDict # backported to Py2.6 + + +Automatic conversion to Py2/3-compatible code +--------------------------------------------- + +``python-future`` comes with two scripts called ``futurize`` and +``pasteurize`` to aid in making Python 2 code or Python 3 code compatible with +both platforms (Py2/3). It is based on 2to3 and uses fixers from ``lib2to3``, +``lib3to2``, and ``python-modernize``, as well as custom fixers. + +``futurize`` passes Python 2 code through all the appropriate fixers to turn it +into valid Python 3 code, and then adds ``__future__`` and ``future`` package +imports so that it also runs under Python 2. + +For conversions from Python 3 code to Py2/3, use the ``pasteurize`` script +instead. This converts Py3-only constructs (e.g. new metaclass syntax) to +Py2/3 compatible constructs and adds ``__future__`` and ``future`` imports to +the top of each module. + +In both cases, the result should be relatively clean Py3-style code that runs +mostly unchanged on both Python 2 and Python 3. + +Futurize: 2 to both +~~~~~~~~~~~~~~~~~~~ + +For example, running ``futurize -w mymodule.py`` turns this Python 2 code: + +.. code-block:: python + + import Queue + from urllib2 import urlopen + def greet(name): + print 'Hello', + print name -Credits -------- + print "What's your name?", + name = raw_input() + greet(name) -:Author: Ed Schofield -:Sponsor: Python Charmers Pty Ltd, Australia, and Python Charmers Pte - Ltd, Singapore. http://pythoncharmers.com -:Others: - The backported ``super()`` and ``range()`` functions are - derived from Ryan Kelly's ``magicsuper`` module and Dan - Crosta's ``xrange`` module. - - The ``futurize`` script uses ``lib2to3``, ``lib3to2``, and - parts of Armin Ronacher's ``python-modernize`` code. - - The ``python_2_unicode_compatible`` decorator is from - Django. The ``implements_iterator`` and ``with_metaclass`` - decorators are from Jinja2. - - Documentation is generated using ``sphinx`` using - ``sphinx_bootstrap_theme``. +into this code which runs on both Py2 and Py3: +.. code-block:: python + + from __future__ import print_function + from future import standard_library + standard_library.install_aliases() + from builtins import input + import queue + from urllib.request import urlopen + + def greet(name): + print('Hello', end=' ') + print(name) + + print("What's your name?", end=' ') + name = input() + greet(name) + +The first four lines have no effect under Python 3 and can be removed from +the codebase when Python 2 compatibility is no longer required. + +See :ref:`forwards-conversion` and :ref:`backwards-conversion` for more details. + + +Automatic translation +~~~~~~~~~~~~~~~~~~~~~ + +The ``past`` package can automatically translate some simple Python 2 +modules to Python 3 upon import. The goal is to support the "long tail" of +real-world Python 2 modules (e.g. on PyPI) that have not been ported yet. For +example, here is how to use a Python 2-only package called ``plotrique`` on +Python 3. First install it: + +.. code-block:: bash + + $ pip3 install plotrique==0.2.5-7 --no-compile # to ignore SyntaxErrors + +(or use ``pip`` if this points to your Py3 environment.) + +Then pass a whitelist of module name prefixes to the ``autotranslate()`` function. +Example: + +.. code-block:: bash + + $ python3 + + >>> from past.translation import autotranslate + >>> autotranslate(['plotrique']) + >>> import plotrique + +This transparently translates and runs the ``plotrique`` module and any +submodules in the ``plotrique`` package that ``plotrique`` imports. + +This is intended to help you migrate to Python 3 without the need for all +your code's dependencies to support Python 3 yet. It should be used as a +last resort; ideally Python 2-only dependencies should be ported +properly to a Python 2/3 compatible codebase using a tool like +``futurize`` and the changes should be pushed to the upstream project. + +Note: the auto-translation feature is still in alpha; it needs more testing and +development, and will likely never be perfect. + + +Pre-commit hooks +~~~~~~~~~~~~~~~~ + +`Pre-commit `_ is a framework for managing and maintaining +multi-language pre-commit hooks. + +In case you need to port your project from Python 2 to Python 3, you might consider +using such hook during the transition period. + +First: + +.. code-block:: bash + + $ pip install pre-commit + +and then in your project's directory: + +.. code-block:: bash + + $ pre-commit install + +Next, you need to add this entry to your ``.pre-commit-config.yaml`` + +.. code-block:: yaml + + - repo: https://github.com/PythonCharmers/python-future + rev: master + hooks: + - id: futurize + args: [--both-stages] + +The ``args`` part is optional, by default only stage1 is applied. Licensing --------- -Copyright 2013 Python Charmers Pty Ltd, Australia. -The software is distributed under an MIT licence. See LICENSE.txt. +:Author: Ed Schofield, Jordan M. Adler, et al + +:Copyright: 2013-2024 Python Charmers, Australia. + +:Sponsors: Python Charmers: https://pythoncharmers.com + + Pinterest https://opensource.pinterest.com + +:Licence: MIT. See ``LICENSE.txt`` or `here `_. + +:Other credits: See `here `_. + +Docs +---- +See the docs `here `_. + +Next steps +---------- + +If you are new to Python-Future, check out the `Quickstart Guide +`_. + +For an update on changes in the latest version, see the `What's New +`_ page. diff --git a/TESTING.txt b/TESTING.txt new file mode 100644 index 00000000..b2ad5c65 --- /dev/null +++ b/TESTING.txt @@ -0,0 +1,11 @@ +A docker image, python-future-builder, is used to do testing and building. The test suite can be run with: + + $ bash build.sh + +which tests the module under a number of different python versions, where available, or with: + + $ py.test + +To execute a single test: + + $ pytest -k test_chained_exceptions_stacktrace diff --git a/discover_tests.py b/discover_tests.py deleted file mode 100644 index 8734cca8..00000000 --- a/discover_tests.py +++ /dev/null @@ -1,51 +0,0 @@ -""" -Simple auto test discovery. - -From http://stackoverflow.com/a/17004409 -""" -import os -import sys -import unittest - -if not hasattr(unittest.defaultTestLoader, 'discover'): - import unittest2 as unittest - -def additional_tests(): - setup_file = sys.modules['__main__'].__file__ - setup_dir = os.path.abspath(os.path.dirname(setup_file)) - testsuite = unittest.defaultTestLoader.discover(setup_dir) - blacklist = [] - if '/home/travis' in __file__: - # Skip some tests that fail on travis-ci - blacklist.append('test_command') - return exclude_tests(testsuite, blacklist) - - -class SkipCase(unittest.TestCase): - def runTest(self): - raise unittest.SkipTest("Test fails spuriously on travis-ci") - - -def exclude_tests(suite, blacklist): - """ - Example: - - blacklist = [ - 'test_some_test_that_should_be_skipped', - 'test_another_test_that_should_be_skipped' - ] - """ - - new_suite = unittest.TestSuite() - - for test_group in suite._tests: - for test in test_group: - if not hasattr(test, '_tests'): - # e.g. ModuleImportFailure - continue - for subtest in test._tests: - method = subtest._testMethodName - if method in blacklist: - setattr(test, method, getattr(SkipCase(), 'runTest')) - new_suite.addTest(test) - return new_suite diff --git a/docs/3rd-party-py3k-compat-code/ipython_py3compat.py b/docs/3rd-party-py3k-compat-code/ipython_py3compat.py index f80a6963..c9fbb2c1 100755 --- a/docs/3rd-party-py3k-compat-code/ipython_py3compat.py +++ b/docs/3rd-party-py3k-compat-code/ipython_py3compat.py @@ -41,9 +41,9 @@ def wrapper(func_or_str): else: func = func_or_str doc = func.__doc__ - + doc = str_change_func(doc) - + if func: func.__doc__ = doc return func @@ -52,97 +52,97 @@ def wrapper(func_or_str): if sys.version_info[0] >= 3: PY3 = True - + input = input builtin_mod_name = "builtins" - + str_to_unicode = no_code unicode_to_str = no_code str_to_bytes = encode bytes_to_str = decode cast_bytes_py2 = no_code - + def isidentifier(s, dotted=False): if dotted: return all(isidentifier(a) for a in s.split(".")) return s.isidentifier() - + open = orig_open - + MethodType = types.MethodType - + def execfile(fname, glob, loc=None): loc = loc if (loc is not None) else glob exec compile(open(fname, 'rb').read(), fname, 'exec') in glob, loc - + # Refactor print statements in doctests. _print_statement_re = re.compile(r"\bprint (?P.*)$", re.MULTILINE) def _print_statement_sub(match): expr = match.groups('expr') return "print(%s)" % expr - + @_modify_str_or_docstring def doctest_refactor_print(doc): """Refactor 'print x' statements in a doctest to print(x) style. 2to3 unfortunately doesn't pick up on our doctests. - + Can accept a string or a function, so it can be used as a decorator.""" return _print_statement_re.sub(_print_statement_sub, doc) - + # Abstract u'abc' syntax: @_modify_str_or_docstring def u_format(s): """"{u}'abc'" --> "'abc'" (Python 3) - + Accepts a string or a function, so it can be used as a decorator.""" return s.format(u='') else: PY3 = False - + input = raw_input builtin_mod_name = "__builtin__" - + str_to_unicode = decode unicode_to_str = encode str_to_bytes = no_code bytes_to_str = no_code cast_bytes_py2 = cast_bytes - + import re _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$") def isidentifier(s, dotted=False): if dotted: return all(isidentifier(a) for a in s.split(".")) return bool(_name_re.match(s)) - + class open(object): """Wrapper providing key part of Python 3 open() interface.""" def __init__(self, fname, mode="r", encoding="utf-8"): self.f = orig_open(fname, mode) self.enc = encoding - + def write(self, s): return self.f.write(s.encode(self.enc)) - + def read(self, size=-1): return self.f.read(size).decode(self.enc) - + def close(self): return self.f.close() - + def __enter__(self): return self - + def __exit__(self, etype, value, traceback): self.f.close() - + def MethodType(func, instance): return types.MethodType(func, instance, type(instance)) - + # don't override system execfile on 2.x: execfile = execfile - + def doctest_refactor_print(func_or_str): return func_or_str @@ -151,7 +151,7 @@ def doctest_refactor_print(func_or_str): @_modify_str_or_docstring def u_format(s): """"{u}'abc'" --> "u'abc'" (Python 2) - + Accepts a string or a function, so it can be used as a decorator.""" return s.format(u='u') diff --git a/docs/3rd-party-py3k-compat-code/jinja2_compat.py b/docs/3rd-party-py3k-compat-code/jinja2_compat.py index 1326cbc6..0456faae 100644 --- a/docs/3rd-party-py3k-compat-code/jinja2_compat.py +++ b/docs/3rd-party-py3k-compat-code/jinja2_compat.py @@ -85,7 +85,7 @@ def encode_filename(filename): def with_metaclass(meta, *bases): # This requires a bit of explanation: the basic idea is to make a - # dummy metaclass for one level of class instanciation that replaces + # dummy metaclass for one level of class instantiation that replaces # itself with the actual metaclass. Because of internal type checks # we also need to make sure that we downgrade the custom metaclass # for one level to something closer to type (that's why __call__ and diff --git a/docs/3rd-party-py3k-compat-code/pandas_py3k.py b/docs/3rd-party-py3k-compat-code/pandas_py3k.py index 6070c0e9..2a8eb5ae 100755 --- a/docs/3rd-party-py3k-compat-code/pandas_py3k.py +++ b/docs/3rd-party-py3k-compat-code/pandas_py3k.py @@ -14,7 +14,7 @@ * Uses the original method if available, otherwise uses items, keys, values. * types: * text_type: unicode in Python 2, str in Python 3 - * binary_type: str in Python 2, bythes in Python 3 + * binary_type: str in Python 2, bytes in Python 3 * string_types: basestring in Python 2, str in Python 3 * bind_method: binds functions to classes diff --git a/docs/_static/python-future-icon-32.ico b/docs/_static/python-future-icon-32.ico new file mode 100644 index 00000000..e3f2cf7f Binary files /dev/null and b/docs/_static/python-future-icon-32.ico differ diff --git a/docs/_static/python-future-icon-white-32.ico b/docs/_static/python-future-icon-white-32.ico new file mode 100644 index 00000000..3fa3dab9 Binary files /dev/null and b/docs/_static/python-future-icon-white-32.ico differ diff --git a/docs/_static/python-future-logo-textless-transparent.png b/docs/_static/python-future-logo-textless-transparent.png new file mode 100644 index 00000000..95ba682d Binary files /dev/null and b/docs/_static/python-future-logo-textless-transparent.png differ diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html index 09cdb2d2..c979ab2d 100644 --- a/docs/_templates/layout.html +++ b/docs/_templates/layout.html @@ -1,21 +1,28 @@ {# Import the theme's layout. #} {% extends "!layout.html" %} -{# Add some extra stuff before and use existing with 'super()' call. #} -{% block footer %} +{% block extrahead %} {{ super() }} - +{% endblock %} - +{% block footer %} +{{ super() }} + {% endblock %} diff --git a/docs/_templates/navbar.html b/docs/_templates/navbar.html index 85e819d4..fc96b5ca 100644 --- a/docs/_templates/navbar.html +++ b/docs/_templates/navbar.html @@ -1,4 +1,4 @@ -Fork me on GitHub +Fork me on GitHub