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:
objectCompatibility facade over smaller internal Odoo operation services.
- 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.
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 serverrun_shell(): start an Odoo shell or handle piped shell inputinstall_module()andupdate_module(): addon lifecycle operationsrun_tests(): run test selections with parsed failure outputcreate_db(),drop_db(),list_db(),db_exists(): database helperscreate_addon()andexport_module_language(): addon development helpersget_odoo_version(): detect the Odoo version fromodoo-binget_environment_context(): return typed environment facts for planninginspect_addon()andplan_update(): return typed addon inspection and update-planning modelsget_addon_install_state()andlist_installed_addons(): typed runtime addon install-state inspection helpersexecute_code(): trusted embedded arbitrary execution with structured resultsinspect_ref(),inspect_cron(),inspect_modules(),inspect_subtypes(),inspect_model(),inspect_field(),inspect_recordset(): structured runtime inspection helpersdescribe_table(),describe_column(),list_constraints(),list_tables(),inspect_m2m(): PostgreSQL inspection helpers through the live Odoo connectionperformance_table_scans(),performance_slow_queries(),performance_indexes(): read-only PostgreSQL performance helpersquery_model(),read_record(),search_count(),get_model_fields(): typed convenience wrappers aroundOdooQueryexecute_python_code(): execute arbitrary trusted Python through the Odoo shell interface, with an explicit or configuredshell_interface
Preferred Public Python Surface
ConfigLoaderfor loading environment or local configurationOdooOperationsfor the main command-oriented and typed inspection APIOdooInspectorwhen you want the dedicated runtime inspection facadeOdooQuerywhen you want direct safe read-only query helpersModuleManagerandAddonsPathManagerfor 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 planningPrefer
OdooQueryfor direct structured read-only model accessPrefer
execute_code()only for trusted arbitrary snippets when no first-class inspector method fitsUse
execute_python_code()only for trusted shell-driven snippets and setshell_interfaceexplicitly or in configurationUse
OdooCodeExecutoronly when you explicitly need arbitrary execution and understand theallow_unsafe=Truecontract