from __future__ import annotations
from functools import partial
from dataclasses import dataclass
from typing import overload
from typing import runtime_checkable
from typing import Protocol
_traits_registry = set()
_impl_registry: dict[str, dict[str, "Trait"]] = {}
_base_trait = None
_base_impl = None
def _is_user_created_meth(name: str):
return not (name.startswith("__") & name.endswith("__"))
class _TraitImplementation:
def __give_self(self, func):
def give_self(*args, **kwargs):
return func(*((self.__instance,) + args), **kwargs)
return give_self
def __init__(self, trait, cls, instance):
self.__instance = instance
for i in list(filter(_is_user_created_meth, dir(trait))):
setattr(self, i, self.__give_self(getattr(cls, i)))
def get_trait[T](trait: type[T], instance) -> T:
return getattr(instance, f"_Trait_.{trait.__module__}.{trait.__qualname__}")(instance)
@dataclass
class TraitSkeleton:
name: str
module: str
qualname: str
def convert_trait_to_skeloton[T](trait: type[T]) -> T:
return TraitSkeleton(trait.__name__, trait.__module__, trait.__qualname__)
@overload
def has_trait(trait: "Trait", cls) -> bool:
pass
@overload
def has_trait(trait: TraitSkeleton, cls) -> bool:
pass
def has_trait(trait: TraitSkeleton | "Triat", cls) -> bool:
if not hasattr(cls, "_Trait_trait"):
return False
if isinstance(trait, TraitSkeleton):
skeleton = trait
else:
skeleton = convert_trait_to_skeloton(trait)
if not skeleton.module in cls._Trait_trait:
return False
if not skeleton.qualname in cls._Trait_trait[skeleton.module]:
return False
return True
class ImplMeta(type):
def __new__(mcs, name, bases, namespace):
global _base_impl
cls = super().__new__(mcs, name, bases, namespace)
is_base_impl = bases == ()
if is_base_impl:
if _base_impl is not None:
raise TypeError(f"only one base Impl can exsist. deleate {name}")
_base_impl = cls
return cls
inher = bases[0]
if inher is _base_impl:
_impl_registry[cls.__module__] = {cls.__qualname__ : cls}
return cls
class TraitMeta(type):
def __new__(mcs, name, bases, namespace):
global _base_trait
global _impl_registry
global _traits_registry
cls = super().__new__(mcs, name, bases, namespace)
is_trait_cls = bases == ()
if is_trait_cls:
if _base_trait is not None:
raise TypeError("only one base trait can exsist")
_base_trait = cls
return cls
base = bases[0]
if base is _base_trait:
_traits_registry.add(cls)
return cls
elif base in _traits_registry:
non_dunder_meth_trait = list(filter(_is_user_created_meth, dir(base)))
non_dunder_meth_cls = list(filter(_is_user_created_meth, dir(cls)))
for method in non_dunder_meth_trait:
if not method in namespace:
raise TypeError(f"method {method} not in {name}, within the {base.__name__} trait")
# else:
# name_space_sig = signature(namespace[method])
# trait_meth_sig = signature(getattr(base, method))
# implement_rule = False
try:
modified_class = _impl_registry[cls.__module__][cls.__qualname__]
except KeyError:
raise TypeError(f"class {name} is not registerd.")
_Trait_impl_layout = partial(_TraitImplementation, base, cls)
setattr(modified_class, f"_Trait_.{base.__module__}.{base.__qualname__}", _Trait_impl_layout)
_impl_registry[modified_class.__module__][modified_class.__qualname__] = modified_class
return modified_class
class RunTimeMeta(type):
def __new__(mcs, name, bases, namespace):
return super().__new__(mcs, name, bases, namespace)
def __getitem__(self, *traits: list[type[Trait]]):
def dummy_func():
pass
name = "_RunTimeMeta_"
methods = {}
for trait in traits:
methods[f"_trait_.{trait.__module__}.{trait.__qualname__}"] = dummy_func
name += f".{trait.__module__}.{trait.__qualname__}"
working_cls = type(name, (Protocol,), methods)
return runtime_checkable(working_cls)
class RunTime(metaclass=RunTimeMeta):
pass
class Impl(metaclass=ImplMeta):
pass
class Trait(metaclass=TraitMeta):
pass
# class Rule(Trait):
# def Rule(self, trait_func_sig: Signature, impl_func_sig: Signature) -> bool:
# raise TypeError("This is ment to be overwritten")
class Cold(Trait):
def is_cold(self) -> bool:
pass
class Cop(Impl):
def __init__(self, social_temp: int, phisical_temp: int):
self.social_temp = social_temp
self.phisical_temp = phisical_temp
class Cop(Cold):
def is_cold(self):
pass
get_trait(Cold, Cop(0,0))
@runtime_checkable
class runtime(Protocol):
def plswork(self):
pass
def social_cold(plswork: runtime):
print("yippy")
dummy_cop = Cop(100, 100)
social_cold(dummy_cop)
social_cold("pls dont work")
### CPython versions tested on:
3.14
### Operating systems tested on:
_No response_
Bug report
Bug description: