From 2cafbe280a623529ee006a9db65356395a005246 Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Mon, 13 Jun 2022 08:55:01 +0200 Subject: [PATCH 1/6] little change to try to load init the registry on module loading --- src/extendable/main.py | 10 ++++++-- src/extendable/registry.py | 1 + tests/test_simple.py | 49 +++++++++++++++++++++++++++++++++++++- 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/extendable/main.py b/src/extendable/main.py index 0fe5d89..2a3973b 100644 --- a/src/extendable/main.py +++ b/src/extendable/main.py @@ -81,7 +81,7 @@ class ExtendableMeta(ABCMeta): @no_type_check def __new__(metacls, name, bases, namespace, extends=None, **kwargs): - """create the expected class anc collect the class definition that will be used + """create the expected class and collect the class definition that will be used at the end of registry load process to build the final class.""" class_def = None if not _registry_build_mode: @@ -94,12 +94,16 @@ def __new__(metacls, name, bases, namespace, extends=None, **kwargs): # for the original class, we wrap the class methods to forward # the call to the aggregated one at runtime namespace = metacls._wrap_class_methods(namespace) - # We build the Origial class + # We build the original class new_cls = metacls._build_original_class( name=name, bases=bases, namespace=namespace, **kwargs ) if not _registry_build_mode and class_def: class_def.original_cls = new_cls + if True: + registry = extendable_registry.get() + with registry.build_mode(): + extendable_registry.get().build_extendable_class(class_def) return new_cls @no_type_check @@ -134,6 +138,8 @@ def _collect_class_def(metacls, name, bases, namespace, extends=None, **kwargs): # For each defined Extendable class, we keep a copy of the class # definition. This copy will be used to create the aggregated class other_bases = [b for b in bases if not metacls._is_extendable(b)] + # namespace = dict(namespace) + # namespace.pop("__classcell__", None) cls_def = ExtendableClassDef( original_name=name, bases=tuple(other_bases), diff --git a/src/extendable/registry.py b/src/extendable/registry.py index e2a6cc2..264246c 100644 --- a/src/extendable/registry.py +++ b/src/extendable/registry.py @@ -157,6 +157,7 @@ def init_registry(self, module_matchings: Optional[List[str]] = None) -> None: The module list accept wildcard expression as last character """ + self._extendable_classes.clear() module_matchings = module_matchings if module_matchings else ["*"] with self.build_mode(), ModuleIndex() as idx: for match in module_matchings: diff --git a/tests/test_simple.py b/tests/test_simple.py index 044a55c..7114023 100644 --- a/tests/test_simple.py +++ b/tests/test_simple.py @@ -30,7 +30,7 @@ def sum(self) -> int: def cls_sum(cls) -> int: return super().cls_sum() + 3 - test_registry.init_registry() + # test_registry.init_registry() result: Union[A, B] = A() assert isinstance(result, A) @@ -42,6 +42,53 @@ def cls_sum(cls) -> int: assert isinstance(result.__class__, ExtendableMeta) +def test_simple_extends_same_class(test_registry): + class A(metaclass=ExtendableMeta): + prop_a: int = 1 + + def sum(self) -> int: + return self.prop_a + + @classmethod + def cls_sum(cls) -> int: + return 2 + + class B(A, extends=A): + prop_b: int = 2 + + def sum(self) -> int: + s = super() + return s.sum() + self.prop_b + + @classmethod + def cls_sum(cls) -> int: + return super().cls_sum() + 3 + + class C(A, extends=A): + prop_c: int = 3 + + def sum(self) -> int: + s = super() + return s.sum() + self.prop_c + + @classmethod + def cls_sum(cls) -> int: + return super().cls_sum() + 4 + + test_registry.init_registry() + + result: Union[A, B, C] = A() + assert isinstance(result, A) + assert isinstance(result, B) + assert isinstance(result, C) + assert result.prop_c == 3 + assert result.prop_b == 2 + assert result.prop_a == 1 + assert result.sum() == 6 + assert A.cls_sum() == 9 + assert isinstance(result.__class__, ExtendableMeta) + + def test_extends_new_model(test_registry): class A(metaclass=ExtendableMeta): value: int = 2 From 2369354de9707fc43fe8b20f1a5fd23dfe1714bc Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Mon, 13 Jun 2022 14:30:10 +0200 Subject: [PATCH 2/6] py3.11 --- .github/workflows/ci.yml | 2 +- src/extendable/main.py | 2 +- tests/test_simple.py | 2 +- tox.ini | 2 ++ 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7facec2..6b56726 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "pypy3"] + python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "pypy3", "3.11-dev"] steps: - uses: "actions/checkout@v2" - uses: "actions/setup-python@v2" diff --git a/src/extendable/main.py b/src/extendable/main.py index 2a3973b..98ab825 100644 --- a/src/extendable/main.py +++ b/src/extendable/main.py @@ -100,7 +100,7 @@ def __new__(metacls, name, bases, namespace, extends=None, **kwargs): ) if not _registry_build_mode and class_def: class_def.original_cls = new_cls - if True: + if False: registry = extendable_registry.get() with registry.build_mode(): extendable_registry.get().build_extendable_class(class_def) diff --git a/tests/test_simple.py b/tests/test_simple.py index 7114023..837f3ba 100644 --- a/tests/test_simple.py +++ b/tests/test_simple.py @@ -30,7 +30,7 @@ def sum(self) -> int: def cls_sum(cls) -> int: return super().cls_sum() + 3 - # test_registry.init_registry() + test_registry.init_registry() result: Union[A, B] = A() assert isinstance(result, A) diff --git a/tox.ini b/tox.ini index 8edf8f7..8d0782e 100644 --- a/tox.ini +++ b/tox.ini @@ -5,6 +5,7 @@ python = 3.8: py38, typing 3.9: py39, typing, pypi-description 3.10: py310, typing + 3.11-dev: py311, typing pypy3: pypy3 [tox] @@ -15,6 +16,7 @@ envlist = py38 py39 py310 + py311 pypy3 lint typing From 97efd462e090346cc3cd8e8684dfb84f5def1b9a Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Mon, 13 Jun 2022 14:39:43 +0200 Subject: [PATCH 3/6] py3.11 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6b56726..10c0758 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "pypy3", "3.11-dev"] + python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "pypy3", "3.11-dev"] steps: - uses: "actions/checkout@v2" - uses: "actions/setup-python@v2" From cb9e9cf14ee9858f5d36b36417bc401d5e588351 Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Mon, 13 Jun 2022 15:52:15 +0200 Subject: [PATCH 4/6] py3.11 --- .github/workflows/ci.yml | 2 +- tox.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10c0758..6b56726 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "pypy3", "3.11-dev"] + python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "pypy3", "3.11-dev"] steps: - uses: "actions/checkout@v2" - uses: "actions/setup-python@v2" diff --git a/tox.ini b/tox.ini index 8d0782e..7dda110 100644 --- a/tox.ini +++ b/tox.ini @@ -5,7 +5,7 @@ python = 3.8: py38, typing 3.9: py39, typing, pypi-description 3.10: py310, typing - 3.11-dev: py311, typing + 3.11: py311, typing pypy3: pypy3 [tox] From 6cff4e1b6377f386f761896ce625ccf6496e25b3 Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Mon, 13 Jun 2022 15:55:37 +0200 Subject: [PATCH 5/6] py3.11 --- src/extendable/main.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/extendable/main.py b/src/extendable/main.py index 98ab825..fd6d79c 100644 --- a/src/extendable/main.py +++ b/src/extendable/main.py @@ -162,9 +162,7 @@ def _build_original_class(metacls, name, bases, namespace, **kwargs): another type. In such a case, the new type should only override this method to call the __new__ method on the other type. """ - return super().__new__( - metacls, name=name, bases=bases, namespace=namespace, **kwargs - ) + return super().__new__(metacls, name, bases, namespace, **kwargs) @classmethod def _wrap_class_methods(metacls, namespace: Dict[str, Any]) -> Dict[str, Any]: From d35303dde1cc210d77a05c1561638fe3ee09214f Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Mon, 13 Jun 2022 16:04:23 +0200 Subject: [PATCH 6/6] fix pre-commit issue --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4c4035f..f0b7d32 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ default_language_version: python: python3 repos: - repo: https://github.com/psf/black - rev: 21.12b0 + rev: 22.3.0 hooks: - id: black - repo: https://github.com/myint/autoflake