summaryrefslogtreecommitdiff
path: root/doc/python3.rst
diff options
context:
space:
mode:
authorVictor Feyens <vfe@odoo.com>2021-04-30 13:24:57 +0000
committerAntoine Vandevenne (anv) <anv@odoo.com>2021-05-04 08:09:20 +0000
commit27bad8c3e32049ec69a588df0558e57a0b928309 (patch)
treeb60e430163d486c8c1fd052738c9854aeb8300f5 /doc/python3.rst
parent75a122bbae3a32bfa79da3506179fc63a8bced5d (diff)
[MOV] doc: move documentation to a dedicated repository
In odoo/documentation-user#945, the developer documentation is merged with the user documentation in a single repository and build config. This commit then removes source files for the developer documentation from the odoo/odoo repository. DOC PR: https://github.com/odoo/documentation-user/pull/945 task-2351938 task-2352371 task-2205684 task-2352544 Co-authored-by: Victor Feyens <vfe@odoo.com> Co-authored-by: Antoine Vandevenne <anv@odoo.com>
Diffstat (limited to 'doc/python3.rst')
-rw-r--r--doc/python3.rst460
1 files changed, 0 insertions, 460 deletions
diff --git a/doc/python3.rst b/doc/python3.rst
deleted file mode 100644
index cfa3389a650..00000000000
--- a/doc/python3.rst
+++ /dev/null
@@ -1,460 +0,0 @@
-:orphan:
-
-==================================
-Python 3 compatibility/conversions
-==================================
-
-Official compatibility: Odoo 11 will be the first LTS release to introduce
-Python 3 compatibility, starting with Python 3.5. It will also be the first
-LTS release to drop official support for Python 2.
-
-Rationale: Python 3 has been around since 2008, and all Python libraries
-used by the official Odoo distribution have been ported and are considered
-stable. Most supported platforms have a Python 3.5 package, or a similar
-way to deploy it. Preserving dual compatibility is therefore considered
-unnecessary, and would represent a significant overhead in testing for the
-lifetime of Odoo 11.
-
-Python 2 and Python 3 are somewhat different language, but following
-backports, forward ports and cross-compatibility library it is possible to
-use a subset of Python 2 and Python 3 in order to have a system compatible
-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
-================
-
-A cross compatible Odoo would only support Python 2.7 and Python 3.5 and
-above: Python 2.7 backported some Python 3 features, and Python 2 features
-were reintroduced in various Python 3 in order to make conversion easier.
-Python 3.6 adds great features (f-strings, ...) and performance improvements
-(ordered compact dicts) but does not seem to reintroduce compatibility
-features whereas:
-
-* Python 3.5 reintroduced ``%`` for bytes/bytestrings (:pep:`461`)
-* 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 (backported to 2.7)and
- reintroduced ``callable``
-
-
-Semantics changes
-=================
-
-Dict & set iteration order ("Hash Randomisation")
--------------------------------------------------
-
-In Python 2, the iteration order depends on the value's hash (modulo the
-collection's capacity and conflict resolution), which provides a
-spec-undefined but implementation-defined order. While that's not supposed to
-happen, it turns out code may depend on the specific order of iteration over
-a hash collection (``dict`` or ``set``).
-
-Python 3.3 enables `hash randomisation`_ by default (this can be optionally
-enabled on previous versions including Python 2 by providing the ``-R``
-command-line parameter), which means *the order of iteration changes from one
-run to the next*.
-
-When discovered, this can be fixed by one of:
-
-* making iteration steps properly independent (removing the dependency of
- order of iteration)
-* using different checking method (e.g. when serialising sets or dictionaries
- and checking against the specific serialised value)
-* fixing dependencies
-* using a ``collections.OrderedDict`` or ``odoo.tools.misc.OrderedSet`` instead
- of a regular one, they guarantee order of iteration is order of insertion
-* sorting the collection's items before iterating over them (this may require
- adding some sort of iteration key to the items)
-
-Moved and removed
-=================
-
-Standard Library Modules
-------------------------
-
-Python 3 reorganised, moved or removed a number of modules in the standard
-library:
-
-* ``StringIO`` and ``cStringIO`` were removed, you can use ``io.BytesIO`` and
- ``io.StringIO`` to replace them in a cross-version manner (``io.BytesIO``
- for binary data, ``io.StringIO`` for text/unicode data).
-* ``urllib``, ``urllib2`` and ``urlparse`` were redistributed across
- ``urllib.parse`` and ``urllib.request``.
-
- Since `requests`_ and `werkzeug`_ are already hard dependencies of Odoo,
- replace ``urllib[2].urlopen``/``urllib2.Request`` uses by `requests`_, and
- ``urlparse`` and a few utilty functions (``urllib.quote``,
- ``urllib.urlencode``) are available through ``werkzeug.urls``, a backport
- of Python 3's ``urllib.parse``.
-
- .. warning:: `requests`_ does not raise by default on non-200 responses
-
-* ``cgi.escape`` (HTML escaping) is deprecated in Python 3, prefer Odoo's own
- :func:`odoo.tools.misc.html_encode`.
-* Most of ``types``'s content has been stripped out in Python 3: only
- "internal" interpreter types (e.g. CodeType, FrameType, ...) have been left
- in, other types can be obtained directly from the corresponding builtin or
- by getting the ``type()`` of a literal value.
-
-Absolute Imports (:pep:`328`)
------------------------------
-
-.. important::
-
- In Python 3, ``import foo`` can only import from a "top-level" library
- (absolute path). If trying to import a sibling or sub-module you *must*
- use an explicitly *relative import* e.g. ``from . import foo`` or
- ``from .foo import bar``.
-
-In Python 2 ``import`` statements are ambiguous: if a file ``a.py`` contains
-``import b``, the import system will first check if there's a ``b.py`` file
-next to it before checking if there is a package called that on the
-PYTHONPATH.
-
-Furthermore if a sibling file is named the same as top-level package, the
-library becomes inaccessible to both the file itself ans siblings, this has
-actually happened in Odoo with :mod:`odoo.tools.mimetypes`.
-
-Additionally, relative imports allow navigating "up" the tree by using
-multiple leading ``.``.
-
-.. note::
-
- Explicitly relative imports are always available in Python 2, and should
- be used everywhere.
-
- You can ensure you are not using any implicitly relative import by adding
- ``from __future__ import absolute_import`` at the top of your files, or by
- running the ``relative-import`` PyLint.
-
-Exception Handlers
-------------------
-
-.. important::
-
- All exception handlers must be converted to ``except ... as ..``. Valid
- forms are::
-
- except Exception:
- except (Exception1, ...):
- except Exception as name:
- except (Exception1, ...) as name:
-
-In Python 2, ``except`` statements are of the form::
-
- except Exception[, name]:
-
-or::
-
- except (Exception1, Exception2)[, name]:
-
-But because the name is optional, this gets confusing and people can stumble
-into the first form when trying for the second and write::
-
- except Exception1, Exception:
-
-which will *not* yield the expected result.
-
-Python 3 changes this syntax to::
-
- except Exception[ as name]:
-
-or::
-
- except (Exception1, Exception2)[ as name]:
-
-This form was implemented in Python 2.5 and is thus compatible across the
-board.
-
-Operators & keywords
---------------------
-
-.. important:: The backtick operator ```foo``` must be converted to an
- explicit call to the ``repr()`` builtin
-
-.. 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.
-
-.. _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)
-
-List/iteration builtins and methods
------------------------------------
-
-In Python 3, a number of builtins and methods formerly returning *lists* were
-converted to return *iterators* or *views*, with the corresponding redundant
-methods or functions having been *removed entirely*:
-
-* In Python 3, ``map``, ``filter`` and ``zip`` return iterators,
- ``itertools.imap``, ``itertools.ifilter`` and ``itertools.izip`` have been
- removed.
-
- .. important::
-
- When possible, use comprehensions (list, generator, ...) rather than
- ``map`` or ``filter``.
-
-* In Python 3, ``dict.keys``, ``dict.values`` and ``dict.items`` return
- *views* rather than lists, and the ``iter*`` and ``view*`` methods have
- been removed.
-
- .. important::
-
- When the result of the above methods is used for more than a one-shot
- loop (e.g. to be included in returned value), or when the dict needs
- to be modified during iteration, wrap the calls in a ``list()``.
-
-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``
-
-
-* 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.
-
-``reduce``
-##########
-
-In Python 3, ``reduce`` has been demoted from builtin to ``functools.reduce``.
-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 2's ``xrange``.
-
-For cross-version code, you can just use ``range()`` everywhere: while this
-will incur a slight allocation cost on Python 2, Python 3's ``range`` supports
-the entire Sequence protocol and thus behaves very much like a regular
-list or tuple.
-
-Removed/renamed methods
------------------------
-
-.. important::
-
- * the ``has_key`` method on dicts must be replaced by use of the ``in``
- operator e.g. ``foo.has_key(bar)`` becomes ``bar in foo``.
-
-``in`` for dicts was introduced in Python 2.3, leading to ``has_key`` being
-redundant, and removed in Python 3.
-
-Minor syntax changes
---------------------
-
-* the ability to unpack a parameter (in the parameter declaration list) has
- been removed in Python 3 e.g.::
-
- def foo((bar, baz), qux):
- …
-
- is now invalid
-
-* octal literals must be prefixed by ``0o`` (or ``0O``). Following the C
- family, in Python 2 an octal literal simply has a leading 0, which can be
- confusing and easy to get wrong when e.g. padding for readability (e.g.
- ``0013`` would be the decimal 11 rather than 13).
-
- In Python 3, leading zeroes followed by neither a 0 nor a period is an
- error, octal literals now follow the hexadecimal convention with a ``0o``
- prefix.
-
-.. _changed-strings:
-
-Bytes/String/Text: The Big One
-==============================
-
-The most impactful Python 3 change by far is to the text model: for historical
-reasons the distinction Python 2's bytestrings (``bytes``/``str``) and text
-strings (``unicode``) is fuzzy and it will try to implicitly convert between
-one and the other using the ASCII encoding.
-
-Python 3 changes this, it removes the implicit conversions, removes APIs which
-contribute to the fuzz and tends to strictly segregate other to work on either
-bytes or text.
-
-This is fundamentally good and mostly sensible, but it means lots of breakage:
-
-the builtins
-------------
-
-Python 3 removes both ``unicode`` and ``basestring``, and ``str`` now
-corresponds to *text* strings (the old ``unicode``) with ``bytes`` being
-bytestrings in both languages [#bytes]_.
-
-Both versions have the following prefixes for string literals:
-
-* ``b'foo'`` is a bytestring (``bytes`` object).
-
-* ``'foo'`` is that version's ``str`` type, which may be either a bytestring
- or a text string [#native-string]_.
-
-* ``u'foo'`` is that version's text string.
-
-For best cross-version compatibility you should avoid unprefixed string
-literals unless you *specifically* need a "native string" [#native-string]_.
-
-``open``
---------
-
-.. important::
-
- the ``open`` builtin should always be explicitly used in binary mode
- (``rb``, ``wb``, ...)
-
- To read *text* files, use ``io.open``.
-
-On both P2 and P3, ``open`` defaults to returning *native strings* in default
-("text") mode, however in P3 that means it actually decodes the file's bytes
-using whatever encoding was set up (default: UTF-8) while on Python 2 it has
-no concept of encoding.
-
-Using ``open`` in binary mode provides bytestrings on both versions and works
-fine. To read *text* files, use ``io.open`` and provide an explicit encoding.
-
-base64
-------
-
-base64 is a bytes->bytes conversion. bytes->bytes codecs were removed from the
-"native" encoding/decoding system which is now exclusively for bytes<->text
-conversions: text is *encoded* to bytes and bytes are *decoded* to text.
-
-.. important::
-
- both ``bytes.encode('base64')`` and ``bytes.decode('base64')`` must be
- migrated to using ``base64.b64encode`` and ``base64.b64decode``
- respectively.
-
-csv
----
-
-``csv`` is a fairly vicious one: not only is it not a very good format, the
-Python 2 and Python 3 versions of the library are text-model incompatible in
-significant ways:
-
-* Python 2's CSV only works on *ascii-compatible byte streams* (it has no
- encoding support at all) and extracts bytestring values
-* Python 3's CSV only works on *text streams* and extract text values
-* And ``io`` doesn't provide "native string" streaming facilities.
-
-However with respect to Odoo it turns out most or all uses of ``csv`` fit
-inside a model of *byte stream to and from text values*.
-
-The latter is thus a model implemented by cross-version wrappers
-:func:`odoo.tools.pycompat.csv_reader` and
-:func:`odoo.tools.pycompat.csv_writer`: they take a *UTF-8 byte stream* and
-read or write *text* values.
-
-.. _hash randomisation: http://bugs.python.org/issue13703
-
-.. _requests: http://docs.python-requests.org/
-
-.. _werkzeug: http://werkzeug.pocoo.org/docs/urls/
-
-.. [#bytes]
-
- with the caveat that Python 3 makes them less text-y and more byte-y e.g.
- in Python 2 ``b"foo"[0]`` is ``b"f"``, but in Python 3 it's ``102`` (the
- value of the first byte), you'll want to *slice* bytestrings for
- compatibility.
-
-.. [#native-string]
-
- this is important because some API/contexts take a *native string* rather
- than either bytes or text. The ``csv`` module of the standard library is
- one such problematic API (it is also notoriously problematic for its
- terrible support of non-ascii-compatible encodings in Python 2).
- ``email.message_from_string`` is an other one.