Skip to main content

Static analyzer that reads Odoo community/enterprise source code and produces a merged, versioned knowledge base of models, fields, and methods.

Project description

odoo-inspect

Static analyzer for Odoo source code. It reads Odoo community and enterprise addons directly from disk (no running Odoo instance needed), parses every .py / .xml file with the standard library, and produces a merged, versioned knowledge base of models, fields, and methods — tagged with the module that contributed each piece.

odoo-inspect is built for Odoo developers who have to reason about schema changes between versions, plan module upgrades, or answer questions like "when did account.move.payment_state appear?" without spinning up four Odoo instances in parallel.

Why

Odoo models are extended across many modules. sale.order is defined in sale/, but account/, sale_stock/, sale_timesheet/ and dozens of others add fields and methods on top. A plain grep can tell you where a field is declared, but not what the complete shape of the model looks like once every addon you enable has been merged together.

odoo-inspect walks every module on disk, runs each .py file through ast, and merges every extension into a single JSON file per model — so you can open knowledge/v17/models/sale.order.json and see the full contributed surface in one place.

Install

pip install odoo-inspect

Requires Python 3.12 or newer.

Quickstart — CLI

Scan a single Odoo version:

odoo-inspect scan \
  --community /path/to/odoo17/odoo/addons /path/to/odoo17/addons \
  --enterprise /path/to/enterprise17 \
  --version 17.0 \
  --output knowledge/v17

--community accepts multiple paths (space-separated) so you can include both odoo/addons/ and the top-level addons/ where base lives. --enterprise is optional. The output directory is overwritten on every scan — each run is a fresh snapshot.

Compare two previously-scanned versions:

odoo-inspect diff \
  --old knowledge/v16 \
  --new knowledge/v17 \
  --output knowledge/diffs/v16_to_v17.json

Build a keyword → model router from a knowledge directory:

odoo-inspect router \
  --knowledge knowledge/v17 \
  --output router/v17

Render an upgrade report

Once you have a diff JSON, report turns it into something a human can actually read. Two formats:

HTML — a single self-contained file you can open in any browser. No server, no external assets, no build step. Inline CSS + JS. Key features:

  • Overview cards at the top (models added / removed / changed counts).
  • One collapsible <details> card per model with field changes. Click to expand; badges on each card show +N added, −N removed, ~N type/selection changes at a glance.
  • A sticky search box that filters the model cards client-side as you type — works fine with thousands of models.
  • Separate "Models added" / "Models removed" / "Financial changes" sections.
odoo-inspect report \
  --diff knowledge/diffs/v16_to_v17.json \
  --format html \
  --output upgrade_v16_to_v17.html

# then just open it
xdg-open upgrade_v16_to_v17.html   # Linux
open upgrade_v16_to_v17.html       # macOS

Markdown — for pasting into GitHub issues, PR descriptions, Slack, or committing into a repo alongside a release. Produces a single .md file with tables per model and a summary section at the bottom.

odoo-inspect report \
  --diff knowledge/diffs/v16_to_v17.json \
  --format markdown \
  --output upgrade_v16_to_v17.md

If you omit --output, the report is printed to stdout — handy for piping into a pager or another tool.

Full end-to-end example

# 1. Scan both versions
odoo-inspect scan --community /path/to/odoo16/odoo/addons \
                  --version 16.0 --output knowledge/v16

odoo-inspect scan --community /path/to/odoo17/odoo/addons \
                  --version 17.0 --output knowledge/v17

# 2. Compute the diff
odoo-inspect diff --old knowledge/v16 --new knowledge/v17 \
                  --output knowledge/diffs/v16_to_v17.json

# 3. Render a human-readable report
odoo-inspect report --diff knowledge/diffs/v16_to_v17.json \
                    --format html --output upgrade_v16_to_v17.html

Quickstart — Python API

from pathlib import Path
from odoo_inspect import Scanner, Differ, Router, KnowledgeLoader

# Scan from source
scanner = Scanner(
    community_paths=[Path("/path/to/odoo17/odoo/addons")],
    enterprise_paths=[Path("/path/to/enterprise17")],
    version="17.0",
)
result = scanner.scan()
result.write(Path("knowledge/v17"))

# Load and diff
old = KnowledgeLoader(Path("knowledge/v16")).load()
new = KnowledgeLoader(Path("knowledge/v17")).load()
diff = Differ(old, new).diff()

print(f"Added models:   {len(diff.models_added)}")
print(f"Removed models: {len(diff.models_removed)}")
print(f"Models with field changes: {len(diff.field_changes)}")

# Build a router
router = Router(new).build()
router.write(Path("router/v17"))

# Render the diff as a single-file HTML report
from odoo_inspect.writers import write_html_diff, write_markdown_diff
write_html_diff(diff, Path("upgrade_v16_to_v17.html"))
write_markdown_diff(diff, Path("upgrade_v16_to_v17.md"))

Output format

knowledge/v17/
  models/<model.name>.json   one file per merged model
  _meta.json                 version info, module index, model index, stats
  _financial.json            account-type classification for this version

Every field entry records the module that contributed it in a source field. When the same field is declared in a base module and then replaced by an extension, the base module's declaration is kept under original_source.

See docs/output-format.md for the full schema.

How merging works

For each models.Model / TransientModel / AbstractModel class:

_name _inherit Treated as
set, not in _inherit definition (locks base module)
set, equals _inherit (_name = _inherit = 'x') in-place extension
set, _inherit = different model new model from parent (parent tracked in inherits)
not set, _inherit = existing model extension (fields/methods merged in, source-tagged)
set, _inherit = list of mixins definition with mixins

The scanner makes two passes:

  1. Collect every class across every scanned module.
  2. Apply definitions first, so every model's base_module is locked by its real owner before any extension can influence it. Only after all definitions are in does the merger walk the extensions.

This is what keeps res.partner.base_module equal to base instead of getting overwritten by whichever _inherit = 'res.partner' extension happened to be scanned first.

Module filtering

test_*, hw_*, theme_*, most l10n_* (except l10n_in and l10n_generic_coa), bus, web, base_setup, iap, gamification, auth_*, google_*, and microsoft_* are skipped by default. Priority modules (base, sale, account, stock, crm, hr, mail, …) are tagged priority in _meta.json; everything else is still scanned but tagged extra.

Override these lists by editing the constants in src/odoo_inspect/constants.py, or by passing a custom ScanConfig to the Scanner class.

License

MIT. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

odoo_inspect-0.1.0.tar.gz (35.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

odoo_inspect-0.1.0-py3-none-any.whl (33.5 kB view details)

Uploaded Python 3

File details

Details for the file odoo_inspect-0.1.0.tar.gz.

File metadata

  • Download URL: odoo_inspect-0.1.0.tar.gz
  • Upload date:
  • Size: 35.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for odoo_inspect-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d3b2e440da2dd9f705e26330bba460f01692f77b9577ea6c2936f0308d9c098c
MD5 3390e09b53835ea3e1d6441bd4ff4b8b
BLAKE2b-256 7d1be546d4c8e094b689bbdf9638296ab3fac16f101f6924dabec0dc8e8d0aef

See more details on using hashes here.

File details

Details for the file odoo_inspect-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: odoo_inspect-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 33.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for odoo_inspect-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 47fd89ea5626aee869222bd4b4230c30b674a26188a20867251331152e1c92ca
MD5 f740564c999cb8872a54097e45f5b72a
BLAKE2b-256 78dae9f14ae2b8c8a5310581ceb825ece8994e7a5b395118d02f838627351a25

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page