diff --git a/doc/_themes/odoodoc/layout.html b/doc/_themes/odoodoc/layout.html
index 7685d8af25f..1a68d31814a 100644
--- a/doc/_themes/odoodoc/layout.html
+++ b/doc/_themes/odoodoc/layout.html
@@ -32,7 +32,7 @@
diff --git a/doc/_themes/odoodoc/sphinx_monkeypatch.py b/doc/_themes/odoodoc/sphinx_monkeypatch.py
index 13c3a305988..182fef89c8d 100644
--- a/doc/_themes/odoodoc/sphinx_monkeypatch.py
+++ b/doc/_themes/odoodoc/sphinx_monkeypatch.py
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
import sphinx.roles
import sphinx.environment
-from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.writers.html import HTMLTranslator
from docutils.writers.html4css1 import HTMLTranslator as DocutilsTranslator
@@ -9,27 +8,17 @@ def patch():
# navify toctree (oh god)
@monkey(sphinx.environment.BuildEnvironment)
def resolve_toctree(old_resolve, self, *args, **kwargs):
- """ If main_navbar, bootstrapify TOC to yield a navbar
+ """ If navbar, bootstrapify TOC to yield a navbar
"""
- main_navbar = kwargs.pop('main_navbar', False)
+ navbar = kwargs.pop('navbar', None)
toc = old_resolve(self, *args, **kwargs)
if toc is None:
return None
- navbarify(toc[0], main_navbar=main_navbar)
+ navbarify(toc[0], navbar=navbar)
return toc
- @monkey(StandaloneHTMLBuilder)
- def _get_local_toctree(old_local, self, *args, **kwargs):
- """ _get_local_toctree generates a documentation toctree for the local
- document (?), called from handle_page
- """
- # so can call toctree(main_navbar=False)
- d = {'main_navbar': True}
- d.update(kwargs)
- return old_local(self, *args, **d)
-
# monkeypatch visit_table to remove border and add .table
HTMLTranslator.visit_table = visit_table
# disable colspec crap
@@ -37,11 +26,18 @@ def patch():
# copy data- attributes straight from source to dest
HTMLTranslator.starttag = starttag_data
-def navbarify(node, main_navbar=False):
- # add classes to toplevel
- if not main_navbar:
- navify([node])
- else:
+def navbarify(node, navbar=None):
+ """
+ :param node: toctree node to navbarify
+ :param navbar: Whether this toctree is a 'main' navbar, a 'side' navbar or
+ not a navbar at all
+ """
+ if navbar == 'side':
+ for n in node.traverse():
+ if n.tagname == 'bullet_list':
+ n['classes'].append('nav')
+ elif navbar == 'main':
+ # add classes to just toplevel
node['classes'].extend(['nav', 'navbar-nav', 'navbar-right'])
for list_item in node.children:
# bullet_list
@@ -52,6 +48,10 @@ def navbarify(node, main_navbar=False):
# list_item
# compact_paragraph
# reference
+ # no bullet_list.list_item -> don't dropdownify
+ if not list_item.children[1].children:
+ return
+
list_item['classes'].append('dropdown')
# list_item.compact_paragraph.reference
link = list_item.children[0].children[0]
@@ -59,11 +59,6 @@ def navbarify(node, main_navbar=False):
link.attributes['data-toggle'] = 'dropdown'
# list_item.bullet_list
list_item.children[1]['classes'].append('dropdown-menu')
-def navify(nodes):
- for node in nodes:
- if node.tagname == 'bullet_list':
- node['classes'].append('nav')
- navify(node.children)
def visit_table(self, node):
"""
diff --git a/doc/_themes/odoodoc/static/style.css b/doc/_themes/odoodoc/static/style.css
index 19f5270109e..7c0b8e82959 100644
--- a/doc/_themes/odoodoc/static/style.css
+++ b/doc/_themes/odoodoc/static/style.css
@@ -5902,8 +5902,10 @@ button.close {
.panel-body:after,
.modal-footer:before,
.modal-footer:after,
-.document-super:before,
-.document-super:after,
+.document-super:not(.stripe):before,
+.document-super:not(.stripe):after,
+.document-super.stripe:before,
+.document-super.stripe:after,
.document:before,
.document:after {
content: " ";
@@ -5924,7 +5926,8 @@ button.close {
.pager:after,
.panel-body:after,
.modal-footer:after,
-.document-super:after,
+.document-super:not(.stripe):after,
+.document-super.stripe:after,
.document:after {
clear: both;
}
@@ -6181,35 +6184,53 @@ body {
overflow: auto;
position: relative;
}
-.document-super {
+.document-super:not(.stripe) {
margin-right: auto;
margin-left: auto;
padding-left: 15px;
padding-right: 15px;
}
@media (min-width: 768px) {
- .document-super {
+ .document-super:not(.stripe) {
width: 750px;
}
}
@media (min-width: 992px) {
- .document-super {
+ .document-super:not(.stripe) {
width: 970px;
}
}
@media (min-width: 1200px) {
- .document-super {
+ .document-super:not(.stripe) {
width: 1170px;
}
}
-.document-super > .navbar-header,
-.document-super > .navbar-collapse {
+.document-super:not(.stripe) > .navbar-header,
+.document-super:not(.stripe) > .navbar-collapse {
margin-right: -15px;
margin-left: -15px;
}
@media (min-width: 768px) {
- .document-super > .navbar-header,
- .document-super > .navbar-collapse {
+ .document-super:not(.stripe) > .navbar-header,
+ .document-super:not(.stripe) > .navbar-collapse {
+ margin-right: 0;
+ margin-left: 0;
+ }
+}
+.document-super.stripe {
+ margin-right: auto;
+ margin-left: auto;
+ padding-left: 15px;
+ padding-right: 15px;
+}
+.document-super.stripe > .navbar-header,
+.document-super.stripe > .navbar-collapse {
+ margin-right: -15px;
+ margin-left: -15px;
+}
+@media (min-width: 768px) {
+ .document-super.stripe > .navbar-header,
+ .document-super.stripe > .navbar-collapse {
margin-right: 0;
margin-left: 0;
}
@@ -6296,7 +6317,7 @@ body {
-o-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
}
-.docs-nav .navbar-nav > li > a:after {
+.docs-nav .navbar-nav > li.dropdown > a:after {
content: " ";
display: inline-block;
width: 0;
@@ -6307,7 +6328,7 @@ body {
border-right: 4px solid transparent;
border-left: 4px solid transparent;
}
-.docs-nav .navbar-nav > li .dropdown-menu > li.current > a.current {
+.docs-nav .navbar-nav > li.dropdown .dropdown-menu > li.current > a.current {
background-color: #a24689;
color: white;
}
@@ -6709,6 +6730,74 @@ td.field-body > ul {
.descclassname {
opacity: 0.5;
}
+.index-tree ul,
+.index-tree li {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+.index-tree > ul > li {
+ margin-bottom: 0.5em;
+}
+.index-tree > ul > li > a {
+ font-family: Lato, Arial, sans-serif;
+ font-weight: 500;
+ line-height: 1.1;
+ color: inherit;
+ margin-top: 20px;
+ margin-bottom: 10px;
+ font-size: 24px;
+ text-align: center;
+}
+.index-tree > ul > li > a small,
+.index-tree > ul > li > a .small {
+ font-weight: normal;
+ line-height: 1;
+ color: #777777;
+}
+.index-tree > ul > li > a small,
+.index-tree > ul > li > a .small {
+ font-size: 65%;
+}
+.index-tree > ul > li > ul {
+ display: -webkit-flex;
+ display: flex;
+ -webkit-flex-wrap: wrap;
+ flex-wrap: wrap;
+}
+.index-tree > ul > li > ul > li {
+ width: 50%;
+}
+.index-tree > ul > li > ul > li a {
+ font-family: Lato, Arial, sans-serif;
+ font-weight: 500;
+ line-height: 1.1;
+ color: inherit;
+ margin-top: 10px;
+ margin-bottom: 10px;
+ font-size: 18px;
+ padding-left: 10%;
+ padding-right: 10%;
+}
+.index-tree > ul > li > ul > li a small,
+.index-tree > ul > li > ul > li a .small {
+ font-weight: normal;
+ line-height: 1;
+ color: #777777;
+}
+.index-tree > ul > li > ul > li a small,
+.index-tree > ul > li > ul > li a .small {
+ font-size: 75%;
+}
+.index-tree > ul > li a {
+ display: block;
+ color: #a24689 !important;
+ padding: 0.3em 0;
+ margin: 3px !important;
+}
+.index-tree > ul > li a:hover {
+ background-color: #eeeeee;
+}
.stripe .section {
margin-bottom: 2em;
}
diff --git a/doc/_themes/odoodoc/static/style.less b/doc/_themes/odoodoc/static/style.less
index 719fa6f10e3..ea53cd95e85 100644
--- a/doc/_themes/odoodoc/static/style.less
+++ b/doc/_themes/odoodoc/static/style.less
@@ -25,9 +25,12 @@ body {
position: relative;
}
-.document-super {
+.document-super:not(.stripe) {
.container();
}
+.document-super.stripe {
+ .container-fluid();
+}
.document {
.make-row();
@@ -89,20 +92,22 @@ body {
opacity: 0;
.transition(all 0.3s ease-out);
}
- > a:after {
- content: " ";
- display: inline-block;
- width: 0;
- height: 0;
- margin-left: 5px;
- vertical-align: middle;
- border-top: 4px solid @gray-light;
- border-right: 4px solid transparent;
- border-left: 4px solid transparent;
- }
- .dropdown-menu > li.current > a.current {
- background-color: @brand-primary;
- color: white;
+ &.dropdown {
+ > a:after {
+ content: " ";
+ display: inline-block;
+ width: 0;
+ height: 0;
+ margin-left: 5px;
+ vertical-align: middle;
+ border-top: 4px solid @gray-light;
+ border-right: 4px solid transparent;
+ border-left: 4px solid transparent;
+ }
+ .dropdown-menu > li.current > a.current {
+ background-color: @brand-primary;
+ color: white;
+ }
}
}
/* version switcher */
@@ -547,6 +552,44 @@ td.field-body {
opacity: 0.5;
}
+
+.index-tree {
+ ul, li {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ }
+ > ul > li {
+ margin-bottom: 0.5em;
+ > a {
+ .h3();
+ text-align: center;
+ }
+ > ul {
+ display: -webkit-flex;
+ display: flex;
+ -webkit-flex-wrap: wrap;
+ flex-wrap: wrap;
+ > li {
+ width: 50%;
+ a {
+ .h4();
+ padding-left: 10%;
+ padding-right: 10%;
+ }
+ }
+ }
+ a {
+ display: block;
+ color: @link-color !important;
+ padding: 0.3em 0;
+ margin: 3px !important;
+ &:hover {
+ background-color: @gray-lighter;
+ }
+ }
+ }
+}
// STRIPE-STYLE PAGES
.stripe {
.section {
diff --git a/doc/modules/api_integration.rst b/doc/api_integration.rst
similarity index 99%
rename from doc/modules/api_integration.rst
rename to doc/api_integration.rst
index 21d0163ba46..12c5b56737e 100644
--- a/doc/modules/api_integration.rst
+++ b/doc/api_integration.rst
@@ -1,7 +1,7 @@
:classes: stripe
===========
-Odoo as API
+Web Service
===========
Odoo is mostly extended internally via modules, but much of its features and
@@ -250,8 +250,8 @@ the login.
Calling methods
===============
-The second — and most generally useful — is ``xmlrpc/2/object`` which is used
-to call methods of odoo models via the ``execute_kw`` RPC function.
+The second endpoint is ``xmlrpc/2/object``, is used to call methods of odoo
+models via the ``execute_kw`` RPC function.
Each call to ``execute_kw`` takes the following parameters:
diff --git a/doc/images/view-on-github.png b/doc/images/view-on-github.png
deleted file mode 100644
index 65a8d42363d..00000000000
Binary files a/doc/images/view-on-github.png and /dev/null differ
diff --git a/doc/index.rst b/doc/index.rst
index 3c1696020d6..56f58b6aa0d 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -4,38 +4,17 @@ odoo developer documentation
Welcome to the Odoo developer documentation.
-This documentation is incomplete and may contain errors, if you wish to
-contribute, every page should have a :guilabel:`View on Github` link:
-
-.. image:: images/view-on-github.*
- :align: center
-
-Through this link you can edit documents and submit changes for review using
-`github's web interface
-`_.
-Contributions are welcome and appreciated.
-
.. todo:: what's the documentation's license?
-The documentation is currently organized in four sections:
-
-* :doc:`tutorials`, aimed at introducing the primary areas of developing Odoo
- modules
-* :doc:`reference`, which ought be the complete and canonical documentation
- for Odoo subsystems
-* :doc:`modules`, documenting useful specialized modules and integration
- methods (and currently empty)
-
-.. hidden toctree w/o titlesonly otherwise the titlesonly "sticks" to
- in-document toctrees and we can't have a toctree showing both "sibling"
- pages and current document sections
-
+.. rst-class:: index-tree
+.. titlesonly breaks level 3 (~in-document) toc of left navbar, so use
+ maxdepth instead
.. toctree::
- :hidden:
+ :maxdepth: 2
tutorials
reference
- modules
+ api_integration
.. ifconfig:: todo_include_todos
diff --git a/doc/modules.rst b/doc/modules.rst
deleted file mode 100644
index cb5ed8d6ca1..00000000000
--- a/doc/modules.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-==============
-Module Objects
-==============
-
-.. toctree::
- :titlesonly:
-
- modules/api_integration
diff --git a/doc/reference/cmdline.rst b/doc/reference/cmdline.rst
index 32c1ef48729..1ec7d96ae9d 100644
--- a/doc/reference/cmdline.rst
+++ b/doc/reference/cmdline.rst
@@ -71,7 +71,7 @@ Scaffolding is available via the :command:`odoo.py scaffold` subcommand.
.. option:: -t
a template directory, files are passed through jinja2_ then copied to
- the :option:`destination` directory
+ the ``destination`` directory
.. option:: name
diff --git a/doc/reference/orm.rst b/doc/reference/orm.rst
index 94aa18b4863..cfc465078b1 100644
--- a/doc/reference/orm.rst
+++ b/doc/reference/orm.rst
@@ -421,10 +421,31 @@ added.
is not written to the database, just used to know which value to send back
to the client
+Low-level SQL
+-------------
+
+The :attr:`~openerp.api.Environment.cr` attribute on environments is the
+cursor for the current database transaction and allows executing SQL directly,
+either for queries which are difficult to express using the ORM (e.g. complex
+joins) or for performance reasons::
+
+ self.env.cr.execute("some_sql", param1, param2, param3)
+
+Because models use the same cursor and the :class:`~openerp.api.Environment`
+holds various caches, these caches must be invalidated when *altering* the
+database in raw SQL, or further uses of models may become incoherent. It is
+necessary to clear caches when using ``CREATE``, ``UPDATE`` or ``DELETE`` in
+SQL, but not ``SELECT`` (which simply reads the database).
+
+Clearing caches can be performed using the
+:meth:`~openerp.api.Environment.invalidate_all` method of the
+:class:`~openerp.api.Environment` object.
+
+
.. _reference/orm/oldapi:
Old API compatibility
----------------------
+=====================
Odoo is currently transitioning from an older (less regular) API, it can be
necessary to manually bridge from one to the other manually:
@@ -508,170 +529,6 @@ return lists of ids, there is also a decorator managing this:
>>> old_style_model.some_method(cr, uid, [1, 2, 3], context=context)
[1, 2, 3]
-Porting from the old API
-------------------------
-
-* methods still written in the old API should be automatically bridged by the
- ORM, no need to switch to the old API, just call them as if they were a new
- API method. See :ref:`reference/orm/oldapi/bridging` for more details.
-* ``search`` returns a recordset, no point in e.g. browsing its result
-* ``fields.related`` and ``fields.function`` are replaced by using a normal
- field type with either a ``related`` or a ``compute`` parameter
-* ``depends`` on field compute methods **must be complete**, it must list
- **all** the fields and sub-fields which the compute method uses. It is
- better to have too many dependencies (will recompute the field in cases
- where that is not needed) than not enough (will forget to recompute the
- field and then values will be incorrect)
-* **remove** all ``onchange`` methods on computed fields. Computed fields are
- automatically re-computed when one of their dependencies is changed, and
- that is used to auto-generate ``onchange`` by the client
-* the decorators :func:`~openerp.api.model` and :func:`~openerp.api.multi` are
- for bridging *when calling from the old API context*, for internal or pure
- new-api (e.g. compute) they are useless
-* remove :attr:`~openerp.models.Model._default`, replace by ``default=``
- parameter on corresponding fields
-* if a field's ``string`` is the titlecased version of the field name::
-
- name = fields.Char(string="Name")
-
- it is useless and should be removed
-* ``multi`` does not do anything on new API fields use the same ``compute``
- methods on all relevant fields for the same result
-* provide ``compute``, ``inverse`` and ``search`` methods by name (as a
- string), this makes them overridable (removes the need for an intermediate
- "trampoline" function)
-* double check that all fields and methods have different names, there is no
- warning in case of collision (because Python handles it before Odoo sees
- anything)
-* the normal new-api import is ``from openerp import fields, models``. If
- compatibility decorators are necessary, use ``from openerp import api,
- fields, models``
-* avoid the :func:`~openerp.api.one` decorator, it probably does not do what
- you expect
-* remove explicit definition of :attr:`~openerp.models.Model.create_uid`,
- :attr:`~openerp.models.Model.create_date`,
- :attr:`~openerp.models.Model.write_uid` and
- :attr:`~openerp.models.Model.write_date` fields: they are now created as
- regular "legitimate" fields, and can be read and written like any other
- field out-of-the-box
-* when straight conversion is impossible (semantics can not be bridged) or the
- "old API" version is not desirable and could be improved for the new API, it
- is possible to use completely different "old API" and "new API"
- implementations for the same method name using :func:`~openerp.api.v7` and
- :func:`~openerp.api.v8`. The method should first be defined using the
- old-API style and decorated with :func:`~openerp.api.v7`, it should then be
- re-defined using the exact same name but the new-API style and decorated
- with :func:`~openerp.api.v8`. Calls from an old-API context will be
- dispatched to the first implementation and calls from a new-API context will
- be dispatched to the second implementation. One implementation can call (and
- frequently does) call the other by switching context.
-
- .. danger:: using these decorators makes methods extremely difficult to
- override and harder to understand and document
-* uses of :attr:`~openerp.models.Model._columns` or
- :attr:`~openerp.models.Model._all_columns` should be replaced by
- :attr:`~openerp.models.Model._fields`, which provides access to instances of
- new-style :class:`openerp.fields.Field` instances (rather than old-style
- :class:`openerp.osv.fields._column`).
-
- Non-stored computed fields created using the new API style are *not*
- available in :attr:`~openerp.models.Model._columns` and can only be
- inspected through :attr:`~openerp.models.Model._fields`
-* reassigning ``self`` in a method is probably unnecessary and may break
- translation introspection
-* :class:`~openerp.api.Environment` objects rely on some threadlocal state,
- which has to be set up before using them. It is necessary to do so using the
- :meth:`openerp.api.Environment.manage` context manager when trying to use
- the new API in contexts where it hasn't been set up yet, such as new threads
- or a Python interactive environment::
-
- >>> from openerp import api, modules
- >>> r = modules.registry.RegistryManager.get('test')
- >>> cr = r.cursor()
- >>> env = api.Environment(cr, 1, {})
- Traceback (most recent call last):
- ...
- AttributeError: environments
- >>> with api.Environment.manage():
- ... env = api.Environment(cr, 1, {})
- ... print env['res.partner'].browse(1)
- ...
- res.partner(1,)
-
-.. _reference/orm/oldapi/bridging:
-
-Automatic bridging of old API methods
-'''''''''''''''''''''''''''''''''''''
-
-When models are initialized, all methods are automatically scanned and bridged
-if they look like models declared in the old API style. This bridging makes
-them transparently callable from new-API-style methods.
-
-Methods are matched as "old-API style" if their second positional parameter
-(after ``self``) is called either ``cr`` or ``cursor``. The system also
-recognizes the third positional parameter being called ``uid`` or ``user`` and
-the fourth being called ``id`` or ``ids``. It also recognizes the presence of
-any parameter called ``context``.
-
-When calling such methods from a new API context, the system will
-automatically fill matched parameters from the current
-:class:`~openerp.api.Environment` (for :attr:`~openerp.api.Environment.cr`,
-:attr:`~openerp.api.Environment.user` and
-:attr:`~openerp.api.Environment.context`) or the current recordset (for ``id``
-and ``ids``).
-
-In the rare cases where it is necessary, the bridging can be customized by
-decorating the old-style method:
-
-* disabling it entirely, by decorating a method with
- :func:`~openerp.api.noguess` there will be no bridging and methods will be
- called the exact same way from the new and old API styles
-* defining the bridge explicitly, this is mostly for methods which are matched
- incorrectly (because parameters are named in unexpected ways):
-
- :func:`~openerp.api.cr`
- will automatically prepend the current cursor to explicitly provided
- parameters, positionally
- :func:`~openerp.api.cr_uid`
- will automatically prepend the current cursor and user's id to explictly
- provided parameters
- :func:`~openerp.api.cr_uid_ids`
- will automatically prepend the current cursor, user's id and recordset's
- ids to explicitly provided parameters
- :func:`~openerp.api.cr_uid_id`
- will loop over the current recordset and call the method once for each
- record, prepending the current cursor, user's id and record's id to
- explicitly provided parameters.
-
- .. danger:: the result of this wrapper is *always a list* when calling
- from a new-API context
-
- All of these methods have a ``_context``-suffixed version
- (e.g. :func:`~openerp.api.cr_uid_context`) which also passes the current
- context *by keyword*.
-* dual implementations using :func:`~openerp.api.v7` and
- :func:`~openerp.api.v8` will be ignored as they provide their own "bridging"
-
-Low-level SQL
--------------
-
-The :attr:`~openerp.api.Environment.cr` attribute on environments is the
-cursor for the current database transaction and allows executing SQL directly,
-either for queries which are difficult to express using the ORM (e.g. complex
-joins) or for performance reasons::
-
- self.env.cr.execute("some_sql", param1, param2, param3)
-
-Because models use the same cursor and the :class:`~openerp.api.Environment`
-holds various caches, these caches must be invalidated when *altering* the
-database in raw SQL, or further uses of models may become incoherent. It is
-necessary to clear caches when using ``CREATE``, ``UPDATE`` or ``DELETE`` in
-SQL, but not ``SELECT`` (which simply reads the database).
-
-Clearing caches can be performed using the
-:meth:`~openerp.api.Environment.invalidate_all` method of the
-:class:`~openerp.api.Environment` object.
-
.. _reference/orm/model:
Model Reference
@@ -1168,3 +1025,148 @@ Domain criteria can be combined using logical operators in *prefix* form:
(name is 'ABC')
AND (language is NOT english)
AND (country is Belgium OR Germany)
+
+Porting from the old API
+========================
+
+* methods still written in the old API should be automatically bridged by the
+ ORM, no need to switch to the old API, just call them as if they were a new
+ API method. See :ref:`reference/orm/oldapi/bridging` for more details.
+* :meth:`~openerp.models.Model.search` returns a recordset, no point in e.g.
+ browsing its result
+* ``fields.related`` and ``fields.function`` are replaced by using a normal
+ field type with either a ``related=`` or a ``compute=`` parameter
+* :func:`~openerp.api.depends` on ``compute=`` methods **must be complete**,
+ it must list **all** the fields and sub-fields which the compute method
+ uses. It is better to have too many dependencies (will recompute the field
+ in cases where that is not needed) than not enough (will forget to recompute
+ the field and then values will be incorrect)
+* **remove** all ``onchange`` methods on computed fields. Computed fields are
+ automatically re-computed when one of their dependencies is changed, and
+ that is used to auto-generate ``onchange`` by the client
+* the decorators :func:`~openerp.api.model` and :func:`~openerp.api.multi` are
+ for bridging *when calling from the old API context*, for internal or pure
+ new-api (e.g. compute) they are useless
+* remove :attr:`~openerp.models.Model._default`, replace by ``default=``
+ parameter on corresponding fields
+* if a field's ``string=`` is the titlecased version of the field name::
+
+ name = fields.Char(string="Name")
+
+ it is useless and should be removed
+* the ``multi=`` parameter does not do anything on new API fields use the same
+ ``compute=`` methods on all relevant fields for the same result
+* provide ``compute=``, ``inverse=`` and ``search=`` methods by name (as a
+ string), this makes them overridable (removes the need for an intermediate
+ "trampoline" function)
+* double check that all fields and methods have different names, there is no
+ warning in case of collision (because Python handles it before Odoo sees
+ anything)
+* the normal new-api import is ``from openerp import fields, models``. If
+ compatibility decorators are necessary, use ``from openerp import api,
+ fields, models``
+* avoid the :func:`~openerp.api.one` decorator, it probably does not do what
+ you expect
+* remove explicit definition of :attr:`~openerp.models.Model.create_uid`,
+ :attr:`~openerp.models.Model.create_date`,
+ :attr:`~openerp.models.Model.write_uid` and
+ :attr:`~openerp.models.Model.write_date` fields: they are now created as
+ regular "legitimate" fields, and can be read and written like any other
+ field out-of-the-box
+* when straight conversion is impossible (semantics can not be bridged) or the
+ "old API" version is not desirable and could be improved for the new API, it
+ is possible to use completely different "old API" and "new API"
+ implementations for the same method name using :func:`~openerp.api.v7` and
+ :func:`~openerp.api.v8`. The method should first be defined using the
+ old-API style and decorated with :func:`~openerp.api.v7`, it should then be
+ re-defined using the exact same name but the new-API style and decorated
+ with :func:`~openerp.api.v8`. Calls from an old-API context will be
+ dispatched to the first implementation and calls from a new-API context will
+ be dispatched to the second implementation. One implementation can call (and
+ frequently does) call the other by switching context.
+
+ .. danger:: using these decorators makes methods extremely difficult to
+ override and harder to understand and document
+* uses of :attr:`~openerp.models.Model._columns` or
+ :attr:`~openerp.models.Model._all_columns` should be replaced by
+ :attr:`~openerp.models.Model._fields`, which provides access to instances of
+ new-style :class:`openerp.fields.Field` instances (rather than old-style
+ :class:`openerp.osv.fields._column`).
+
+ Non-stored computed fields created using the new API style are *not*
+ available in :attr:`~openerp.models.Model._columns` and can only be
+ inspected through :attr:`~openerp.models.Model._fields`
+* reassigning ``self`` in a method is probably unnecessary and may break
+ translation introspection
+* :class:`~openerp.api.Environment` objects rely on some threadlocal state,
+ which has to be set up before using them. It is necessary to do so using the
+ :meth:`openerp.api.Environment.manage` context manager when trying to use
+ the new API in contexts where it hasn't been set up yet, such as new threads
+ or a Python interactive environment::
+
+ >>> from openerp import api, modules
+ >>> r = modules.registry.RegistryManager.get('test')
+ >>> cr = r.cursor()
+ >>> env = api.Environment(cr, 1, {})
+ Traceback (most recent call last):
+ ...
+ AttributeError: environments
+ >>> with api.Environment.manage():
+ ... env = api.Environment(cr, 1, {})
+ ... print env['res.partner'].browse(1)
+ ...
+ res.partner(1,)
+
+.. _reference/orm/oldapi/bridging:
+
+Automatic bridging of old API methods
+-------------------------------------
+
+When models are initialized, all methods are automatically scanned and bridged
+if they look like models declared in the old API style. This bridging makes
+them transparently callable from new-API-style methods.
+
+Methods are matched as "old-API style" if their second positional parameter
+(after ``self``) is called either ``cr`` or ``cursor``. The system also
+recognizes the third positional parameter being called ``uid`` or ``user`` and
+the fourth being called ``id`` or ``ids``. It also recognizes the presence of
+any parameter called ``context``.
+
+When calling such methods from a new API context, the system will
+automatically fill matched parameters from the current
+:class:`~openerp.api.Environment` (for :attr:`~openerp.api.Environment.cr`,
+:attr:`~openerp.api.Environment.user` and
+:attr:`~openerp.api.Environment.context`) or the current recordset (for ``id``
+and ``ids``).
+
+In the rare cases where it is necessary, the bridging can be customized by
+decorating the old-style method:
+
+* disabling it entirely, by decorating a method with
+ :func:`~openerp.api.noguess` there will be no bridging and methods will be
+ called the exact same way from the new and old API styles
+* defining the bridge explicitly, this is mostly for methods which are matched
+ incorrectly (because parameters are named in unexpected ways):
+
+ :func:`~openerp.api.cr`
+ will automatically prepend the current cursor to explicitly provided
+ parameters, positionally
+ :func:`~openerp.api.cr_uid`
+ will automatically prepend the current cursor and user's id to explictly
+ provided parameters
+ :func:`~openerp.api.cr_uid_ids`
+ will automatically prepend the current cursor, user's id and recordset's
+ ids to explicitly provided parameters
+ :func:`~openerp.api.cr_uid_id`
+ will loop over the current recordset and call the method once for each
+ record, prepending the current cursor, user's id and record's id to
+ explicitly provided parameters.
+
+ .. danger:: the result of this wrapper is *always a list* when calling
+ from a new-API context
+
+ All of these methods have a ``_context``-suffixed version
+ (e.g. :func:`~openerp.api.cr_uid_context`) which also passes the current
+ context *by keyword*.
+* dual implementations using :func:`~openerp.api.v7` and
+ :func:`~openerp.api.v8` will be ignored as they provide their own "bridging"