Skip to content

Commit

Permalink
allow to freeze all instances of a class by using a metaclass argument
Browse files Browse the repository at this point in the history
  • Loading branch information
MatthieuDartiailh committed Apr 16, 2024
1 parent a5b1cee commit e26e815
Showing 1 changed file with 20 additions and 6 deletions.
26 changes: 20 additions & 6 deletions atom/meta/atom_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
Mapping,
MutableMapping,
Optional,
Type,
Sequence,
Set,
Tuple,
Expand Down Expand Up @@ -79,7 +80,7 @@
POST_VALIDATE_PREFIX = "_post_validate_"
GETSTATE_PREFIX = "_getstate_"


T = TypeVar("T")
M = TypeVar("M", bound=Member)


Expand Down Expand Up @@ -527,7 +528,7 @@ def clone_if_needed(m: Member) -> Member:
self.name, name, members, "observe decorated"
)

def create_class(self, meta: type) -> type:
def create_class(self, meta: Type[T], freeze: bool) -> T:
"""Create the class after adding class variables."""

# Put a reference to the members dict on the class. This is used
Expand All @@ -541,11 +542,14 @@ def create_class(self, meta: type) -> type:
m for m in self.specific_members
)

# Store wether or not to freeze the new instance after initialization
self.dct["__atom_freeze__"] = freeze

# Create the class object.
# We do it once everything else has been setup so that if users wants
# to use __init__subclass__ they have access to fully initialized
# Atom type.
cls: type = type.__new__(meta, self.name, self.bases, self.dct)
cls: T = type.__new__(meta, self.name, self.bases, self.dct)

# Generate slotnames cache
# (using a private function that mypy does not know about).
Expand Down Expand Up @@ -603,16 +607,18 @@ class so that the CAtom class can allocate exactly enough space for

__atom_members__: Mapping[str, Member]
__atom_specific_members__: FrozenSet[str]
__atom_freeze__: bool

def __new__(
meta,
meta: Type[T],
name: str,
bases: Tuple[type, ...],
dct: Dict[str, Any],
enable_weakrefs: bool = False,
use_annotations: bool = True,
type_containers: int = 1,
):
freeze: bool = False,
) -> T:
# Ensure there is no weird mro calculation and that we can use our
# re-implementation of C3
assert meta.mro is type.mro, "Custom MRO calculation are not supported"
Expand Down Expand Up @@ -640,4 +646,12 @@ def __new__(
# Customize the members based on the specified static modifiers
helper.apply_members_static_behaviors()

return helper.create_class(meta)
return helper.create_class(meta, freeze)

def __call__(self, *args: Any, **kwds: Any) -> Any:
new = super().__call__(*args, **kwds)
if self.__atom_freeze__:
# We get a Atom instance here, so freeze exists
new.freeze() # type: ignore

return new

0 comments on commit e26e815

Please sign in to comment.