Skip to content

Commit fb30ee0

Browse files
authored
feat: deprecate CLI switch --outfile; use new --output-file instead (#875)
Signed-off-by: Jan Kowalleck <[email protected]>
1 parent bbae05f commit fb30ee0

File tree

7 files changed

+58
-46
lines changed

7 files changed

+58
-46
lines changed

cyclonedx_py/_internal/cli.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
else:
5050
BooleanOptionalAction = None
5151

52+
OPTION_OUTPUT_STDOUT = '-'
53+
5254

5355
class Command:
5456
@classmethod
@@ -74,14 +76,20 @@ def make_argument_parser(cls, sco: ArgumentParser, **kwargs: Any) -> ArgumentPar
7476
action='store_true',
7577
dest='short_purls',
7678
default=False)
77-
op.add_argument('-o', '--outfile',
79+
op.add_argument('--outfile', # DEPRECATED
80+
metavar='<file>',
81+
help='DEPRECATED alias for "--output-file".',
82+
type=FileType('wt', encoding='utf8'),
83+
dest='output_file',
84+
default=OPTION_OUTPUT_STDOUT)
85+
op.add_argument('-o', '--output-file',
7886
metavar='<file>',
7987
help='Output file path for your SBOM'
80-
' (set to "-" to output to <stdout>)'
88+
f' (set to "{OPTION_OUTPUT_STDOUT}" to output to <stdout>)'
8189
' (default: %(default)s)',
8290
type=FileType('wt', encoding='utf8'),
83-
dest='outfile',
84-
default='-')
91+
dest='output_file',
92+
default=OPTION_OUTPUT_STDOUT)
8593
op.add_argument('--schema-version', # DEPRECATED
8694
metavar='<version>',
8795
help='DEPRECATED alias for option "--spec-version".',
@@ -159,7 +167,7 @@ def make_argument_parser(cls, sco: ArgumentParser, **kwargs: Any) -> ArgumentPar
159167
# the arg keywords from __init__()
160168
'logger', 'short_purls', 'output_format', 'spec_version', 'output_reproducible', 'should_validate',
161169
# the arg keywords from __call__()
162-
'outfile'
170+
'output_file'
163171
}
164172

165173
@classmethod
@@ -232,10 +240,10 @@ def _validate(self, output: str) -> bool:
232240
self._logger.debug('result is schema-valid')
233241
return True
234242

235-
def _write(self, output: str, outfile: TextIO) -> int:
236-
self._logger.info('Writing to: %s', outfile.name)
237-
written = outfile.write(output)
238-
self._logger.debug('Wrote %i bytes to %s', written, outfile.name)
243+
def _write(self, output: str, output_file: TextIO) -> int:
244+
self._logger.info('Writing to: %s', output_file.name)
245+
written = output_file.write(output)
246+
self._logger.debug('Wrote %i bytes to %s', written, output_file.name)
239247
return written
240248

241249
def _make_output(self, bom: 'Bom') -> str:
@@ -259,14 +267,14 @@ def _make_bom(self, **kwargs: Any) -> 'Bom':
259267
return self._bbc(**self._clean_kwargs(kwargs))
260268

261269
def __call__(self,
262-
outfile: TextIO,
270+
output_file: TextIO,
263271
**kwargs: Any) -> None:
264272
bom = self._make_bom(**kwargs)
265273
self._shorten_purls(bom)
266274
output = self._make_output(bom)
267275
del bom
268276
self._validate(output)
269-
self._write(output, outfile)
277+
self._write(output, output_file)
270278

271279

272280
def run(*, argv: Optional[Sequence[str]] = None, **kwargs: Any) -> Union[int, NoReturn]:

docs/usage.rst

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Example usage: save SBOM in CycloneDX 1.6 XML format, generated from current pyt
3535

