diff --git a/src/simantic/install.py b/src/simantic/install.py index 40be34f..2509d12 100644 --- a/src/simantic/install.py +++ b/src/simantic/install.py @@ -302,7 +302,22 @@ def rust_engine_root() -> Path: def is_rust_engine(d: Path) -> bool: - return d.is_dir() and any(p.name.startswith("simantic_rust.") for p in d.iterdir()) + """True when `d` holds an importable `simantic_rust`. + + maturin ships the extension as a package: `simantic_rust/__init__.py` + beside `simantic_rust/simantic_rust.abi3.so`. A bare `simantic_rust.` + laid out flat is equally importable. Accept either, because the only thing + that matters here is whether putting `d` on `sys.path` makes the module + import; matching one layout silently re-downloaded the engine on every + process, since the managed copy was never recognised. + """ + if not d.is_dir(): + return False + return any( + p.name.startswith("simantic_rust.") + or (p.name == "simantic_rust" and (p / "__init__.py").exists()) + for p in d.iterdir() + ) def installed_rust_engine() -> Path | None: diff --git a/tests/test_install.py b/tests/test_install.py index 5ef9f05..8bc2bd9 100644 --- a/tests/test_install.py +++ b/tests/test_install.py @@ -434,3 +434,32 @@ def capture(request, **k): with pytest.raises(install.InstallError): install.fetch_rust_manifest() assert seen[0].endswith("/pyrite/latest.json") + + +# -- engine layouts ---------------------------------------------------------- +# +# maturin ships the Rust engine as a package, not a bare .so. Recognising only +# the flat shape looked harmless (the import still worked once the directory was +# on sys.path) but meant the managed copy was never found, so every process +# re-downloaded the wheel. + + +def test_a_maturin_package_layout_is_recognised(tmp_path): + """What `maturin build` actually produces, verified against a real wheel.""" + pkg = tmp_path / "simantic_rust" + pkg.mkdir() + (pkg / "__init__.py").write_text("from .simantic_rust import *\n") + (pkg / "simantic_rust.abi3.so").write_bytes(b"\x7fELF") + (tmp_path / "simantic_rust-0.3.0.dist-info").mkdir() + assert install.is_rust_engine(tmp_path) + + +def test_a_flat_extension_is_recognised(tmp_path): + (tmp_path / "simantic_rust.abi3.so").write_bytes(b"\x7fELF") + assert install.is_rust_engine(tmp_path) + + +def test_a_directory_without_the_module_is_not(tmp_path): + (tmp_path / "simantic_rust-0.3.0.dist-info").mkdir() + (tmp_path / "simantic_rust").mkdir() # no __init__.py: not importable + assert not install.is_rust_engine(tmp_path)