Base Operations¶
Shared CRUD, messaging, attachment, and display helpers. The DomainNamespace base class provides common methods inherited by all domain namespace classes.
base
¶
Base operations for Odoo models - shared functionality.
mask_binary_fields
¶
Replace binary field values with a human-readable size summary.
Binary fields in Odoo are returned as base64-encoded strings which can be
very large and flood terminal output. This function replaces them with a
placeholder like <binary 14.2 KB>.
| PARAMETER | DESCRIPTION |
|---|---|
records
|
List of record dictionaries (modified in place and returned).
TYPE:
|
binary_fields
|
Set of field names known to be binary.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict[str, Any]]
|
The same list with binary values replaced by summary strings. |
Source code in src/vodoo/base.py
detect_binary_fields
¶
detect_binary_fields(client: OdooClient, model: str, field_names: list[str] | None = None) -> set[str]
Return the set of field names that are binary type.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client
TYPE:
|
model
|
Model name
TYPE:
|
field_names
|
If given, only check these fields. Otherwise check all.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
set[str]
|
Set of field names with type |
Source code in src/vodoo/base.py
save_binary_field
¶
Decode a base64 binary field value and save to a file.
| PARAMETER | DESCRIPTION |
|---|---|
data
|
Base64-encoded string from Odoo.
TYPE:
|
output
|
Destination file path.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Path
|
The resolved output path. |
Source code in src/vodoo/base.py
list_records
¶
list_records(client: OdooClient, model: str, domain: list[Any] | None = None, limit: int | None = 50, fields: list[str] | None = None, order: str = 'create_date desc') -> list[dict[str, Any]]
List records from a model.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client
TYPE:
|
model
|
Model name (e.g., 'helpdesk.ticket', 'project.task')
TYPE:
|
domain
|
Search domain filters
TYPE:
|
limit
|
Maximum number of records
TYPE:
|
fields
|
List of fields to fetch (None = default fields)
TYPE:
|
order
|
Sort order
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict[str, Any]]
|
List of record dictionaries |
Source code in src/vodoo/base.py
get_record
¶
get_record(client: OdooClient, model: str, record_id: int, fields: list[str] | None = None) -> dict[str, Any]
Get detailed record information.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client
TYPE:
|
model
|
Model name
TYPE:
|
record_id
|
Record ID
TYPE:
|
fields
|
List of field names to read (None = all fields)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, Any]
|
Record dictionary |
| RAISES | DESCRIPTION |
|---|---|
RecordNotFoundError
|
If record not found |
Source code in src/vodoo/base.py
list_fields
¶
list_fields(client: OdooClient, model: str) -> dict[str, Any]
Get all available fields for a model.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client
TYPE:
|
model
|
Model name
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, Any]
|
Dictionary of field definitions with field names as keys |
Source code in src/vodoo/base.py
set_record_fields
¶
set_record_fields(client: OdooClient, model: str, record_id: int, values: dict[str, Any]) -> bool
Update fields on a record.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client
TYPE:
|
model
|
Model name
TYPE:
|
record_id
|
Record ID
TYPE:
|
values
|
Dictionary of field names and values to update
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
bool
|
True if successful |
Examples:
>>> set_record_fields(client, "project.task", 42, {"name": "New title", "priority": "1"})
>>> set_record_fields(client, "helpdesk.ticket", 42, {"user_id": 5, "stage_id": 3})
Source code in src/vodoo/base.py
add_comment
¶
add_comment(client: OdooClient, model: str, record_id: int, message: str, user_id: int | None = None, markdown: bool = True) -> bool
Add a comment to a record (visible to customers).
user_id requests displayed author attribution only. Cross-user attribution
requires an internal authenticated user; Odoo may reject or override it for share
users, which can reliably attribute only to their own partner.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client
TYPE:
|
model
|
Model name
TYPE:
|
record_id
|
Record ID
TYPE:
|
message
|
Comment message (plain text or markdown)
TYPE:
|
user_id
|
User whose partner is requested as author (uses default if None)
TYPE:
|
markdown
|
If True, convert markdown to HTML (default: True)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
bool
|
True if successful |
Source code in src/vodoo/base.py
add_note
¶
add_note(client: OdooClient, model: str, record_id: int, message: str, user_id: int | None = None, markdown: bool = True) -> bool
Add an internal note to a record (not visible to customers).
user_id requests displayed author attribution only. Cross-user attribution
requires an internal authenticated user; Odoo may reject or override it for share
users, which can reliably attribute only to their own partner.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client
TYPE:
|
model
|
Model name
TYPE:
|
record_id
|
Record ID
TYPE:
|
message
|
Note message (plain text or markdown)
TYPE:
|
user_id
|
User whose partner is requested as author (uses default if None)
TYPE:
|
markdown
|
If True, convert markdown to HTML (default: True)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
bool
|
True if successful |
Source code in src/vodoo/base.py
list_tags
¶
list_tags(client: OdooClient, model: str) -> list[dict[str, Any]]
List available tags for a model.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client
TYPE:
|
model
|
Tag model name (e.g., 'helpdesk.tag', 'project.tags')
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict[str, Any]]
|
List of tag dictionaries |
Source code in src/vodoo/base.py
add_tag_to_record
¶
add_tag_to_record(client: OdooClient, model: str, record_id: int, tag_id: int) -> bool
Add a tag to a record.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client
TYPE:
|
model
|
Model name
TYPE:
|
record_id
|
Record ID
TYPE:
|
tag_id
|
Tag ID
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
bool
|
True if successful |
Source code in src/vodoo/base.py
list_messages
¶
list_messages(client: OdooClient, model: str, record_id: int, limit: int | None = None) -> list[dict[str, Any]]
List messages/chatter for a record.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client
TYPE:
|
model
|
Model name
TYPE:
|
record_id
|
Record ID
TYPE:
|
limit
|
Maximum number of messages (None = all)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict[str, Any]]
|
List of message dictionaries |
Source code in src/vodoo/base.py
list_attachments
¶
list_attachments(client: OdooClient, model: str, record_id: int) -> list[dict[str, Any]]
List attachments for a record.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client
TYPE:
|
model
|
Model name
TYPE:
|
record_id
|
Record ID
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict[str, Any]]
|
List of attachment dictionaries |
Source code in src/vodoo/base.py
download_attachment
¶
download_attachment(client: OdooClient, attachment_id: int, output_path: Path | None = None) -> Path
Download an attachment.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client
TYPE:
|
attachment_id
|
Attachment ID
TYPE:
|
output_path
|
Output file path (defaults to attachment name in current dir)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Path
|
Path to downloaded file |
| RAISES | DESCRIPTION |
|---|---|
RecordNotFoundError
|
If attachment not found |
Source code in src/vodoo/base.py
download_record_attachments
¶
download_record_attachments(client: OdooClient, model: str, record_id: int, output_dir: Path | None = None, extension: str | None = None) -> list[Path]
Download all attachments for a record.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client
TYPE:
|
model
|
Model name
TYPE:
|
record_id
|
Record ID
TYPE:
|
output_dir
|
Output directory (defaults to current directory)
TYPE:
|
extension
|
File extension filter (e.g., 'pdf', 'jpg')
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[Path]
|
List of paths to downloaded files |
Source code in src/vodoo/base.py
get_attachment_data
¶
get_attachment_data(client: OdooClient, attachment_id: int) -> bytes
Read an attachment and return its raw binary content.
Unlike :func:download_attachment, the file is never written to disk;
the decoded bytes are returned directly.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client
TYPE:
|
attachment_id
|
Attachment ID
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
bytes
|
Raw bytes of the attachment |
| RAISES | DESCRIPTION |
|---|---|
RecordNotFoundError
|
If attachment not found or has no data |
Source code in src/vodoo/base.py
get_record_attachment_data
¶
get_record_attachment_data(client: OdooClient, model: str, record_id: int) -> list[tuple[int, str, bytes]]
Read all attachments for a record and return their binary content.
Unlike :func:download_record_attachments, files are never written to
disk; each attachment's decoded bytes are returned in-memory.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client
TYPE:
|
model
|
Model name
TYPE:
|
record_id
|
Record ID
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[tuple[int, str, bytes]]
|
List of |
list[tuple[int, str, bytes]]
|
Attachments with empty or missing |
Source code in src/vodoo/base.py
create_attachment
¶
create_attachment(client: OdooClient, model: str, record_id: int, file_path: Path | str | None = None, *, data: bytes | None = None, name: str | None = None) -> int
Create an attachment for a record.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client
TYPE:
|
model
|
Model name
TYPE:
|
record_id
|
Record ID
TYPE:
|
file_path
|
Path to file to attach (mutually exclusive with data)
TYPE:
|
data
|
Raw bytes to attach (mutually exclusive with file_path)
TYPE:
|
name
|
Attachment name (defaults to filename; required when using data)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
int
|
ID of created attachment |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If arguments are invalid |
FileNotFoundError
|
If file path is invalid |
Examples:
>>> create_attachment(client, "project.task", 42, "screenshot.png")
>>> create_attachment(client, "helpdesk.ticket", 42, "/path/to/file.pdf", name="Report.pdf")
>>> create_attachment(client, "project.task", 42, data=b"content", name="doc.txt")
Source code in src/vodoo/base.py
get_record_url
¶
get_record_url(client: OdooClient | Any, model: str, record_id: int) -> str
Get the web URL for a record.
Uses the canonical path URL for a selected JSON-2 transport and the legacy hash URL otherwise. Works with sync and async clients without making an additional request.
| PARAMETER | DESCRIPTION |
|---|---|
client
|
Odoo client (sync or async)
TYPE:
|
model
|
Model name
TYPE:
|
record_id
|
Record ID
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str
|
URL to view the record in Odoo web interface |
Examples:
>>> get_record_url(client, "helpdesk.ticket", 42)
'https://odoo.example.com/web#id=42&model=helpdesk.ticket&view_type=form'
Source code in src/vodoo/base.py
is_json_output
¶
is_toon_output
¶
is_structured_output
¶
json_print
¶
toon_print
¶
structured_print
¶
display_records
¶
display_record_detail
¶
display_record_detail(record: dict[str, Any], *, show_html: bool = False, record_type: str = 'Record') -> None
Deprecated compatibility shim for CLI record-detail rendering.
Source code in src/vodoo/base.py
display_tags
¶
display_messages
¶
Deprecated compatibility shim for CLI message rendering.