diff options
| author | xmo-odoo <xmo@odoo.com> | 2017-04-27 13:59:33 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-04-27 13:59:33 +0200 |
| commit | 2e6a589f417af48e3322955ffff6e94b6d8a24e3 (patch) | |
| tree | aa613ecc1f74a9531a03de89aa2bdc7bb32eed3b /doc | |
| parent | de4a2216b953abb86094c9bfa5f45b1eaaa79d3d (diff) | |
[FIX] builtins removed from Python 3
* Reverse wrapper courtesy of @rco-odoo's original P3 branch
* thin compat module stripped down from werkzeug (to augment as needed)
issue 8530
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/python3.rst | 149 |
1 files changed, 132 insertions, 17 deletions
diff --git a/doc/python3.rst b/doc/python3.rst index cb60965eb6c..407d8e9ee56 100644 --- a/doc/python3.rst +++ b/doc/python3.rst @@ -16,13 +16,28 @@ with both. Here are a few useful steps or reminders to make Python 2 code compatible with Python 3. +.. important:: + + This is not a general-purpose guide for porting Python 2 to Python 3, it's + a guide to write 2/3-compatible Odoo code. It does not go through all the + changes in Python but rather through issues which have been found in the + standard Odoo distribution in order to show how to evolve such code such + that it works on both Python 2 and Python 3. + References/useful documents: +* `What's new in Python 3? <https://docs.python.org/3.0/whatsnew/3.0.html>`_ + covers many of the changes between Python 2 and Python 3, though it is + missing a number of changes which `were backported to Python 2.7 <https://docs.python.org/2.7/whatsnew/2.7.html#python-3-1-features>`_ + as well as :ref:`some feature reintroductions <p3support>` of later Python 3 + revisions * `How do I port to Python 3? <https://eev.ee/blog/2016/07/31/python-faq-how-do-i-port-to-python-3/>`_ * `Python-Future <http://python-future.org/index.html>`_ * `Porting Python 2 code to Python 3 <https://docs.python.org/3/howto/pyporting.html>`_ * `Porting to Python 3: A Guide <http://lucumr.pocoo.org/2010/2/11/porting-to-python-3-a-guide/>`_ (a bit outdated but useful for the extensive comments on strings and IO) +.. _p3support: + Versions Support ================ @@ -37,16 +52,17 @@ features whereas: * Python 3.4 has no specific compatibility improvement but is the lowest P3 version for PyLint * Python 3.3 reintroduced the "u" prefix for proper (unicode) strings -* Python 3.2 made ``range`` views more list-like and reintroduced ``callable`` +* Python 3.2 made ``range`` views more list-like (backported to 2.7)and + reintroduced ``callable`` .. warning:: - Python 3 adds plenty of great features (keyword-only parameters, - generator delegation, pathlib, ...), do not use them until Python 2 - support is dropped + While Python 3 adds plenty of great features (keyword-only parameters, + generator delegation, pathlib, ...), you must *not *use them in Odoo + until Python 2 support is dropped -Fixes -===== +Moved and removed +================= Exception Handlers ------------------ @@ -87,33 +103,132 @@ or:: This form was implemented in Python 2.5 and is thus compatible across the board. -Removed Operators ------------------ +Operators & keywords +-------------------- -.. important:: +.. important:: The backtick operator ```foo``` must be converted to an + explicit call to the ``repr()`` builtin - * The backtick operator ``\`foo\``` must be converted to an explicit call - to the ``repr()`` builtin - * The ``<>`` operator must be replaced by ``!=`` +.. important:: The ``<>`` operator must be replaced by ``!=`` These two operators were long recommended against/deprecated in Python 2, Python 3 removed them from the language. -Removed/renamed builtins ------------------------- +.. _changed-exec: + +.. important:: ``exec`` is now a builtin + +In Python 2, ``exec`` is a statement/keyword. Much like ``print``, it's been +converted to a builtin function in Python 3. However because the Python 2 +version can take a tuple parameter it is easy to convert the odd ``exec`` +statement to the following cross-language forms:: + + exec(source) + exec(source, globals) + exec(source, globals, locals) + +builtins +-------- + +``cmp`` +####### + +The ``cmp`` builtin function has been removed from Python 3. + +* Most of its uses are in ``cmp=`` parameters to sort functions where it can + usually be replaced by a key function. +* Other uses found were obtaining the sign of an item (``cmp(item, 0)``), this + can be replicated using the standard library's ``math.copysign`` e.g. + ``math.copysign(1, item)`` will return ``1.0`` if ``item`` is positive and + ``-1.0`` if ``item`` is negative. + +``execfile`` +############ + +``execfile(path)`` has been removed completely from Python 3 but it is +trivially replaceable in all cases by:: + + exec(open(path, 'rb').open()) + +of a variant thereof (see :ref:`exec changes <changed-exec>` for details) + +``file`` +######## + +The ``file`` builtin has been removed in Python 3. Generally, it can just +be replaced by the ``open`` builtin, although you may want to use ``io.open`` +which is more flexible and better handles the binary/text dichotomy, +:ref:`a big issue in cross-version Python <changed-strings>`. + +.. note:: + + In Python 3, the ``open`` builtin is actually an alias for ``io.open``. + +``long`` +######## + +In Python 2, integers can be either ``int`` or ``long``. Python 3 unifies this +under the single ``int`` type. + +.. important:: + + * the ``L`` suffix for integer literals must be removed + * calls to ``long`` must be replaced by calls to ``int`` + * ``(int, long)`` for type-checking purposes must be replaced by + :py:data:`odoo.tools.pycompat.integer_types` + + +* the ``L`` suffix on numbers is unsupported in Python 3, and unnecessary in + Python 2 as "overflowing" integer literals will implicitly instantiate long. +* in Python 2, a call to ``int()`` will implicitly create a ``long`` object if + necessary. +* type-testing is the last and bigger issue as in Python 2 ``long`` is not a + subtype of ``int`` (nor the reverse), and ``isinstance(value, (int, long))`` + is thus generally necessary to catch all integrals. + + For that case, Odoo 11 now provides a compatibility module with an + :py:data:`~odoo.tools.pycompat.integer_types` definition which can be used + for type-testing. + + It is a tuple of types so when used with ``isinstance`` it can be provided + directly or inside an other tuple alongside other types e.g. + ``isinstance(value, (BaseModel, integer_types))``. + + However when used with ``type`` directly (which should be avoided) you + should use the ``in`` operator, and if you need other types you need to + concatenate ``integer_types`` to an other tuple. ``reduce`` ########## In Python 3, ``reduce`` has been demoted from builtin to ``functools.reduce``. -However this is because many (if not most) uses of ``reduce`` can be replaced -by ``sum``, ``all``, ``any`` or a list comprehension for a more readable and -faster result. +However this is because *most uses of ``reduce`` can be replaced by ``sum``, +``all``, ``any``* or a list comprehension for a more readable and faster +result. It is easy enough to just add ``from functools import reduce`` to the file and compatible with Python 2.6 and later, but consider whether you get better code by replacing it with some other method altogether. +``xrange`` +########## + +In Python 3, ``range()`` behaves the same as Python 3's ``xrange``. For +cross-versions code you can: + +* just use ``range()`` everywhere and ignore the allocation cost of a list in + Python 2 (often not an issue) +* conditionally alias ``xrange`` to ``range`` in Python 3 and use that +* use a combination of ``itertools.count`` and ``takewhile`` for a + cross-compatible lazy increasing sequence of numbers + +.. warning:: + + In the *rare* cases where you need conditional code (code which applies + for one version of python and not the other), use ``sys.version_info`` + e.g. ``sys.version_info() >= (3,)`` for Python3+ code or + ``sys.version_info() < (3,)`` for Python 2 code. + Removed/renamed methods ----------------------- |
