diff --git a/MANIFEST.in b/MANIFEST.in index d1d9628c55b4f..f9ff8c6a9d35a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,8 @@ include requirements.txt include LICENSE include README.md +include pyproject.toml +include setup/pep517_odoo.py graft odoo recursive-exclude * *.py[co] recursive-exclude .git * diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000000..228f3019ecc9c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,4 @@ +[build-system] +requires = ["setuptools>=41"] +build-backend = "pep517_odoo" +backend-path = ["setup"] diff --git a/setup/pep517_odoo.py b/setup/pep517_odoo.py new file mode 100644 index 0000000000000..bd93c9e238d3b --- /dev/null +++ b/setup/pep517_odoo.py @@ -0,0 +1,65 @@ +"""Specialized PEP 517 build backend for Odoo. + +It is based on setuptools, and extends it to + +- symlink all addons into odoo/addons before building, so setuptools discovers them + automatically, and +- enforce the 'compat' editable mode, because the default mode for flat layout + is not compatible with the Odoo addon import system. +""" +import contextlib +from pathlib import Path + +from setuptools import build_meta +from setuptools.build_meta import * # noqa: F403 + + +@contextlib.contextmanager +def _symlink_addons(): + symlinks = [] + try: + target_addons_path = Path("addons") + addons_path = Path("odoo", "addons") + link_target = Path("..", "..", "addons") + if target_addons_path.is_dir(): + for target_addon_path in target_addons_path.iterdir(): + if not target_addon_path.is_dir(): + continue + addon_path = addons_path / target_addon_path.name + if not addon_path.is_symlink(): + addon_path.symlink_to( + link_target / target_addon_path.name, target_is_directory=True + ) + symlinks.append(addon_path) + yield + finally: + for symlink in symlinks: + symlink.unlink() + + +def build_sdist(*args, **kwargs): + with _symlink_addons(): + return build_meta.build_sdist(*args, **kwargs) + + +def build_wheel(*args, **kwargs): + with _symlink_addons(): + return build_meta.build_wheel(*args, **kwargs) + + +if hasattr(build_meta, "build_editable"): + + def build_editable( + wheel_directory, config_settings=None, metadata_directory=None, **kwargs + ): + if config_settings is None: + config_settings = {} + # Use setuptools's compat editable mode, because the default mode for + # flat layout projects is not compatible with pkgutil.extend_path, + # and the strict mode is too strict for the Odoo development workflow + # where new files are added frequently. This is currently being discussed + # by the setuptools maintainers. + config_settings["editable-mode"] = "compat" + return build_meta.build_editable( + wheel_directory, config_settings, metadata_directory, **kwargs + )