OdooOperations

OdooOperations provides the preferred high-level Python API for running Odoo, installing or updating addons, running tests, planning addon changes, and performing safe read-only inspection.

For read-only data access inside Odoo models, prefer OdooQuery or the higher-level OdooInspector-backed methods such as inspect_ref(), inspect_model(), and inspect_field(). Use execute_python_code() only for trusted shell-driven execution flows, with either an explicit shell_interface=... argument or shell_interface set in the environment configuration.

class oduit.odoo_operations.OdooOperations(env_config: dict, verbose: bool = False)[source]

Bases: object

Compatibility facade over smaller internal Odoo operation services.

__init__(env_config: dict, verbose: bool = False)[source]
run_odoo(no_http: bool = False, dev: str | None = None, log_level: str | None = None, stop_after_init: bool = False) None[source]

Start the Odoo server with the specified configuration.

run_shell(shell_interface: str | None = 'python', no_http: bool = True, compact: bool = False, log_level: str | None = None) dict[source]

Start an interactive Odoo shell or execute piped commands.

update_module(module: str, no_http: bool = False, suppress_output: bool = False, raise_on_error: bool = False, compact: bool = False, log_level: str | None = None, max_cron_threads: int | None = None, without_demo: str | bool = False, stop_after_init: bool = True, i18n_overwrite: bool = False, language: str | None = None) dict[source]

Update a module and return operation result

install_module(module: str, verbose: bool = False, no_http: bool = False, suppress_output: bool = False, raise_on_error: bool = False, compact: bool = False, max_cron_threads: int | None = None, log_level: str | None = None, without_demo: str | bool = False, language: str | None = None, with_demo: bool = False, stop_after_init: bool = True) dict[source]

Install a module and return operation result

export_module_language(module: str, filename: str, language: str, no_http: bool = False, log_level: str | None = None, suppress_output: bool = False) dict[source]

Export language translations for a specific module to a file.

run_tests(module: str | None = None, stop_on_error: bool = False, install: str | None = None, update: str | None = None, coverage: str | None = None, test_file: str | None = None, test_tags: str | None = None, compact: bool = False, suppress_output: bool = False, raise_on_error: bool = False, log_level: str | None = None) dict[source]

Run tests for a module

db_exists(with_sudo: bool = True, suppress_output: bool = False, raise_on_error: bool = False, db_user: str | None = None) dict[source]

Check if database exists and return operation result

drop_db(with_sudo: bool = True, suppress_output: bool = False, raise_on_error: bool = False) dict[source]

Drop database and return operation result

create_db(with_sudo: bool = True, suppress_output: bool = False, create_role: bool = False, alter_role: bool = False, extension: str | None = None, raise_on_error: bool = False, db_user: str | None = None, with_demo: bool = False, without_demo: bool = False, country: str | None = None, language: str | None = None, username: str = 'admin', password: str = 'admin', odoo_series: OdooSeries | None = None) dict[source]

Create database and return operation result

list_db(with_sudo: bool = True, suppress_output: bool = False, raise_on_error: bool = False, db_user: str | None = None) dict[source]

List all databases and return operation result

create_addon(addon_name: str, destination: str | None = None, template: str | None = None, suppress_output: bool = False) dict[source]

Create a new Odoo addon using the scaffold command.

get_odoo_version(suppress_output: bool = False, raise_on_error: bool = False) dict[source]

Get the Odoo version from odoo-bin

get_environment_context(env_name: str | None = None, config_source: str | None = None, config_path: str | None = None, odoo_series: OdooSeries | None = None) EnvironmentContext[source]

Return a typed environment snapshot for planning and inspection.

inspect_addon(module_name: str, odoo_series: OdooSeries | None = None) AddonInspection[source]

Return a typed inspection payload for one addon.

addon_info(module_name: str, *, odoo_series: OdooSeries | None = None, database: str | None = None, timeout: float = 30.0) AddonInfo[source]

Return a combined addon summary for onboarding and planning.

