Skip to content

Commit 063baa1

Browse files
committed
Update What's New to mention fix for issue #47: "Contradictory terminology about native types"
1 parent 2959d2c commit 063baa1

File tree

2 files changed

+261
-0
lines changed

2 files changed

+261
-0
lines changed

docs/futurize.rst

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
.. _forwards-conversion:
2+
3+
Futurize: 2 to both
4+
--------------------
5+
6+
For example, running ``futurize`` turns this Python 2 code::
7+
8+
import ConfigParser # Py2 module name
9+
10+
class Upper(object):
11+
def __init__(self, iterable):
12+
self._iter = iter(iterable)
13+
def next(self): # Py2-style iterator interface
14+
return next(self._iter).upper()
15+
def __iter__(self):
16+
return self
17+
18+
itr = Upper('hello')
19+
print next(itr),
20+
for letter in itr:
21+
print letter, # Py2-style print statement
22+
23+
into this code which runs on both Py2 and Py3::
24+
25+
from __future__ import print_function
26+
from future import standard_library
27+
standard_library.install_hooks()
28+
from future.builtins import next
29+
from future.builtins import object
30+
import configparser # Py3-style import
31+
32+
class Upper(object):
33+
def __init__(self, iterable):
34+
self._iter = iter(iterable)
35+
def __next__(self): # Py3-style iterator interface
36+
return next(self._iter).upper()
37+
def __iter__(self):
38+
return self
39+
40+
itr = Upper('hello')
41+
print(next(itr), end=' ') # Py3-style print function
42+
for letter in itr:
43+
print(letter, end=' ')
44+
45+
46+
To write out all the changes to your Python files that ``futurize`` suggests,
47+
use the ``-w`` flag.
48+
49+
For complex projects, it is probably best to divide the porting into two stages.
50+
Stage 1 is for "safe" changes that modernize the code but do not break Python
51+
2.6 compatibility or introduce a depdendency on the ``future`` package. Stage 2
52+
is to complete the process.
53+
54+
55+
.. _forwards-conversion-stage1:
56+
57+
Stage 1: "safe" fixes
58+
~~~~~~~~~~~~~~~~~~~~~
59+
60+
Run the first stage of the conversion process with::
61+
62+
futurize --stage1 mypackage/*.py
63+
64+
or, if you are using zsh, recursively::
65+
66+
futurize --stage1 mypackage/**/*.py
67+
68+
This applies fixes that modernize Python 2 code without changing the effect of
69+
the code. With luck, this will not introduce any bugs into the code, or will at
70+
least be trivial to fix. The changes are those that bring the Python code
71+
up-to-date without breaking Py2 compatibility. The resulting code will be
72+
modern Python 2.6-compatible code plus ``__future__`` imports from the
73+
following set::
74+
75+
from __future__ import absolute_import
76+
from __future__ import division
77+
from __future__ import print_function
78+
79+
Only those ``__future__`` imports deemed necessary will be added unless
80+
the ``--all-imports`` command-line option is passed to ``futurize``, in
81+
which case they are all added.
82+
83+
The ``from __future__ import unicode_literals`` declaration is not added
84+
unless the ``--unicode-literals`` flag is passed to ``futurize``.
85+
86+
The changes include::
87+
88+
- except MyException, e:
89+
+ except MyException as e:
90+
91+
- print >>stderr, "Blah"
92+
+ from __future__ import print_function
93+
+ print("Blah", stderr)
94+
95+
- class MyClass:
96+
+ class MyClass(object):
97+
98+
- def next(self):
99+
+ def __next__(self):
100+
101+
- if d.has_key(key):
102+
+ if key in d:
103+
104+
Implicit relative imports fixed, e.g.::
105+
106+
- import mymodule
107+
+ from __future__ import absolute_import
108+
+ from . import mymodule
109+
110+
.. and all unprefixed string literals '...' gain a b prefix to be b'...'.
111+
112+
.. (This last step can be prevented using --no-bytes-literals if you already have b'...' markup in your code, whose meaning would otherwise be lost.)
113+
114+
Stage 1 does not add any imports from the ``future`` package. The output of
115+
stage 1 will probably not (yet) run on Python 3.
116+
117+
The goal for this stage is to create most of the ``diff`` for the entire
118+
porting process, but without introducing any bugs. It should be uncontroversial
119+
and safe to apply to every Python 2 package. The subsequent patches introducing
120+
Python 3 compatibility should then be shorter and easier to review.
121+
122+
The complete set of fixers applied by ``futurize --stage1`` is::
123+
124+
lib2to3.fixes.fix_apply
125+
lib2to3.fixes.fix_except
126+
lib2to3.fixes.fix_exitfunc
127+
lib2to3.fixes.fix_funcattrs
128+
lib2to3.fixes.fix_has_key
129+
lib2to3.fixes.fix_idioms
130+
lib2to3.fixes.fix_intern
131+
lib2to3.fixes.fix_isinstance
132+
lib2to3.fixes.fix_methodattrs
133+
lib2to3.fixes.fix_ne
134+
lib2to3.fixes.fix_next
135+
lib2to3.fixes.fix_numliterals
136+
lib2to3.fixes.fix_paren
137+
lib2to3.fixes.fix_reduce
138+
lib2to3.fixes.fix_renames
139+
lib2to3.fixes.fix_repr
140+
lib2to3.fixes.fix_standarderror
141+
lib2to3.fixes.fix_sys_exc
142+
lib2to3.fixes.fix_throw
143+
lib2to3.fixes.fix_tuple_params
144+
lib2to3.fixes.fix_types
145+
lib2to3.fixes.fix_ws_comma
146+
lib2to3.fixes.fix_xreadlines
147+
libfuturize.fixes.fix_absolute_import
148+
libfuturize.fixes.fix_division
149+
libfuturize.fixes.fix_print_with_import
150+
libfuturize.fixes.fix_raise
151+
libfuturize.fixes.fix_order___future__imports
152+
153+
154+
.. _forwards-conversion-stage2:
155+
156+
Stage 2: Py3-style code with ``future`` wrappers for Py2
157+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
158+
159+
Run stage 2 of the conversion process with::
160+
161+
futurize —-stage2 myfolder/*.py
162+
163+
This stage adds a dependency on the ``future`` package. The goal for stage 2 is
164+
to make further mostly safe changes to the Python 2 code to use Python 3-style
165+
code that then still runs on Python 2 with the help of the appropriate builtins
166+
and utilities in ``future``.
167+
168+
For example::
169+
170+
name = raw_input('What is your name?\n')
171+
172+
for k, v in d.iteritems():
173+
assert isinstance(v, basestring)
174+
175+
class MyClass(object):
176+
def __unicode__(self):
177+
return u'My object'
178+
def __str__(self):
179+
return unicode(self).encode('utf-8')
180+
181+
would be converted by Stage 2 to this code::
182+
183+
from future.builtins import input
184+
from future.builtins import str
185+
from future.utils import iteritems, python_2_unicode_compatible
186+
187+
name = input('What is your name?\n')
188+
189+
for k, v in iteritems(d):
190+
assert isinstance(v, (str, bytes))
191+
192+
@python_2_unicode_compatible
193+
class MyClass(object):
194+
def __str__(self):
195+
return u'My object'
196+
197+
Stage 2 also renames standard-library imports to their Py3 names and adds these
198+
two lines::
199+
200+
from future import standard_library
201+
standard_library.install_hooks()
202+
203+
For example::
204+
205+
import ConfigParser
206+
207+
becomes::
208+
209+
from future import standard_library
210+
standard_library.install_hooks()
211+
import configparser
212+
213+
214+
.. Ideally the output of this stage should not be a ``SyntaxError`` on either
215+
.. Python 3 or Python 2.
216+
217+
.. _forwards-conversion-text:
218+
219+
Separating text from bytes
220+
~~~~~~~~~~~~~~~~~~~~~~~~~~
221+
222+
After applying stage 2, the recommended step is to decide which of your Python
223+
2 strings represent text and which represent binary data and to prefix all
224+
string literals with either ``b`` or ``u`` accordingly. Furthermore, to ensure
225+
that these types behave similarly on Python 2 as on Python 3, also wrap
226+
byte-strings or text in the ``bytes`` and ``str`` types from ``future``. For
227+
example::
228+
229+
from future.builtins import bytes, str
230+
b = bytes(b'\x00ABCD')
231+
s = str(u'This is normal text')
232+
233+
Any unadorned string literals will then represent native platform strings
234+
(byte-strings on Py2, unicode strings on Py3).
235+
236+
An alternative is to pass the ``--unicode_literals`` flag::
237+
238+
$ futurize --unicode_literals mypython2script.py
239+
240+
After running this, all string literals that were not explicitly marked up as
241+
``b''`` will mean text (Python 3 ``str`` or Python 2 ``unicode``).
242+
243+
244+
245+
.. _forwards-conversion-stage3:
246+
247+
Post-conversion
248+
~~~~~~~~~~~~~~~
249+
250+
After running ``futurize``, we recommend first running your tests on Python 3 and making further code changes until they pass on Python 3.
251+
252+
The next step would be manually tweaking the code to re-enable Python 2
253+
compatibility with the help of the ``future`` package. For example, you can add
254+
the ``@python_2_unicode_compatible`` decorator to any classes that define custom
255+
``__str__`` methods. See :ref:`what-else` for more info.
256+
257+

docs/whatsnew.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@ Many small improvements and fixes have been made across the project. Some highli
239239

240240
- Improved compatibility with py2exe (`issue #31 <https://github.com/PythonCharmers/python-future/issues/31>`_).
241241

242+
- The ``future.utils.bytes_to_native_str`` function now returns a ``newbytes``
243+
object on Py2. (`Issue #47
244+
<https://github.com/PythonCharmers/python-future/issues/47>`_).
245+
242246

243247
.. whats-new-0.11.5:
244248

0 commit comments

Comments
 (0)