Skip to content

Commit

Permalink
Preserve kwargs values in class defintion to ensure to properly creat…
Browse files Browse the repository at this point in the history
…e a concrete class with the same attributes as the original one.
  • Loading branch information
lmignon committed Jul 13, 2023
1 parent 6be4360 commit 502445b
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 6 deletions.
1 change: 1 addition & 0 deletions news/.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Preserve kwargs values in class defintion to ensure to properly create a concrete class with the same attributes as the original one.
21 changes: 16 additions & 5 deletions src/extendable/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ class ExtendableClassDef:
hierarchy: List["ExtendableClassDef"]
metaclass: "ExtendableMeta"
original_cls: Type["ExtendableMeta"]
kwargs: Dict[str, Any]

def __init__(
self,
original_name: str,
bases: List[Any],
namespace: Dict[str, Any],
metaclass: "ExtendableMeta",
kwargs: Dict[str, Any],
) -> None:
self.namespace = namespace
self.name = namespace["__xreg_name__"]
Expand All @@ -42,6 +44,7 @@ def __init__(
self.base_names = namespace["__xreg_base_names__"] or []
self.hierarchy = [self]
self.metaclass = metaclass
self.kwargs = kwargs

def add_child(self, cls_def: "ExtendableClassDef") -> None:
self.hierarchy.append(cls_def)
Expand Down Expand Up @@ -69,7 +72,11 @@ def clone(self) -> "ExtendableClassDef":
hierarchy.
"""
clone = ExtendableClassDef(
self.original_name, self.others_bases, self.namespace, self.metaclass
self.original_name,
self.others_bases,
self.namespace,
self.metaclass,
self.kwargs,
)
clone.original_cls = self.original_cls
return clone
Expand Down Expand Up @@ -154,8 +161,9 @@ def _collect_class_def(metacls, name, bases, namespace, extends=None, **kwargs):
cls_def = ExtendableClassDef(
original_name=name,
bases=tuple(other_bases),
namespace=namespace,
namespace=namespace.copy(),
metaclass=metacls,
kwargs=kwargs,
)
__register_class_def__(
namespace["__module__"],
Expand Down Expand Up @@ -191,9 +199,12 @@ def new_method(
# ensure that arggs and kwargs are conform to the
# initial signature
inspect.signature(_initial_func).bind(cls, *args, **kwargs)
return getattr(cls._get_assembled_cls(), _method_name)(
*args, **kwargs
)
try:
return getattr(cls._get_assembled_cls(), _method_name)(
*args, **kwargs
)
except KeyError:
return _initial_func(cls, *args, **kwargs)

new_method_def = functools.partial(
new_method, _method_name=key, _initial_func=func
Expand Down
2 changes: 1 addition & 1 deletion src/extendable/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def build_extendable_class(
extendableClass = types.new_class(
simple_name,
tuple(bases),
kwds={"metaclass": cls_def.metaclass},
kwds=dict(class_def.kwargs, metaclass=cls_def.metaclass),
exec_body=(
lambda ns, namespace=namespace: ns.update(namespace) # type: ignore
),
Expand Down

0 comments on commit 502445b

Please sign in to comment.