Skip to content

Commit 6ef1ee2

Browse files
committed
Improve docs
1 parent b3ff0cb commit 6ef1ee2

3 files changed

Lines changed: 119 additions & 48 deletions

File tree

README.rst

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ yet been ported to Python 3.
1111

1212
It is designed to be used as follows::
1313

14-
from __future__ import (division, absolute_import,
14+
from __future__ import (absolute_import, division,
1515
print_function, unicode_literals)
1616
from future import standard_library
1717
from future.builtins import *
@@ -99,11 +99,11 @@ future::
9999

100100
Utilities
101101
---------
102-
``future`` also provides some useful functions and decorators in the
103-
to ease backward compatibility with Py2 in the ``future.utils`` module.
104-
These are a selection of the most useful functions from ``six`` and
105-
various home-grown Py2/3 compatibility modules from prominent Python
106-
projects (Jinja2, Pandas, Django).
102+
``future`` also provides some useful functions and decorators to ease backward
103+
compatibility with Py2 in the ``future.utils`` module. These are a selection
104+
of the most useful functions from ``six`` and various home-grown Py2/3
105+
compatibility modules from various Python projects, such as Jinja2, Pandas,
106+
IPython, and Django.
107107

108108
Examples::
109109

@@ -124,8 +124,8 @@ Examples::
124124

125125

126126
# Iterators on Py3 require a __next__() method, whereas on Py2 this
127-
is called next(). This decorator allows Py3-style iterators to work
128-
identically on Py2:
127+
# is called next(). This decorator allows Py3-style iterators to work
128+
# identically on Py2:
129129

130130
@implements_iterator
131131
class Upper(object):
@@ -167,8 +167,8 @@ See the docstrings for each of these modules for more info::
167167
Automatic conversion
168168
====================
169169

170-
There is a script included called ``futurize`` to aid in making either
171-
Python 2 code or Python 3 code compatible with both platforms using the
170+
There is an experimental script included called ``futurize`` to aid in making
171+
either Python 2 code or Python 3 code compatible with both platforms using the
172172
``future`` module. It is based on 2to3 and uses fixers from ``lib2to3``,
173173
``lib3to2``, and ``python-modernize``.
174174

@@ -317,13 +317,16 @@ FAQ
317317
easier upgrade path to Python 3.
318318

319319

320-
:Q: Are there any example of Python 2 packages ported to Python 3 using ``future`` and ``futurize``?
320+
:Q: Are there any example of Python 2 packages ported to Python 3 using
321+
``future`` and ``futurize``?
321322

322323
:A: Yes, an example is the port of ``xlwt``, available here::
323-
``xlwt`` and ``iso8601``, available here::
324324

325325
- https://github.com/python-excel/xlwt/pull/32
326326

327+
The code also contains backports for several Py3 standard library modules
328+
under ``future/standard_library/backports/``.
329+
327330

328331
Other compatibility tools
329332
-------------------------
@@ -336,9 +339,9 @@ Other compatibility tools
336339
one-way porting efforts, for projects that can leave behind Python 2
337340
support.
338341

339-
The example at the top of the 2to3 docs
340-
(http://docs.python.org/2/library/2to3.html) illustrates this point.
341-
After transformation, ``example.py`` looks like this::
342+
The example at the top of the ``2to3`` docs
343+
(http://docs.python.org/2/library/2to3.html) demonstrates this.
344+
After transformation by ``2to3``, ``example.py`` looks like this::
342345

343346
def greet(name):
344347
print("Hello, {0}!".format(name))
@@ -349,7 +352,8 @@ Other compatibility tools
349352
This is Python 3 code that, although syntactically valid on Python 2,
350353
is semantically incorrect. On Python 2, it raises an exception for
351354
most inputs; worse, it allows arbitrary code execution by the user
352-
for specially crafted inputs.
355+
for specially crafted inputs because of the ``eval()`` executed by Python
356+
2's ``input()`` function.
353357

354358
This is not an isolated example; almost every output of ``2to3`` will
355359
need modification to provide backward compatibility with Python 2.
@@ -365,10 +369,10 @@ Other compatibility tools
365369
convert to Python 3 in the setup script?
366370

367371
:A: Yes, this is possible, and was originally the approach recommended by
368-
Python's core developers, but has big drawbacks.
372+
Python's core developers, but has some large drawbacks.
369373

370374
First, your actual working codebase will be stuck with only Python
371-
2's features (and its warts) for as long as you need to retain Python
375+
2's features, and its warts, for as long as you need to retain Python
372376
2 compatibility. This may be at least 5 years for many projects.
373377

374378
This approach also carries the significant disadvantage that you
@@ -384,11 +388,10 @@ Other compatibility tools
384388

385389
They share the same goal of making it possible to write a
386390
single-source codebase that works on both Python 2 and Python 3
387-
without modification. ``future`` makes it easier to write standard
388-
Python 3 code that is a cleaner interface that runs on both
389-
platforms, and ``future`` provides a more complete set of support for
390-
Python 3's features (and restores a few Py2 features removed from
391-
Python 3).
391+
without modification. ``future`` provides a more complete set of support
392+
for Python 3's features and a cleaner interface (supporting standard Py3
393+
code). ``future`` also restores a few Py2 features that were removed from
394+
Python 3.
392395

393396
Codebases that use ``six`` directly tend to be mixtures of
394397
Python 2 code, Python 3 code, and ``six``-specific wrapper
@@ -472,9 +475,9 @@ Other compatibility tools
472475
unlearn various habits soon. We searched for ways to avoid polluting the
473476
world with more deprecated code, but didn't find a good way.
474477

475-
Also, in attempting to port ``scikit-learn`` to Python 3, I (Ed) was
476-
dissatisfied with how much code cruft was necessary to introduce to
477-
support Python 2 and 3 from a single codebase (the preferred porting
478+
Also, in attempting to port packages such as ``scikit-learn`` to Python 3,
479+
I (Ed) was dissatisfied with how much code cruft was necessary to introduce
480+
to support Python 2 and 3 from a single codebase (the preferred porting
478481
option).
479482

480483
Since backward-compatibility with Python 2 may be necessary

future/__init__.py

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,17 @@
1212
1313
It is designed to be used as follows::
1414
15-
from __future__ import (division, absolute_import, print_function,
16-
unicode_literals)
15+
from __future__ import (absolute_import, division,
16+
print_function, unicode_literals)
1717
from future import standard_library
1818
from future.builtins import *
1919
2020
followed by clean Python 3 code (with a few restrictions) that can run
2121
unchanged on Python 2.7.
2222
23-
On Python 3, ``from future import standard_library`` has no effect. On
24-
Python 2, it module installs import hooks to allow renamed and moved
25-
standard library modules to be imported from their new Py3 locations.
26-
27-
Likewise, on Python 3, the ``from future.builtins import *`` line has no
28-
effect (i.e. zero namespace pollution.) On Python 2 it shadows builtins
29-
to provide their Python 3 semantics. (See below for the explicit import
30-
form.)
31-
3223
After the imports, this code runs identically on Python 3 and 2::
3324
34-
# Support for renamed standard library modules (see below)
25+
# Support for renamed standard library modules via import hooks
3526
from http.client import HttpConnection
3627
from itertools import filterfalse
3728
from test import support
@@ -61,16 +52,28 @@ def append(self, item):
6152
# Rounding" to the nearest even last digit:
6253
assert round(0.1250, 2) == 0.12
6354
64-
# input() is now safe (no eval()):
55+
# input() replaces Py2's raw_input() (with no eval()):
6556
name = input('What is your name? ')
6657
print('Hello ' + name)
6758
6859
60+
On Python 3, the import lines have zero effect (and zero namespace
61+
pollution).
62+
63+
On Python 2, ``from future import standard_library`` installs
64+
import hooks to allow renamed and moved standard library modules to be
65+
imported from their new Py3 locations.
66+
67+
On Python 2, the ``from future.builtins import *`` line shadows builtins
68+
to provide their Python 3 semantics. (See below for the explicit import
69+
form.)
70+
71+
6972
Standard library reorganization
7073
-------------------------------
7174
``future`` supports the standard library reorganization (PEP 3108)
7275
via import hooks, allowing almost all moved standard library modules to be
73-
accessed under their Python 3 names and locations::
76+
accessed under their Python 3 names and locations in Python 2::
7477
7578
from future import standard_library
7679
@@ -95,6 +98,51 @@ def append(self, item):
9598
import urllib, urllib.parse, urllib.request, urllib.error
9699
97100
101+
Utilities
102+
---------
103+
``future`` also provides some useful functions and decorators to ease backward
104+
compatibility with Py2 in the ``future.utils`` module. These are a selection
105+
of the most useful functions from ``six`` and various home-grown Py2/3
106+
compatibility modules from various Python projects, such as Jinja2, Pandas,
107+
IPython, and Django.
108+
109+
Examples::
110+
111+
# Functions like print() expect __str__ on Py2 to return a byte
112+
string. This decorator maps the __str__ to __unicode__ on Py2 and
113+
defines __str__ to encode it as utf-8:
114+
115+
from future.utils import python_2_unicode_compatible
116+
117+
@python_2_unicode_compatible
118+
class MyClass(object):
119+
def __str__(self):
120+
return u'Unicode string: \u5b54\u5b50'
121+
a = MyClass()
122+
123+
# These lines then both print the Chinese characters for Confucius:
124+
print(a)
125+
126+
127+
# Iterators on Py3 require a __next__() method, whereas on Py2 this
128+
# is called next(). This decorator allows Py3-style iterators to work
129+
# identically on Py2:
130+
131+
@implements_iterator
132+
class Upper(object):
133+
def __init__(self, iterable):
134+
self._iter = iter(iterable)
135+
def __next__(self): # note the Py3 interface
136+
return next(self._iter).upper()
137+
def __iter__(self):
138+
return self
139+
140+
print(list(Upper('hello')))
141+
# prints ['H', 'E', 'L', 'L', 'O']
142+
143+
On Python 3 these decorators are no-ops.
144+
145+
98146
Explicit imports
99147
----------------
100148
If you prefer explicit imports, the explicit equivalent of the ``from
@@ -119,9 +167,9 @@ def append(self, item):
119167
120168
Automatic conversion
121169
====================
122-
A script called ``futurize`` is included to aid in making either Python 2
123-
code or Python 3 code compatible with both platforms using the ``future``
124-
module. See
170+
An experimental script called ``futurize`` is included to aid in making
171+
either Python 2 code or Python 3 code compatible with both platforms
172+
using the ``future`` module. See
125173
https://github.com/edschofield/python-future#automatic-conversion.
126174
127175

future/utils/frompy2.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
"""
2-
A resurrection of old from Python 2 for both platforms.
2+
A resurrection of some old functions from Python 2. These should be used
3+
sparingly, to help with porting efforts, since code using them is no
4+
longer standard Python 3 code.
5+
6+
We provide these builtin functions which have no equivalent on Py3:
7+
8+
- cmp()
9+
- execfile()
10+
11+
These aliases are also provided:
12+
13+
- raw_input() <- input()
14+
- unicode() <- str()
15+
- unichr() <- chr()
16+
17+
For reference, the following Py2 builtin functions are available from
18+
these standard locations on both Py2.6+ and Py3:
19+
20+
- reduce() <- functools.reduce()
21+
- reload() <- imp.reload()
322
423
"""
524

@@ -11,10 +30,14 @@
1130
if PY3:
1231
# Bring back the cmp function
1332
cmp = lambda a, b: (a > b) - (a < b)
33+
raw_input = input
1434
unicode = str
35+
unichr = chr
1536
else:
1637
cmp = __builtin__.cmp
38+
raw_input = __builtin__.raw_input
1739
unicode = __builtin__.unicode
40+
unichr = __builtin__.unichr
1841

1942

2043
def execfile(filename, myglobals=None, mylocals=None):
@@ -43,8 +66,5 @@ def execfile(filename, myglobals=None, mylocals=None):
4366
__builtin__.execfile(filename, myglobals=myglobals,
4467
mylocals=mylocals)
4568

46-
if PY3:
47-
__all__ = []
48-
else:
49-
__all__ = ['cmp', 'unicode', 'execfile']
5069

70+
__all__ = ['cmp', 'raw_input', 'unichr', 'unicode', 'execfile']

0 commit comments

Comments
 (0)