3636
.. code-block:: shell
3737
38-
cyclonedx-py environment --outfile my-sbom.xml --spec-version 1.6 --output-format XML
38+
cyclonedx-py environment --spec-version 1.6 --output-format XML --output-file my-sbom.xml
3939
4040
4141
For Python (virtual) environment
@@ -81,7 +81,8 @@ The full documentation can be issued by running with ``environment --help``:
8181
(default: application)
8282
--short-PURLs Omit all qualifiers from PackageURLs.
8383
This causes information loss in trade-off shorter PURLs, which might improve ingesting these strings.
84-
-o <file>, --outfile <file>
84+
--outfile <file> DEPRECATED alias for "--output-file".
85+
-o <file>, --output-file <file>
8586
Output file path for your SBOM
8687
(set to "-" to output to STDOUT)
8788
(default: -)
@@ -254,7 +255,8 @@ The full documentation can be issued by running with ``pipenv --help``:
254255
(default: application)
255256
--short-PURLs Omit all qualifiers from PackageURLs.
256257
This causes information loss in trade-off shorter PURLs, which might improve ingesting these strings.
257-
-o <file>, --outfile <file>
258+
--outfile <file> DEPRECATED alias for "--output-file".
259+
-o <file>, --output-file <file>
258260
Output file path for your SBOM
259261
(set to "-" to output to <stdout>)
260262
(default: -)
@@ -331,7 +333,8 @@ The full documentation can be issued by running with ``poetry --help``:
331333
(default: application)
332334
--short-PURLs Omit all qualifiers from PackageURLs.
333335
This causes information loss in trade-off shorter PURLs, which might improve ingesting these strings.
334-
-o <file>, --outfile <file>
336+
--outfile <file> DEPRECATED alias for "--output-file".
337+
-o <file>, --output-file <file>
335338
Output file path for your SBOM
336339
(set to "-" to output to <stdout>)
337340
(default: -)
@@ -404,7 +407,8 @@ The full documentation can be issued by running with ``requirements --help``:
404407
(default: application)
405408
--short-PURLs Omit all qualifiers from PackageURLs.
406409
This causes information loss in trade-off shorter PURLs, which might improve ingesting these strings.
407-
-o <file>, --outfile <file>
410+
--outfile <file> DEPRECATED alias for "--output-file".
411+
-o <file>, --output-file <file>
408412
Output file path for your SBOM
409413
(set to "-" to output to <stdout>)
410414
(default: -)

tests/integration/test_cli_environment.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def test_fails_with_python_not_found(self, wrong_python: str, expected_error: st
7979
'-vvv',
8080
f'--sv={sv.to_version()}',
8181
f'--of={of.name}',
82-
'--outfile=-',
82+
'-o=-',
8383
wrong_python)
8484
self.assertNotEqual(0, res, err)
8585
self.assertIn(expected_error, err)
@@ -96,7 +96,7 @@ def test_fails_with_python_unexpected(self, wrong_python: str, expected_error: s
9696
'-vvv',
9797
f'--sv={sv.to_version()}',
9898
f'--of={of.name}',
99-
'--outfile=-',
99+
'-o=-',
100100
wrong_python)
101101
self.assertNotEqual(0, res, err)
102102
self.assertIn(expected_error, err)
@@ -108,7 +108,7 @@ def test_with_pyproject_not_found(self) -> None:
108108
'-vvv',
109109
'--sv', sv.to_version(),
110110
'--of', of.name,
111-
'--outfile=-',
111+
'-o=-',
112112
'--pyproject=something-that-must-not-exist.testing',
113113
projectdir
114114
)
@@ -124,7 +124,7 @@ def test_with_current_python(self) -> None:
124124
'--sv', sv.to_version(),
125125
'--of', of.name,
126126
'--output-reproducible',
127-
'--outfile=-',
127+
'-o=-',
128128
# no project dir -> search in current python
129129
)
130130
self.assertEqual(0, res, err)
@@ -134,7 +134,7 @@ def test_with_current_python(self) -> None:
134134
'--sv', sv.to_version(),
135135
'--of', of.name,
136136
'--output-reproducible',
137-
'--outfile=-',
137+
'-o=-',
138138
executable # explicitly current python
139139
)
140140
self.assertEqual(0, res, err)
@@ -151,7 +151,7 @@ def test_plain_as_expected(self, projectdir: str, sv: SchemaVersion, of: OutputF
151151
'--sv', sv.to_version(),
152152
'--of', of.name,
153153
'--output-reproducible',
154-
'--outfile=-',
154+
'-o=-',
155155
'--pyproject', join(projectdir, 'pyproject.toml'),
156156
join(projectdir, '.venv'))
157157
self.assertEqual(0, res, err)
@@ -165,7 +165,7 @@ def test_pep639_as_expected(self, projectdir: str, sv: SchemaVersion, of: Output
165165
'--sv', sv.to_version(),
166166
'--of', of.name,
167167
'--output-reproducible',
168-
'--outfile=-',
168+
'-o=-',
169169
'--pyproject', join(projectdir, 'pyproject.toml'),
170170
'--PEP-639',
171171
join(projectdir, '.venv'))
@@ -180,7 +180,7 @@ def test_pep639_texts_as_expected(self, projectdir: str, sv: SchemaVersion, of:
180180
'--sv', sv.to_version(),
181181
'--of', of.name,
182182
'--output-reproducible',
183-
'--outfile=-',
183+
'-o=-',
184184
'--pyproject', join(projectdir, 'pyproject.toml'),
185185
'--PEP-639',
186186
'--gather-license-texts',
@@ -196,7 +196,7 @@ def test_texts_as_expected(self, projectdir: str, sv: SchemaVersion, of: OutputF
196196
'--sv', sv.to_version(),
197197
'--of', of.name,
198198
'--output-reproducible',
199-
'--outfile=-',
199+
'-o=-',
200200
'--pyproject', join(projectdir, 'pyproject.toml'),
201201
'--gather-license-texts',
202202
join(projectdir, '.venv'))

tests/integration/test_cli_pipenv.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def test_fails_with_dir_not_found(self) -> None:
5656
'-vvv',
5757
'--sv', sv.to_version(),
5858
'--of', of.name,
59-
'--outfile=-',
59+
'-o=-',
6060
'something-that-must-not-exist.testing')
6161
self.assertNotEqual(0, res, err)
6262
self.assertIn('Could not open lock file: something-that-must-not-exist.testing', err)
@@ -68,7 +68,7 @@ def test_with_pyproject_not_found(self) -> None:
6868
'-vvv',
6969
'--sv', sv.to_version(),
7070
'--of', of.name,
71-
'--outfile=-',
71+
'-o=-',
7272
'--pyproject=something-that-must-not-exist.testing',
7373
projectdir)
7474
self.assertNotEqual(0, res, err)
@@ -82,7 +82,7 @@ def test_plain_as_expected(self, projectdir: str, sv: SchemaVersion, of: OutputF
8282
'--sv', sv.to_version(),
8383
'--of', of.name,
8484
'--output-reproducible',
85-
'--outfile=-',
85+
'-o=-',
8686
'--pyproject', join(projectdir, 'pyproject.toml'),
8787
projectdir)
8888
self.assertEqual(0, res, err)
@@ -96,7 +96,7 @@ def test_with_categories_as_expected(self, projectdir: str, sv: SchemaVersion, o
9696
'--sv', sv.to_version(),
9797
'--of', of.name,
9898
'--output-reproducible',
99-
'--outfile=-',
99+
'-o=-',
100100
'--categories', 'categoryB,groupA packages,dev-packages',
101101
projectdir)
102102
self.assertEqual(0, res, err)
@@ -110,7 +110,7 @@ def test_with_dev_as_expected(self, projectdir: str, sv: SchemaVersion, of: Outp
110110
'--sv', sv.to_version(),
111111
'--of', of.name,
112112
'--output-reproducible',
113-
'--outfile=-',
113+
'-o=-',
114114
'--dev',
115115
projectdir)
116116
self.assertEqual(0, res, err)
@@ -124,7 +124,7 @@ def test_with_pypi_mirror_as_expected(self, projectdir: str, sv: SchemaVersion,
124124
'--sv', sv.to_version(),
125125
'--of', of.name,
126126
'--output-reproducible',
127-
'--outfile=-',
127+
'-o=-',
128128
'--pypi-mirror', 'https://user:[email protected]/simple/',
129129
projectdir)
130130
self.assertEqual(0, res, err)

