[Python-modules-commits] [python-odoorpc] 02/06: Import python-odoorpc_0.5.1.orig.tar.gz
Wolfgang Borgert
debacle at moszumanska.debian.org
Sun Jan 22 13:40:19 UTC 2017
This is an automated email from the git hooks/post-receive script.
debacle pushed a commit to branch master
in repository python-odoorpc.
commit 30a2f6f1f9bab0404ebcb9347711f70b56afa68e
Author: W. Martin Borgert <debacle at debian.org>
Date: Sun Jan 22 13:26:15 2017 +0000
Import python-odoorpc_0.5.1.orig.tar.gz
---
.travis.yml | 13 ++++++----
CHANGELOG | 21 +++++++++++++++
README.rst | 4 +--
doc/source/conf.py | 5 ++--
doc/source/download_install.rst | 2 +-
doc/source/faq.rst | 12 ++++-----
doc/source/index.rst | 6 ++---
doc/source/tuto_browse.rst | 4 +--
doc/source/tuto_browse_methods.rst | 2 +-
doc/source/tuto_browse_update.rst | 47 +++++++++++++++++----------------
doc/source/tuto_login.rst | 8 +++---
doc/source/tuto_report.rst | 10 +++----
doc/source/tuto_rpc_queries.rst | 4 +--
doc/source/tuto_session.rst | 2 +-
doc/source/tutorials.rst | 5 ++++
odoorpc/__init__.py | 2 +-
odoorpc/error.py | 15 ++++++++---
odoorpc/models.py | 4 +++
odoorpc/odoo.py | 13 +++++-----
odoorpc/rpc/__init__.py | 49 +++++++++++++++++++++++++----------
odoorpc/session.py | 4 +--
odoorpc/tests/__init__.py | 16 ++++++++----
odoorpc/tests/test_db.py | 1 +
odoorpc/tests/test_field_binary.py | 38 +++++++++++++++++++++++++++
odoorpc/tests/test_field_many2many.py | 47 ++++++++++++++++++---------------
odoorpc/tests/test_field_reference.py | 44 +++++++++++++++++++++----------
odoorpc/tests/test_init.py | 10 +++++++
setup.py | 2 +-
28 files changed, 265 insertions(+), 125 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 4880f3e..0a033a6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,5 @@
language: python
+cache: pip
python:
- "2.7"
- "3.2"
@@ -8,23 +9,25 @@ python:
- "pypy"
env:
- - ODOO_BRANCH=8.0 ORPC_TEST_VERSION=$ODOO_BRANCH
- - ODOO_BRANCH=9.0 ORPC_TEST_VERSION=$ODOO_BRANCH
+ - ODOO_BRANCH=8.0 ORPC_TEST_VERSION=$ODOO_BRANCH ODOO_CMD="/usr/bin/python2.7 /usr/local/bin/openerp-server -r $USER --addons-path=/opt/odoo/addons"
+ - ODOO_BRANCH=9.0 ORPC_TEST_VERSION=$ODOO_BRANCH ODOO_CMD="/usr/bin/python2.7 /usr/local/bin/openerp-server -r $USER --addons-path=/opt/odoo/addons"
+ - ODOO_BRANCH=10.0 ORPC_TEST_VERSION=$ODOO_BRANCH ODOO_CMD="/usr/bin/python2.7 /usr/local/bin/odoo -r $USER --addons-path=/opt/odoo/addons"
before_install:
+ # Upgrade pip
+ - "sudo pip install pip --upgrade"
# Install wkhtmltox
- "wget http://download.gna.org/wkhtmltopdf/0.12/0.12.1/wkhtmltox-0.12.1_linux-precise-amd64.deb"
- "sudo dpkg -i wkhtmltox-0.12.1_linux-precise-amd64.deb || true"
- "sudo apt-get update && sudo apt-get install -f -y"
# Install Odoo on the system (outside the virtualenv)
- "sudo git clone --depth=1 -b $ODOO_BRANCH https://github.com/odoo/odoo.git /opt/odoo"
- - "sudo apt-get install python-pip"
- - "sudo /usr/bin/pip install -r /opt/odoo/requirements.txt"
+ - "sudo pip install -r /opt/odoo/requirements.txt"
- "echo $PWD"
- "cd /opt/odoo && sudo /usr/bin/python setup.py install"
- "cd $TRAVIS_BUILD_DIR"
# Start Odoo
- - "nohup /usr/bin/python2.7 /usr/local/bin/openerp-server -r $USER --addons-path=/opt/odoo/addons &"
+ - "nohup $ODOO_CMD &"
install:
# OdooRPC dependencies
diff --git a/CHANGELOG b/CHANGELOG
index d59e609..19a558c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,24 @@
+0.5.1
+=====
+- FIX: Session file loading, read the `timeout` value as a float
+
+0.5.0
+=====
+- IMP: Support added for Odoo 10.0
+- IMP: Documentation updated to be in line with Odoo 10.0
+
+0.4.3
+=====
+- IMP: Documentation (minor fixes)
+
+0.4.2
+=====
+- IMP: Unit tests:
+ - autodetect server version
+ - tests added for binary fields
+- IMP: The timeout can be set to 'None' (infinite timeout)
+- FIX: Underscore prefixed methods are not forwarded to the server
+
0.4.1
=====
- IMP: New feature, check if a model exists in the Odoo database (see the
diff --git a/README.rst b/README.rst
index 6e26a97..2cad005 100644
--- a/README.rst
+++ b/README.rst
@@ -73,7 +73,7 @@ See the documentation for more details and features.
Supported Odoo server versions
------------------------------
-`OdooRPC` has been tested on `Odoo` 8.0 and 9.0.
+`OdooRPC` has been tested on `Odoo` 8.0, 9.0 and 10.0.
It should work on next versions if `Odoo` keeps a stable API.
Supported Python versions
@@ -92,7 +92,7 @@ Generate the documentation
To generate the documentation, you have to install `Sphinx` documentation
generator::
- easy_install -U sphinx
+ pip install sphinx
Then, you can use the ``build_doc`` option of the ``setup.py``::
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 1d347ff..2946843 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -14,6 +14,7 @@
import sys
import os
+from datetime import datetime
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
@@ -40,7 +41,7 @@ PORT = os.environ.get('ORPC_TEST_PORT', 8069)
DB = os.environ.get('ORPC_TEST_DB', 'odoorpc_doctest')
USER = os.environ.get('ORPC_TEST_USER', 'admin')
PWD = os.environ.get('ORPC_TEST_PWD', 'admin')
-VERSION = os.environ.get('ORPC_TEST_VERSION', '8.0')
+VERSION = os.environ.get('ORPC_TEST_VERSION', '10.0')
SUPER_PWD = os.environ.get('ORPC_TEST_SUPER_PWD', 'admin')
import odoorpc
odoo = odoorpc.ODOO(HOST, protocol=PROTOCOL, port=PORT, version=VERSION)
@@ -75,7 +76,7 @@ master_doc = 'index'
# General information about the project.
project = u'OdooRPC'
-copyright = u'2014, Sébastien Alix'
+copyright = u'2014-{0}, Sébastien Alix'.format(datetime.now().year)
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
diff --git a/doc/source/download_install.rst b/doc/source/download_install.rst
index 0561b8e..b4d4d05 100644
--- a/doc/source/download_install.rst
+++ b/doc/source/download_install.rst
@@ -45,7 +45,7 @@ available::
$ export ORPC_TEST_DB=odoorpc_test
$ export ORPC_TEST_USER=admin
$ export ORPC_TEST_PWD=admin
- $ export ORPC_TEST_VERSION=8.0
+ $ export ORPC_TEST_VERSION=10.0
$ export ORPC_TEST_SUPER_PWD=admin
$ python -m unittest discover -v
diff --git a/doc/source/faq.rst b/doc/source/faq.rst
index 2d440c1..2ea56a1 100644
--- a/doc/source/faq.rst
+++ b/doc/source/faq.rst
@@ -33,10 +33,10 @@ It was a tough decision, but several reasons motivated the `OdooRPC` project:
**New server API**
One goal of `OERPLib` was to give an API not too different from the server
side API to reduce the learning gap between server-side development and
- client-side with an `RPC` library. With the new 8.0 API which appears in
- `Odoo` 8.0 this is another brake (the old API will be removed one day), so
- the current API of `OERPLib` will not be consistent for the next years.
- As such, `OdooRPC` mimics A LOT the new API 8.0 of Odoo, for more
+ client-side with an `RPC` library. With the new API which appears in
+ `Odoo` 8.0 this is another brake (the old API has even been removed
+ since Odoo 10.0), so the current API of `OERPLib` is not anymore consistent.
+ As such, `OdooRPC` mimics A LOT the new API of Odoo, for more
consistency (see the :ref:`tutorials <tutorials>`).
**New brand Odoo**
@@ -46,7 +46,7 @@ It was a tough decision, but several reasons motivated the `OdooRPC` project:
confusing for newcomers in the `Odoo` world. So, `OdooRPC` speaks for
itself.
-**Maintening cost, code cleanup**
+**Maintenance cost, code cleanup**
`OpenERP` has evolved a lot since the version 5.0 (2009), making `OERPLib`
hard to maintain (write tests for all versions before each `OERPLib` and
`OpenERP` release is very time consuming). All the compatibility code for
@@ -126,7 +126,7 @@ for instance::
for session in odoorpc.ODOO.list():
odoo = odoorpc.ODOO.load(session)
- if v(odoo.version) > v('8.0'):
+ if v(odoo.version) < v('10.0'):
pass # do some stuff
else:
pass # do something else
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 4910266..c04bb86 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -10,7 +10,7 @@ Introduction
------------
**OdooRPC** is a Python module providing an easy way to
-pilot your **Odoo** servers through `RPC`.
+pilot your `Odoo <https://www.odoo.com>`_ servers through `RPC`.
Features supported:
- access to all data model methods (even ``browse``) with an API similar
@@ -79,7 +79,7 @@ Contents
Supported Odoo server versions
------------------------------
-`OdooRPC` has been tested on `Odoo` 8.0 and 9.0.
+`OdooRPC` has been tested on `Odoo` 8.0, 9.0 and 10.0.
It should work on next versions if `Odoo` keeps a stable API.
Supported Python versions
@@ -96,7 +96,7 @@ Bugs or suggestions
-------------------
Please, feel free to report bugs or suggestions in the `Bug Tracker
-<TODO>`_!
+<https://github.com/osiell/odoorpc/issues>`_!
Make a donation
---------------
diff --git a/doc/source/tuto_browse.rst b/doc/source/tuto_browse.rst
index e649b8f..4e3d7f3 100644
--- a/doc/source/tuto_browse.rst
+++ b/doc/source/tuto_browse.rst
@@ -40,10 +40,8 @@ and ``datetime.datetime``::
>>> Purchase = odoo.env['purchase.order']
>>> order = Purchase.browse(1)
- >>> order.minimum_planned_date
- datetime.date(2014, 10, 8)
>>> order.date_order
- datetime.datetime(2014, 10, 7, 20, 54, 21)
+ datetime.datetime(2016, 11, 6, 11, 23, 10)
A list of data types used by records fields are available :ref:`here <fields>`.
diff --git a/doc/source/tuto_browse_methods.rst b/doc/source/tuto_browse_methods.rst
index 0f79685..0ad1118 100644
--- a/doc/source/tuto_browse_methods.rst
+++ b/doc/source/tuto_browse_methods.rst
@@ -30,4 +30,4 @@ This is a behaviour `by design`: `OdooRPC` has no way to make the difference
between a `class` or an `instance` method through RPC, this is why it differs
from the `Odoo` API.
-:ref:`Next step: Update data through browsable records <tuto-update-browse-records>`
+:ref:`Next step: Update data through records <tuto-update-browse-records>`
diff --git a/doc/source/tuto_browse_update.rst b/doc/source/tuto_browse_update.rst
index 5ae32f4..c7e1720 100644
--- a/doc/source/tuto_browse_update.rst
+++ b/doc/source/tuto_browse_update.rst
@@ -1,29 +1,30 @@
.. _tuto-update-browse-records:
-Update data through browsable records
-*************************************
+Update data through records
+***************************
By default when updating values of a record, the change is automatically sent
to the server.
Let's update the name of a partner::
>>> Partner = odoo.env['res.partner']
- >>> partner = Partner.browse(1)
- >>> partner.name = "MyCompany"
+ >>> partner_id = Partner.create({'name': "Contact Test"})
+ >>> partner = Partner.browse(partner_id)
+ >>> partner.name = "MyContact"
This is equivalent to::
- >>> Partner.write([partner.id], {'name': "MyCompany"})
+ >>> Partner.write([partner.id], {'name': "MyContact"})
As one update is equivalent to one RPC query, if you need to update several
fields for one record it is encouraged to use the `write` method as above ::
- >>> partner.write({'name': "MyCompany", 'website': 'http://example.net'}) # one RPC query
+ >>> partner.write({'name': "MyContact", 'website': 'http://example.net'}) # one RPC query
Or, deactivate the ``auto_commit`` option and commit the changes manually::
>>> odoo.config['auto_commit'] = False
- >>> partner.name = "MyCompany"
+ >>> partner.name = "MyContact"
>>> partner.website = 'http://example.net'
>>> partner.env.commit() # one RPC by record modified
@@ -41,15 +42,15 @@ Same as above, except there is a check about the value assigned. For instance,
the field ``type`` of the ``res.partner`` model accept values contains
in ``['default', 'invoice', 'delivery', 'contact', 'other']``::
- >>> partner.type = 'default' # Ok
- >>> partner.type = 'foobar' # Error!
+ >>> partner.type = 'delivery' # Ok
+ >>> partner.type = 'foobar' # Error!
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "odoorpc/service/model/fields.py", line 148, in __set__
value = self.check_value(value)
File "odoorpc/service/model/fields.py", line 160, in check_value
field_name=self.name,
- ValueError: The value 'foobar' supplied doesn't match with the possible values '['default', 'invoice', 'delivery', 'contact', 'other']' for the 'type' field
+ ValueError: The value 'foobar' supplied doesn't match with the possible values '['contact', 'invoice', 'delivery', 'other']' for the 'type' field
Many2one
''''''''
@@ -57,7 +58,7 @@ Many2one
You can also update a ``many2one`` field, with either an ID or a record::
>>> partner.parent_id = 1 # with an ID
- >>> partner.parent_id = Partner.browse(1) # with a browsable record
+ >>> partner.parent_id = Partner.browse(1) # with a record object
You can't put any ID or record, a check is made on the relationship
to ensure data integrity::
@@ -78,8 +79,9 @@ One2many and Many2many
''''''''''''''''''''''
``one2many`` and ``many2many`` fields can be updated by providing
-a list of tuple as specified in the `OpenERP/Odoo` documentation, a list of
-records, a list of record IDs or an empty list or ``False``:
+a list of tuple as specified in the `Odoo` documentation
+(`link <https://github.com/odoo/odoo/blob/10.0/odoo/models.py#L3479>`_),
+a list of records, a list of record IDs, an empty list or ``False``:
With a tuple (as documented), no magic here::
@@ -142,13 +144,13 @@ With a record only::
Reference
'''''''''
-To update a ``reference`` field, you have to use either a string or a browsable
-record as below::
+To update a ``reference`` field, you have to use either a string or a record
+object as below::
>>> IrActionServer = odoo.env['ir.actions.server']
- >>> action_server = IrActionServer.browse(7)
- >>> action_server.ref_object = 'res.partner,1' # with a string with the format '{relation},{id}'
- >>> action_server.ref_object = Partner.browse(1) # with a browsable record
+ >>> action_server = IrActionServer.browse(8)
+ >>> action_server.ref_object = 'res.partner,1' # with a string with the format '{relation},{id}'
+ >>> action_server.ref_object = Partner.browse(1) # with a record object
A check is made on the relation name::
@@ -174,13 +176,12 @@ With ``datetime.date`` and ``datetime.datetime`` objects::
>>> import datetime
>>> Purchase = odoo.env['purchase.order']
>>> order = Purchase.browse(1)
- >>> order.date_order = datetime.date(2011, 9, 20)
- >>> order.minimum_planned_date = datetime.datetime(2011, 9, 20, 12, 31, 24)
+ >>> order.date_order = datetime.datetime(2016, 11, 7, 11, 23, 10)
With formated strings::
- >>> order.date_order = "2011-09-20" # %Y-%m-%d
- >>> order.minimum_planned_date = "2011-09-20 12:31:24" # %Y-%m-%d %H:%M:%S
+ >>> order.date_order = "2016-11-07" # %Y-%m-%d
+ >>> order.date_order = "2016-11-07 12:31:24" # %Y-%m-%d %H:%M:%S
As always, a wrong type will raise an exception::
@@ -191,6 +192,6 @@ As always, a wrong type will raise an exception::
value = self.check_value(value)
File "odoorpc/fields.py", line 203, in check_value
self.pattern))
- ValueError: Value not well formatted, expecting '%Y-%m-%d' format
+ ValueError: Value not well formatted, expecting '%Y-%m-%d %H:%M:%S' format
:ref:`Next step: Download reports <tuto-download-report>`
diff --git a/doc/source/tuto_login.rst b/doc/source/tuto_login.rst
index 81dcb27..0e30bf1 100644
--- a/doc/source/tuto_login.rst
+++ b/doc/source/tuto_login.rst
@@ -10,10 +10,10 @@ account of your choice::
.. note::
- Underhood the login method create a cookie, and all requests thereafter
- which need a user authentication are cookie-based.
+ Under the hood the login method creates a cookie, and all requests
+ thereafter which need a user authentication are cookie-based.
-Once logged, you can check some information through the
+Once logged in, you can check some information through the
:class:`environment <odoorpc.ODOO.env>`::
>>> odoo.env.db
@@ -27,7 +27,7 @@ Once logged, you can check some information through the
>>> odoo.env.user.name # name of the user
'Administrator'
>>> odoo.env.user.company_id.name # the name of its company
- 'Your Company'
+ 'YourCompany'
From now, you can easily execute any kind of queries on your
`Odoo` server (execute model methods, trigger workflow, download reports...).
diff --git a/doc/source/tuto_report.rst b/doc/source/tuto_report.rst
index 7cfebba..550dbe1 100644
--- a/doc/source/tuto_report.rst
+++ b/doc/source/tuto_report.rst
@@ -3,7 +3,7 @@
Download reports
****************
-Another nice functionnality is the reports generation with the
+Another nice feature is the reports generation with the
:attr:`report <odoorpc.ODOO.report>` property.
The :func:`list <odoorpc.report.Report.list>` method allows you to list
all reports available on your `Odoo` server (classified by models), while the
@@ -13,16 +13,16 @@ retrieve a report as a file (in PDF, HTML... depending of the report).
To list available reports::
>>> odoo.report.list()
- {u'ir.module.module': [{u'name': u'Technical guide', u'report_type': u'pdf', u'report_name': u'ir.module.reference'}], u'ir.model': [{u'name': u'Model Overview', u'report_type': u'sxw', u'report_name': u'ir.model.overview'}], u'res.partner': [{u'name': u'Labels', u'report_type': u'pdf', u'report_name': u'res.partner'}], u'res.company': [{u'name': u'Preview Report', u'report_type': u'pdf', u'report_name': u'preview.report'}]}
+ {u'account.invoice': [{u'name': u'Duplicates', u'report_type': u'qweb-pdf', u'report_name': u'account.account_invoice_report_duplicate_main'}, {u'name': u'Invoices', u'report_type': u'qweb-pdf', u'report_name': u'account.report_invoice'}], u'res.partner': [{u'name': u'Aged Partner Balance', u'report_type': u'qweb-pdf', u'report_name': u'account.report_agedpartnerbalance'}, {u'name': u'Due Payments', u'report_type': u'qweb-pdf', u'report_name': u'account.report_overdue'}], ...}
To download a report::
- >>> report = odoo.report.download('preview.report', [1])
+ >>> report = odoo.report.download('account.report_invoice', [1])
The method will return a file-like object, you will have to read its content
-in order to save it on your filesystem::
+in order to save it on your file-system::
- >>> with open('company_preview_report.pdf', 'w') as report_file:
+ >>> with open('invoice.pdf', 'w') as report_file:
... report_file.write(report.read())
...
diff --git a/doc/source/tuto_rpc_queries.rst b/doc/source/tuto_rpc_queries.rst
index fec7108..5ca7cbd 100644
--- a/doc/source/tuto_rpc_queries.rst
+++ b/doc/source/tuto_rpc_queries.rst
@@ -30,13 +30,13 @@ context automatically::
{'lang': 'fr_FR', 'tz': False}
>>> Product = odoo.env['product.product']
>>> Product.name_get([3, 4])
- [[3, '[PC1] PC Basic'], [4, '[PC2] Basic+ PC (assembl\xe9 sur commande)']]
+ [[3, '[SERV_COST] Audit externe''], [4, '[PROD_DEL] Commutateur, 24 ports']]
To stop sending the user context, use the :attr:`odoorpc.ODOO.config` property::
>>> odoo.config['auto_context'] = False
>>> Product.name_get([3, 4]) # Without context, lang 'en_US' by default
- [[3, '[PC1] Basic PC'], [4, '[PC2] Basic+ PC (assembly on order)']]
+ [[3, '[SERV_COST] External Audit'], [4, '[PROD_DEL] Switch, 24 ports']]
.. note::
diff --git a/doc/source/tuto_session.rst b/doc/source/tuto_session.rst
index e584ed9..27718c1 100644
--- a/doc/source/tuto_session.rst
+++ b/doc/source/tuto_session.rst
@@ -5,7 +5,7 @@ Save your credentials (session)
Once you are authenticated with your :class:`ODOO <odoorpc.ODOO>` instance, you
can :func:`save <odoorpc.ODOO.save>` your credentials under a code name and use
-this one to quickly instanciate a new :class:`ODOO <odoorpc.ODOO>` class::
+this one to quickly instantiate a new :class:`ODOO <odoorpc.ODOO>` class::
>>> import odoorpc
>>> odoo = odoorpc.ODOO('localhost')
diff --git a/doc/source/tutorials.rst b/doc/source/tutorials.rst
index 35ca5e6..00ed11d 100644
--- a/doc/source/tutorials.rst
+++ b/doc/source/tutorials.rst
@@ -3,6 +3,11 @@
Tutorials
=========
+.. note::
+
+ The tutorial is based on `Odoo 10.0`, the examples must be adapted
+ following the version of `Odoo` you are using.
+
.. toctree::
:maxdepth: 2
diff --git a/odoorpc/__init__.py b/odoorpc/__init__.py
index 5ea79fc..f4af113 100644
--- a/odoorpc/__init__.py
+++ b/odoorpc/__init__.py
@@ -28,7 +28,7 @@ automated jobs that communicate with a `Odoo` server.
__author__ = 'ABF Osiell - Sebastien Alix'
__email__ = 'sebastien.alix at osiell.com'
__licence__ = 'LGPL v3'
-__version__ = '0.4.1'
+__version__ = '0.5.1'
__all__ = ['ODOO', 'error']
diff --git a/odoorpc/error.py b/odoorpc/error.py
index 9936979..d359d7f 100644
--- a/odoorpc/error.py
+++ b/odoorpc/error.py
@@ -43,11 +43,12 @@ class RPCError(Error):
... pp(exc.info)
...
{'code': 200,
- 'data': {'arguments': ["'res.users' object has no attribute 'wrong_method'"],
+ 'data': {'arguments': ["type object 'res.users' has no attribute 'wrong_method'"],
'debug': 'Traceback (most recent call last):\\n File ...',
+ 'exception_type': 'internal_error',
'message': "'res.users' object has no attribute 'wrong_method'",
'name': 'exceptions.AttributeError'}
- 'message': 'OpenERP Server Error'}
+ 'message': 'Odoo Server Error'}
.. doctest::
:hide:
@@ -58,9 +59,15 @@ class RPCError(Error):
... except odoorpc.error.RPCError as exc:
... exc.info['code'] == 200
... 'message' in exc.info
- ... exc.info['data']['arguments'] == ["'res.users' object has no attribute 'wrong_method'"]
+ ... exc.info['data']['arguments'] in [
+ ... ["'res.users' object has no attribute 'wrong_method'"], # >= 8.0
+ ... ["type object 'res.users' has no attribute 'wrong_method'"], # >= 10.0
+ ... ]
... exc.info['data']['debug'].startswith('Traceback (most recent call last):\\n File')
- ... exc.info['data']['message'] == "'res.users' object has no attribute 'wrong_method'"
+ ... exc.info['data']['message'] in [
+ ... "'res.users' object has no attribute 'wrong_method'", # >= 8.0
+ ... "type object 'res.users' has no attribute 'wrong_method'", # >= 10.0
+ ... ]
... exc.info['data']['name'] == 'exceptions.AttributeError'
...
True
diff --git a/odoorpc/models.py b/odoorpc/models.py
index 67a85f8..6e5a1b8 100644
--- a/odoorpc/models.py
+++ b/odoorpc/models.py
@@ -63,6 +63,8 @@ class MetaModel(type):
def __getattr__(cls, method):
"""Provide a dynamic access to a RPC method."""
+ if method.startswith('_'):
+ return super(MetaModel, cls).__getattr__(method)
def rpc_method(*args, **kwargs):
"""Return the result of the RPC request."""
if cls._odoo.config['auto_context'] \
@@ -325,6 +327,8 @@ class Model(BaseModel):
True
"""
+ if method.startswith('_'):
+ return super(Model, self).__getattr__(method)
def rpc_method(*args, **kwargs):
"""Return the result of the RPC request."""
args = tuple([self.ids]) + args
diff --git a/odoorpc/odoo.py b/odoorpc/odoo.py
index ffaca4f..93d017d 100644
--- a/odoorpc/odoo.py
+++ b/odoorpc/odoo.py
@@ -46,7 +46,7 @@ class ODOO(object):
.. doctest::
:options: +SKIP
- >>> odoo = odoorpc.ODOO('localhost', version='8.0')
+ >>> odoo = odoorpc.ODOO('localhost', version='10.0')
*Python 2:*
@@ -73,9 +73,10 @@ class ODOO(object):
except ValueError:
raise ValueError("The port must be an integer")
try:
- timeout = int(timeout)
+ if timeout is not None:
+ timeout = float(timeout)
except ValueError:
- raise ValueError("The timeout must be an integer")
+ raise ValueError("The timeout must be a float")
self._host = host
self._port = port
self._protocol = protocol
@@ -152,7 +153,7 @@ class ODOO(object):
:options: +SKIP
>>> odoo.version
- '8.0'
+ '10.0'
"""
return self._connector.version
@@ -268,7 +269,7 @@ class ODOO(object):
return data
def http(self, url, data=None, headers=None):
- """Low level method to execute raw HTPP queries.
+ """Low level method to execute raw HTTP queries.
.. note::
@@ -281,7 +282,7 @@ class ODOO(object):
URL parameters (with :func:`urllib.urlencode` function for simple
parameters, or multipart/form-data structure to handle file upload).
- E.g., the HTTP raw query to backup a database on `Odoo 8.0`:
+ E.g., the HTTP raw query to get the company logo on `Odoo 10.0`:
.. doctest::
diff --git a/odoorpc/rpc/__init__.py b/odoorpc/rpc/__init__.py
index c328c89..da45c54 100644
--- a/odoorpc/rpc/__init__.py
+++ b/odoorpc/rpc/__init__.py
@@ -92,24 +92,47 @@ class ConnectorJSONRPC(Connector):
:options: +SKIP
>>> cnt.proxy_json.web.session.authenticate(db='db_name', login='admin', password='password')
- {'jsonrpc': '2.0', 'id': 202516757,
- 'result': {'username': 'admin', 'user_context': {'lang': 'fr_FR', 'tz': 'Europe/Brussels', 'uid': 1},
- 'db': 'db_name', 'company_id': 1, 'uid': 1, 'session_id': '308816f081394a9c803613895b988540'}}
+ {'id': 51373612,
+ 'jsonrpc': '2.0',
+ 'result': {'company_id': 1,
+ 'currencies': {'1': {'digits': [69, 2],
+ 'position': 'after',
+ 'symbol': '\u20ac'},
+ '3': {'digits': [69, 2],
+ 'position': 'before',
+ 'symbol': '$'}},
+ 'db': 'db_name',
+ 'is_admin': True,
+ 'is_superuser': True,
+ 'name': 'Administrator',
+ 'partner_id': 3,
+ 'server_version': '10.0',
+ 'server_version_info': [10, 0, 0, 'final', 0, ''],
+ 'session_id': '6dd7a34f16c1c67b38bfec413cca4962d5c01d53',
+ 'uid': 1,
+ 'user_companies': False,
+ 'user_context': {'lang': 'en_US',
+ 'tz': 'Europe/Brussels',
+ 'uid': 1},
+ 'username': 'admin',
+ 'web.base.url': 'http://localhost:8069',
+ 'web_tours': []}}
.. doctest::
:hide:
:options: +NORMALIZE_WHITESPACE
- >>> from pprint import pprint as pp
- >>> pp(cnt.proxy_json.web.session.authenticate(db=DB, login=USER, password=PWD))
- {'id': ...,
- 'jsonrpc': '2.0',
- 'result': {'company_id': 1,
- 'db': ...,
- 'session_id': ...,
- 'uid': 1,
- 'user_context': ...,
- 'username': 'admin'}}
+ >>> from odoorpc.tools import v
+ >>> data = cnt.proxy_json.web.session.authenticate(db=DB, login=USER, password=PWD)
+ >>> keys = ['company_id', 'db', 'session_id', 'uid', 'user_context', 'username']
+ >>> if v(VERSION) >= v('10.0'):
+ ... keys.extend([
+ ... 'currencies', 'is_admin', 'is_superuser', 'name',
+ ... 'partner_id', 'server_version', 'server_version_info',
+ ... 'user_companies', 'web.base.url', 'web_tours',
+ ... ])
+ >>> all([key in data['result'] for key in keys])
+ True
Read data of a partner:
diff --git a/odoorpc/session.py b/odoorpc/session.py
index bc04da8..fe874e4 100644
--- a/odoorpc/session.py
+++ b/odoorpc/session.py
@@ -79,7 +79,7 @@ def get_all(rc_file='~/.odoorpcrc'):
'host': conf.get(name, 'host'),
'protocol': conf.get(name, 'protocol'),
'port': conf.getint(name, 'port'),
- 'timeout': conf.getint(name, 'timeout'),
+ 'timeout': conf.getfloat(name, 'timeout'),
'user': conf.get(name, 'user'),
'passwd': conf.get(name, 'passwd'),
'database': conf.get(name, 'database'),
@@ -137,7 +137,7 @@ def get(name, rc_file='~/.odoorpcrc'):
'host': conf.get(name, 'host'),
'protocol': conf.get(name, 'protocol'),
'port': conf.getint(name, 'port'),
- 'timeout': conf.getint(name, 'timeout'),
+ 'timeout': conf.getfloat(name, 'timeout'),
'user': conf.get(name, 'user'),
'passwd': conf.get(name, 'passwd'),
'database': conf.get(name, 'database'),
diff --git a/odoorpc/tests/__init__.py b/odoorpc/tests/__init__.py
index d7fd2b8..fe24a78 100644
--- a/odoorpc/tests/__init__.py
+++ b/odoorpc/tests/__init__.py
@@ -23,31 +23,37 @@ class BaseTestCase(unittest.TestCase):
'db': os.environ.get('ORPC_TEST_DB', 'odoorpc_test'),
'user': os.environ.get('ORPC_TEST_USER', 'admin'),
'pwd': os.environ.get('ORPC_TEST_PWD', 'admin'),
- 'version': os.environ.get('ORPC_TEST_VERSION', '8.0'),
+ 'version': os.environ.get('ORPC_TEST_VERSION', None),
'super_pwd': os.environ.get('ORPC_TEST_SUPER_PWD', 'admin'),
}
self.odoo = odoorpc.ODOO(
self.env['host'], protocol=self.env['protocol'],
port=self.env['port'], version=self.env['version'])
# Create the database
+ default_timeout = self.odoo.config['timeout']
self.odoo.config['timeout'] = 600
if self.env['db'] not in self.odoo.db.list():
self.odoo.db.create(
self.env['super_pwd'], self.env['db'], True)
- self.odoo.config['timeout'] = 120
+ self.odoo.config['timeout'] = default_timeout
class LoginTestCase(BaseTestCase):
"""Instanciates an ``odoorpc.ODOO`` object and perform the user login."""
def setUp(self):
BaseTestCase.setUp(self)
+ default_timeout = self.odoo.config['timeout']
self.odoo.login(self.env['db'], self.env['user'], self.env['pwd'])
- # Install 'sale' and 'crm' modules
+ # Install 'sale' + 'crm_claim' on Odoo < 10.0,
+ # and 'sale' + 'subscription' on Odoo >= 10.0
self.odoo.config['timeout'] = 600
module_obj = self.odoo.env['ir.module.module']
- module_ids = module_obj.search([('name', 'in', ['sale', 'crm_claim'])])
+ modules = ['sale', 'crm_claim']
+ if self.odoo.version == '10.0':
+ modules = ['sale', 'subscription']
+ module_ids = module_obj.search([('name', 'in', modules)])
module_obj.button_immediate_install(module_ids)
- self.odoo.config['timeout'] = 120
+ self.odoo.config['timeout'] = default_timeout
# Get user record and model after the installation of modules
# to get all available fields (avoiding test failures)
self.user = self.odoo.env.user
diff --git a/odoorpc/tests/test_db.py b/odoorpc/tests/test_db.py
index b07bbf0..5bc4afc 100644
--- a/odoorpc/tests/test_db.py
+++ b/odoorpc/tests/test_db.py
@@ -11,6 +11,7 @@ class TestDB(BaseTestCase):
def setUp(self):
BaseTestCase.setUp(self)
+ self.odoo.logout()
self.databases = [] # Keep databases created during tests
def test_db_dump(self):
diff --git a/odoorpc/tests/test_field_binary.py b/odoorpc/tests/test_field_binary.py
new file mode 100644
index 0000000..bbe6871
--- /dev/null
+++ b/odoorpc/tests/test_field_binary.py
@@ -0,0 +1,38 @@
+# -*- coding: UTF-8 -*-
+
+import base64
+
+from odoorpc.tests import LoginTestCase
+
+
+class TestFieldBinary(LoginTestCase):
+
+ def test_field_binary_read(self):
+ img = self.user.image
+ base64.b64decode(img.encode('ascii'))
+
+ def test_field_binary_write(self):
+ backup = self.user.image
+ jpeg_file = (
+ b"\xff\xd8\xff\xdb\x00\x43\x00\x03\x02\x02\x02\x02\x02\x03\x02\x02"
+ b"\x02\x03\x03\x03\x03\x04\x06\x04\x04\x04\x04\x04\x08\x06\x06\x05"
+ b"\x06\x09\x08\x0a\x0a\x09\x08\x09\x09\x0a\x0c\x0f\x0c\x0a\x0b\x0e"
+ b"\x0b\x09\x09\x0d\x11\x0d\x0e\x0f\x10\x10\x11\x10\x0a\x0c\x12\x13"
+ b"\x12\x10\x13\x0f\x10\x10\x10\xff\xc9\x00\x0b\x08\x00\x01\x00\x01"
+ b"\x01\x01\x11\x00\xff\xcc\x00\x06\x00\x10\x10\x05\xff\xda\x00\x08"
+ b"\x01\x01\x00\x00\x3f\x00\xd2\xcf\x20\xff\xd9"
+ ) # https://github.com/mathiasbynens/small/blob/master/jpeg.jpg
+
+ self.user.image = base64.b64encode(jpeg_file).decode('ascii')
+ data = self.user.read(['image'])[0]
+ decoded = base64.b64decode(data['image'].encode('ascii'))
+ self.assertEqual(decoded, jpeg_file)
+
+ # Restore original value
+ self.user.image = backup
+ data = self.user.read(['image'])[0]
+ self.assertEqual(data['image'], backup)
+ self.assertEqual(self.user.image, backup)
+
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/odoorpc/tests/test_field_many2many.py b/odoorpc/tests/test_field_many2many.py
index 138cbe4..315df25 100644
--- a/odoorpc/tests/test_field_many2many.py
+++ b/odoorpc/tests/test_field_many2many.py
@@ -11,10 +11,17 @@ class TestFieldMany2many(LoginTestCase):
def setUp(self):
LoginTestCase.setUp(self)
self.group_obj = self.odoo.env['res.groups']
- self.u0_id = self.user_obj.create(
- {'name': "TestMany2many", 'login': 'test_m2m_%s' % time.time()})
+ self.u0_id = self.user_obj.create({
+ 'name': "TestMany2many User 1",
+ 'login': 'test_m2m_u1_%s' % time.time(),
+ })
self.g1_id = self.group_obj.create({'name': "Group 1"})
self.g2_id = self.group_obj.create({'name': "Group 2"})
+ self.u1_id = self.user_obj.create({
+ 'name': "TestMany2many User 2",
+ 'login': 'test_m2m_u2_%s' % time.time(),
+ 'groups_id': [(4, self.g1_id), (4, self.g2_id)],
+ })
def test_field_many2many_read(self):
self.assertIsInstance(self.user.company_ids, Model)
@@ -123,30 +130,28 @@ class TestFieldMany2many(LoginTestCase):
self.assertIn(self.g2_id, group_ids)
def test_field_many2many_write_isub_id(self):
- user = self.user_obj.browse(self.u0_id)
- group_id = user.read(['groups_id'])[0]['groups_id'][0]
+ user = self.user_obj.browse(self.u1_id)
+ self.assertIn(self.g1_id, user.groups_id.ids)
# -= ID
- user.groups_id -= group_id
+ user.groups_id -= self.g1_id
data = user.read(['groups_id'])[0]
- self.assertNotIn(group_id, data['groups_id'])
+ self.assertNotIn(self.g1_id, data['groups_id'])
group_ids = [grp.id for grp in user.groups_id]
- self.assertNotIn(group_id, group_ids)
+ self.assertNotIn(self.g1_id, group_ids)
def test_field_many2many_write_isub_record(self):
- user = self.user_obj.browse(self.u0_id)
- group = user.groups_id[0]
+ user = self.user_obj.browse(self.u1_id)
+ self.assertIn(self.g1_id, user.groups_id.ids)
# -= Record
- data = user.read(['groups_id'])[0]
- self.assertIn(group.id, data['groups_id'])
+ group = self.group_obj.browse(self.g1_id)
user.groups_id -= group
data = user.read(['groups_id'])[0]
self.assertNotIn(group.id, data['groups_id'])
- group_ids = [grp.id for grp in user.groups_id]
- self.assertNotIn(group.id, group_ids)
+ self.assertNotIn(group.id, user.groups_id.ids)
def test_field_many2many_write_isub_recordset(self):
- user = self.user_obj.browse(self.u0_id)
- groups = user.groups_id
+ user = self.user_obj.browse(self.u1_id)
+ groups = self.group_obj.browse([self.g1_id, self.g2_id])
# -= Recordset
data = user.read(['groups_id'])[0]
self.assertIn(groups.ids[0], data['groups_id'])
@@ -160,8 +165,8 @@ class TestFieldMany2many(LoginTestCase):
self.assertNotIn(groups.ids[1], group_ids)
def test_field_many2many_write_isub_list_ids(self):
- user = self.user_obj.browse(self.u0_id)
- groups = user.groups_id
+ user = self.user_obj.browse(self.u1_id)
+ groups = self.group_obj.browse([self.g1_id, self.g2_id])
# -= List of IDs
data = user.read(['groups_id'])[0]
self.assertIn(groups.ids[0], data['groups_id'])
@@ -175,8 +180,8 @@ class TestFieldMany2many(LoginTestCase):
self.assertNotIn(groups.ids[1], group_ids)
def test_field_many2many_write_isub_list_records(self):
- user = self.user_obj.browse(self.u0_id)
- groups = user.groups_id
+ user = self.user_obj.browse(self.u1_id)
+ groups = self.group_obj.browse([self.g1_id, self.g2_id])
# -= List of records
data = user.read(['groups_id'])[0]
self.assertIn(groups.ids[0], data['groups_id'])
@@ -190,8 +195,8 @@ class TestFieldMany2many(LoginTestCase):
self.assertNotIn(groups.ids[1], group_ids)
def test_field_many2many_write_isub_id_and_list_ids(self):
- user = self.user_obj.browse(self.u0_id)
- groups = user.groups_id
+ user = self.user_obj.browse(self.u1_id)
+ groups = self.group_obj.browse([self.g1_id, self.g2_id])
# -= ID and -= [ID]
data = user.read(['groups_id'])[0]
self.assertIn(groups.ids[0], data['groups_id'])
diff --git a/odoorpc/tests/test_field_reference.py b/odoorpc/tests/test_field_reference.py
index 5c0e52f..67f9e6c 100644
--- a/odoorpc/tests/test_field_reference.py
+++ b/odoorpc/tests/test_field_reference.py
@@ -2,25 +2,41 @@
from odoorpc.tests import LoginTestCase
from odoorpc.models import Model
+from odoorpc.tools import v
class TestFieldReference(LoginTestCase):
def test_field_reference_read(self):
- Claim = self.odoo.env['crm.claim']
- claim_id = Claim.search([])[0]
- # Test field containing a value
- self.odoo.execute(
- 'crm.claim', 'write', [claim_id], {'ref': 'res.partner,1'})
- claim = Claim.browse(claim_id)
- self.assertIsInstance(claim.ref, Model)
- self.assertEqual(claim.ref._name, 'res.partner')
- self.assertEqual(claim.ref.id, 1)
- # Test if empty field returns False (unable to guess the model to use)
- self.odoo.execute(
- 'crm.claim', 'write', [claim_id], {'ref': None})
- claim = Claim.browse(claim_id)
- self.assertEqual(claim.ref, False)
+ # 8.0 and 9.0
+ if v(self.odoo.version) < v('10'):
+ Claim = self.odoo.env['crm.claim']
+ claim_id = Claim.search([])[0]
+ # Test field containing a value
+ self.odoo.execute(
+ 'crm.claim', 'write', [claim_id], {'ref': 'res.partner,1'})
+ claim = Claim.browse(claim_id)
+ self.assertIsInstance(claim.ref, Model)
+ self.assertEqual(claim.ref._name, 'res.partner')
+ self.assertEqual(claim.ref.id, 1)
+ # Test if empty field returns False (unable to guess the model to use)
+ self.odoo.execute(
+ 'crm.claim', 'write', [claim_id], {'ref': None})
+ claim = Claim.browse(claim_id)
+ self.assertEqual(claim.ref, False)
+ # 10.0
+ else:
+ Subscription = self.odoo.env['subscription.subscription']
+ fields_list = list(Subscription.fields_get([]))
+ vals = Subscription.default_get(fields_list)
+ vals['name'] = "ODOORPC TEST (fields.Reference)"
+ vals['doc_source'] = 'res.partner,1'
+ subscription_id = Subscription.create(vals)
+ # Test field containing a value
+ subscription = Subscription.browse(subscription_id)
+ self.assertIsInstance(subscription.doc_source, Model)
+ self.assertEqual(subscription.doc_source._name, 'res.partner')
+ self.assertEqual(subscription.doc_source.id, 1)
def test_field_reference_write(self):
# TODO
diff --git a/odoorpc/tests/test_init.py b/odoorpc/tests/test_init.py
index 3d6a167..c81a489 100644
--- a/odoorpc/tests/test_init.py
+++ b/odoorpc/tests/test_init.py
@@ -35,6 +35,16 @@ class TestInit(BaseTestCase):
self.assertEqual(odoo.port, self.env['port'])
self.assertEqual(odoo.config['timeout'], 42)
+ def test_init_timeout_none(self):
+ odoo = odoorpc.ODOO(
+ self.env['host'], self.env['protocol'], self.env['port'], None)
+ self.assertIs(odoo.config['timeout'], None)
+
+ def test_init_timeout_float(self):
+ odoo = odoorpc.ODOO(
+ self.env['host'], self.env['protocol'], self.env['port'], 23.42)
+ self.assertEqual(odoo.config['timeout'], 23.42)
+
def test_init_wrong_protocol(self):
self.assertRaises(
ValueError,
diff --git a/setup.py b/setup.py
index 312597c..489a064 100644
--- a/setup.py
+++ b/setup.py
... 9 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-odoorpc.git
More information about the Python-modules-commits
mailing list