[IMP] doc: improve index, WS page

This commit is contained in:
Xavier Morel 2014-11-17 16:25:34 +01:00
commit c92e70b929
10 changed files with 358 additions and 257 deletions

View File

@ -32,7 +32,7 @@
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
{{ toctree(maxdepth=4, collapse=False, includehidden=True,
main_navbar=False, titles_only=False) }}
navbar='side', titles_only=False) }}
{% if github_link %}
<p><a href="{{ github_link(mode='edit') }}" class="github">
Edit on GitHub
@ -72,7 +72,8 @@
{% endif %}
</div>
<nav class="collapse navbar-collapse navbar-main" role="navigation">
{{ toctree(titles_only=True, maxdepth=2, includehidden=True, collapse=False) }}
{{ toctree(titles_only=True, maxdepth=2, includehidden=True,
collapse=False, navbar='main') }}
</nav>
</div>
</header>

View File

@ -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):
"""

View File

@ -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;
}

View File

@ -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 {

View File

@ -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:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -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
<https://help.github.com/articles/editing-files-in-your-repository/>`_.
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

View File

@ -1,8 +0,0 @@
==============
Module Objects
==============
.. toctree::
:titlesonly:
modules/api_integration

View File

@ -71,7 +71,7 @@ Scaffolding is available via the :command:`odoo.py scaffold` subcommand.
.. option:: -t <template>
a template directory, files are passed through jinja2_ then copied to
the :option:`destination` directory
the ``destination`` directory
.. option:: name

View File

@ -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"