tests/integration/test_cli_poetry.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def test_fails_with_dir_not_found(self) -> None:
5656
'-vvv',
5757
'--sv', sv.to_version(),
5858
'--of', of.name,
59-
'--outfile=-',
59+
'-o=-',
6060
'something-that-must-not-exist.testing')
6161
self.assertNotEqual(0, res, err)
6262
self.assertIn('Could not open pyproject file: something-that-must-not-exist.testing', err)
@@ -109,7 +109,7 @@ def test_plain_as_expected(self, projectdir: str, sv: SchemaVersion, of: OutputF
109109
'--sv', sv.to_version(),
110110
'--of', of.name,
111111
'--output-reproducible',
112-
'--outfile=-',
112+
'-o=-',
113113
projectdir)
114114
self.assertEqual(0, res, err)
115115
self.assertEqualSnapshot(out, 'plain', projectdir, sv, of)
@@ -124,7 +124,7 @@ def test_with_groups_as_expected(self, projectdir: str, sv: SchemaVersion, of: O
124124
'--sv', sv.to_version(),
125125
'--of', of.name,
126126
'--output-reproducible',
127-
'--outfile=-',
127+
'-o=-',
128128
projectdir)
129129
self.assertEqual(0, res, err)
130130
self.assertEqualSnapshot(out, 'some-groups', projectdir, sv, of)
@@ -138,7 +138,7 @@ def test_only_groups_as_expected(self, projectdir: str, sv: SchemaVersion, of: O
138138
'--sv', sv.to_version(),
139139
'--of', of.name,
140140
'--output-reproducible',
141-
'--outfile=-',
141+
'-o=-',
142142
projectdir)
143143
self.assertEqual(0, res, err)
144144
self.assertEqualSnapshot(out, 'only-groups', projectdir, sv, of)
@@ -153,7 +153,7 @@ def test_nodev_as_expected(self, projectdir: str, sv: SchemaVersion, of: OutputF
153153
'--sv', sv.to_version(),
154154
'--of', of.name,
155155
'--output-reproducible',
156-
'--outfile=-',
156+
'-o=-',
157157
projectdir)
158158
self.assertEqual(0, res, err)
159159
self.assertEqualSnapshot(out, 'no-dev', projectdir, sv, of)
@@ -167,7 +167,7 @@ def test_with_extras_as_expected(self, projectdir: str, sv: SchemaVersion, of: O
167167
'--sv', sv.to_version(),
168168
'--of', of.name,
169169
'--output-reproducible',
170-
'--outfile=-',
170+
'-o=-',
171171
projectdir)
172172
self.assertEqual(0, res, err)
173173
self.assertEqualSnapshot(out, 'some-extras', projectdir, sv, of)
@@ -181,7 +181,7 @@ def test_with_all_extras_as_expected(self, projectdir: str, sv: SchemaVersion, o
181181
'--sv', sv.to_version(),
182182
'--of', of.name,
183183
'--output-reproducible',
184-
'--outfile=-',
184+
'-o=-',
185185
projectdir)
186186
self.assertEqual(0, res, err)
187187
self.assertEqualSnapshot(out, 'all-extras', projectdir, sv, of)

