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.
is_json_output
¶
is_toon_output
¶
is_structured_output
¶
json_print
¶
Print data as JSON to stdout.
Used by display functions and CLI commands when --json is active.
toon_print
¶
Print data as TOON to stdout.
Used by display functions and CLI commands when --toon is active.
structured_print
¶
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
display_records
¶
Display records in a table, TSV, or JSON format.
| PARAMETER | DESCRIPTION |
|---|---|
records
|
List of record dictionaries
TYPE:
|
title
|
Table title
TYPE:
|
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
display_record_detail
¶
display_record_detail(record: dict[str, Any], *, show_html: bool = False, record_type: str = 'Record') -> None
Display detailed record information.
| PARAMETER | DESCRIPTION |
|---|---|
record
|
Record dictionary
TYPE:
|
show_html
|
If True, show raw HTML description, else convert to markdown
TYPE:
|
record_type
|
Human-readable record type (e.g., "Ticket", "Task")
TYPE:
|
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).
| 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 ID to post as (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).
| 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 ID to post as (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
display_tags
¶
Display tags in a table, TSV, or JSON format.
| PARAMETER | DESCRIPTION |
|---|---|
tags
|
List of tag dictionaries
TYPE:
|
title
|
Table title
TYPE:
|
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
display_messages
¶
Display messages in a formatted list or simple format.
| PARAMETER | DESCRIPTION |
|---|---|
messages
|
List of message dictionaries
TYPE:
|
show_html
|
Whether to show raw HTML body
TYPE:
|
Source code in src/vodoo/base.py
773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 | |
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
display_attachments
¶
Display attachments in a table, TSV, or JSON format.
| PARAMETER | DESCRIPTION |
|---|---|
attachments
|
List of attachment dictionaries
TYPE:
|
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.
Works with both sync OdooClient and async AsyncOdooClient —
only client.config.url is accessed.
| 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'