# Odoo Connect
A simple library to use Odoo RPC.
[![PyPI version](https://badge.fury.io/py/odoo-connect.svg)](https://pypi.org/project/odoo-connect/)
## Usage
```python
import odoo_connect
odoo = env = odoo_connect.connect(url='http://localhost:8069', username='admin', password='admin')
so = env['sale.order']
so.search_read([('create_uid', '=', 1)], [])
```
## Rationale
[OdooRPC](https://pypi.org/project/OdooRPC/)
or [Odoo RPC Client](https://pypi.org/project/odoo-rpc-client/)
are both more complete and mimic internal Odoo API.
Then [aio-odoorpc](https://pypi.org/project/aio-odoorpc/) provides
an asynchronous API.
This library provides only a simple API for connecting to the server
and call methods, so the maintenance should be minimal.
Note that each RPC call is executed in a transaction.
So the following code on the server, will add one to every line ordered
quantity or fail and do nothing.
However, RPC client libraries will perform multiple steps, on a failure,
already executed code was committed. You can end with race conditions
where some other code sets product_uom_qty to 0 before you increment it.
A better way of doing this is to implement a function on Odoo side and call it.
```python
lines = env['sale.order.line'].search([
('order_id.name', '=', 'S00001')
])
# this is fine on the server, but not in RPC (multiple transactions)
for line in lines:
if line.product_uom_qty > 1:
line.product_uom_qty += 1
# single transaction
lines.increment_qty([('product_uom_qty', '>', 1)])
```
## Export and import data
A separate package provides utilities to more easily extract data from Odoo.
It also contains utility to get binary data (attachments) and reports;
however this requires administrative permissions.
Since Odoo doesn't accept all kind of values, the `format` package will help
with converting between python values and values returned by Odoo.
The provided function will return a table-like (list of lists) structure
with the requested data.
You can also pass `ir.filters` names or `ir.exports` names instead of,
respectively, domains and fields. Note that this doesn't support groupping.
```python
import odoo_connect.data as odoo_data
so = env['sale.order']
# Read data as usual
data = so.search_read_dict([('state', '=', 'sale')], ['name', 'partner_id.name'])
so.read_group([], ['amount_untaxed'], ['partner_id', 'create_date:month'])
odoo_data.add_url(so, data)
# Exporting flattened data
all_data = odoo_data.export_data(so, [('state', '=', 'sale')], ['name', 'partner_id.name'])
with io.StringIO(newline='') as f:
w = csv.writer(f, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
w.writerows(all_data.to_csv())
all_data.to_pandas() # as a data frame
all_data.to_dbapi(con, 'table_name') # create a table
# Import data using Odoo's load() function
odoo_data.load_data(so, data)
# Import data using writes and creates (or another custom method)
for batch in odoo_data.make_batches(data):
# add ids by querying the model using the 'name' field
# if you remove 'id' from the data, only create() is called
odoo_data.add_fields(so, batch, 'name', ['id'])
odoo_data.load_data(so, batch, method='write')
```
## Explore
Provides a simple abstraction for querying data with a local cache.
It may be easier than executing and parsing a `read()`.
Also, auto-completion for fields is provided in jupyter.
```python
from odoo_connect.explore import explore
sale_order = explore(env['sale.order'])
sale_order = sale_order.search([], limit=1)
sale_order.read()
```
## Development
You can use a vscode container and open this repository inside it.
Alternatively, clone and setup the repository manually.
```bash
git clone $url
cd odoo-connect
# Install dev libraries
pip install -r requirements.txt
./pre-commit install
# Run some tests
pytest
```
Raw data
{
"_id": null,
"home_page": "",
"name": "odoo-connect",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "",
"keywords": "odoo,rpc",
"author": "",
"author_email": "Krzysztof Magusiak <chrmag@poczta.onet.pl>",
"download_url": "https://files.pythonhosted.org/packages/3f/13/6ac469c50c5c2e03fbfecd8472e7f6c611d4c8a78c0b7d19c7cc149fb6d8/odoo-connect-0.5.0.tar.gz",
"platform": null,
"description": "# Odoo Connect\n\nA simple library to use Odoo RPC.\n\n[![PyPI version](https://badge.fury.io/py/odoo-connect.svg)](https://pypi.org/project/odoo-connect/)\n\n## Usage\n\n```python\nimport odoo_connect\nodoo = env = odoo_connect.connect(url='http://localhost:8069', username='admin', password='admin')\nso = env['sale.order']\nso.search_read([('create_uid', '=', 1)], [])\n```\n\n## Rationale\n\n[OdooRPC](https://pypi.org/project/OdooRPC/)\nor [Odoo RPC Client](https://pypi.org/project/odoo-rpc-client/)\nare both more complete and mimic internal Odoo API.\nThen [aio-odoorpc](https://pypi.org/project/aio-odoorpc/) provides\nan asynchronous API.\n\nThis library provides only a simple API for connecting to the server\nand call methods, so the maintenance should be minimal.\n\nNote that each RPC call is executed in a transaction.\nSo the following code on the server, will add one to every line ordered\nquantity or fail and do nothing.\nHowever, RPC client libraries will perform multiple steps, on a failure,\nalready executed code was committed. You can end with race conditions\nwhere some other code sets product_uom_qty to 0 before you increment it.\nA better way of doing this is to implement a function on Odoo side and call it.\n\n```python\nlines = env['sale.order.line'].search([\n\t('order_id.name', '=', 'S00001')\n])\n# this is fine on the server, but not in RPC (multiple transactions)\nfor line in lines:\n\tif line.product_uom_qty > 1:\n\t\tline.product_uom_qty += 1\n# single transaction\nlines.increment_qty([('product_uom_qty', '>', 1)])\n```\n\n## Export and import data\n\nA separate package provides utilities to more easily extract data from Odoo.\nIt also contains utility to get binary data (attachments) and reports;\nhowever this requires administrative permissions.\n\nSince Odoo doesn't accept all kind of values, the `format` package will help\nwith converting between python values and values returned by Odoo.\n\nThe provided function will return a table-like (list of lists) structure\nwith the requested data.\nYou can also pass `ir.filters` names or `ir.exports` names instead of,\nrespectively, domains and fields. Note that this doesn't support groupping.\n\n```python\nimport odoo_connect.data as odoo_data\nso = env['sale.order']\n\n# Read data as usual\ndata = so.search_read_dict([('state', '=', 'sale')], ['name', 'partner_id.name'])\nso.read_group([], ['amount_untaxed'], ['partner_id', 'create_date:month'])\nodoo_data.add_url(so, data)\n\n# Exporting flattened data\nall_data = odoo_data.export_data(so, [('state', '=', 'sale')], ['name', 'partner_id.name'])\nwith io.StringIO(newline='') as f:\n w = csv.writer(f, delimiter=',', quotechar='\"', quoting=csv.QUOTE_MINIMAL)\n w.writerows(all_data.to_csv())\nall_data.to_pandas() # as a data frame\nall_data.to_dbapi(con, 'table_name') # create a table\n\n# Import data using Odoo's load() function\nodoo_data.load_data(so, data)\n\n# Import data using writes and creates (or another custom method)\nfor batch in odoo_data.make_batches(data):\n\t# add ids by querying the model using the 'name' field\n\t# if you remove 'id' from the data, only create() is called\n\todoo_data.add_fields(so, batch, 'name', ['id'])\n\todoo_data.load_data(so, batch, method='write')\n```\n\n## Explore\n\nProvides a simple abstraction for querying data with a local cache.\nIt may be easier than executing and parsing a `read()`.\nAlso, auto-completion for fields is provided in jupyter.\n\n```python\nfrom odoo_connect.explore import explore\nsale_order = explore(env['sale.order'])\nsale_order = sale_order.search([], limit=1)\nsale_order.read()\n```\n\n## Development\n\nYou can use a vscode container and open this repository inside it.\nAlternatively, clone and setup the repository manually.\n\n```bash\ngit clone $url\ncd odoo-connect\n# Install dev libraries\npip install -r requirements.txt\n./pre-commit install\n# Run some tests\npytest\n```\n",
"bugtrack_url": null,
"license": "GNU Lesser General Public License v3 (LGPLv3)",
"summary": "Simple RPC client for Odoo",
"version": "0.5.0",
"project_urls": {
"Homepage": "https://github.com/kmagusiak/odoo-connect"
},
"split_keywords": [
"odoo",
"rpc"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "3e357fce2fee982c9ab65baaa3baccc7d9212efb86d67994850c04455c714d07",
"md5": "63ecc7db3781c89f53d49a0bf1fc2aaf",
"sha256": "11e80205ef89fa37a774f6c1d6c26b04d2128aa92aa095d17b9c5abbdeac9432"
},
"downloads": -1,
"filename": "odoo_connect-0.5.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "63ecc7db3781c89f53d49a0bf1fc2aaf",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 26131,
"upload_time": "2024-01-02T15:16:46",
"upload_time_iso_8601": "2024-01-02T15:16:46.496989Z",
"url": "https://files.pythonhosted.org/packages/3e/35/7fce2fee982c9ab65baaa3baccc7d9212efb86d67994850c04455c714d07/odoo_connect-0.5.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "3f136ac469c50c5c2e03fbfecd8472e7f6c611d4c8a78c0b7d19c7cc149fb6d8",
"md5": "0a7cd8ab9c1f9c9d966ce705266f8910",
"sha256": "4547544849e56f83444734e2ee79f12c2678296cc94c0c3401069b43714f0dd2"
},
"downloads": -1,
"filename": "odoo-connect-0.5.0.tar.gz",
"has_sig": false,
"md5_digest": "0a7cd8ab9c1f9c9d966ce705266f8910",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 35170,
"upload_time": "2024-01-02T15:16:48",
"upload_time_iso_8601": "2024-01-02T15:16:48.519969Z",
"url": "https://files.pythonhosted.org/packages/3f/13/6ac469c50c5c2e03fbfecd8472e7f6c611d4c8a78c0b7d19c7cc149fb6d8/odoo-connect-0.5.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-01-02 15:16:48",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "kmagusiak",
"github_project": "odoo-connect",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"lcname": "odoo-connect"
}