fix(documents): guard Unix-only resource import for Windows (#877)
`document_processors/_isolation.py` did an unconditional module-level `import resource`, a POSIX-only stdlib module absent on Windows. It was pulled into the API startup path via `server/webdav.py -> utils/document_parser -> document_processors`, so the MCP server failed to start on Windows since 0.101.2 with `ModuleNotFoundError: No module named 'resource'`. - Guard the import behind `sys.platform`; bind `resource = None` on win32. `_apply_mem_limit()` degrades to a logged no-op when the module is unavailable (the RLIMIT_AS cap is a Linux-pod safety measure, not a correctness requirement). - Make the document-parser import in `server/webdav.py` lazy so server startup never loads the ingest document stack (document_processors -> pymupdf -> _isolation) at all -- it is only needed when a file is actually read and parsed. This both fixes #877 and decouples the API layer from ingest-only deps. - Add unit regressions for the no-op path and the win32 import guard. - Add a cross-platform `package-smoke` CI job (ubuntu + windows) that installs the package isolated and runs the CLI, exercising the cli -> server -> webdav import chain that crashed in #877. Fixes #877 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
96c0491f14
commit
fc8a4e4dfa
@@ -14,6 +14,7 @@ or depend on the sample files).
|
||||
"""
|
||||
|
||||
import resource
|
||||
import sys
|
||||
|
||||
import anyio
|
||||
import anyio.to_process
|
||||
@@ -161,6 +162,41 @@ def test_apply_mem_limit_is_applied_once(monkeypatch):
|
||||
assert len(calls) == 1 # second call is a no-op
|
||||
|
||||
|
||||
# --- Windows / no-``resource`` platform compatibility (#877) -----------------
|
||||
|
||||
|
||||
def test_apply_mem_limit_noop_when_resource_unavailable(monkeypatch):
|
||||
"""On a platform without ``resource`` (e.g. Windows) the cap is skipped.
|
||||
|
||||
Regression for #877: ``resource`` is Unix-only, so ``_apply_mem_limit`` must
|
||||
degrade to a no-op (rather than crash) when the module is unavailable.
|
||||
"""
|
||||
monkeypatch.setattr(_isolation, "_MEM_LIMIT_APPLIED", False)
|
||||
monkeypatch.setattr(_isolation, "resource", None)
|
||||
_isolation._apply_mem_limit(1536) # must not raise
|
||||
assert _isolation._MEM_LIMIT_APPLIED is True
|
||||
|
||||
|
||||
def test_isolation_imports_on_windows_without_resource(monkeypatch):
|
||||
"""Importing ``_isolation`` on Windows must not crash on ``import resource``.
|
||||
|
||||
Regression for #877: a module-scope ``import resource`` raised
|
||||
``ModuleNotFoundError`` on Windows and took down server startup. With
|
||||
``sys.platform == 'win32'`` the module must import cleanly and bind
|
||||
``resource`` to ``None``.
|
||||
"""
|
||||
import importlib
|
||||
|
||||
monkeypatch.setattr(sys, "platform", "win32")
|
||||
monkeypatch.delitem(
|
||||
sys.modules,
|
||||
"nextcloud_mcp_server.document_processors._isolation",
|
||||
raising=False,
|
||||
)
|
||||
mod = importlib.import_module("nextcloud_mcp_server.document_processors._isolation")
|
||||
assert mod.resource is None
|
||||
|
||||
|
||||
# --- PyMuPDF processor wiring ------------------------------------------------
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user