def test_deref(): assert 1 == runtime.deref(atom.Atom(1)) assert vec.PersistentVector.empty() == runtime.deref( atom.Atom(vec.PersistentVector.empty()) ) with pytest.raises(TypeError): runtime.deref(1) with pytest.raises(TypeError): runtime.deref(vec.PersistentVector.empty())
def ns_cache(core_ns_sym: sym.Symbol, core_ns: Namespace) -> atom.Atom[NamespaceMap]: """Patch the Namespace cache with a test fixture.""" with patch( "basilisp.lang.runtime.Namespace._NAMESPACES", new=atom.Atom(lmap.map({core_ns_sym: core_ns})), ) as cache: yield cache
def test_reset_atom_meta(): a = atom.Atom(None) assert a.meta is None a.reset_meta(lmap.map({"type": sym.symbol("str")})) assert a.meta == lmap.m(type=sym.symbol("str")) a.reset_meta(lmap.m(tag=kw.keyword("async"))) assert a.meta == lmap.m(tag=kw.keyword("async"))
def test_alter_atom_meta(): a = atom.Atom(None) assert a.meta is None a.alter_meta(runtime.assoc, "type", sym.symbol("str")) assert a.meta == lmap.m(type=sym.symbol("str")) a.alter_meta(runtime.assoc, "tag", kw.keyword("async")) assert a.meta == lmap.m(type=sym.symbol("str"), tag=kw.keyword("async"))
def ns_cache_with_existing_ns(ns_sym: sym.Symbol, core_ns_sym: sym.Symbol, core_ns: Namespace) -> atom.Atom[NamespaceMap]: """Patch the Namespace cache with a test fixture with an existing namespace.""" with patch( "basilisp.lang.runtime.Namespace._NAMESPACES", atom.Atom( lmap.map({ core_ns_sym: core_ns, ns_sym: Namespace(ns_sym) })), ) as cache: yield cache
def test_atom_validators(): with pytest.raises(ExceptionInfo): atom.Atom(None, validator=lambda v: v is not None) even_validator = lambda i: isinstance(i, int) and i % 2 == 0 a = atom.Atom(0, validator=even_validator) assert even_validator == a.get_validator() assert 2 == a.swap(lambda i: i + 2) with pytest.raises(ExceptionInfo): a.swap(lambda i: i + 1) a.set_validator() assert None is a.get_validator() assert 1 == a.reset(1) odd_validator = lambda i: isinstance(i, int) and i % 2 == 1 a.set_validator(odd_validator) with pytest.raises(ExceptionInfo): a.compare_and_set(1, 4)
def test_atom(): a = atom.Atom(vec.PersistentVector.empty()) assert vec.PersistentVector.empty() == a.deref() assert vec.v(1) == a.swap(lambda v, e: v.cons(e), 1) assert vec.v(1) == a.deref() assert vec.v(1, 2) == a.swap(lambda v, e: v.cons(e), 2) assert vec.v(1, 2) == a.deref() assert lmap.PersistentMap.empty() == a.reset(lmap.PersistentMap.empty()) assert lmap.PersistentMap.empty() == a.deref() assert False is a.compare_and_set("not a map", vec.PersistentVector.empty()) assert True is a.compare_and_set(lmap.PersistentMap.empty(), "new string") assert "new string" == a.deref()
def test_atom_watchers(): a = atom.Atom(0) assert a is a.remove_watch("nonexistent-watch") watcher1_key = kw.keyword("watcher-the-first") watcher1_vals = [] def watcher1(k, ref, old, new): assert watcher1_key is k assert a is ref watcher1_vals.append((old, new)) a.add_watch(watcher1_key, watcher1) a.swap(lambda v: v * 2) # == 0 a.reset(4) # == 4 watcher2_key = kw.keyword("watcher-the-second") watcher2_vals = [] def watcher2(k, ref, old, new): assert watcher2_key is k assert a is ref watcher2_vals.append((old, new)) a.add_watch(watcher2_key, watcher2) a.swap(lambda v: v * 2) # == 8 a.remove_watch(watcher1_key) a.reset(10) # == 10 a.swap(lambda v: "a" * v) # == "aaaaaaaaaa" # A failing CAS won't notify watches, so we'll test that: assert False is a.compare_and_set(10, "ten") assert [(0, 0), (0, 4), (4, 8)] == watcher1_vals assert [(4, 8), (8, 10), (10, "aaaaaaaaaa")] == watcher2_vals
def ns_cache(ns_sym: sym.Symbol) -> atom.Atom[NamespaceMap]: with patch( "basilisp.lang.runtime.Namespace._NAMESPACES", atom.Atom(lmap.map({ns_sym: Namespace(ns_sym)})), ) as ns_cache: yield ns_cache
def __init__(self, f: Callable[[], T]) -> None: self._state = atom.Atom( # pylint:disable=assigning-non-slot _DelayState(f=f, value=None, computed=False))
"__setattr__", "__setitem__", "__setslice__", "__setstate__", "__str__", "__sub__", "__subclasscheck__", "__subclasshook__", "__truediv__", "__xor__", }) # Use an atomically incremented integer as a suffix for all # user-defined function and variable names compiled into Python # code so no conflicts occur _NAME_COUNTER = atom.Atom(1) def next_name_id() -> int: """Increment the name counter and return the next value.""" return _NAME_COUNTER.swap(lambda x: x + 1) def genname(prefix: str) -> str: """Generate a unique function name with the given prefix.""" i = next_name_id() return f"{prefix}_{i}" def decimal_from_str(decimal_str: str) -> Decimal: """Create a Decimal from a numeric string."""
def test_atom_deref_interface(interface): assert isinstance(atom.Atom(1), interface) assert issubclass(atom.Atom, interface)