fix(pfs,cli): the CPT parser imports rex lazily so the stack CLI starts in the api image (no fsspec there) — the nightly Zotero sync and mail poller run inside it (refs #718)
Some checks failed
CI / lint (push) Successful in 33s
CI / notebooks-smoke (push) Successful in 1m26s
Deploy / notebooks (push) Has been skipped
Deploy / zotero (push) Has been skipped
Deploy / docs (push) Has been skipped
Deploy / api (push) Has been skipped
Deploy / llm (push) Has been skipped
Deploy / mc (push) Has been skipped
Infra CI / notebooks (push) Successful in 51s
Infra CI / zotero (push) Successful in 13s
Infra CI / docs (push) Successful in 20s
Infra CI / api (push) Successful in 1m13s
Infra CI / llm (push) Successful in 45s
Infra CI / mc (push) Failing after 13s
Deploy / report (push) Successful in 14s
CI / test (push) Successful in 14m20s
Some checks failed
CI / lint (push) Successful in 33s
CI / notebooks-smoke (push) Successful in 1m26s
Deploy / notebooks (push) Has been skipped
Deploy / zotero (push) Has been skipped
Deploy / docs (push) Has been skipped
Deploy / api (push) Has been skipped
Deploy / llm (push) Has been skipped
Deploy / mc (push) Has been skipped
Infra CI / notebooks (push) Successful in 51s
Infra CI / zotero (push) Successful in 13s
Infra CI / docs (push) Successful in 20s
Infra CI / api (push) Successful in 1m13s
Infra CI / llm (push) Successful in 45s
Infra CI / mc (push) Failing after 13s
Deploy / report (push) Successful in 14s
CI / test (push) Successful in 14m20s
This commit is contained in:
@@ -47,7 +47,6 @@ from pfs.cpt_model import (
|
||||
CptReference,
|
||||
CptSection,
|
||||
)
|
||||
from rex.comments.epub_text import content_root
|
||||
|
||||
# One CPT code: 4 digits + a digit/letter (99490, 0202U, 99213F, 0042T, 0001A).
|
||||
_CODE = re.compile(r"\b\d{4}[0-9A-Z]\b")
|
||||
@@ -906,6 +905,11 @@ def parse_epub(path: Path, *, year: int | None = None) -> CptEdition:
|
||||
# Resolved once via container.xml -> the OPF's own path, not
|
||||
# hard-coded — falls back to "OPS/" (every edition checked so
|
||||
# far) when container.xml is missing/malformed (F2).
|
||||
# Lazy: importing rex.comments pulls in the rex package (fsspec),
|
||||
# which the api image's `cli` extra does not carry — the CLI must
|
||||
# import without it (tests/cli/test_cli_import_without_optional_deps.py).
|
||||
from rex.comments.epub_text import content_root
|
||||
|
||||
root = content_root(zf)
|
||||
|
||||
toc_ranges: dict[str, tuple[str, str]] = {}
|
||||
|
||||
32
tests/cli/test_cli_import_without_optional_deps.py
Normal file
32
tests/cli/test_cli_import_without_optional_deps.py
Normal file
@@ -0,0 +1,32 @@
|
||||
"""The api image installs the ``cli`` extra only (no fsspec/s3fs/obstore —
|
||||
those belong to the lake/rex extras). ``stack`` must still start there:
|
||||
the nightly Zotero sync and the mail poller run inside that image. On
|
||||
2026-09-11 a module-level ``pfs.cpt_load → pfs.cpt_epub → rex`` import
|
||||
chain made every ``stack`` invocation in the api image die with
|
||||
``ModuleNotFoundError: fsspec``."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
_PROBE = """
|
||||
import builtins
|
||||
_real = builtins.__import__
|
||||
def _fake(name, *a, **k):
|
||||
if name.split('.')[0] in {'fsspec', 's3fs', 'obstore'}:
|
||||
raise ModuleNotFoundError(name)
|
||||
return _real(name, *a, **k)
|
||||
builtins.__import__ = _fake
|
||||
import cli # the `stack` entry point package
|
||||
import cli.pfs, cli.bib, cli.llm
|
||||
print('cli ok')
|
||||
"""
|
||||
|
||||
|
||||
def test_stack_cli_imports_without_lake_extras():
|
||||
r = subprocess.run(
|
||||
[sys.executable, "-c", _PROBE], capture_output=True, text=True, check=False
|
||||
)
|
||||
assert r.returncode == 0, r.stderr[-1200:]
|
||||
assert "cli ok" in r.stdout
|
||||
Reference in New Issue
Block a user