plan_update(module_name: str, odoo_series: OdooSeries | None = None) UpdatePlan[source]

Return a typed, read-only update plan for one addon.

inspect_addons(module_names: list[str], odoo_series: OdooSeries | None = None) list[AddonInspection][source]

Return typed inspection payloads for multiple addons.

locate_model(module_name: str, model: str) ModelSourceLocation[source]

Return static source candidates for a model extension.

locate_field(module_name: str, model: str, field_name: str) FieldSourceLocation[source]

Return static field source candidates inside one addon.

list_addon_tests(module_name: str, model: str | None = None, field_name: str | None = None) AddonTestInventory[source]

Return likely addon test files for one addon.

list_addon_models(module_name: str) AddonModelInventory[source]

Return a static model inventory for one addon.

recommend_tests(module_name: str, paths: list[str]) dict[str, Any][source]

Return changed-file to test recommendations for one addon.

find_model_extensions(model: str, database: str | None = None, timeout: float = 30.0, source_roots: list[tuple[str, str]] | None = None, scan_cache: SourceScanCache | None = None) ModelExtensionInventory[source]

Return combined source and installed metadata for one model.

list_duplicates() dict[str, list[str]][source]

Return duplicate module names across configured addon paths.

list_addons_inventory(module_names: list[str], odoo_series: OdooSeries | None = None) list[dict[str, Any]][source]

Return structured addon inventory records.

get_addon_install_state(module: str, *, database: str | None = None, timeout: float = 30.0) AddonInstallState[source]

Return the runtime install state for one addon.

list_installed_dependents(module: str, *, database: str | None = None, timeout: float = 30.0) InstalledAddonInventory[source]

Return installed addons that depend on the target module.

uninstall_module(module: str, *, suppress_output: bool = False, raise_on_error: bool = False, compact: bool = False, log_level: str | None = None, allow_uninstall: bool = False, check_dependents: bool = True) dict[str, Any][source]

Uninstall a module through a trusted runtime action.

list_installed_addons(*, modules: list[str] | None = None, states: list[str] | None = None, database: str | None = None, timeout: float = 30.0) InstalledAddonInventory[source]

Return runtime addon inventory from ir.module.module.

dependency_graph(module_names: list[str]) dict[str, Any][source]

Return dependency graph data for one or more addons.

build_addon_documentation(module_name: str, *, odoo_series: OdooSeries | None = None, database: str | None = None, timeout: float = 30.0, source_only: bool = False, include_arch: bool = False, field_attributes: list[str] | tuple[str, ...] | None = None, view_types: list[str] | tuple[str, ...] | None = None, max_models: int | None = None, max_fields_per_model: int | None = None, path_prefix: str | None = None, progress: Callable[[str, dict[str, Any]], None] | None = None, progress_level: str = 'compact') AddonDocumentation[source]

Build one addon documentation bundle.

build_model_documentation(model: str, *, database: str | None = None, timeout: float = 30.0, source_only: bool = False, include_arch: bool = False, field_attributes: list[str] | tuple[str, ...] | None = None, view_types: list[str] | tuple[str, ...] | None = None, max_fields: int | None = None, source_modules: list[str] | tuple[str, ...] | None = None, path_prefix: str | None = None) ModelDocumentation[source]

Build one model documentation bundle.

build_addons_documentation(module_names: list[str], *, odoo_series: OdooSeries | None = None, database: str | None = None, timeout: float = 30.0, source_only: bool = False, include_arch: bool = False, field_attributes: list[str] | tuple[str, ...] | None = None, view_types: list[str] | tuple[str, ...] | None = None, max_models: int | None = None, max_fields_per_model: int | None = None, path_prefix: str | None = None) MultiAddonDocumentation[source]

Build one documentation bundle spanning multiple addons.

