1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
#!/usr/bin/env python3
# --------------------( LICENSE )--------------------
# Copyright (c) 2014-2025 Beartype authors.
# See "LICENSE" for further details.
'''
Project-wide **caching metaclasses** (i.e., classes performing general-purpose
memoization of classes that declare the former to be their metaclasses).
This private submodule is *not* intended for importation by downstream callers.
'''
# ....................{ IMPORTS }....................
from beartype.typing import Type
from beartype._data.typing.datatyping import T
from beartype._util.cache.utilcachecall import callable_cached
# ....................{ METACLASSES }....................
class BeartypeCachingMeta(type):
'''
**Caching metaclass** (i.e., metaclass caching immutable instances of
classes whose metaclasses are this metaclass, cached via the positional
arguments instantiating those classes).
This metaclass is superior to the usual approach of caching immutable
objects: overriding the ``__new__`` method to conditionally create a new
instance of that class only if an instance has *not* already been created
with the passed positional arguments. Why? Because that approach unavoidably
re-calls the ``__init__`` method of a previously initialized instance on
each instantiation of that class -- which is clearly harmful, especially
where immutability is concerned.
This metaclass instead guarantees that the ``__init__`` method of an
instance is only called once on the first instantiation of that instance.
Caveats
----------
**This metaclass assumes immutability.** Ideally, instances of classes whose
metaclasses are this metaclass should be **immutable** (i.e., frozen). Where
this is *not* the case, the behaviour of this metaclass is undefined.
**This metaclass prohibits keyword arguments.** ``__init__`` methods of
classes whose metaclass is this metaclass must accept *only* positional
arguments. Why? Efficiency, the entire point of caching. While feasible,
permitting ``__init__`` methods to also accept keyword arguments would be
sufficiently slow as to entirely defeat the point of caching. That's bad.
See Also
----------
https://stackoverflow.com/a/8665179/2809027
StackOverflow answers strongly inspiring this implementation.
'''
# ..................{ INITIALIZERS }..................
@callable_cached
def __call__(cls: Type[T], *args) -> T: # type: ignore[reportIncompatibleMethodOverride]
'''
Instantiate the passed class with the passed positional arguments if
this is the first instantiation of this class passed these arguments
*or* simply return the previously instantiated instance of this class
otherwise (i.e., if this is a subsequent instantiation of this class
re-passed these same arguments).
Caveats
----------
This method intentionally accepts *only* positional arguments. See the
metaclass docstring for further details.
Parameters
----------
cls : type
Class whose class is this metaclass.
All remaining parameters are passed as is to the superclass
:meth:`type.__call__` method.
'''
# Bear witness to the terrifying power of @callable_cached.
return super().__call__(*args) # type: ignore[misc]
|