Skip to content

Async Documents

AsyncDocumentNamespace for the documents.document model (Odoo Enterprise), accessed as client.documents on AsyncOdooClient.

documents

Async Odoo Documents operations for Vodoo.

AsyncDocumentNamespace

AsyncDocumentNamespace(client: AsyncOdooClient)

Bases: GeneratedAsyncDocumentNamespace

Async namespace for the documents.document model.

Source code in src/vodoo/aio/_domain.py
def __init__(self, client: AsyncOdooClient) -> None:
    self._client = client

folders async

folders(limit: int | None = 50, *, tree: bool = False) -> list[dict[str, Any]]

List accessible folders, normalizing parent relationships across Odoo versions.

Source code in src/vodoo/aio/documents.py
async def folders(self, limit: int | None = 50, *, tree: bool = False) -> list[dict[str, Any]]:
    """List accessible folders, normalizing parent relationships across Odoo versions."""
    modern = await self._uses_document_folder_records()
    model = self._model if modern else "documents.folder"
    fields = list(_MODERN_FOLDER_FIELDS if modern else _LEGACY_FOLDER_FIELDS)
    records = await self._client.search_read(
        model,
        domain=_folder_domain(modern),
        fields=fields,
        limit=limit,
        order="name, id",
    )
    folders = _normalize_modern_folders(records) if modern else records
    return _order_folder_tree(folders) if tree else folders

resolve_folder async

resolve_folder(folder: int | str) -> int

Resolve a positive folder ID or exact folder name to its record ID.

Source code in src/vodoo/aio/documents.py
async def resolve_folder(self, folder: int | str) -> int:
    """Resolve a positive folder ID or exact folder name to its record ID."""
    numeric_id = _numeric_id(folder)
    if numeric_id is not None:
        return numeric_id
    return await self._resolve_folder(str(folder), None)

upload async

upload(file_path: Path | str, *, folder: int | str | None = None, folder_id: int | None = None, tags: list[str | int] | None = None, owner: str | int | None = None, name: str | None = None) -> int

Upload a file, specifying exactly one of folder or folder_id.

Optional tags and owner may be resolved by positive ID or exact name.

Source code in src/vodoo/aio/documents.py
async def upload(
    self,
    file_path: Path | str,
    *,
    folder: int | str | None = None,
    folder_id: int | None = None,
    tags: list[str | int] | None = None,
    owner: str | int | None = None,
    name: str | None = None,
) -> int:
    """Upload a file, specifying exactly one of ``folder`` or ``folder_id``.

    Optional tags and owner may be resolved by positive ID or exact name.
    """
    resolved_folder_id = await self._resolve_folder(folder, folder_id)
    tag_ids = [await self._resolve_named_record("documents.tag", tag) for tag in tags or []]
    owner_id = (
        await self._resolve_named_record("res.users", owner) if owner is not None else None
    )
    values = _prepare_document_values(
        file_path,
        folder_id=resolved_folder_id,
        name=name,
        tag_ids=tag_ids,
        owner_id=owner_id,
    )
    return await self._client.create(self._model, values)

download_file async

download_file(document_id: int, output: Path | str | None = None) -> Path

Download a document and return the resolved output path.

Source code in src/vodoo/aio/documents.py
async def download_file(self, document_id: int, output: Path | str | None = None) -> Path:
    """Download a document and return the resolved output path."""
    records = await self._client.read(
        self._model,
        [document_id],
        fields=["name", "type", "file_size", "datas"],
    )
    if not records:
        raise RecordNotFoundError(self._model, document_id)

    document = records[0]
    data = _decode_document_data(document, document_id)
    filename = _safe_document_filename(document.get("name"), document_id)
    output_path = Path(output) if output is not None else Path.cwd() / filename
    if output_path.is_dir():
        output_path /= filename
    output_path.parent.mkdir(parents=True, exist_ok=True)
    output_path.write_bytes(data)
    return output_path.resolve()