ecosyste-ms-cli 1.3.2__tar.gz → 1.4.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.
- ecosyste_ms_cli-1.4.1/CHANGELOG.md +11 -0
- {ecosyste_ms_cli-1.3.2/ecosyste_ms_cli.egg-info → ecosyste_ms_cli-1.4.1}/PKG-INFO +5 -5
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1/ecosyste_ms_cli.egg-info}/PKG-INFO +5 -5
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosyste_ms_cli.egg-info/requires.txt +4 -4
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/__init__.py +1 -1
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/cli.py +7 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/advisories.py +5 -3
- ecosyste_ms_cli-1.4.1/ecosystems_cli/commands/dependabot.py +39 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/packages.py +99 -9
- ecosyste_ms_cli-1.4.1/ecosystems_cli/commands/repos.py +56 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/pyproject.toml +5 -5
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/tests/test_cli.py +11 -0
- ecosyste_ms_cli-1.3.2/CHANGELOG.md +0 -6
- ecosyste_ms_cli-1.3.2/ecosystems_cli/commands/dependabot.py +0 -5
- ecosyste_ms_cli-1.3.2/ecosystems_cli/commands/repos.py +0 -5
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/LICENSE +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/MANIFEST.in +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/Readme.md +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosyste_ms_cli.egg-info/SOURCES.txt +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosyste_ms_cli.egg-info/dependency_links.txt +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosyste_ms_cli.egg-info/entry_points.txt +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosyste_ms_cli.egg-info/top_level.txt +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/__main__.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/__init__.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/advisories.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/archives.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/commits.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/dependabot.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/diff.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/docker.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/issues.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/licenses.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/opencollective.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/packages.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/parser.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/registries.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/repos.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/resolve.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/sbom.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/sponsors.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/summary.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/timeline.openapi.yaml +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/__init__.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/archives.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/commits.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/decorators.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/diff.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/docker.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/execution.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/generator.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/__init__.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/advisories.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/archives.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/base.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/commits.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/default.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/dependabot.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/diff.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/docker.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/factory.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/issues.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/licenses.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/opencollective.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/packages.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/parser.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/repos.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/resolve.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/sbom.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/sponsors.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/summary.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/timeline.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/issues.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/licenses.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/mcp.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/opencollective.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/parser.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/resolve.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/sbom.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/sponsors.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/summary.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/timeline.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/constants.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/exceptions.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/helpers/click_params.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/helpers/flatten_dict.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/helpers/format_value.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/helpers/get_domain.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/helpers/load_api_spec.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/helpers/print_error.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/helpers/print_operations.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/helpers/print_output.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/helpers/purl_parser.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/mcp_server.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/openapi_client.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/setup.cfg +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/tests/test_cli_domain.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/tests/test_constants.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/tests/test_format_value.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/tests/test_help_output.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/tests/test_load_api_spec.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/tests/test_mcp_server.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/tests/test_openapi_client.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/tests/test_package_metadata.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/tests/test_print_operations.py +0 -0
- {ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/tests/test_print_output.py +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Changelog for v1.4.1
|
|
2
|
+
|
|
3
|
+
## Changes since v1.4.0
|
|
4
|
+
|
|
5
|
+
- fix: corrections and docs for purl usage (07698f5)
|
|
6
|
+
- fix: more inconsitent apis (7028846)
|
|
7
|
+
- fix: parameter precendence consistent \ \ * check for invalid purls \ * small errors corrected (b112cff)
|
|
8
|
+
- feature: purl parameter for features (b9fd27c)
|
|
9
|
+
- feature: purl for all repos commands (8a064b5)
|
|
10
|
+
- feature: dependabot api receives --purl parameter (10f3feb)
|
|
11
|
+
- feature: --purl parameter (0beb032)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ecosyste_ms_cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.1
|
|
4
4
|
Summary: CLI for ecosyste.ms API
|
|
5
5
|
Author-email: Sebastian Schürmann <sebs@2xs.org>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -22,10 +22,10 @@ Requires-Python: >=3.9
|
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
License-File: LICENSE
|
|
24
24
|
Requires-Dist: click~=8.3.1
|
|
25
|
-
Requires-Dist: requests~=2.
|
|
25
|
+
Requires-Dist: requests~=2.33.1
|
|
26
26
|
Requires-Dist: pyyaml~=6.0.3
|
|
27
|
-
Requires-Dist: rich~=
|
|
28
|
-
Requires-Dist: mcp~=1.
|
|
27
|
+
Requires-Dist: rich~=15.0.0
|
|
28
|
+
Requires-Dist: mcp~=1.27.0
|
|
29
29
|
Requires-Dist: openapi-core~=0.23.0
|
|
30
30
|
Requires-Dist: packageurl-python~=0.17.6
|
|
31
31
|
Requires-Dist: importlib-resources; python_version < "3.9"
|
|
@@ -36,7 +36,7 @@ Requires-Dist: black~=26.3.1; extra == "dev"
|
|
|
36
36
|
Requires-Dist: isort~=8.0.1; extra == "dev"
|
|
37
37
|
Requires-Dist: flake8~=7.3.0; extra == "dev"
|
|
38
38
|
Requires-Dist: bandit~=1.9.4; extra == "dev"
|
|
39
|
-
Requires-Dist: complexipy~=5.
|
|
39
|
+
Requires-Dist: complexipy~=5.3.0; extra == "dev"
|
|
40
40
|
Requires-Dist: tomli~=2.3.0; python_version < "3.11" and extra == "dev"
|
|
41
41
|
Dynamic: license-file
|
|
42
42
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ecosyste_ms_cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.1
|
|
4
4
|
Summary: CLI for ecosyste.ms API
|
|
5
5
|
Author-email: Sebastian Schürmann <sebs@2xs.org>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -22,10 +22,10 @@ Requires-Python: >=3.9
|
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
License-File: LICENSE
|
|
24
24
|
Requires-Dist: click~=8.3.1
|
|
25
|
-
Requires-Dist: requests~=2.
|
|
25
|
+
Requires-Dist: requests~=2.33.1
|
|
26
26
|
Requires-Dist: pyyaml~=6.0.3
|
|
27
|
-
Requires-Dist: rich~=
|
|
28
|
-
Requires-Dist: mcp~=1.
|
|
27
|
+
Requires-Dist: rich~=15.0.0
|
|
28
|
+
Requires-Dist: mcp~=1.27.0
|
|
29
29
|
Requires-Dist: openapi-core~=0.23.0
|
|
30
30
|
Requires-Dist: packageurl-python~=0.17.6
|
|
31
31
|
Requires-Dist: importlib-resources; python_version < "3.9"
|
|
@@ -36,7 +36,7 @@ Requires-Dist: black~=26.3.1; extra == "dev"
|
|
|
36
36
|
Requires-Dist: isort~=8.0.1; extra == "dev"
|
|
37
37
|
Requires-Dist: flake8~=7.3.0; extra == "dev"
|
|
38
38
|
Requires-Dist: bandit~=1.9.4; extra == "dev"
|
|
39
|
-
Requires-Dist: complexipy~=5.
|
|
39
|
+
Requires-Dist: complexipy~=5.3.0; extra == "dev"
|
|
40
40
|
Requires-Dist: tomli~=2.3.0; python_version < "3.11" and extra == "dev"
|
|
41
41
|
Dynamic: license-file
|
|
42
42
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
click~=8.3.1
|
|
2
|
-
requests~=2.
|
|
2
|
+
requests~=2.33.1
|
|
3
3
|
pyyaml~=6.0.3
|
|
4
|
-
rich~=
|
|
5
|
-
mcp~=1.
|
|
4
|
+
rich~=15.0.0
|
|
5
|
+
mcp~=1.27.0
|
|
6
6
|
openapi-core~=0.23.0
|
|
7
7
|
packageurl-python~=0.17.6
|
|
8
8
|
|
|
@@ -16,7 +16,7 @@ black~=26.3.1
|
|
|
16
16
|
isort~=8.0.1
|
|
17
17
|
flake8~=7.3.0
|
|
18
18
|
bandit~=1.9.4
|
|
19
|
-
complexipy~=5.
|
|
19
|
+
complexipy~=5.3.0
|
|
20
20
|
|
|
21
21
|
[dev:python_version < "3.11"]
|
|
22
22
|
tomli~=2.3.0
|
|
@@ -7,6 +7,7 @@ import click
|
|
|
7
7
|
from rich.console import Console
|
|
8
8
|
from rich.panel import Panel
|
|
9
9
|
|
|
10
|
+
from ecosystems_cli import __version__
|
|
10
11
|
from ecosystems_cli.commands.advisories import advisories
|
|
11
12
|
from ecosystems_cli.commands.archives import archives
|
|
12
13
|
from ecosystems_cli.commands.commits import commits
|
|
@@ -139,6 +140,12 @@ main.add_command(mcp)
|
|
|
139
140
|
# Dynamic op commands have been removed
|
|
140
141
|
|
|
141
142
|
|
|
143
|
+
@main.command(name="version", help="Show the ecosystems CLI version and exit.")
|
|
144
|
+
def version():
|
|
145
|
+
"""Print the installed ecosystems CLI version."""
|
|
146
|
+
click.echo(__version__)
|
|
147
|
+
|
|
148
|
+
|
|
142
149
|
def _parse_json_param(param: Optional[str]) -> Optional[Dict]:
|
|
143
150
|
"""Parse JSON parameter if provided."""
|
|
144
151
|
if not param:
|
|
@@ -73,12 +73,14 @@ def get_advisories(
|
|
|
73
73
|
"""
|
|
74
74
|
update_context(ctx, timeout, format, domain, mailto)
|
|
75
75
|
|
|
76
|
-
# If PURL is provided,
|
|
76
|
+
# If PURL is provided, decompose it; explicit flags win over PURL-derived values.
|
|
77
77
|
if purl:
|
|
78
78
|
parsed_ecosystem, parsed_package_name = parse_purl(purl)
|
|
79
|
-
if parsed_ecosystem:
|
|
79
|
+
if not parsed_ecosystem and not parsed_package_name:
|
|
80
|
+
raise click.UsageError(f"Invalid PURL: {purl!r}. Expected format: pkg:type/name (e.g. pkg:npm/axios).")
|
|
81
|
+
if parsed_ecosystem and not ecosystem:
|
|
80
82
|
ecosystem = parsed_ecosystem
|
|
81
|
-
if parsed_package_name:
|
|
83
|
+
if parsed_package_name and not package_name:
|
|
82
84
|
package_name = parsed_package_name
|
|
83
85
|
|
|
84
86
|
# Build kwargs for the API call
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Commands for the dependabot API."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from ecosystems_cli.commands.generator import APICommandGenerator
|
|
6
|
+
from ecosystems_cli.helpers.purl_parser import parse_purl
|
|
7
|
+
|
|
8
|
+
dependabot = APICommandGenerator.create_api_group("dependabot")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# Attach --purl as an optional parameter to the auto-generated get_advisories
|
|
12
|
+
# command. When provided, its type/name decompose into --ecosystem/--package-name,
|
|
13
|
+
# letting users pass a single PURL instead of two flags.
|
|
14
|
+
if "get_advisories" in dependabot.commands:
|
|
15
|
+
_get_advisories_cmd = dependabot.commands["get_advisories"]
|
|
16
|
+
_get_advisories_cmd.params.insert(
|
|
17
|
+
0,
|
|
18
|
+
click.Option(
|
|
19
|
+
["--purl"],
|
|
20
|
+
type=str,
|
|
21
|
+
default=None,
|
|
22
|
+
help="Package URL (PURL). Example: pkg:npm/fsa. Decomposes into --ecosystem and --package-name.",
|
|
23
|
+
),
|
|
24
|
+
)
|
|
25
|
+
_original_get_advisories_callback = _get_advisories_cmd.callback
|
|
26
|
+
|
|
27
|
+
def _get_advisories_with_purl(*args, **kwargs):
|
|
28
|
+
purl = kwargs.pop("purl", None)
|
|
29
|
+
if purl:
|
|
30
|
+
parsed_ecosystem, parsed_package_name = parse_purl(purl)
|
|
31
|
+
if not parsed_ecosystem and not parsed_package_name:
|
|
32
|
+
raise click.UsageError(f"Invalid PURL: {purl!r}. Expected format: pkg:type/name (e.g. pkg:npm/axios).")
|
|
33
|
+
if parsed_ecosystem and not kwargs.get("ecosystem"):
|
|
34
|
+
kwargs["ecosystem"] = parsed_ecosystem
|
|
35
|
+
if parsed_package_name and not kwargs.get("package_name"):
|
|
36
|
+
kwargs["package_name"] = parsed_package_name
|
|
37
|
+
return _original_get_advisories_callback(*args, **kwargs)
|
|
38
|
+
|
|
39
|
+
_get_advisories_cmd.callback = _get_advisories_with_purl
|
|
@@ -12,6 +12,92 @@ from ecosystems_cli.helpers.purl_parser import parse_purl_with_version, purl_typ
|
|
|
12
12
|
packages = APICommandGenerator.create_api_group("packages")
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
# Attach --purl as an optional parameter to the auto-generated get_dependencies
|
|
16
|
+
# command. When provided, its type/name decompose into --ecosystem/--package-name,
|
|
17
|
+
# letting users pass a single PURL instead of multiple flags.
|
|
18
|
+
if "get_dependencies" in packages.commands:
|
|
19
|
+
_get_dependencies_cmd = packages.commands["get_dependencies"]
|
|
20
|
+
_get_dependencies_cmd.params.insert(
|
|
21
|
+
0,
|
|
22
|
+
click.Option(
|
|
23
|
+
["--purl"],
|
|
24
|
+
type=str,
|
|
25
|
+
default=None,
|
|
26
|
+
help="Package URL (PURL). Example: pkg:npm/axios@1.7.9. Decomposes into --ecosystem and --package-name.",
|
|
27
|
+
),
|
|
28
|
+
)
|
|
29
|
+
_original_get_dependencies_callback = _get_dependencies_cmd.callback
|
|
30
|
+
|
|
31
|
+
def _get_dependencies_with_purl(*args, **kwargs):
|
|
32
|
+
purl = kwargs.pop("purl", None)
|
|
33
|
+
if purl:
|
|
34
|
+
parsed_ecosystem, parsed_package_name, _ = parse_purl_with_version(purl)
|
|
35
|
+
if not parsed_ecosystem and not parsed_package_name:
|
|
36
|
+
raise click.UsageError(f"Invalid PURL: {purl!r}. Expected format: pkg:type/name (e.g. pkg:npm/axios).")
|
|
37
|
+
if parsed_ecosystem and not kwargs.get("ecosystem"):
|
|
38
|
+
# getDependencies filters by ecosystem name (e.g. "npm"), not the
|
|
39
|
+
# registry name ("npmjs.org"), so pass the raw PURL type through.
|
|
40
|
+
kwargs["ecosystem"] = parsed_ecosystem
|
|
41
|
+
if parsed_package_name and not kwargs.get("package_name"):
|
|
42
|
+
kwargs["package_name"] = parsed_package_name
|
|
43
|
+
return _original_get_dependencies_callback(*args, **kwargs)
|
|
44
|
+
|
|
45
|
+
_get_dependencies_cmd.callback = _get_dependencies_with_purl
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _add_purl_to_registry_package_command(command_name: str) -> None:
|
|
49
|
+
"""Attach --purl to a command whose path args are registryName + packageName.
|
|
50
|
+
|
|
51
|
+
Makes the positional REGISTRY_NAME and PACKAGE_NAME args optional, injects
|
|
52
|
+
--purl, and wraps the callback so a PURL decomposes into those two args.
|
|
53
|
+
Purl type is mapped to a registry name (e.g. 'npm' -> 'npmjs.org').
|
|
54
|
+
Positional args still win over a PURL when both are passed.
|
|
55
|
+
"""
|
|
56
|
+
if command_name not in packages.commands:
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
cmd = packages.commands[command_name]
|
|
60
|
+
|
|
61
|
+
for param in cmd.params:
|
|
62
|
+
if isinstance(param, click.Argument) and param.name in ("registryname", "packagename"):
|
|
63
|
+
param.required = False
|
|
64
|
+
|
|
65
|
+
cmd.params.insert(
|
|
66
|
+
0,
|
|
67
|
+
click.Option(
|
|
68
|
+
["--purl"],
|
|
69
|
+
type=str,
|
|
70
|
+
default=None,
|
|
71
|
+
help="Package URL (PURL). Example: pkg:npm/lodash. Decomposes into REGISTRY_NAME and PACKAGE_NAME.",
|
|
72
|
+
),
|
|
73
|
+
)
|
|
74
|
+
original_callback = cmd.callback
|
|
75
|
+
|
|
76
|
+
def wrapped_callback(*args, **kwargs):
|
|
77
|
+
purl = kwargs.pop("purl", None)
|
|
78
|
+
if purl:
|
|
79
|
+
parsed_ecosystem, parsed_package_name, _ = parse_purl_with_version(purl)
|
|
80
|
+
if not parsed_ecosystem and not parsed_package_name:
|
|
81
|
+
raise click.UsageError(f"Invalid PURL: {purl!r}. Expected format: pkg:type/name (e.g. pkg:npm/lodash).")
|
|
82
|
+
if parsed_ecosystem and not kwargs.get("registryname"):
|
|
83
|
+
kwargs["registryname"] = purl_type_to_registry(parsed_ecosystem)
|
|
84
|
+
if parsed_package_name and not kwargs.get("packagename"):
|
|
85
|
+
kwargs["packagename"] = parsed_package_name
|
|
86
|
+
if not kwargs.get("registryname") or not kwargs.get("packagename"):
|
|
87
|
+
raise click.UsageError("Either --purl or both REGISTRY_NAME and PACKAGE_NAME arguments are required")
|
|
88
|
+
return original_callback(*args, **kwargs)
|
|
89
|
+
|
|
90
|
+
cmd.callback = wrapped_callback
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
for _op in (
|
|
94
|
+
"get_registry_package_dependent_packages",
|
|
95
|
+
"get_registry_package_versions",
|
|
96
|
+
"get_registry_package_version_numbers",
|
|
97
|
+
):
|
|
98
|
+
_add_purl_to_registry_package_command(_op)
|
|
99
|
+
|
|
100
|
+
|
|
15
101
|
# Remove auto-generated commands to replace with custom implementations
|
|
16
102
|
if "get_registry_package" in packages.commands:
|
|
17
103
|
del packages.commands["get_registry_package"]
|
|
@@ -55,13 +141,14 @@ def get_registry_package(
|
|
|
55
141
|
"""
|
|
56
142
|
update_context(ctx, timeout, format, domain, mailto)
|
|
57
143
|
|
|
58
|
-
# If PURL is provided,
|
|
144
|
+
# If PURL is provided, decompose it; explicit positional args win over PURL-derived values.
|
|
59
145
|
if purl:
|
|
60
146
|
parsed_ecosystem, parsed_package_name, _ = parse_purl_with_version(purl)
|
|
61
|
-
if parsed_ecosystem:
|
|
62
|
-
|
|
147
|
+
if not parsed_ecosystem and not parsed_package_name:
|
|
148
|
+
raise click.UsageError(f"Invalid PURL: {purl!r}. Expected format: pkg:type/name (e.g. pkg:npm/lodash).")
|
|
149
|
+
if parsed_ecosystem and not registry_name:
|
|
63
150
|
registry_name = purl_type_to_registry(parsed_ecosystem)
|
|
64
|
-
if parsed_package_name:
|
|
151
|
+
if parsed_package_name and not package_name:
|
|
65
152
|
package_name = parsed_package_name
|
|
66
153
|
|
|
67
154
|
# Validate that we have the required parameters
|
|
@@ -120,15 +207,18 @@ def get_registry_package_version(
|
|
|
120
207
|
"""
|
|
121
208
|
update_context(ctx, timeout, format, domain, mailto)
|
|
122
209
|
|
|
123
|
-
# If PURL is provided,
|
|
210
|
+
# If PURL is provided, decompose it; explicit positional args win over PURL-derived values.
|
|
124
211
|
if purl:
|
|
125
212
|
parsed_ecosystem, parsed_package_name, parsed_version = parse_purl_with_version(purl)
|
|
126
|
-
if parsed_ecosystem:
|
|
127
|
-
|
|
213
|
+
if not parsed_ecosystem and not parsed_package_name:
|
|
214
|
+
raise click.UsageError(
|
|
215
|
+
f"Invalid PURL: {purl!r}. Expected format: pkg:type/name@version (e.g. pkg:npm/lodash@4.17.21)."
|
|
216
|
+
)
|
|
217
|
+
if parsed_ecosystem and not registry_name:
|
|
128
218
|
registry_name = purl_type_to_registry(parsed_ecosystem)
|
|
129
|
-
if parsed_package_name:
|
|
219
|
+
if parsed_package_name and not package_name:
|
|
130
220
|
package_name = parsed_package_name
|
|
131
|
-
if parsed_version:
|
|
221
|
+
if parsed_version and not version_number:
|
|
132
222
|
version_number = parsed_version
|
|
133
223
|
|
|
134
224
|
# Validate that we have the required parameters
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Commands for the repos API."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from ecosystems_cli.commands.generator import APICommandGenerator
|
|
6
|
+
from ecosystems_cli.helpers.purl_parser import parse_purl
|
|
7
|
+
|
|
8
|
+
repos = APICommandGenerator.create_api_group("repos")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _add_purl_to_ecosystem_package_command(command_name: str) -> None:
|
|
12
|
+
"""Attach --purl to a command whose first two path args are ecosystem + package.
|
|
13
|
+
|
|
14
|
+
Makes the positional ECOSYSTEM and PACKAGE args optional, injects --purl, and
|
|
15
|
+
wraps the callback so a PURL decomposes into those two args when provided.
|
|
16
|
+
Positional args still win over a PURL when both are passed.
|
|
17
|
+
"""
|
|
18
|
+
if command_name not in repos.commands:
|
|
19
|
+
return
|
|
20
|
+
|
|
21
|
+
cmd = repos.commands[command_name]
|
|
22
|
+
|
|
23
|
+
for param in cmd.params:
|
|
24
|
+
if isinstance(param, click.Argument) and param.name in ("ecosystem", "package"):
|
|
25
|
+
param.required = False
|
|
26
|
+
|
|
27
|
+
cmd.params.insert(
|
|
28
|
+
0,
|
|
29
|
+
click.Option(
|
|
30
|
+
["--purl"],
|
|
31
|
+
type=str,
|
|
32
|
+
default=None,
|
|
33
|
+
help="Package URL (PURL). Example: pkg:npm/lodash. Decomposes into ECOSYSTEM and PACKAGE.",
|
|
34
|
+
),
|
|
35
|
+
)
|
|
36
|
+
original_callback = cmd.callback
|
|
37
|
+
|
|
38
|
+
def wrapped_callback(*args, **kwargs):
|
|
39
|
+
purl = kwargs.pop("purl", None)
|
|
40
|
+
if purl:
|
|
41
|
+
parsed_ecosystem, parsed_package = parse_purl(purl)
|
|
42
|
+
if not parsed_ecosystem and not parsed_package:
|
|
43
|
+
raise click.UsageError(f"Invalid PURL: {purl!r}. Expected format: pkg:type/name (e.g. pkg:npm/lodash).")
|
|
44
|
+
if parsed_ecosystem and not kwargs.get("ecosystem"):
|
|
45
|
+
kwargs["ecosystem"] = parsed_ecosystem
|
|
46
|
+
if parsed_package and not kwargs.get("package"):
|
|
47
|
+
kwargs["package"] = parsed_package
|
|
48
|
+
if not kwargs.get("ecosystem") or not kwargs.get("package"):
|
|
49
|
+
raise click.UsageError("Either --purl or both ECOSYSTEM and PACKAGE arguments are required")
|
|
50
|
+
return original_callback(*args, **kwargs)
|
|
51
|
+
|
|
52
|
+
cmd.callback = wrapped_callback
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
for _op in ("usage_package", "usage_package_dependencies", "usage_package_dependent_repositories"):
|
|
56
|
+
_add_purl_to_ecosystem_package_command(_op)
|
|
@@ -52,7 +52,7 @@ exclude = ["tests*"]
|
|
|
52
52
|
|
|
53
53
|
[project]
|
|
54
54
|
name = "ecosyste_ms_cli"
|
|
55
|
-
version = "1.
|
|
55
|
+
version = "1.4.1"
|
|
56
56
|
description = "CLI for ecosyste.ms API"
|
|
57
57
|
authors = [
|
|
58
58
|
{name = "Sebastian Schürmann", email = "sebs@2xs.org"}
|
|
@@ -76,10 +76,10 @@ classifiers = [
|
|
|
76
76
|
]
|
|
77
77
|
dependencies = [
|
|
78
78
|
"click~=8.3.1",
|
|
79
|
-
"requests~=2.
|
|
79
|
+
"requests~=2.33.1",
|
|
80
80
|
"pyyaml~=6.0.3",
|
|
81
|
-
"rich~=
|
|
82
|
-
"mcp~=1.
|
|
81
|
+
"rich~=15.0.0",
|
|
82
|
+
"mcp~=1.27.0",
|
|
83
83
|
"openapi-core~=0.23.0",
|
|
84
84
|
"packageurl-python~=0.17.6",
|
|
85
85
|
"importlib-resources; python_version < '3.9'",
|
|
@@ -93,7 +93,7 @@ dev = [
|
|
|
93
93
|
"isort~=8.0.1",
|
|
94
94
|
"flake8~=7.3.0",
|
|
95
95
|
"bandit~=1.9.4",
|
|
96
|
-
"complexipy~=5.
|
|
96
|
+
"complexipy~=5.3.0",
|
|
97
97
|
"tomli~=2.3.0; python_version < '3.11'"
|
|
98
98
|
]
|
|
99
99
|
|
|
@@ -6,6 +6,7 @@ from unittest import mock
|
|
|
6
6
|
import pytest
|
|
7
7
|
from click.testing import CliRunner
|
|
8
8
|
|
|
9
|
+
from ecosystems_cli import __version__
|
|
9
10
|
from ecosystems_cli.cli import main
|
|
10
11
|
|
|
11
12
|
|
|
@@ -24,6 +25,16 @@ def mock_api_client():
|
|
|
24
25
|
yield mock_factory
|
|
25
26
|
|
|
26
27
|
|
|
28
|
+
class TestVersionCommand:
|
|
29
|
+
"""Test the version subcommand."""
|
|
30
|
+
|
|
31
|
+
def test_version_prints_package_version(self, runner):
|
|
32
|
+
"""Version output must match __version__ so semantic-release stays the source of truth."""
|
|
33
|
+
result = runner.invoke(main, ["version"])
|
|
34
|
+
assert result.exit_code == 0
|
|
35
|
+
assert result.output.strip() == __version__
|
|
36
|
+
|
|
37
|
+
|
|
27
38
|
class TestAdvisoriesCommands:
|
|
28
39
|
"""Test the advisories commands."""
|
|
29
40
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosyste_ms_cli.egg-info/dependency_links.txt
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
|
{ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/apis/opencollective.openapi.yaml
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
|
{ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/__init__.py
RENAMED
|
File without changes
|
{ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/advisories.py
RENAMED
|
File without changes
|
{ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/archives.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/dependabot.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/licenses.py
RENAMED
|
File without changes
|
{ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/opencollective.py
RENAMED
|
File without changes
|
{ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/packages.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/sponsors.py
RENAMED
|
File without changes
|
|
File without changes
|
{ecosyste_ms_cli-1.3.2 → ecosyste_ms_cli-1.4.1}/ecosystems_cli/commands/handlers/timeline.py
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|