codekingpro/portable-devtools
114k
1"""2meta.py3 4Some useful metaclasses.5"""6 7from __future__ import annotations8 9from typing import TYPE_CHECKING10 11if TYPE_CHECKING:12 from typing import Any13 14 15class LeafClassesMeta(type):16 """17 A metaclass for classes that keeps track of all of them that18 aren't base classes.19 20 >>> Parent = LeafClassesMeta('MyParentClass', (), {})21 >>> Parent in Parent._leaf_classes22 True23 >>> Child = LeafClassesMeta('MyChildClass', (Parent,), {})24 >>> Child in Parent._leaf_classes25 True26 >>> Parent in Parent._leaf_classes27 False28 29 >>> Other = LeafClassesMeta('OtherClass', (), {})30 >>> Parent in Other._leaf_classes31 False32 >>> len(Other._leaf_classes)33 134 """35 36 _leaf_classes: set[type[Any]]37 38 def __init__(39 cls,40 name: str,41 bases: tuple[type[object], ...],42 attrs: dict[str, object],43 ) -> None:44 if not hasattr(cls, '_leaf_classes'):45 cls._leaf_classes = set()46 leaf_classes = getattr(cls, '_leaf_classes')47 leaf_classes.add(cls)48 # remove any base classes49 leaf_classes -= set(bases)50 51 52class TagRegistered(type):53 """54 As classes of this metaclass are created, they keep a registry in the55 base class of all classes by a class attribute, indicated by attr_name.56 57 >>> FooObject = TagRegistered('FooObject', (), dict(tag='foo'))58 >>> FooObject._registry['foo'] is FooObject59 True60 >>> BarObject = TagRegistered('Barobject', (FooObject,), dict(tag='bar'))61 >>> FooObject._registry is BarObject._registry62 True63 >>> len(FooObject._registry)64 265 66 '...' below should be 'jaraco.classes' but for pytest-dev/pytest#339667 >>> FooObject._registry['bar']68 <class '....meta.Barobject'>69 """70 71 attr_name = 'tag'72 73 def __init__(74 cls,75 name: str,76 bases: tuple[type[object], ...],77 namespace: dict[str, object],78 ) -> None:79 super(TagRegistered, cls).__init__(name, bases, namespace)80 if not hasattr(cls, '_registry'):81 cls._registry = {}82 meta = cls.__class__83 attr = getattr(cls, meta.attr_name, None)84 if attr:85 cls._registry[attr] = cls86 