libcontext 0.6.0__tar.gz → 0.6.1__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.6.0 → libcontext-0.6.1}/CHANGELOG.md +10 -1
- {libcontext-0.6.0 → libcontext-0.6.1}/PKG-INFO +1 -1
- {libcontext-0.6.0 → libcontext-0.6.1}/pyproject.toml +1 -1
- {libcontext-0.6.0 → libcontext-0.6.1}/src/libcontext/collector.py +14 -2
- {libcontext-0.6.0 → libcontext-0.6.1}/tests/test_collector.py +50 -10
- {libcontext-0.6.0 → libcontext-0.6.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/.github/workflows/ci.yml +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/.github/workflows/release.yml +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/.gitignore +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/CONTRIBUTING.md +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/DEPENDENCIES.md +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/LICENSE +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/README.md +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/SECURITY.md +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/docs/adr/001-progressive-disclosure-over-always-on-context.md +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/docs/adr/002-skill-plus-cli-as-primary-integration.md +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/docs/adr/004-ast-only-inspection.md +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/docs/adr/README.md +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/src/libcontext/__init__.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/src/libcontext/_envsetup.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/src/libcontext/_security.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/src/libcontext/cache.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/src/libcontext/cli.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/src/libcontext/config.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/src/libcontext/diff.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/src/libcontext/exceptions.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/src/libcontext/inspector.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/src/libcontext/mcp_server.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/src/libcontext/models.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/src/libcontext/py.typed +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/src/libcontext/renderer.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/tests/__init__.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/tests/test_cache.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/tests/test_cli.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/tests/test_cli_mcp_parity.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/tests/test_config.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/tests/test_diff.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/tests/test_envsetup.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/tests/test_inspector.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/tests/test_mcp_server.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/tests/test_models.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/tests/test_renderer.py +0 -0
- {libcontext-0.6.0 → libcontext-0.6.1}/tests/test_security.py +0 -0
|
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.6.1] - 2026-03-25
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **ImportError crash with `packages_distributions()`**: wrapped call in try/except to handle broken metadata or mixed Python installations (e.g. `_csv` ImportError on Python 3.13).
|
|
15
|
+
- **Python 3.9 compatibility**: fixed parenthesized context managers and `create=True` for `mock.patch`.
|
|
16
|
+
|
|
10
17
|
## [0.5.0] - 2026-03-23
|
|
11
18
|
|
|
12
19
|
### Added
|
|
@@ -101,7 +108,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
101
108
|
- Free-form `extra_context` field for library authors.
|
|
102
109
|
- Python API for programmatic usage (`collect_package`, `render_package`).
|
|
103
110
|
|
|
104
|
-
[Unreleased]: https://github.com/Syclaw/libcontext/compare/v0.
|
|
111
|
+
[Unreleased]: https://github.com/Syclaw/libcontext/compare/v0.6.1...HEAD
|
|
112
|
+
[0.6.1]: https://github.com/Syclaw/libcontext/compare/v0.6.0...v0.6.1
|
|
113
|
+
[0.6.0]: https://github.com/Syclaw/libcontext/compare/v0.5.0...v0.6.0
|
|
105
114
|
[0.5.0]: https://github.com/Syclaw/libcontext/compare/v0.4.0...v0.5.0
|
|
106
115
|
[0.4.0]: https://github.com/Syclaw/libcontext/compare/v0.3.0...v0.4.0
|
|
107
116
|
[0.3.0]: https://github.com/Syclaw/libcontext/compare/v0.2.0...v0.3.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: libcontext
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.1
|
|
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
|
|
@@ -47,8 +47,20 @@ def _get_installed_package_names() -> list[str]:
|
|
|
47
47
|
names: set[str] = set()
|
|
48
48
|
|
|
49
49
|
if sys.version_info >= (3, 11):
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
try:
|
|
51
|
+
for import_name in importlib.metadata.packages_distributions():
|
|
52
|
+
names.add(import_name)
|
|
53
|
+
except (ImportError, Exception):
|
|
54
|
+
# packages_distributions() may fail when the environment
|
|
55
|
+
# contains distributions with broken metadata or when a
|
|
56
|
+
# mixed Python installation causes an ImportError inside
|
|
57
|
+
# stdlib modules (e.g. csv). Fall through to the
|
|
58
|
+
# distributions()-based collection below which is more
|
|
59
|
+
# resilient.
|
|
60
|
+
logger.debug(
|
|
61
|
+
"packages_distributions() failed; falling back to distributions() only",
|
|
62
|
+
exc_info=True,
|
|
63
|
+
)
|
|
52
64
|
|
|
53
65
|
seen_distributions: set[str] = set()
|
|
54
66
|
for dist in importlib.metadata.distributions():
|
|
@@ -676,26 +676,66 @@ def test_suggest_similar_packages_uses_top_level_names() -> None:
|
|
|
676
676
|
assert "PIL" in suggestions
|
|
677
677
|
|
|
678
678
|
|
|
679
|
+
_PKGS_DISTS_PATH = "libcontext.collector.importlib.metadata.packages_distributions"
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
def test_get_installed_package_names_handles_import_error() -> None:
|
|
683
|
+
"""packages_distributions() raising ImportError is caught gracefully."""
|
|
684
|
+
dists = [
|
|
685
|
+
_make_mock_dist("requests"),
|
|
686
|
+
]
|
|
687
|
+
err = ImportError("cannot import name '__version__' from '_csv'")
|
|
688
|
+
with patch(_PKGS_DISTS_PATH, side_effect=err, create=True): # noqa: SIM117
|
|
689
|
+
with patch(_DISTS_PATH, return_value=dists):
|
|
690
|
+
names = _get_installed_package_names()
|
|
691
|
+
|
|
692
|
+
# Should still collect names from distributions() fallback
|
|
693
|
+
assert "requests" in names
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
def test_get_installed_package_names_handles_generic_exception() -> None:
|
|
697
|
+
"""packages_distributions() raising any Exception is caught gracefully."""
|
|
698
|
+
dists = [
|
|
699
|
+
_make_mock_dist("flask"),
|
|
700
|
+
]
|
|
701
|
+
err = RuntimeError("broken metadata")
|
|
702
|
+
with patch(_PKGS_DISTS_PATH, side_effect=err, create=True): # noqa: SIM117
|
|
703
|
+
with patch(_DISTS_PATH, return_value=dists):
|
|
704
|
+
names = _get_installed_package_names()
|
|
705
|
+
|
|
706
|
+
assert "flask" in names
|
|
707
|
+
|
|
708
|
+
|
|
709
|
+
def test_suggest_similar_packages_resilient_to_import_error() -> None:
|
|
710
|
+
"""suggest_similar_packages works even if packages_distributions() fails."""
|
|
711
|
+
dists = [
|
|
712
|
+
_make_mock_dist("requests"),
|
|
713
|
+
_make_mock_dist("flask"),
|
|
714
|
+
]
|
|
715
|
+
err = ImportError("csv import broken")
|
|
716
|
+
with patch(_PKGS_DISTS_PATH, side_effect=err, create=True): # noqa: SIM117
|
|
717
|
+
with patch(_DISTS_PATH, return_value=dists):
|
|
718
|
+
suggestions = suggest_similar_packages("reqeusts")
|
|
719
|
+
|
|
720
|
+
assert "requests" in suggestions
|
|
721
|
+
|
|
722
|
+
|
|
679
723
|
def test_collect_package_error_includes_suggestions() -> None:
|
|
680
724
|
"""PackageNotFoundError from collect_package includes suggestions."""
|
|
681
725
|
dists = [
|
|
682
726
|
_make_mock_dist("click"),
|
|
683
727
|
_make_mock_dist("flask"),
|
|
684
728
|
]
|
|
685
|
-
with (
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
):
|
|
689
|
-
collect_package("clck")
|
|
729
|
+
with patch(_DISTS_PATH, return_value=dists): # noqa: SIM117
|
|
730
|
+
with pytest.raises(PackageNotFoundError, match="Did you mean"):
|
|
731
|
+
collect_package("clck")
|
|
690
732
|
|
|
691
733
|
|
|
692
734
|
def test_collect_package_error_no_suggestions() -> None:
|
|
693
735
|
"""PackageNotFoundError without suggestions shows install hint."""
|
|
694
|
-
with (
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
):
|
|
698
|
-
collect_package("totally_nonexistent_pkg_xyz_999")
|
|
736
|
+
with patch(_DISTS_PATH, return_value=[]): # noqa: SIM117
|
|
737
|
+
with pytest.raises(PackageNotFoundError, match="Make sure it is installed"):
|
|
738
|
+
collect_package("totally_nonexistent_pkg_xyz_999")
|
|
699
739
|
|
|
700
740
|
|
|
701
741
|
# ---------------------------------------------------------------------------
|
|
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.6.0 → libcontext-0.6.1}/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
|