test hooks

This commit is contained in:
John Lancaster
2026-02-20 23:44:42 -06:00
parent 424ce9acab
commit ba5fffa959

View File

@@ -2,7 +2,7 @@ from __future__ import annotations
from collections import defaultdict from collections import defaultdict
from collections.abc import Iterable, Iterator, MutableMapping, MutableSet from collections.abc import Iterable, Iterator, MutableMapping, MutableSet
from typing import DefaultDict, Generic, Set, TypeVar from typing import Generic, Set, TypeVar
from .set import DAGSet from .set import DAGSet
@@ -20,15 +20,27 @@ class DAG(Generic[T], MutableMapping[T, MutableSet[T]]):
""" """
def __init__(self) -> None: def __init__(self) -> None:
self._succ: DefaultDict[T, Set[T]] = defaultdict(set) self._succ: defaultdict[T, Set[T]] = defaultdict(set)
self.reverse: DefaultDict[T, Set[T]] = defaultdict(set) self.reverse: defaultdict[T, Set[T]] = defaultdict(set)
# --- MutableMapping interface --- # --- MutableMapping interface ---
def __getitem__(self, u: T) -> MutableSet[T]: def __getitem__(self, u: T) -> MutableSet[T]:
# defaultdict semantics: touch key dagset = DAGSet(self._succ.get(u))
_ = self._succ[u]
return DAGSet(self, u) def on_add(v: T) -> None:
self._succ[u].add(v)
self.reverse[v].add(u)
print(f"Adding edge {u} -> {v}")
def on_remove(v: T) -> None:
self._succ[u].remove(v)
self.reverse[v].remove(u)
print(f"Removing edge {u} -> {v}")
dagset.on_add = on_add
dagset.on_remove = on_remove
return dagset
def __setitem__(self, u: T, vs: Iterable[T]) -> None: def __setitem__(self, u: T, vs: Iterable[T]) -> None:
view = DAGSet(self, u) view = DAGSet(self, u)
@@ -45,7 +57,7 @@ class DAG(Generic[T], MutableMapping[T, MutableSet[T]]):
return len(self._succ) return len(self._succ)
def __repr__(self) -> str: def __repr__(self) -> str:
return f"DagAdj({dict(self._succ)!r})" return f"{self.__class__.__name__}{dict(self._succ)!r}"
# --- core edge/node operations (single source of truth) --- # --- core edge/node operations (single source of truth) ---
@@ -53,6 +65,11 @@ class DAG(Generic[T], MutableMapping[T, MutableSet[T]]):
if u == v: if u == v:
raise ValueError("Self-loops are not allowed in a DAG") raise ValueError("Self-loops are not allowed in a DAG")
if u not in self._succ:
self._succ[u] = set()
if v not in self.reverse:
self.reverse[v] = set()
if v not in self._succ[u]: if v not in self._succ[u]:
self._succ[u].add(v) self._succ[u].add(v)
self.reverse[v].add(u) self.reverse[v].add(u)