libcontext 0.7.1__tar.gz → 0.7.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {libcontext-0.7.1 → libcontext-0.7.2}/PKG-INFO +1 -1
- {libcontext-0.7.1 → libcontext-0.7.2}/pyproject.toml +1 -1
- {libcontext-0.7.1 → libcontext-0.7.2}/src/libcontext/_envsetup.py +54 -28
- {libcontext-0.7.1 → libcontext-0.7.2}/tests/test_envsetup.py +14 -8
- {libcontext-0.7.1 → libcontext-0.7.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/.github/workflows/ci.yml +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/.github/workflows/release.yml +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/.gitignore +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/CHANGELOG.md +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/CONTRIBUTING.md +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/DEPENDENCIES.md +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/LICENSE +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/README.md +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/SECURITY.md +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/docs/adr/001-progressive-disclosure-over-always-on-context.md +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/docs/adr/002-skill-plus-cli-as-primary-integration.md +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/docs/adr/004-ast-only-inspection.md +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/docs/adr/README.md +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/src/libcontext/__init__.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/src/libcontext/_security.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/src/libcontext/cache.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/src/libcontext/cli.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/src/libcontext/collector.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/src/libcontext/config.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/src/libcontext/diff.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/src/libcontext/exceptions.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/src/libcontext/inspector.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/src/libcontext/mcp_server.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/src/libcontext/models.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/src/libcontext/py.typed +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/src/libcontext/renderer.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/tests/__init__.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/tests/test_cache.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/tests/test_cli.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/tests/test_cli_mcp_parity.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/tests/test_collector.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/tests/test_config.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/tests/test_diff.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/tests/test_inspector.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/tests/test_mcp_server.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/tests/test_models.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/tests/test_renderer.py +0 -0
- {libcontext-0.7.1 → libcontext-0.7.2}/tests/test_security.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: libcontext
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.2
|
|
4
4
|
Summary: Generate optimized LLM context from Python library APIs — CLI, skill, and MCP server
|
|
5
5
|
Project-URL: Homepage, https://github.com/Syclaw/libcontext
|
|
6
6
|
Project-URL: Repository, https://github.com/Syclaw/libcontext
|
|
@@ -46,6 +46,50 @@ _INTERPRETER_CANDIDATES = (
|
|
|
46
46
|
Path("bin") / "python3", # Unix alternative
|
|
47
47
|
)
|
|
48
48
|
|
|
49
|
+
# Script executed in the *target* interpreter to collect site-packages
|
|
50
|
+
# directories. Kept as a module constant so it can be tested directly.
|
|
51
|
+
# Uses only stdlib modules guaranteed present in Python 3.9+.
|
|
52
|
+
_SITE_PACKAGES_SCRIPT = """\
|
|
53
|
+
import json, site, sys, os
|
|
54
|
+
|
|
55
|
+
paths = []
|
|
56
|
+
|
|
57
|
+
# site-packages directories (includes system site-packages when the
|
|
58
|
+
# venv was created with --system-site-packages)
|
|
59
|
+
try:
|
|
60
|
+
paths.extend(site.getsitepackages())
|
|
61
|
+
except AttributeError:
|
|
62
|
+
pass
|
|
63
|
+
|
|
64
|
+
# User site-packages (e.g. ~/.local/lib/python3.x/site-packages),
|
|
65
|
+
# honoured only when ENABLE_USER_SITE is not explicitly disabled.
|
|
66
|
+
if site.ENABLE_USER_SITE:
|
|
67
|
+
try:
|
|
68
|
+
user = site.getusersitepackages()
|
|
69
|
+
if isinstance(user, str):
|
|
70
|
+
paths.append(user)
|
|
71
|
+
except AttributeError:
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
# .pth files in site-packages can inject arbitrary paths into sys.path
|
|
75
|
+
# (editable installs, namespace packages, etc.). Collect them by
|
|
76
|
+
# diffing sys.path against site-packages — any path that is not a
|
|
77
|
+
# site-packages dir and not under sys.base_prefix is .pth-injected.
|
|
78
|
+
site_set = set(os.path.realpath(p) for p in paths)
|
|
79
|
+
base = os.path.realpath(sys.base_prefix)
|
|
80
|
+
for p in sys.path:
|
|
81
|
+
if not p:
|
|
82
|
+
continue
|
|
83
|
+
rp = os.path.realpath(p)
|
|
84
|
+
if rp in site_set:
|
|
85
|
+
continue
|
|
86
|
+
if rp == base or rp.startswith(base + os.sep):
|
|
87
|
+
continue
|
|
88
|
+
paths.append(p)
|
|
89
|
+
|
|
90
|
+
print(json.dumps(paths))
|
|
91
|
+
"""
|
|
92
|
+
|
|
49
93
|
|
|
50
94
|
def _has_python_interpreter(venv_dir: Path) -> bool:
|
|
51
95
|
"""Check whether a directory contains a recognisable Python interpreter."""
|
|
@@ -262,44 +306,26 @@ def resolve_python_executable(python_arg: str) -> Path:
|
|
|
262
306
|
|
|
263
307
|
|
|
264
308
|
def get_target_sys_path(python_exe: Path) -> list[str]:
|
|
265
|
-
"""Query a
|
|
309
|
+
"""Query a target interpreter for its package-discovery paths.
|
|
266
310
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
target
|
|
311
|
+
Collects site-packages directories (including system site-packages
|
|
312
|
+
for ``--system-site-packages`` venvs), user site-packages, and
|
|
313
|
+
any paths injected by ``.pth`` files (editable installs, namespace
|
|
314
|
+
packages). Stdlib paths are **excluded** to prevent cross-version
|
|
315
|
+
import contamination when tool and target run different Python
|
|
316
|
+
versions.
|
|
272
317
|
|
|
273
318
|
Args:
|
|
274
319
|
python_exe: Absolute path to the target Python executable.
|
|
275
320
|
|
|
276
321
|
Returns:
|
|
277
|
-
List of
|
|
322
|
+
List of path strings suitable for prepending to ``sys.path``
|
|
323
|
+
in the tool process.
|
|
278
324
|
|
|
279
325
|
Raises:
|
|
280
326
|
EnvironmentSetupError: If the subprocess fails or times out.
|
|
281
327
|
"""
|
|
282
|
-
|
|
283
|
-
# When the target runs a different Python version from the tool,
|
|
284
|
-
# injecting stdlib paths causes C-extension mismatches (e.g.
|
|
285
|
-
# Python 3.13 loading csv.py from 3.11 stdlib → _csv ImportError).
|
|
286
|
-
script = (
|
|
287
|
-
"import json, os, sys\n"
|
|
288
|
-
"base = os.path.realpath(sys.base_prefix)\n"
|
|
289
|
-
"prefix = os.path.realpath(sys.prefix)\n"
|
|
290
|
-
"in_venv = prefix != base\n"
|
|
291
|
-
"def _under(p, root):\n"
|
|
292
|
-
" return p == root or p.startswith(root + os.sep)\n"
|
|
293
|
-
"paths = [\n"
|
|
294
|
-
" p for p in sys.path\n"
|
|
295
|
-
" if p and not (\n"
|
|
296
|
-
" in_venv\n"
|
|
297
|
-
" and _under(os.path.realpath(p), base)\n"
|
|
298
|
-
" and not _under(os.path.realpath(p), prefix)\n"
|
|
299
|
-
" )\n"
|
|
300
|
-
"]\n"
|
|
301
|
-
"print(json.dumps(paths))\n"
|
|
302
|
-
)
|
|
328
|
+
script = _SITE_PACKAGES_SCRIPT
|
|
303
329
|
try:
|
|
304
330
|
result = subprocess.run(
|
|
305
331
|
[str(python_exe), "-c", script],
|
|
@@ -82,8 +82,8 @@ def test_get_target_sys_path_bad_executable(tmp_path):
|
|
|
82
82
|
get_target_sys_path(fake)
|
|
83
83
|
|
|
84
84
|
|
|
85
|
-
def
|
|
86
|
-
"""
|
|
85
|
+
def test_get_target_sys_path_returns_site_packages_not_stdlib():
|
|
86
|
+
"""Returns site-packages paths and excludes base-interpreter stdlib."""
|
|
87
87
|
paths = get_target_sys_path(Path(sys.executable))
|
|
88
88
|
|
|
89
89
|
base = os.path.realpath(sys.base_prefix)
|
|
@@ -91,14 +91,20 @@ def test_get_target_sys_path_excludes_base_stdlib_in_venv():
|
|
|
91
91
|
if prefix == base:
|
|
92
92
|
pytest.skip("not running inside a venv")
|
|
93
93
|
|
|
94
|
-
#
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
# At least one site-packages directory must be present.
|
|
95
|
+
assert any("site-packages" in p for p in paths), (
|
|
96
|
+
f"no site-packages found in returned paths: {paths}"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# No path should resolve under the base Python installation
|
|
100
|
+
# (stdlib, lib-dynload, zip archives) unless it is also under
|
|
101
|
+
# the venv prefix.
|
|
102
|
+
def _under(child: str, root: str) -> bool:
|
|
103
|
+
return child == root or child.startswith(root + os.sep)
|
|
104
|
+
|
|
97
105
|
for p in paths:
|
|
98
106
|
rp = os.path.realpath(p)
|
|
99
|
-
|
|
100
|
-
is_under_venv = rp.startswith(prefix + os.sep) or rp == prefix
|
|
101
|
-
if is_under_base and not is_under_venv:
|
|
107
|
+
if _under(rp, base) and not _under(rp, prefix):
|
|
102
108
|
pytest.fail(f"base-interpreter stdlib path leaked: {p}")
|
|
103
109
|
|
|
104
110
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{libcontext-0.7.1 → libcontext-0.7.2}/docs/adr/001-progressive-disclosure-over-always-on-context.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|