Files
eco/tests/test_memory_shared_dir_fallback.py
T
lemke_handClaude Sonnet 5 8637d8096c Don't crash Assembly construction when an account can't create its shared memory directory
A brand new namespace object's memory/presets directory doesn't exist yet,
and accounts differ in whether they're in the group the shared memory tree
(eco_cnf_bernina/memory/) is setgid to -- gac-bernina's default group isn't
unx-sf_bernina_bs and that can't easily be changed. ensure_dir() already
warns-and-continues on a permission failure, but AdjustableFS's write then
turned that into an uncaught FileNotFoundError, taking the whole Assembly
(and anything wrapping it, e.g. Namespace.append_obj) down -- hit live when
constructing the new bernina.status_server object.

Memory.setup_path() now falls back to a private, per-account directory under
home (the same pattern AdjustableFS's own group_writable=False already uses
for RecentComponents/ComponentBookmarks) when the shared one can't be
created, so an account like gac-bernina still gets working memory/presets,
just not cross-account-shared for objects it's the first to touch.
Assembly.__init__ additionally degrades to self.memory = None on any other
unexpected failure there, rather than ever letting it take the object down.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 18:51:24 +02:00

43 lines
1.7 KiB
Python

"""When an account can't create a new directory in the shared memory tree
(eco_cnf_bernina/memory/ -- e.g. the gac-bernina console account, whose
default group isn't the one that tree is setgid to, and that isn't
something eco can fix by chmod'ing anything), Memory.setup_path() falls
back to a private, per-account directory under the home dir instead of
losing memories/presets outright. See test_assembly_memory_degrades.py for
the outer safety net (Assembly construction itself must never crash even
if this fallback also fails)."""
from pathlib import Path
from eco.elements import memory
from eco.elements.assembly import Assembly
def test_setup_path_falls_back_to_home_dir_when_the_shared_one_is_unwritable(
monkeypatch, tmp_path
):
shared_dir = tmp_path / "shared"
home_dir = tmp_path / "home"
home_dir.mkdir()
monkeypatch.setattr(memory, "global_memory_dir", shared_dir)
# simulate a shared directory this account can never create in, without
# actually needing a second unprivileged account in the test
monkeypatch.setattr(memory, "ensure_dir", lambda *a, **k: None)
monkeypatch.setattr(Path, "home", lambda: home_dir)
asm = Assembly(name="some_device")
assert asm.memory is not None
assert not (shared_dir / "some_device").exists()
assert asm.memory._memories() == {}
assert asm.memory.dir == home_dir / ".eco" / "memory" / "some_device"
def test_setup_path_uses_the_shared_dir_when_it_is_writable(monkeypatch, tmp_path):
monkeypatch.setattr(memory, "global_memory_dir", tmp_path)
asm = Assembly(name="some_device")
assert asm.memory.dir == tmp_path / "some_device"
assert asm.memory.dir.is_dir()