Skip to content

Commit 6c96077

Browse files
ant-uct2034
andauthored
feature/ relocate checks (#67)
* added for each check an own file to increade structure and understandability --------- Signed-off-by: Anton Utz <uta5fe@bosch.com> Co-authored-by: Christian Henkel <6976069+ct2034@users.noreply.github.com>
1 parent 890756d commit 6c96077

File tree

7 files changed

+433
-306
lines changed

7 files changed

+433
-306
lines changed

src/ros_license_toolkit/checks.py

Lines changed: 0 additions & 301 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,8 @@
1616

1717
"""This module contains the checks for the linter."""
1818

19-
import os
2019
from enum import IntEnum
21-
from pprint import pformat
22-
from typing import Any, Dict, List, Optional
2320

24-
from ros_license_toolkit.common import get_spdx_license_name
25-
from ros_license_toolkit.license_tag import (LicenseTag,
26-
is_license_name_in_spdx_list)
2721
from ros_license_toolkit.package import Package, PackageException
2822
from ros_license_toolkit.ui_elements import NO_REASON_STR, green, red, yellow
2923

@@ -110,298 +104,3 @@ def check(self, package: Package):
110104
def _check(self, package: Package):
111105
"""Check `package`. To be overwritten by subclasses."""
112106
raise NotImplementedError("Overwrite this")
113-
114-
115-
class LicenseTagExistsCheck(Check):
116-
"""This ensures that a tag defining the license exists."""
117-
118-
def _check(self, package: Package):
119-
if len(package.license_tags) == 0:
120-
self._failed("No license tag defined.")
121-
self.verbose_output = red(str(package.package_xml))
122-
else:
123-
self._success(
124-
f"Found licenses {list(map(str, package.license_tags))}")
125-
126-
127-
class LicenseTagIsInSpdxListCheck(Check):
128-
"""This ensures that the license tag is in the SPDX list of licenses."""
129-
130-
def _check(self, package: Package):
131-
licenses_not_in_spdx_list = []
132-
for license_tag in package.license_tags.keys():
133-
if not is_license_name_in_spdx_list(
134-
license_tag):
135-
licenses_not_in_spdx_list.append(license_tag)
136-
if len(licenses_not_in_spdx_list) > 0:
137-
self._warning(
138-
f"Licenses {licenses_not_in_spdx_list} are "
139-
"not in SPDX list of licenses. "
140-
"Make sure to exactly match one of https://spdx.org/licenses/."
141-
)
142-
else:
143-
self._success("All license tags are in SPDX list of licenses.")
144-
145-
146-
class LicenseTextExistsCheck(Check):
147-
"""This ensures that the license text file referenced by the tag exists."""
148-
149-
def __init__(self: 'LicenseTextExistsCheck'):
150-
Check.__init__(self)
151-
self.license_tags_without_license_text: Dict[LicenseTag, str] = {}
152-
self.missing_license_texts_status: Dict[LicenseTag, Status] = {}
153-
self.files_with_wrong_tags: Dict[LicenseTag, Dict[str, str]] = {}
154-
self.found_license_texts: Dict[str, Any] = {}
155-
156-
def _check(self, package: Package):
157-
if len(package.license_tags) == 0:
158-
self._failed("No license tag defined.")
159-
return
160-
161-
self._check_licenses(package)
162-
self._evaluate_results()
163-
164-
def _check_licenses(self, package: Package) -> None:
165-
'''checks each license tag for the corresponding license text. Also
166-
detects inofficial licenses when tag is not in the SPDX license list'''
167-
self.found_license_texts = package.found_license_texts
168-
for license_tag in package.license_tags.values():
169-
if not license_tag.has_license_text_file():
170-
self.license_tags_without_license_text[
171-
license_tag] = "No license text file defined."
172-
self.missing_license_texts_status[license_tag] = Status.FAILURE
173-
continue
174-
license_text_file = license_tag.get_license_text_file()
175-
if not os.path.exists(
176-
os.path.join(package.abspath, license_text_file)):
177-
self.license_tags_without_license_text[license_tag] =\
178-
f"License text file '{license_text_file}' does not exist."
179-
self.missing_license_texts_status[license_tag] = Status.FAILURE
180-
continue
181-
if license_text_file not in self.found_license_texts:
182-
self.license_tags_without_license_text[license_tag] =\
183-
f"License text file '{license_text_file}' not included" +\
184-
" in scan results."
185-
self.missing_license_texts_status[license_tag] = Status.FAILURE
186-
continue
187-
if not get_spdx_license_name(
188-
self.found_license_texts[license_text_file]):
189-
self.license_tags_without_license_text[license_tag] =\
190-
f"License text file '{license_text_file}' is not " +\
191-
"recognized as license text."
192-
self.missing_license_texts_status[license_tag] = Status.FAILURE
193-
continue
194-
actual_license: Optional[str] = get_spdx_license_name(
195-
self.found_license_texts[license_text_file])
196-
if actual_license is None:
197-
self.license_tags_without_license_text[
198-
license_tag
199-
] = f"License text file '{license_text_file}'" +\
200-
" is not recognized as license text."
201-
self.missing_license_texts_status[license_tag] = Status.FAILURE
202-
continue
203-
if actual_license != license_tag.get_license_id():
204-
self.license_tags_without_license_text[license_tag] =\
205-
f"License text file '{license_text_file}' is " +\
206-
f"of license {actual_license} but tag is " +\
207-
f"{license_tag.get_license_id()}."
208-
# If Tag and File both are in SPDX but don't match -> Error
209-
if is_license_name_in_spdx_list(license_tag.get_license_id()):
210-
self.missing_license_texts_status[license_tag] =\
211-
Status.FAILURE
212-
else:
213-
self.missing_license_texts_status[license_tag] =\
214-
Status.WARNING
215-
self.files_with_wrong_tags[license_tag] = \
216-
{'actual_license': actual_license,
217-
'license_tag': license_tag.get_license_id()}
218-
continue
219-
220-
def _evaluate_results(self):
221-
if len(self.license_tags_without_license_text) > 0:
222-
if max(self.missing_license_texts_status.values()) \
223-
== Status.WARNING:
224-
self._warning(
225-
"Since they are not in the SPDX list, "
226-
"we can not check if these tags have the correct "
227-
"license text:\n" + "\n".join(
228-
[f" '{x[0]}': {x[1]}" for x in
229-
self.license_tags_without_license_text.items()]))
230-
else:
231-
self._failed(
232-
"The following license tags do not "
233-
"have a valid license text "
234-
"file:\n" + "\n".join(
235-
[f" '{x[0]}': {x[1]}" for x in
236-
self.license_tags_without_license_text.items()]))
237-
self.verbose_output = red(
238-
"\n".join([f" '{x[0]}': {x[1]}" for x in
239-
self.found_license_texts.items()]))
240-
else:
241-
self._success("All license tags have a valid license text file.")
242-
243-
244-
class LicensesInCodeCheck(Check):
245-
"""Check if all found licenses have a declaration in the package.xml."""
246-
247-
def __init__(self: 'LicensesInCodeCheck'):
248-
Check.__init__(self)
249-
self.declared_licenses: Dict[str, LicenseTag] = {}
250-
self.files_with_uncovered_licenses: Dict[str, List[str]] = {}
251-
self.files_not_matched_by_any_license_tag: Dict[str, List[str]] = {}
252-
self.files_with_inofficial_tag: Dict[str, List[str]] = {}
253-
254-
def _check(self, package: Package):
255-
if len(package.license_tags) == 0:
256-
self._failed('No license tag defined.')
257-
return
258-
self.declared_licenses = package.license_tags
259-
self._check_license_files(package)
260-
self._evaluate_result(package)
261-
262-
def _check_license_files(self, package: Package) -> None:
263-
for fname, found_licenses in package.found_files_w_licenses.items():
264-
if fname in package.get_license_files():
265-
# the actual license text files are not relevant for this
266-
continue
267-
found_licenses_str = found_licenses[
268-
'detected_license_expression_spdx']
269-
if not found_licenses_str:
270-
continue
271-
licenses = found_licenses_str.split(' AND ')
272-
for license_str in licenses:
273-
if license_str not in self.declared_licenses:
274-
# this license has an inofficial tag
275-
inofficial_licenses = {
276-
lic_tag.id_from_license_text: key
277-
for key, lic_tag in package.license_tags.items()
278-
if lic_tag.id_from_license_text != ''}
279-
if license_str in inofficial_licenses.keys():
280-
if fname not in self.files_with_inofficial_tag:
281-
self.files_with_inofficial_tag[fname] = []
282-
self.files_with_inofficial_tag[fname].append(
283-
license_str)
284-
self.files_with_inofficial_tag[fname].append(
285-
inofficial_licenses[license_str])
286-
continue
287-
# this license is not declared by any license tag
288-
if fname not in self.files_with_uncovered_licenses:
289-
self.files_with_uncovered_licenses[fname] = []
290-
self.files_with_uncovered_licenses[fname].append(
291-
license_str)
292-
continue
293-
if fname not in self.declared_licenses[
294-
license_str].source_files:
295-
# this license is declared by a license tag but the file
296-
# is not listed in the source files of the license tag
297-
if fname not in self.files_not_matched_by_any_license_tag:
298-
self.files_not_matched_by_any_license_tag[fname] = []
299-
self.files_not_matched_by_any_license_tag[fname].append(
300-
license_str)
301-
continue
302-
303-
def _evaluate_result(self, package: Package) -> None:
304-
if self.files_with_uncovered_licenses:
305-
info_str = ''
306-
info_str += '\nThe following files contain licenses that ' +\
307-
'are not covered by any license tag:\n' + '\n'.join(
308-
[f" '{x[0]}': {x[1]}" for x in
309-
self.files_with_uncovered_licenses.items()])
310-
self._print_info(
311-
info_str,
312-
self.files_with_uncovered_licenses,
313-
self.files_not_matched_by_any_license_tag,
314-
package,
315-
)
316-
elif len(self.files_not_matched_by_any_license_tag) > 0:
317-
info_str = ''
318-
info_str += '\nThe following files contain licenses that ' +\
319-
'are covered by a license tag but are not listed in ' +\
320-
'the source files of the license tag:\n' + '\n'.join(
321-
[f" '{x[0]}': {x[1]}" for x in
322-
self.files_not_matched_by_any_license_tag.items()])
323-
self._print_info(
324-
info_str,
325-
self.files_with_uncovered_licenses,
326-
self.files_not_matched_by_any_license_tag,
327-
package,
328-
)
329-
elif self.files_with_inofficial_tag:
330-
info_str = ''
331-
info_str += 'For the following files, please change the ' +\
332-
'License Tag in the package file to SPDX format:\n' +\
333-
'\n'.join(
334-
[f" '{x[0]}' is of {x[1][0]} but its Tag is {x[1][1]}."
335-
for x in self.files_with_inofficial_tag.items()])
336-
self._warning(info_str)
337-
else:
338-
self._success('All licenses found in the code are covered by a '
339-
'license declaration.')
340-
341-
def _print_info(self, info_str, files_with_uncovered_licenses,
342-
files_not_matched_by_any_license_tag, package):
343-
assert info_str != ''
344-
self._failed(info_str)
345-
self.verbose_output = red(
346-
'\n Relevant scan results:\n' + pformat(
347-
list(filter(
348-
lambda x: x[0] in files_with_uncovered_licenses or (
349-
x[0] in files_not_matched_by_any_license_tag),
350-
package.found_files_w_licenses.items()))))
351-
352-
353-
class LicenseFilesReferencedCheck(Check):
354-
"""Check if all found License file have a reference in package.xml."""
355-
356-
def _check(self, package: Package):
357-
not_covered_texts: Dict[str, str] = {}
358-
inofficial_covered_texts: Dict[str, List[str]] = {}
359-
for filename, license_text in package.found_license_texts.items():
360-
# skipping all declarations above the package
361-
if not is_in_package(package, filename):
362-
continue
363-
if 'detected_license_expression_spdx' in license_text and \
364-
license_text['detected_license_expression_spdx'] not in \
365-
package.license_tags:
366-
spdx_expression = license_text[
367-
'detected_license_expression_spdx']
368-
inofficial_licenses = {
369-
lic_tag.id_from_license_text: key
370-
for key, lic_tag in package.license_tags.items()
371-
if lic_tag.id_from_license_text != ''}
372-
if spdx_expression in inofficial_licenses:
373-
inofficial_covered_texts[filename] = \
374-
[spdx_expression,
375-
inofficial_licenses[spdx_expression]]
376-
else:
377-
not_covered_texts[filename] = \
378-
spdx_expression
379-
if not_covered_texts:
380-
info_str = ''
381-
info_str += 'The following license files are not' +\
382-
' mentioned by any tag:\n' +\
383-
'\n'.join(
384-
[f" '{x[0]}' is of {x[1]}."
385-
for x in not_covered_texts.items()])
386-
self._failed(info_str)
387-
elif inofficial_covered_texts:
388-
info_str = ''
389-
info_str += 'The following license files are not' +\
390-
' mentioned by any tag:\n' +\
391-
'\n'.join(
392-
[f" '{x[0]}' is of {x[1][0]} but its tag is {x[1][1]}."
393-
for x in inofficial_covered_texts.items()])
394-
self._warning(info_str)
395-
else:
396-
self._success("All license declaration are referenced by a tag.")
397-
398-
399-
def is_in_package(package: Package, file: str) -> bool:
400-
"""Return TRUE if the file is underneath the absolute package path.
401-
Return FALSE if file is located above package."""
402-
parent = os.path.abspath(package.abspath)
403-
child = os.path.abspath(package.abspath + '/' + file)
404-
405-
comm_parent = os.path.commonpath([parent])
406-
comm_child_parent = os.path.commonpath([parent, child])
407-
return comm_parent == comm_child_parent

0 commit comments

Comments
 (0)