Skip to content

Commit 4e679b8

Browse files
committed
doc: add new subcommand to readme
1 parent b74e0ef commit 4e679b8

File tree

2 files changed

+209
-0
lines changed

2 files changed

+209
-0
lines changed

README.md

+17
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Options:
4545
--help Show this message and exit.
4646

4747
Commands:
48+
extract-subtree Extract a subtree of resources from an Opossum file.
4849
generate Generate an Opossum file from various other file formats.
4950
```
5051

@@ -78,6 +79,22 @@ Options:
7879
--help Show this message and exit.
7980
```
8081

82+
### extract-subtree
83+
84+
```bash
85+
Usage: opossum-file extract-subtree [OPTIONS] OPOSSUM_FILE SUBPATH
86+
87+
Extract all resources from OPOSSUMFILE that are children of the specified
88+
SUBPATH into a new .opossum-file (default: output.opossum).
89+
90+
Options:
91+
-o, --outfile FILE The file path to write the generated opossum document
92+
to. If appropriate, the extension ".opossum" is
93+
appended. If the output file already exists, it is
94+
overwritten. [default: output.opossum]
95+
--help Show this message and exit.
96+
```
97+
8198
# Development
8299

83100
## Setting up the environment
+192
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
# SPDX-FileCopyrightText: TNG Technology Consulting GmbH <https://www.tngtech.com>
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
from pathlib import PurePath
6+
7+
from opossum_lib.core.entities.resource import Resource, ResourceType
8+
from opossum_lib.core.services.extract_subtree_impl import extract_subtree_impl
9+
from tests.setup.opossum_faker_setup import OpossumFaker
10+
11+
12+
class TestExtractSubtreeHighlevel:
13+
def test_extraction_is_generally_successful_without_review_results(
14+
self, opossum_faker: OpossumFaker
15+
) -> None:
16+
opossum = opossum_faker.opossum(generate_review_results=False)
17+
all_folders = [
18+
resource.path
19+
for resource in opossum.scan_results.resources.all_resources()
20+
if resource.type == ResourceType.FOLDER
21+
]
22+
subpath = (
23+
opossum_faker.random_element(all_folders) if all_folders else PurePath("")
24+
)
25+
extracted = extract_subtree_impl(opossum, subpath)
26+
27+
assert extracted
28+
assert extracted.review_results is None
29+
assert extracted.scan_results
30+
if opossum.scan_results.resources.children:
31+
assert extracted.scan_results.resources.children
32+
33+
def test_extraction_is_generally_successful_including_review_results(
34+
self, opossum_faker: OpossumFaker
35+
) -> None:
36+
opossum = opossum_faker.opossum(generate_review_results=True)
37+
all_folders = [
38+
resource.path
39+
for resource in opossum.scan_results.resources.all_resources()
40+
if resource.type == ResourceType.FOLDER
41+
]
42+
subpath = (
43+
opossum_faker.random_element(all_folders) if all_folders else PurePath("")
44+
)
45+
extracted = extract_subtree_impl(opossum, subpath)
46+
47+
assert extracted
48+
assert extracted.review_results
49+
assert extracted.scan_results
50+
if opossum.scan_results.resources.children:
51+
assert extracted.scan_results.resources.children
52+
53+
54+
class TestExtractSubTreeAttributes:
55+
SUBTREE = PurePath("toplevel/folder")
56+
57+
def _get_test_resources(self, opossum_faker: OpossumFaker) -> list[Resource]:
58+
return [
59+
opossum_faker.resource(
60+
path=PurePath("toplevel/resource1.txt"), type=ResourceType.FILE
61+
),
62+
opossum_faker.resource(
63+
path=PurePath("toplevel/folder"), type=ResourceType.FOLDER
64+
),
65+
opossum_faker.resource(
66+
path=PurePath("toplevel/folder/resource2"), type=ResourceType.FILE
67+
),
68+
opossum_faker.resource(
69+
path=PurePath("toplevel/folder/resource3"), type=ResourceType.FILE
70+
),
71+
]
72+
73+
def test_extraction_is_extracts_correct_resources(
74+
self, opossum_faker: OpossumFaker
75+
) -> None:
76+
resources = self._get_test_resources(opossum_faker)
77+
scan_results = opossum_faker.scan_results(resources=resources)
78+
opossum = opossum_faker.opossum(scan_results=scan_results)
79+
80+
extracted = extract_subtree_impl(opossum, TestExtractSubTreeAttributes.SUBTREE)
81+
extracted_root_resource = extracted.scan_results.resources
82+
extracted_paths = [
83+
str(resource.path) for resource in extracted_root_resource.all_resources()
84+
]
85+
extracted_attributions = {
86+
attribution
87+
for resource in extracted_root_resource.all_resources()
88+
for attribution in resource.attributions
89+
}
90+
91+
assert set(extracted_paths) == {
92+
"folder",
93+
"folder/resource2",
94+
"folder/resource3",
95+
}
96+
97+
expected_attributions = {
98+
attribution
99+
for resource in resources[1:]
100+
for attribution in resource.attributions
101+
}
102+
assert expected_attributions == extracted_attributions
103+
104+
def test_extraction_is_filters_attribution_to_ids(
105+
self, opossum_faker: OpossumFaker
106+
) -> None:
107+
resources = self._get_test_resources(opossum_faker)
108+
scan_results = opossum_faker.scan_results(resources=resources)
109+
opossum = opossum_faker.opossum(scan_results=scan_results)
110+
111+
extracted = extract_subtree_impl(opossum, TestExtractSubTreeAttributes.SUBTREE)
112+
extracted_root_resource = extracted.scan_results.resources
113+
extracted_attributions = {
114+
attribution
115+
for resource in extracted_root_resource.all_resources()
116+
for attribution in resource.attributions
117+
}
118+
119+
expected_attributions = {
120+
attribution
121+
for resource in resources[1:]
122+
for attribution in resource.attributions
123+
}
124+
assert expected_attributions == extracted_attributions
125+
assert set(extracted.scan_results.attribution_to_id.keys()) == (
126+
expected_attributions | opossum.scan_results.unassigned_attributions
127+
)
128+
129+
def test_extraction_keeps_configuration_and_metadata(
130+
self, opossum_faker: OpossumFaker
131+
) -> None:
132+
resources = self._get_test_resources(opossum_faker)
133+
scan_results = opossum_faker.scan_results(resources=resources)
134+
opossum = opossum_faker.opossum(scan_results=scan_results)
135+
136+
extracted = extract_subtree_impl(opossum, TestExtractSubTreeAttributes.SUBTREE)
137+
138+
assert extracted.scan_results.config == opossum.scan_results.config
139+
assert extracted.scan_results.metadata == opossum.scan_results.metadata
140+
assert (
141+
extracted.scan_results.base_urls_for_sources
142+
== opossum.scan_results.base_urls_for_sources
143+
)
144+
assert (
145+
extracted.scan_results.frequent_licenses
146+
== opossum.scan_results.frequent_licenses
147+
)
148+
assert (
149+
extracted.scan_results.external_attribution_sources
150+
== opossum.scan_results.external_attribution_sources
151+
)
152+
assert (
153+
extracted.scan_results.unassigned_attributions
154+
== opossum.scan_results.unassigned_attributions
155+
)
156+
157+
def test_extraction_filters_review_results(
158+
self, opossum_faker: OpossumFaker
159+
) -> None:
160+
resources = self._get_test_resources(opossum_faker)
161+
scan_results = opossum_faker.scan_results(resources=resources)
162+
manual_attributions = {
163+
"1": opossum_faker.manual_attribution(),
164+
"2": opossum_faker.manual_attribution(),
165+
"3": opossum_faker.manual_attribution(),
166+
}
167+
resources_to_attributions = {
168+
"/toplevel/resource1.txt": ["1"],
169+
"/toplevel/folder/": ["2"],
170+
"/toplevel/folder/resource2.txt": ["3"],
171+
}
172+
review_results = opossum_faker.output_file(
173+
manual_attributions=manual_attributions,
174+
resources_to_attributions=resources_to_attributions,
175+
)
176+
opossum = opossum_faker.opossum(
177+
review_results=review_results, scan_results=scan_results
178+
)
179+
180+
extracted = extract_subtree_impl(opossum, TestExtractSubTreeAttributes.SUBTREE)
181+
182+
assert extracted.review_results
183+
assert opossum.review_results # make mypy happy
184+
assert extracted.review_results.metadata == opossum.review_results.metadata
185+
assert {"2", "3"} == set(extracted.review_results.manual_attributions.keys())
186+
assert {"/toplevel/folder/", "/toplevel/folder/resource2.txt"} == set(
187+
extracted.review_results.resources_to_attributions.keys()
188+
)
189+
assert extracted.review_results.resolved_external_attributions is not None
190+
assert set(extracted.review_results.resolved_external_attributions).issubset(
191+
set(extracted.scan_results.attribution_to_id.values())
192+
)

0 commit comments

Comments
 (0)