Skip to content

Commit aaed12a

Browse files
authored
feat: subcommand environment got aliases env, venv (#850)
fixes #845 Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
1 parent 12cc59b commit aaed12a

File tree

5 files changed

+42
-27
lines changed

5 files changed

+42
-27
lines changed

README.md

+9-8
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,21 @@ python3 -m cyclonedx_py # call python module CLI
7171

7272
```shellSession
7373
$ cyclonedx-py --help
74-
usage: cyclonedx-py [-h] [--version] command ...
74+
usage: cyclonedx-py [-h] [--version] <command> ...
7575

7676
Creates CycloneDX Software Bill of Materials (SBOM) from Python projects and environments.
7777

7878
positional arguments:
79-
command
80-
environment Build an SBOM from Python (virtual) environment
81-
requirements Build an SBOM from Pip requirements
82-
pipenv Build an SBOM from Pipenv manifest
83-
poetry Build an SBOM from Poetry project
79+
<command>
80+
environment (env, venv)
81+
Build an SBOM from Python (virtual) environment
82+
requirements Build an SBOM from Pip requirements
83+
pipenv Build an SBOM from Pipenv manifest
84+
poetry Build an SBOM from Poetry project
8485

8586
options:
86-
-h, --help show this help message and exit
87-
--version show program's version number and exit
87+
-h, --help show this help message and exit
88+
--version show program's version number and exit
8889
```
8990

9091
### Advanced usage and details

cyclonedx_py/_internal/cli.py

+13-7
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import sys
2020
from argparse import ArgumentParser, FileType, RawDescriptionHelpFormatter
2121
from itertools import chain
22-
from typing import TYPE_CHECKING, Any, Dict, NoReturn, Optional, Sequence, TextIO, Type, Union
22+
from typing import TYPE_CHECKING, Any, Dict, List, NoReturn, Optional, Sequence, TextIO, Type, Union
2323

2424
from cyclonedx.model import Property
2525
from cyclonedx.output import make_outputter
@@ -53,6 +53,7 @@
5353
class Command:
5454
@classmethod
5555
def make_argument_parser(cls, sco: ArgumentParser, **kwargs: Any) -> ArgumentParser:
56+
# region Command
5657
p = ArgumentParser(
5758
description='Creates CycloneDX Software Bill of Materials (SBOM) from Python projects and environments.',
5859
formatter_class=RawDescriptionHelpFormatter,
@@ -62,7 +63,9 @@ def make_argument_parser(cls, sco: ArgumentParser, **kwargs: Any) -> ArgumentPar
6263
sp = p.add_subparsers(metavar='<command>', dest='command',
6364
# not required. if omitted: show help and exit
6465
required=False)
66+
# region Command
6567

68+
# region SubCOmmand
6669
op = ArgumentParser(add_help=False)
6770
op.add_argument('--short-PURLs',
6871
help='Omit all qualifiers from PackageURLs.\n'
@@ -124,21 +127,24 @@ def make_argument_parser(cls, sco: ArgumentParser, **kwargs: Any) -> ArgumentPar
124127
action='store_false')
125128

126129
scbbc: Type['BomBuilder']
127-
for sct, scbbc in (
128-
('environment', EnvironmentBB),
129-
('requirements', RequirementsBB),
130-
('pipenv', PipenvBB),
131-
('poetry', PoetryBB),
130+
sct: str
131+
scta: List[str]
132+
for scbbc, sct, *scta in (
133+
(EnvironmentBB, 'environment', 'env', 'venv'),
134+
(RequirementsBB, 'requirements'),
135+
(PipenvBB, 'pipenv'),
136+
(PoetryBB, 'poetry'),
132137
):
133138
spp = scbbc.make_argument_parser(add_help=False)
134-
sp.add_parser(sct,
139+
sp.add_parser(sct, aliases=scta,
135140
help=(spp.description or '').split('\n')[0].strip('. '),
136141
description=spp.description,
137142
epilog=spp.epilog,
138143
parents=[spp, op, sco],
139144
formatter_class=p.formatter_class,
140145
allow_abbrev=p.allow_abbrev,
141146
).set_defaults(_bbc=scbbc)
147+
# endregion SubCommand
142148

143149
return p
144150

cyclonedx_py/_internal/poetry.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ def __purl_qualifiers4lock(self, package: 'T_NameDict') -> 'T_NameDict':
444444
# > For version-controlled files, the VCS location syntax is similar to a URL and has the:
445445
# > `<vcs_tool>+<transport>://<host_name>[/<path_to_repository>][@<revision_tag_or_branch>][#<sub_path>]`
446446
qs['vcs_url'] = f'{source_type}+{redact_auth_from_url(source["url"])}@' + \
447-
source.get('resolved_reference', source.get('reference', ''))
447+
source.get('resolved_reference', source.get('reference', ''))
448448
elif source_type == 'url':
449449
if '://files.pythonhosted.org/' not in source['url']:
450450
# skip PURL bloat, do not add implicit information

docs/usage.rst

+12-8
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,16 @@ The full documentation can be issued by running with ``--help``:
2020
2121
positional arguments:
2222
<command>
23-
environment Build an SBOM from Python (virtual) environment
24-
requirements Build an SBOM from Pip requirements
25-
pipenv Build an SBOM from Pipenv manifest
26-
poetry Build an SBOM from Poetry project
23+
environment (env, venv)
24+
Build an SBOM from Python (virtual) environment
25+
requirements Build an SBOM from Pip requirements
26+
pipenv Build an SBOM from Pipenv manifest
27+
poetry Build an SBOM from Poetry project
2728
2829
options:
29-
-h, --help show this help message and exit
30-
--version show program's version number and exit
30+
-h, --help show this help message and exit
31+
--version show program's version number and exit
32+
3133
3234
Example usage: save SBOM in CycloneDX 1.6 XML format, generated from current python environment
3335

@@ -41,10 +43,12 @@ For Python (virtual) environment
4143

4244
**subcommand:** ``environment``
4345

46+
**aliases:** ``env``, ``venv``
47+
4448
.. TODO: describe what an environment is...
4549
46-
This will produce the most accurate and complete CycloneDX BOM as it analyses the actually installed packages.
47-
It will include metadata, licenses, dependency graph, and more in the generated CycloneDX SBOM.
50+
By analyzing the actually installed packages, this will produce the most accurate and complete CycloneDX BOM.
51+
The generated CycloneDX SBOM will include metadata, licenses, dependency graph, and more.
4852

4953
The full documentation can be issued by running with ``environment --help``:
5054

tests/integration/test_cli_environment.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from unittest import TestCase, skipIf
2626

2727
from cyclonedx.schema import OutputFormat, SchemaVersion
28-
from ddt import ddt, named_data
28+
from ddt import data, ddt, named_data
2929

3030
from tests import INFILES_DIRECTORY, INIT_TESTBEDS, SUPPORTED_OF_SV, SnapshotMixin, make_comparable
3131
from tests.integration import run_cli
@@ -45,8 +45,12 @@ def test_data_file_filter(s: str) -> Generator[Any, None, None]:
4545
@ddt
4646
class TestCliEnvironment(TestCase, SnapshotMixin):
4747

48-
def test_help(self) -> None:
49-
res, out, err = run_cli('environment', '--help')
48+
@data(
49+
'environment',
50+
'env', 'venv' # aliases
51+
)
52+
def test_help(self, subcommand: str) -> None:
53+
res, out, err = run_cli(subcommand, '--help')
5054
self.assertEqual(0, res, '\n'.join((out, err)))
5155

5256
@classmethod

0 commit comments

Comments
 (0)