build_technical_documentation(target: str, *, template: str = 'arc42', odoo_series: OdooSeries | None = None, database: str | None = None, timeout: float = 30.0, source_only: bool = False, include_arch: bool = False, field_attributes: list[str] | tuple[str, ...] | None = None, view_types: list[str] | tuple[str, ...] | None = None, max_models: int | None = None, max_fields_per_model: int | None = None, path_prefix: str | None = None, path_base_dir: str | None = None, documentation_policy: DocumentationDirectoryPolicy | None = None, progress: Callable[[str, dict[str, Any]], None] | None = None, progress_level: str = 'compact', render_markdown: bool = True) TechnicalDocumentation[source]

Build one technical-documentation bundle for an addon target.

refresh_technical_documentation(target: str, *, odoo_series: OdooSeries | None = None, database: str | None = None, timeout: float = 30.0, source_only: bool | None = None, include_arch: bool | None = None, field_attributes: list[str] | tuple[str, ...] | None = None, view_types: list[str] | tuple[str, ...] | None = None, max_models: int | None = None, max_fields_per_model: int | None = None, path_prefix: str | None = None, path_base_dir: str | None = None, documentation_policy: DocumentationDirectoryPolicy | None = None, overwrite_edited: bool = False, add_missing: bool = False, write: bool = False) dict[str, Any][source]

Refresh managed generated blocks in addon-local architecture docs.

build_technical_evidence(target: str, *, template: str = 'arc42', odoo_series: OdooSeries | None = None, database: str | None = None, timeout: float = 30.0, source_only: bool = False, include_arch: bool = False, field_attributes: list[str] | tuple[str, ...] | None = None, view_types: list[str] | tuple[str, ...] | None = None, max_models: int | None = None, max_fields_per_model: int | None = None, path_prefix: str | None = None, path_base_dir: str | None = None, documentation_policy: DocumentationDirectoryPolicy | None = None, progress: Callable[[str, dict[str, Any]], None] | None = None, progress_level: str = 'compact', render_markdown: bool = True, evidence_version: int | None = None) TechnicalDocumentation[source]

Build split deterministic technical evidence bundle.

write_technical_evidence(target: str, *, force: bool = False, template: str = 'arc42', odoo_series: OdooSeries | None = None, database: str | None = None, timeout: float = 30.0, source_only: bool = False, include_arch: bool = False, field_attributes: list[str] | tuple[str, ...] | None = None, view_types: list[str] | tuple[str, ...] | None = None, max_models: int | None = None, max_fields_per_model: int | None = None, path_base_dir: str | None = None, documentation_policy: DocumentationDirectoryPolicy | None = None, progress: Callable[[str, dict[str, Any]], None] | None = None, progress_level: str = 'compact') dict[str, Any][source]

Write split deterministic evidence markdown and sidecar.

build_technical_report_seed(target: str, *, evidence_metadata: Any | None = None, generate_evidence_if_missing: bool = True, template: str = 'arc42', odoo_series: OdooSeries | None = None, database: str | None = None, timeout: float = 30.0, source_only: bool = False, include_arch: bool = False, field_attributes: list[str] | tuple[str, ...] | None = None, view_types: list[str] | tuple[str, ...] | None = None, max_models: int | None = None, max_fields_per_model: int | None = None, path_base_dir: str | None = None, documentation_policy: DocumentationDirectoryPolicy | None = None, progress: Callable[[str, dict[str, Any]], None] | None = None, progress_level: str = 'compact') TechnicalDocumentation[source]

Build split LLM/human report seed bundle.

diff_technical_report_evidence(target: str, *, include_diff: bool = False, significant_only: bool = False, path_base_dir: str | None = None, documentation_policy: DocumentationDirectoryPolicy | None = None) dict[str, Any][source]

Diff report snapshots against current evidence document.

build_dependency_graph_documentation(module_names: list[str], *, database: str | None = None, timeout: float = 30.0, source_only: bool = False, installed_only: bool = False, transitive: bool = True, path_prefix: str | None = None) DependencyGraphDocumentation[source]

Build dependency graph documentation for one or more addons.