tests/integration/test_cli_requirements.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def test_with_file_not_found(self) -> None:
6767
'-vvv',
6868
'--sv', sv.to_version(),
6969
'--of', of.name,
70-
'--outfile=-',
70+
'-o=-',
7171
'something-that-must-not-exist.testing')
7272
self.assertNotEqual(0, res, err)
7373
self.assertIn('Could not open requirements file: something-that-must-not-exist.testing', err)
@@ -79,7 +79,7 @@ def test_with_pyproject_not_found(self) -> None:
7979
'-vvv',
8080
'--sv', sv.to_version(),
8181
'--of', of.name,
82-
'--outfile=-',
82+
'-o=-',
8383
'--pyproject=something-that-must-not-exist.testing',
8484
infile
8585
)
@@ -94,7 +94,7 @@ def test_with_file_as_expected(self, infile: str, sv: SchemaVersion, of: OutputF
9494
'--sv', sv.to_version(),
9595
'--of', of.name,
9696
'--output-reproducible',
97-
'--outfile=-',
97+
'-o=-',
9898
'--pyproject', pyproject_file,
9999
infile)
100100
self.assertEqual(0, res, err)
@@ -109,7 +109,7 @@ def test_with_stream_as_expected(self, infile: str, sv: SchemaVersion, of: Outpu
109109
'--sv', sv.to_version(),
110110
'--of', of.name,
111111
'--output-reproducible',
112-
'--outfile=-',
112+
'-o=-',
113113
# no pyproject for this case
114114
'-',
115115
inp=inp)
@@ -127,7 +127,7 @@ def test_with_index_auth(self, infile: str, sv: SchemaVersion, of: OutputFormat)
127127
'--sv', sv.to_version(),
128128
'--of', of.name,
129129
'--output-reproducible',
130-
'--outfile=-',
130+
'-o=-',
131131
'--pyproject', pyproject_file,
132132
infile)
133133
self.assertEqual(0, res, err)

tests/unit/test_cli.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def __new__(cls, *args: Any, **kwargs: Any) -> BomBuilder:
8282
output_reproducible=True,
8383
_bbc=MyBBC
8484
)
85-
command(outfile=outs)
85+
command(output_file=outs)
8686

8787
out = outs.getvalue()
8888

@@ -109,7 +109,7 @@ def __new__(cls, *args: Any, **kwargs: Any) -> BomBuilder:
109109
command._make_output = Mock(return_value=r'["invalid to CDX schema"]')
110110

111111
with self.assertRaisesRegex(ValueError, 'is schema-invalid'):
112-
command(outfile=outs)
112+
command(output_file=outs)
113113

114114
def test_validation_skip_with_invalid(self) -> None:
115115
class MyBBC(BomBuilder):
@@ -131,7 +131,7 @@ def __new__(cls, *args: Any, **kwargs: Any) -> BomBuilder:
131131
)
132132
command._make_output = Mock(return_value=r'["invalid to CDX schema"]')
133133

134-
command(outfile=outs)
134+
command(output_file=outs)
135135

136136
log = logs.getvalue()
137137
out = outs.getvalue()

0 commit comments

Comments
 (0)