Skip to content

Frequently Asked Questions

Multi-release Odoo addons? Are you crazy?

Developing multi-release Odoo addons isn’t officially supported. That makes sense for Odoo SA — each release is a full product. Need new features? Just upgrade. Their strict no-database-changes rule, auto-forward ports, and 3-year support policy keep things manageable. When a new Odoo ships, their whole product upgrades. This works great for upstream.

For downstream, multi-release addons also bring challenges:

  • Code decay, messy shared code, and tech debt
  • Can’t always use the newest ORM features in older versions

So, yeah, maybe we’re crazy. But if you’re crazy like us, here’s what you now can do:

  • Develop addons that are production-ready the day a new Odoo is released
  • Maintain your module like any normal Python project — treat Odoo as just another dependency
  • Build your own product on top of Odoo
  • Support older releases with way less work
  • Never migrate modules again — just add or drop Odoo release support

Crazy too? Welcome aboard!

Installation

How do I install polytropos?

From PyPI (recommended):

pip install polytropos

Or with uv:

uv pip install polytropos

You can also run it without installing it:

uvx polytropos --help

Can I install from GitLab Packages?

Yes! The package is public, so no authentication required. GitLab Packages mirrors PyPI releases:

pip install polytropos --index-url https://gitlab.com/api/v4/projects/moduon%2Fpolytropos/packages/pypi/simple

Or with uv, add this to your pyproject.toml:

pyproject.toml
[[tool.uv.pip]]
index-url = "https://gitlab.com/api/v4/projects/moduon%2Fpolytropos/packages/pypi/simple"

Do I need uv?

uv is recommended for best experience, but not required. You can also use pip.

Can't I just use Nix?

Of course!

nix run github:moduon/polytropos

Usage

How do I create a new module?

uvx polytropos init my_module

This creates a pyproject.toml with sensible defaults.

How do I build a wheel for a specific Odoo release?

uv build --wheel --config-setting odoo_release=17.0

The wheel will include the Odoo release in its version (e.g., odoo-addon-my-module-17.0.1.0.0-py3-none-any.whl).

How do I develop in editable mode?

Use uv's built-in editable support:

cd /path/to/your/integration/env
uv add --editable ../my_module

Then set the Odoo release:

uv sync --config-setting odoo_release=17.0

Or add it in your integration environment's pyproject.toml:

pyproject.toml
[tool.uv.config-settings]
odoo_release = "17.0"

Odoo development

How to generate multi-release translations

Let's say your module works accross Odoo 18 and 19, and you want to add the translations.

  1. Export Odoo 18 translations (old-style CLI):

     dev-18 # Somehow, enable your Odoo 18 environment
     mkdir -p ./addons/my_addon/i18n
     odoo --stop-after-init --workers 0 -d my_db --modules my_addon -i my_addon \
       --i18n-export ./addons/my_addon/i18n/my_addon-18.pot
    
  2. Export Odoo 19 translations:

    dev-19 # Somehow, enable your Odoo 19 environment
    odoo i18n export -l pot -o ./addons/my_addon/i18n/my_addon-19.pot my_addon
    
  3. Join the translations (following upstream docs):

    xgettext -o ./addons/my_addon/i18n/my_addon.pot ./addons/my_addon/i18n/my_addon-18.pot ./addons/my_addon/i18n/my_addon-19.pot
    
  4. Clear mono-release translation files:

    rm ./addons/my_addon/i18n/my_addon-*.pot
    
  5. Now that you have the final my_addon.pot file, you can use it to translate your addon. It will include all strings needed for all releases.

Configuration

What's the difference between releases and default_odoo_release?

  • default_odoo_release: Fallback odoo release to use when building/installing
  • releases: Which Odoo releases this manifest section applies to

Example

pyproject.toml
[tool.polytropos]
default_odoo_release = "18.0"

[[tool.polytropos.manifest]]
releases = ">=18"
# This applies to all Odoo 18+

[[tool.polytropos.manifest]]
releases = ">=17,<18"
# This applies only to Odoo 17.x

Polytropos uses PEP 440 version specifiers.

How does version building work?

Polytropos combines your module version with the Odoo release:

  • Module version: 1.2.3 (from pyproject.toml)
  • Odoo release: 17.0
  • Full version: 17.0.1.2.3

This follows Odoo's versioning convention where the Odoo release comes first.

Documentation

How to read a specific version of the docs?

Warning

Public docs are built on last commit always, so they might not exactly reflect the last published stable version.

To get a specific version of the docs, run:

git_ref=v3.1.0 # Change for the docs you want to see
nix --extra-experimental-features 'nix-command flakes' --accept-flake-config \
    "gitlab:moduon/polytropos/$git_ref#livedocs"

It will run a local docs server built at that specific version.

Architecture

Polytropos uses manifestoo-core for metadata generation:

  1. Polytropos reads pyproject.toml and generates a version-specific __manifest__.py
  2. Manifestoo-core converts the Odoo manifest to Python package metadata (including Requires-Dist conversion of Odoo addon dependencies)
  3. Polytropos builds the wheel from the metadata

Why the addon version must have 3 or more components?

The version format A.B.X.Y.Z (5 components) is required so that manifestoo-core and Odoo are able to distinguish between the Odoo release and the addon version. The format breaks down as:

  • A.B - Odoo release, always prepended by Polytropos (e.g., 17.0)
  • X.Y.Z - Module version (e.g., 1.2.3)

Your module version must have at least 3 components (X.Y.Z). If your module version has fewer than 3 components (e.g., 1.0), polytropos will raise an error.

Troubleshooting

uv sync fails with "missing build dependencies"

Make sure your integration environment's pyproject.toml includes polytropos as a build dependency:

pyproject.toml
[build-system]
requires = ["polytropos[build]"]
build-backend = "polytropos.build"

uv sync doesn't rebuild when I switch Odoo release

UV caches builds by source file hash. When you switch Odoo releases, UV may not detect that it should rebuild because the source files haven't technically changed from its perspective.

To fix this, add cache keys to your addon's pyproject.toml:

pyproject.toml
[tool.uv]
cache-keys = [
    { env = "ODOO_RELEASE" },
    { file = "*.md" },
    { file = "pyproject.toml" },
    { file = "src/__manifest__.py" },
]

Why these cache keys:

  • ODOO_RELEASE: Affects the built release. It is the recommended approach when developing in multi-release environments, as it is very easy to switch and hook with direnv or similar tools.
  • *.md: The README is bundled into the __manifest__.py, so these changes should trigger a rebuild.
  • pyproject.toml: Changes to the manifest configuration should trigger a rebuild, since they affect the generated manifest.
  • src/__manifest__.py: The generated manifest is a crucial artifact for distribution, so this tells UV to rebuild it always.

The built wheel has wrong Odoo release

Make sure you're passing the correct odoo_release config setting to uv/pip when building.

uv build fails because sdist and wheel have different versions

Running uv build on an addon will fail with:

uv build --no-build-isolation
Building source distribution...
Building wheel from source distribution...
  × Failed to build
   `polytropos/examples/conditional_assets`
  ╰─▶ The source distribution declares version 1.0.0, but the wheel declares version 19.0.1.0.0

This is on purpose.

To workaround the problem, build in 2 separate steps:

uv build --sdist
uv build --wheel