query_model(model: str, domain: list[Any] | tuple[Any, ...] | None = None, fields: list[str] | tuple[str, ...] | None = None, limit: int = 80, include_total_count: bool = False, database: str | None = None, timeout: float = 30.0) QueryModelResult[source]

Delegate typed read-only model queries to OdooQuery.

read_record(model: str, record_id: int, fields: list[str] | tuple[str, ...] | None = None, database: str | None = None, timeout: float = 30.0) RecordReadResult[source]

Delegate typed single-record reads to OdooQuery.

search_count(model: str, domain: list[Any] | tuple[Any, ...] | None = None, database: str | None = None, timeout: float = 30.0) SearchCountResult[source]

Delegate typed count queries to OdooQuery.

get_model_fields(model: str, attributes: list[str] | tuple[str, ...] | None = None, module: str | None = None, database: str | None = None, timeout: float = 30.0) ModelFieldsResult[source]

Delegate typed field metadata queries to OdooQuery.

get_model_views(model: str, view_types: list[str] | tuple[str, ...] | None = None, database: str | None = None, timeout: float = 30.0, include_arch: bool = True) ModelViewInventory[source]

Return primary and extension DB views for one model.

get_models_documentation_runtime(models: list[str], *, module_name: str | None = None, attributes: list[str] | tuple[str, ...] | None = None, view_types: list[str] | tuple[str, ...] | None = None, include_arch: bool = False, progress: Callable[[str, dict[str, Any]], None] | None = None, database: str | None = None, timeout: float = 60.0) DocumentationRuntimeInventory[source]

Return batched runtime metadata for documentation generation.

execute_python_code(python_code: str, no_http: bool = True, capture_output: bool = True, suppress_output: bool = False, raise_on_error: bool = False, shell_interface: str | None = None, log_level: str | None = None) dict[source]

Execute Python code in the Odoo shell environment

execute_code(code: str, *, database: str | None = None, commit: bool = False, timeout: float = 30.0) dict[str, Any][source]

Execute trusted arbitrary Python through the embedded executor.

inspect_ref(xmlid: str, *, database: str | None = None, timeout: float = 30.0) dict[str, Any][source]

Resolve one XMLID through the embedded Odoo runtime.

inspect_cron(xmlid: str, *, trigger: bool = False, database: str | None = None, timeout: float = 30.0) dict[str, Any][source]

Inspect or explicitly trigger one cron job by XMLID.

inspect_modules(*, state: str | None = None, names_only: bool = False, database: str | None = None, timeout: float = 30.0) dict[str, Any][source]

Return runtime addon inventory with inspect-command semantics.

inspect_subtypes(model: str, *, database: str | None = None, timeout: float = 30.0) dict[str, Any][source]

List message subtypes registered for one model.

inspect_model(model: str, *, database: str | None = None, timeout: float = 30.0) dict[str, Any][source]

Inspect runtime model registration metadata.

inspect_field(model: str, field: str, *, with_db: bool = False, database: str | None = None, timeout: float = 30.0) dict[str, Any][source]

Inspect runtime field metadata.

inspect_recordset(expression: str, *, database: str | None = None, timeout: float = 30.0) dict[str, Any][source]

Execute a trusted recordset expression as an inspection escape hatch.

describe_table(table_name: str, *, database: str | None = None, timeout: float = 30.0) dict[str, Any][source]

Describe one PostgreSQL table through the live Odoo connection.

describe_column(table_name: str, column_name: str, *, database: str | None = None, timeout: float = 30.0) dict[str, Any][source]

Describe one PostgreSQL column through the live Odoo connection.

list_constraints(table_name: str, *, database: str | None = None, timeout: float = 30.0) dict[str, Any][source]

List PostgreSQL constraints for one table.

list_tables(pattern: str | None = None, *, database: str | None = None, timeout: float = 30.0) dict[str, Any][source]

List PostgreSQL tables through the live Odoo connection.

inspect_m2m(model: str, field: str, *, database: str | None = None, timeout: float = 30.0) dict[str, Any][source]

