Skip to content

IPEP 4: Python 3 Compatibility #2440

@bfroehle

Description

@bfroehle

See IPEP 4: Python 3 Compatibility.

[Meta] Python 2 and 3 compatibility without 2to3... "2and3"

We've discussed using a Python 2 & 3 compatible syntax in our source in the past, and have included changes from several of the 2to3 fixers. C.f.,

With the release of Python 3.3 in the next few days (which again allows unicode literals u"..."), porting our code to a jointly compatible syntax should be more feasible.

Now there are some headaches, but they all can be worked around. I've been playing with this on a branch bfroehle/py3k but it's an ugly mess at the moment.

If we are going to seriously consider this undertaking, I think we should first agree upon the parameters and break the process up into a lot of smaller chunks. In addition, since these changes will possibly conflict with existing pull requests, we should probably also decide on appropriate timing.

I expect this proposal to be rather controversial, so let me attempt to outline exactly what would be required... it's probably more than you expect.

The Bite-Sized Pieces

  • six: Take much of the six module and add it to IPython.utils.py3compat. Or decide to abandon part of py3compat and just ship a copy of six.
  • exec: In Python 3 exec becomes a function. This necessitates replacing each call exec code in globals, locals with exec_(code, globals, locals) where exec_ is a wrapper defined in six.
  • execfile: Add a Python3 compatible definition of execfile in ipython.py
  • long: Replace long literals (0L) with explicit calls to long (long(0)) or decide if the literal was actually necessary in the first place.
  • dict: Apply the 2to3 dict fixer (iteritems -> items, etc) with a lot of manual oversight.
  • print: Apply the 2to3 print fixer. (This is already partially applied).
  • import: Apply the 2to3 import fixer to differentiate between absolute and relative imports.
  • funcattrs: Workaround changes to attribute names on function objects (f.func_code -> f.__code__), possibly by getattr(f, _func_code) where _func_code is defined in six or py3compat.
  • imports: The builtin module was renamed from __builtin__ to builtins. In addition many other modules were renamed (cPickle -> pickle, StringIO.StringIO -> io.StringIO, ConfigParser.ConfigParser -> configparser.ConfigParser, urllib2, etc). This means lots of try: import ...; except ImportError: ... or perhaps using six.moves.
  • unicode/basestring: unicode and basestring no longer exist. Use compatibility wrappers from six. Also functions like os.getcwdu are just os.getcwd now. Lastly, raw unicode strings are not allowed, but this can be worked around like u'' + r'...'
  • metaclasses: The method to indicate a metaclass has changed. The 2and3 compatible syntax is obscure, but easy... just call the metaclass directly to instantiate the class (_FormatterABC = abc.ABCMeta("_FormatterABC", (object,), {}))
  • reraise: The method of raising an exception with a traceback changed. Use six.reraise.

A taste (Python 2.7 & Python 3.3)

The following snippet shows me running ipython in Python 2.7 and 3.3 with the same source:

[bfroehle@highorder ipython (py3k)]$ python ipython.py 
Python 2.7.3 (default, Aug  1 2012, 05:14:39) 
Type "copyright", "credits" or "license" for more information.

IPython 0.14.dev -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: quit

[bfroehle@highorder ipython (py3k)]$ python3 ipython.py 
WARNING: IPython History requires SQLite, your history will not be saved
Python 3.3.0rc3 (default, Sep 27 2012, 08:35:53) 
Type "copyright", "credits" or "license" for more information.

IPython 0.14.dev -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: quit

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions