This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
import weakref
|
||||
import pytest
|
||||
from utils.registry import Registry, RegistryMeta, instances, _collect_instances
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def clean_registry():
|
||||
"""Reset all registries before each test."""
|
||||
for cls in Registry.__subclasses__():
|
||||
cls.__instances__.clear()
|
||||
|
||||
# RegistryMeta Tests
|
||||
|
||||
def test_metaclass_creates_weakset():
|
||||
|
||||
# Test if RegistryMeta creates WeakSet on classes
|
||||
class TestClass(metaclass=RegistryMeta):
|
||||
pass
|
||||
|
||||
assert hasattr(TestClass, '__instances__')
|
||||
assert isinstance(TestClass.__instances__, weakref.WeakSet)
|
||||
|
||||
def test_metaclass_tracks_instances():
|
||||
# Test instance tracking through metaclass
|
||||
class TestClass(metaclass=RegistryMeta):
|
||||
def __init__(self, x):
|
||||
self.x = x
|
||||
|
||||
instance = TestClass(42)
|
||||
assert instance in TestClass.__instances__
|
||||
|
||||
# Registry Class Tests
|
||||
def test_registry_inheritance(clean_registry):
|
||||
# Test if a Registry subclass gets registry functionality
|
||||
class TestClass(Registry):
|
||||
pass
|
||||
|
||||
assert isinstance(TestClass.__instances__, weakref.WeakSet)
|
||||
|
||||
def test_instance_tracking(clean_registry):
|
||||
# Test basic instance tracking
|
||||
class Animal(Registry):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
cat = Animal("Misty")
|
||||
dog = Animal("Rex")
|
||||
|
||||
assert len(Animal.__instances__) == 2
|
||||
assert cat in Animal.__instances__
|
||||
assert dog in Animal.__instances__
|
||||
|
||||
# Utility function Tests
|
||||
def test_collect_instances_recursive(clean_registry):
|
||||
# Test recursive instance collection
|
||||
class Animal(Registry):
|
||||
pass
|
||||
|
||||
class Dog(Animal):
|
||||
pass
|
||||
|
||||
a = Animal()
|
||||
d = Dog()
|
||||
|
||||
collected = _collect_instances(Animal, recursive=True)
|
||||
assert len(collected) == 2
|
||||
assert a in collected
|
||||
assert d in collected
|
||||
|
||||
def test_instances_function(clean_registry):
|
||||
# Test instances() function behavior
|
||||
class Vehicle(Registry):
|
||||
pass
|
||||
|
||||
class Car(Vehicle):
|
||||
pass
|
||||
|
||||
v = Vehicle()
|
||||
c = Car()
|
||||
|
||||
# Non-recursive
|
||||
assert len(instances(Vehicle, recursive=False)) == 1
|
||||
assert v in instances(Vehicle, recursive=False)
|
||||
|
||||
# Recursive
|
||||
assert len(instances(Vehicle, recursive=True)) == 2
|
||||
assert c in instances(Vehicle, recursive=True)
|
||||
|
||||
# Weak vs strong references
|
||||
assert isinstance(instances(Vehicle, weak=True), weakref.WeakSet)
|
||||
assert isinstance(instances(Vehicle, weak=False), set)
|
||||
|
||||
# Error Cases
|
||||
def test_non_registry_class_error():
|
||||
|
||||
# Test error on non-registry classes
|
||||
class RegularClass:
|
||||
pass
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
_collect_instances(RegularClass)
|
||||
|
||||
def test_signature_preservation():
|
||||
# Test constructor signature preservation
|
||||
class TestClass(Registry):
|
||||
def __init__(self, x: int, y: str = "hello"):
|
||||
pass
|
||||
|
||||
assert "x: int" in str(TestClass.__signature__)
|
||||
assert "y: str = 'hello'" in str(TestClass.__signature__)
|
||||
|
||||
def test_weakset_vs_set_behavior(clean_registry):
|
||||
# Test WeakSet vs set reference behavior
|
||||
class Item(Registry):
|
||||
pass
|
||||
|
||||
item = Item()
|
||||
reg_set = instances(Item, weak=False)
|
||||
reg_weak = instances(Item, weak=True)
|
||||
|
||||
assert len(reg_set) == 1
|
||||
assert len(reg_weak) == 1
|
||||
|
||||
del item
|
||||
assert len(reg_weak) == 0 # WeakSet auto-clears
|
||||
assert len(reg_set) == 1 # Regular set maintains reference
|
||||
Reference in New Issue
Block a user