Inspect Many2many relation-table metadata.

performance_table_scans(*, limit: int = 20, database: str | None = None, timeout: float = 30.0) dict[str, Any][source]

Return sequential scan metrics for PostgreSQL tables.

performance_slow_queries(*, limit: int = 10, database: str | None = None, timeout: float = 30.0) dict[str, Any][source]

Return slow-query metrics from pg_stat_statements when available.

performance_indexes(*, limit: int = 20, database: str | None = None, timeout: float = 30.0) dict[str, Any][source]

Return basic index-usage metrics for PostgreSQL tables.

Usage Examples

from oduit import ConfigLoader, OdooOperations

loader = ConfigLoader()
config = loader.load_config("dev")
ops = OdooOperations(config, verbose=True)

install_result = ops.install_module("sale")
update_result = ops.update_module("sale")
test_result = ops.run_tests(module="sale")
version_result = ops.get_odoo_version(suppress_output=True)
db_result = ops.db_exists(suppress_output=True)

context = ops.get_environment_context(env_name="dev", config_source="env")
addon = ops.inspect_addon("sale")
plan = ops.plan_update("sale")
state = ops.get_addon_install_state("sale")
installed_addons = ops.list_installed_addons(modules=["sale"])
xmlid = ops.inspect_ref("base.action_partner_form")
model = ops.inspect_model("res.partner")
field = ops.inspect_field("res.partner", "email", with_db=True)
table = ops.describe_table("res_partner")
scans = ops.performance_table_scans(limit=10)
partners = ops.query_model("res.partner", fields=["name", "email"], limit=5)

Key Methods

  • run_odoo(): start the Odoo server

  • run_shell(): start an Odoo shell or handle piped shell input

  • install_module() and update_module(): addon lifecycle operations

  • run_tests(): run test selections with parsed failure output

  • create_db(), drop_db(), list_db(), db_exists(): database helpers

  • create_addon() and export_module_language(): addon development helpers

  • get_odoo_version(): detect the Odoo version from odoo-bin

  • get_environment_context(): return typed environment facts for planning

  • inspect_addon() and plan_update(): return typed addon inspection and update-planning models

  • get_addon_install_state() and list_installed_addons(): typed runtime addon install-state inspection helpers

  • execute_code(): trusted embedded arbitrary execution with structured results

  • inspect_ref(), inspect_cron(), inspect_modules(), inspect_subtypes(), inspect_model(), inspect_field(), inspect_recordset(): structured runtime inspection helpers

  • describe_table(), describe_column(), list_constraints(), list_tables(), inspect_m2m(): PostgreSQL inspection helpers through the live Odoo connection

  • performance_table_scans(), performance_slow_queries(), performance_indexes(): read-only PostgreSQL performance helpers

  • query_model(), read_record(), search_count(), get_model_fields(): typed convenience wrappers around OdooQuery

  • execute_python_code(): execute arbitrary trusted Python through the Odoo shell interface, with an explicit or configured shell_interface

Preferred Public Python Surface

  • ConfigLoader for loading environment or local configuration

  • OdooOperations for the main command-oriented and typed inspection API

  • OdooInspector when you want the dedicated runtime inspection facade

  • OdooQuery when you want direct safe read-only query helpers

  • ModuleManager and AddonsPathManager for lower-level addon analysis

Safe vs Unsafe Paths

  • Prefer OdooOperations.get_environment_context(), inspect_addon(), plan_update(), get_addon_install_state(), list_installed_addons(), inspect_ref(), inspect_model(), inspect_field(), describe_table(), and the query delegation helpers for inspection and planning

  • Prefer OdooQuery for direct structured read-only model access

  • Prefer execute_code() only for trusted arbitrary snippets when no first-class inspector method fits

  • Use execute_python_code() only for trusted shell-driven snippets and set shell_interface explicitly or in configuration

  • Use OdooCodeExecutor only when you explicitly need arbitrary execution and understand the allow_unsafe=True contract