pyodoo-rpc-client (Odoo RPC)
Python client for the Odoo legacy RPC API (XML-RPC object/common services), intended for Odoo v19 and below.
For the Odoo JSON 2 API (v19+ compliant), use pyodoo-client.
Features
- XML-RPC
common+objectservice support. - ORM-like model accessor (
client.model("res.partner")). with_contextsupport on model instances.OdooRpcEntityconvenience wrapper withsave,delete,refresh.- Runtime debug behavior —
debug=Falsesuppresses errors and returns safe fallbacks;debug=Trueraises.
Installation
pip install pyodoo-rpc-client
Quick Start
from pyodoo_rpc_client import OdooRpcClient
odoo = OdooRpcClient(
url="https://mycompany.example.com",
db="mycompany",
username="api-user@example.com",
password="secret", # or use key= for an API key
debug=True,
)
partners = odoo.model("res.partner").search_read(
[["is_company", "=", True]],
fields=["name", "email"],
)
for p in partners:
print(p.id, p.name)
Authentication
# Username + password
odoo = OdooRpcClient(url=..., db=..., username=..., password="secret")
# Username + API key
odoo = OdooRpcClient(url=..., db=..., username=..., key="your-api-key")
After construction, odoo.logged_in is True when authentication succeeded.
OdooRpcClient
OdooRpcClient(
url, # Odoo base URL, e.g. "http://localhost:8069"
db, # database name
username, # login username
password=None, # password (use password or key, not both)
key=None, # API key (takes priority over password)
debug=False, # True → raises OdooRpcError on failure
allow_none=True,
)
Attributes
| Attribute | Description |
|---|---|
logged_in |
True when authenticated successfully |
uid |
Authenticated user ID |
error |
Last error, or None |
debug |
Current debug flag |
Methods
| Method | Description |
|---|---|
model(model_name) |
Returns an OdooRpcModel for the given Odoo model |
set_debug(bool) |
Toggle debug mode |
execute_kw(model, method, args, kwargs) |
Raw XML-RPC call |
OdooRpcModel
Obtained via odoo.model("res.partner").
Common methods
All domain arguments are standard Odoo domain lists, e.g. [["field", "operator", value]].
Additional Odoo keyword arguments (fields, limit, offset, order, context) are passed as keyword arguments.
model = odoo.model("res.partner")
# Search — returns list of IDs
ids = model.search([["is_company", "=", True]], limit=10)
# Read — returns list of dicts
records = model.read([1, 2, 3], fields=["name", "email"])
# Search + read in one call — returns list of OdooRpcEntity
partners = model.search_read(
[["is_company", "=", True]],
fields=["name", "email"],
limit=50,
order="name asc",
)
# Create — returns new record ID
new_id = model.create({"name": "ACME", "is_company": True})
# Write — returns True on success
model.write([new_id], {"name": "ACME Corp"})
# Unlink (delete) — returns True on success
model.unlink([new_id])
# Fields metadata
meta = model.fields_get([], attributes=["string", "type", "required"])
Context
# Attach context to all calls made on this model instance
model_fr = odoo.model("res.partner").with_context({"lang": "fr_FR"})
partners = model_fr.search_read([["is_company", "=", True]], fields=["name"])
# Or pass context per-call
partners = odoo.model("res.partner").search_read(
[["is_company", "=", True]],
fields=["name"],
context={"lang": "fr_FR"},
)
Arbitrary methods
Any Odoo model method can be called directly:
result = odoo.model("account.move").action_post(ids=[42])
OdooRpcEntity
search_read returns a list of OdooRpcEntity objects. Field values are accessible as attributes.
partners = odoo.model("res.partner").search_read(
[["is_company", "=", True]],
fields=["name", "email"],
)
for p in partners:
print(p.id, p.name, p.email)
# Load a single entity by ID
partner = odoo.model("res.partner").get(1)
# Refresh from the server
partner.refresh()
# Modify and save
partner.name = "Updated Name"
partner.save() # calls write() for existing records, create() for new ones
# Delete
partner.delete()
# Check if entity has an ID
partner.exists() # True / False
# Get field data as a dict
data = partner.get_data(["name", "email"])
changed = partner.get_changed_data() # only fields changed since load
Error Handling
# debug=False (default): safe fallback returned, error stored on client/model
odoo = OdooRpcClient(..., debug=False)
result = odoo.model("res.partner").search_read([["id", "=", -1]])
# result → []
# odoo.model(...).error or odoo.error holds the exception
# debug=True: raises OdooRpcError immediately
from pyodoo_rpc_client.exceptions import OdooRpcError
odoo = OdooRpcClient(..., debug=True)
try:
result = odoo.model("res.partner").search_read([["bad_field", "=", 1]])
except OdooRpcError as e:
print(e)
Compatibility Notes
- Targets the Odoo XML-RPC API (
/xmlrpc/2/common,/xmlrpc/2/object), available in Odoo v8–v19. - For the Odoo JSON 2 API (v19+), use
pyodoo-clientinstead.
Contributing
- Open Issues for bugs and concrete feature requests.
- Open Pull Requests for code/docs improvements.
- For open-ended questions and ideas, use GitHub Discussions.
- See
CONTRIBUTING.mdfor workflow and expectations.
Development
# Install locally in editable mode (changes take effect immediately)
pip install -e .
# Build a distribution
pip install build twine
python -m build
python -m twine check dist/*
Metadata
Release files for pyodoo-rpc-client 18.0.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pyodoo_rpc_client-18.0.6.tar.gz | 10.3 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyodoo_rpc_client-18.0.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 19.0 kB
Release files / pyodoo_rpc_client-18.0.6.tar.gz
| Download URL | pyodoo_rpc_client-18.0.6.tar.gz |
|---|---|
| Size | 10.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
09b922326a52276727d2ef5998febc6de78521d24003478190b1d1a9a28d913a
|
|
BLAKE2b-256 checksum How to use checksums |
c1ab18a9b7ae5fd4d18032f1b529c3335c78204c1f4561772d63cd89d8342ca9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / pyodoo_rpc_client-18.0.6-py3-none-any.whl
| Download URL | pyodoo_rpc_client-18.0.6-py3-none-any.whl |
|---|---|
| Size | 8.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
44b11488d0d9e034c1fee37bc8aafcb17fa6d613b8a41fe398ce6df1df49e40c
|
|
BLAKE2b-256 checksum How to use checksums |
09f43f6ce6bfd96d07fda9c9c3a78eceafcbb1d4210bee2c94dfc0b6a9d968ed
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Security for pyodoo-rpc-client 18.0.6
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.