repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources15d ago| #1 | """[issue #53] Regression test for `hermes mnemosyne version` ImportError. |
| #2 | |
| #3 | The repo has a nested-package layout: |
| #4 | mnemosyne/ ← outer: repo root + Hermes plugin entry stub |
| #5 | __init__.py ← used to NOT define __version__/__author__ |
| #6 | mnemosyne/ ← inner: actual library |
| #7 | __init__.py ← defines __version__ / __author__ |
| #8 | |
| #9 | When Hermes installs the plugin via repo-tree symlink, the OUTER package |
| #10 | becomes the resolved `mnemosyne` module on `sys.path`. Pre-fix, |
| #11 | `from mnemosyne import __version__, __author__` raised ImportError because |
| #12 | the outer stub didn't re-export those names. Post-fix, the outer stub |
| #13 | re-exports from `.mnemosyne` (the inner subpackage). |
| #14 | |
| #15 | This test simulates the Hermes plugin-loader sys.path layout via subprocess |
| #16 | so it doesn't pollute the test process's already-loaded `mnemosyne` module |
| #17 | (pytest runs from the repo with the inner package directly on path, which |
| #18 | bypasses the failure mode). |
| #19 | """ |
| #20 | |
| #21 | from __future__ import annotations |
| #22 | |
| #23 | import subprocess |
| #24 | import sys |
| #25 | import textwrap |
| #26 | from pathlib import Path |
| #27 | |
| #28 | REPO_ROOT = Path(__file__).resolve().parent.parent |
| #29 | |
| #30 | |
| #31 | def test_outer_package_reexports_version_and_author(): |
| #32 | """Simulate Hermes plugin-loader layout: parent of repo root on sys.path, |
| #33 | so `import mnemosyne` resolves to the OUTER stub package. The outer must |
| #34 | re-export __version__ and __author__ from the inner subpackage.""" |
| #35 | # Run a subprocess with sys.path manipulated so the outer mnemosyne stub |
| #36 | # is the resolved `mnemosyne` module — exactly the layout Hermes' plugin |
| #37 | # loader produces when symlinking the repo root into ~/.hermes/plugins. |
| #38 | script = textwrap.dedent(f""" |
| #39 | import sys |
| #40 | # Put the parent of the repo first so `mnemosyne` resolves to the |
| #41 | # outer __init__.py at the repo root, mirroring the plugin layout. |
| #42 | sys.path.insert(0, {str(REPO_ROOT.parent)!r}) |
| #43 | # Drop the inner-package path (if present) so we don't accidentally |
| #44 | # resolve to the inner __init__.py instead. |
| #45 | sys.path = [p for p in sys.path if p != {str(REPO_ROOT)!r}] |
| #46 | |
| #47 | import mnemosyne |
| #48 | # Sanity check: we loaded the OUTER stub, not the inner library. |
| #49 | assert mnemosyne.__file__.endswith({str(REPO_ROOT / "__init__.py")!r}), ( |
| #50 | "test setup failed: did not load outer package, got " + mnemosyne.__file__ |
| #51 | ) |
| #52 | |
| #53 | # The actual contract: |
| #54 | from mnemosyne import __version__, __author__ |
| #55 | print("VERSION=" + __version__) |
| #56 | print("AUTHOR=" + __author__) |
| #57 | """) |
| #58 | |
| #59 | result = subprocess.run( |
| #60 | [sys.executable, "-c", script], |
| #61 | capture_output=True, |
| #62 | text=True, |
| #63 | cwd=str(REPO_ROOT.parent), # avoid CWD on path leaking inner package |
| #64 | ) |
| #65 | |
| #66 | assert result.returncode == 0, ( |
| #67 | f"subprocess failed:\nstdout:\n{result.stdout}\nstderr:\n{result.stderr}" |
| #68 | ) |
| #69 | assert "VERSION=" in result.stdout, result.stdout |
| #70 | assert "AUTHOR=" in result.stdout, result.stdout |
| #71 | |
| #72 | # Don't pin a specific version (it bumps); just assert non-empty and not |
| #73 | # the fallback "unknown" that the except-branch would emit if the inner |
| #74 | # subpackage somehow couldn't be imported. |
| #75 | version_line = next( |
| #76 | ln for ln in result.stdout.splitlines() if ln.startswith("VERSION=") |
| #77 | ) |
| #78 | version = version_line.split("=", 1)[1].strip() |
| #79 | assert version and version != "unknown", ( |
| #80 | f"outer __init__.py exported VERSION={version!r}; expected a real " |
| #81 | f"version string from the inner subpackage. Likely cause: the " |
| #82 | f"`from .mnemosyne import __version__` re-export failed and we " |
| #83 | f"fell through to the except-branch fallback." |
| #84 | ) |
| #85 |