===================================
Compatibility with Python versions.
===================================

Theano is compatible with Python versions >= 2.6 including 3.x series.
This guide provides coding guidelines on how to maintain
comnpatibility.


Installation (2to3 and setup.py)
--------------------------------


Python code compatibility
-------------------------
Ideally, Python 3-incompatible changes should be caught by the Travis build,
but here are some guidelines for the major things to be aware of.

* When catching an exception and giving a name to it, use the new-style
  syntax:

    .. code-block:: python
        except Exception as e:
           ...

* No tuple-unpacking in the argument list:

    .. code-block:: python
        def f(a, (b, c)):  # wrong
            ...

        def f(a, others):
            b, c = others  # right

* Always use ``print(...)`` as a function, and add

    .. code-block:: python
        from __future__ import print_function

  At the top of files that use ``print``, above all other imports.

* If you mean to iterate over a range, use ``six.moves.xrange``. If you need
  a range as a list, use ``list(range(...))``.

* If you mean to iterate over a zipped sequence, use ``theano.compat.izip``.
  If you actually need it to be a list, use ``list(zip(...))``.

* If you mean to iterate over the output of a ``map``, use
  ``theano.compat.imap``.  If you actually need it to be a list, use
  ``list(map(...))``.

* If using ``reduce``, ``StringIO``, ``pickle``/``cPickle``, or ``copy_reg``,
  use the one in ``six.moves`` (note that ``copy_reg`` is named ``copyreg``).

* For iterating over the items, keys, values of a list, use
  ``six.iteritems(...)``, ``six.iterkeys(...)``, ``six.itervalues(...)``. If
  you wish to grab these as lists, wrap them in a ``list(...)`` call.

* Avoid ``itertools.{izip,ifilter,imap}``. Use the equivalently named functions
  from ``theano.compat``.

* Don't use `__builtin__`. Rather, ``six.moves.builtins``.

* Rather than the three-argument version of ``raise``, use
  ``six.reraise(...)``.

* Don't call the ``.next()`` method of iterators. Use the builtin
  ``next(...)``.

* When type testing for ``str`` or ``int``/``long``, use ``six.string_types``
  and ``six.integer_types``, respectively.

* Use the ``six.add_metaclass`` class decorator for adding metaclasses.


Compatibility package (theano.compat)
.....................................

Compatibility between 2.x and 3.x is implemented using six_, a Python
2 and 3 compatibility library by Benjamin Peterson.  Additionally,
certain additional or modified functions are available in the ``theano.compat``
module.


Strings, bytes and unicode
..........................
``str`` and ``bytes`` are different types in Python 3. Mostly this doesn't
come up for Theano's purposes. ``str`` represents encoded text, i.e. character
encoding-aware; all Python 3 strings are internally stored as Unicode. When
converting from one or the other, you must `.encode(...)` bytes and
`.decode(...)` strings with a given character encoding (e.g. ``'ascii'``,
``'utf8'``, ``'latin1'``). Fortunately, these methods exist as no-ops
in Python 2.6 and 2.7.

C code compatibility
--------------------

Module initialization
.....................

PyCapsule and PyCObject
.......................



References
----------

.. _six: http://pythonhosted.org/six
