8000 [Issue 305] add new json parser by meretp · Pull Request #366 · spdx/tools-python · GitHub
[go: up one dir, main page]

Skip to content

[Issue 305] add new json parser #366

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Dec 28, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
296816b
[issue-305] add new parser
meretp Nov 25, 2022
cd095e2
[issue-305, refactor] add method to construct an object and raise SPD…
meretp Dec 14, 2022
f2f91fd
[issue-305, refactor] annotation_parser: extract methods to improve r…
meretp Dec 14, 2022
190cd5a
[issue-305, refactor] add methods to parse required/ optional fields …
meretp Dec 14, 2022
2834000
[issue-305, refactor] relationship_parser: extract dict to invert rel…
meretp Dec 14, 2022
6297673
[issue-305, refactor] add method to raise error if logger has message…
meretp Dec 14, 2022
4741a43
[issue-305, review] refactor methods in dict_parsing_functions.py, sm…
meretp Dec 15, 2022
080d848
[issue-305, refactor] json_parser
meretp Dec 15, 2022
5826922
[issue-305, reformat]
meretp Dec 19, 2022
e6332cb
[issue-305] add testcases and update license_expression parser
meretp Dec 19, 2022
1f6d5b6
[issue-305, refactor] delete duplicated check for error type
meretp Dec 20, 2022
fc980b1
[issue-305, review] fix messages, naming, type hints
meretp Dec 21, 2022
3fe3e11
[issue-305, review] refactor relationship_parser
meretp Dec 21, 2022
0be1780
[issue-305, review] refactor snippet_parser
meretp Dec 21, 2022
c5b8d3c
[issue-305, review] make naming consistent
meretp Dec 21, 2022
03cce38
[issue-305, review] add test for dict parsing functions and catch Val…
meretp Dec 21, 2022
2dcd125
[issue-305, review] add None handling for required fields
meretp Dec 21, 2022
50c3038
[issue-305, review] make error messages consistent, add test for json…
meretp Dec 28, 2022
562f288
[issue-305, review] add tests, change test data, naming of tests and …
meretp Dec 22, 2022
a722036
[issue-305, review] add method to parse fields that can be SpdxNone o…
meretp Dec 22, 2022
c8851d8
[issue-305, review] refactor parse_field_or_log_error
meretp Dec 22, 2022
347051a
[issue-305, review] reformat, type hints, fix typos, error messages
meretp Dec 28, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[issue-305, review] add method to parse fields that can be SpdxNone o…
…r SpdxNoAssertion

Signed-off-by: Meret Behrens <meret.behrens@tngtech.com>
  • Loading branch information
meretp committed Dec 28, 2022
commit a7220363eb859ddda5d787168da9c70a92ba6032
5 changes: 0 additions & 5 deletions src/parser/json/actor_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@


class ActorParser:
def parse_actor_or_no_assertion(self, actor_or_no_assertion: str) -> Union[SpdxNoAssertion, Actor]:
if actor_or_no_assertion == SpdxNoAssertion.__str__:
return SpdxNoAssertion()
else:
return self.parse_actor(actor_or_no_assertion)

@staticmethod
def parse_actor(actor: str) -> Actor:
Expand Down
6 changes: 3 additions & 3 deletions src/parser/json/creation_info_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
from src.parser.json.actor_parser import ActorParser
from src.parser.json.checksum_parser import ChecksumParser
from src.parser.json.dict_parsing_functions import append_parsed_field_or_log_error, datetime_from_str, \
raise_parsing_error_if_logger_has_messages, construct_or_raise_parsing_error, parse_field_or_log_error
raise_parsing_error_if_logger_has_messages, construct_or_raise_parsing_error, parse_field_or_log_error, \
parse_field_or_no_assertion
from src.parser.logger import Logger


Expand Down Expand Up @@ -80,8 +81,7 @@ def parse_creators(self, creators_list_from_dict: List[str]) -> List[Actor]:
logger = Logger()
creators = []
for creator_str in creators_list_from_dict:
creators = append_parsed_field_or_log_error(logger, creators, creator_str,
self.actor_parser.parse_actor_or_no_assertion)
creators = append_parsed_field_or_log_error(logger, creators, creator_str, lambda x: parse_field_or_no_assertion(x, self.actor_parser.parse_actor))

raise_parsing_error_if_logger_has_messages(logger)
return creators
Expand Down
18 changes: 17 additions & 1 deletion src/parser/json/dict_parsing_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from datetime import datetime
from typing import Any, Callable, Dict, List
from typing import Any, Callable, Dict, List, Union

from src.model.spdx_no_assertion import SpdxNoAssertion
from src.model.spdx_none import SpdxNone
from src.model.typing.constructor_type_errors import ConstructorTypeErrors
from src.parser.error import SPDXParsingError
from src.parser.logger import Logger
Expand Down Expand Up @@ -67,3 +69,17 @@ def raise_parsing_error_if_logger_has_messages(logger: Logger, parsed_object_nam
raise SPDXParsingError([f"Error while parsing {parsed_object_name}: {logger.get_messages()}"])
else:
raise SPDXParsingError(logger.get_messages())

def parse_field_or_no_assertion_or_none(field: str, method_for_field: Callable=lambda x: x) -> Union[SpdxNoAssertion, SpdxNone, Any]:
if field == SpdxNoAssertion().__str__():
return SpdxNoAssertion()
elif field == SpdxNone().__str__():
return SpdxNone()
else:
return method_for_field(field)

def parse_field_or_no_assertion(field: str, method_for_field: Callable = lambda x: x) -> Union[SpdxNoAssertion, Any]:
if field == SpdxNoAssertion().__str__():
return SpdxNoAssertion()
else:
return method_for_field(field)
29 changes: 10 additions & 19 deletions src/parser/json/extracted_licensing_info_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from src.model.extracted_licensing_info import ExtractedLicensingInfo
from src.model.spdx_no_assertion import SpdxNoAssertion
from src.parser.json.dict_parsing_functions import raise_parsing_error_if_logger_has_messages, \
append_parsed_field_or_log_error, construct_or_raise_parsing_error, parse_field_or_log_error
append_parsed_field_or_log_error, construct_or_raise_parsing_error, parse_field_or_no_assertion
from src.parser.logger import Logger


Expand All @@ -28,32 +28,23 @@ def parse_extracted_licensing_infos(self, extracted_licensing_info_dicts: List[D
extracted_licensing_infos = []
for extracted_licensing_info_dict in extracted_licensing_info_dicts:
extracted_licensing_infos = append_parsed_field_or_log_error(self.logger, extracted_licensing_infos,
extracted_licensing_info_dict,
self.parse_extracted_licensing_info)
extracted_licensing_info_dict,
self.parse_extracted_licensing_info)

raise_parsing_error_if_logger_has_messages(self.logger)
return extracted_licensing_infos

def parse_extracted_licensing_info(self, extracted_licensing_info_dict: Dict) -> ExtractedLicensingInfo:
license_id: Optional[str] = extracted_licensing_info_dict.get("licenseId")
extracted_text: Optional[str] = extracted_licensing_info_dict.get("extractedText")
license_name: Optional[Union[str, SpdxNoAssertion]] = parse_field_or_log_error(self.logger,
extracted_licensing_info_dict.get(
"name"),
self.parse_extracted_licensing_info_name)
license_name: Optional[Union[str, SpdxNoAssertion]] = parse_field_or_no_assertion(
extracted_licensing_info_dict.get("name"))
cross_references: List[str] = extracted_licensing_info_dict.get("seeAlsos", [])
comment: Optional[str] = extracted_licensing_info_dict.get("comment")
extracted_licensing_info = construct_or_raise_parsing_error(ExtractedLicensingInfo,
dict(license_id=license_id,
extracted_text=extracted_text,
comment=comment,
license_name=license_name,
cross_references=cross_references))
dict(license_id=license_id,
extracted_text=extracted_text,
comment=comment,
license_name=license_name,
cross_references=cross_references))
return extracted_licensing_info

@staticmethod
def parse_extracted_licensing_info_name(extracted_licensing_info_name_or_no_assertion) -> Union[str, SpdxNoAssertion]:
if extracted_licensing_info_name_or_no_assertion == SpdxNoAssertion().__str__():
return SpdxNoAssertion()
else:
return extracted_licensing_info_name_or_no_assertion
7 changes: 4 additions & 3 deletions src/parser/json/file_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
from src.model.spdx_none import SpdxNone
from src.parser.json.checksum_parser import ChecksumParser
from src.parser.json.dict_parsing_functions import append_parsed_field_or_log_error, \
raise_parsing_error_if_logger_has_messages, construct_or_raise_parsing_error, parse_field_or_log_error
raise_parsing_error_if_logger_has_messages, construct_or_raise_parsing_error, parse_field_or_log_error, \
parse_field_or_no_assertion_or_none
from src.parser.json.license_expression_parser import LicenseExpressionParser
from src.parser.logger import Logger

Expand Down Expand Up @@ -56,10 +57,10 @@ def parse_file(self, file_dict: Dict) -> Optional[File]:
license_comments: Optional[str] = file_dict.get("licenseComments")

license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error(
logger, file_dict.get("licenseConcluded"), self.license_expression_parser.parse_license_expression)
logger, file_dict.get("licenseConcluded"), lambda x: parse_field_or_no_assertion_or_none(x, self.license_expression_parser.parse_license_expression))

license_info_in_files: Optional[Union[List[LicenseExpression], SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error(
3372 logger, file_dict.get("licenseInfoInFiles"), self.license_expression_parser.parse_license_expression)
logger, file_dict.get("licenseInfoInFiles"), lambda x: parse_field_or_no_assertion_or_none(x, self.license_expression_parser.parse_license_expressions))
notice_text: Optional[str] = file_dict.get("noticeText")
raise_parsing_error_if_logger_has_messages(logger, "File")

Expand Down
25 changes: 8 additions & 17 deletions src/parser/json/license_expression_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,22 @@
from typing import Union, List

from src.model.license_expression import LicenseExpression
from src.model.spdx_no_assertion import SpdxNoAssertion
from src.model.spdx_none import SpdxNone
from src.parser.error import SPDXParsingError
from src.parser.json.dict_parsing_functions import construct_or_raise_parsing_error, append_parsed_field_or_log_error, \
raise_parsing_error_if_logger_has_messages
from src.parser.logger import Logger


class LicenseExpressionParser:
def parse_license_expression(self, license_expression_str_or_list: Union[str, List[str]]) -> Union[
LicenseExpression, SpdxNoAssertion, SpdxNone, List[LicenseExpression]]:
if license_expression_str_or_list == SpdxNone().__str__():
return SpdxNone()
if license_expression_str_or_list == SpdxNoAssertion().__str__():
return SpdxNoAssertion()
elif isinstance(license_expression_str_or_list, list):
return self.parse_license_expressions(license_expression_str_or_list)
@staticmethod
def parse_license_expression(license_expression_str_or_list: str) -> LicenseExpression:
license_expression = construct_or_raise_parsing_error(LicenseExpression,
dict(expression_string=license_expression_str_or_list))
return license_expression

else:
license_expression = construct_or_raise_parsing_error(LicenseExpression,
dict(
expression_string=license_expression_str_or_list))
return license_expression

def parse_license_expressions(self, license_expression_str_or_list: List[str]) -> List[LicenseExpression]:
def parse_license_expressions(self, license_expression_str_or_list: Union[str, List[str]]) -> Union[LicenseExpression, List[LicenseExpression]]:
if isinstance(license_expression_str_or_list, str):
return self.parse_license_expression(license_expression_str_or_list)
license_expressions = []
logger = Logger()
for license_expression_str in license_expression_str_or_list:
Expand Down
27 changes: 13 additions & 14 deletions src/parser/json/package_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from src.parser.json.checksum_parser import ChecksumParser
from src.parser.json.dict_parsing_functions import append_parsed_field_or_log_error, datetime_from_str, \
raise_parsing_error_if_logger_has_messages, json_str_to_enum_name, construct_or_raise_parsing_error, \
parse_field_or_log_error
parse_field_or_log_error, parse_field_or_no_assertion_or_none, parse_field_or_no_assertion
from src.parser.json.license_expression_parser import LicenseExpressionParser
from src.parser.logger import Logger

Expand Down Expand Up @@ -62,7 +62,7 @@ def parse_package(self, package_dict: Dict) -> Package:
comment: Optional[str] = package_dict.get("comment")
copyright_text: Optional[str] = package_dict.get("copyrightText")
description: Optional[str] = package_dict.get("description")
download_location: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = self.parse_download_location(
download_location: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = parse_field_or_no_assertion_or_none(
package_dict.get("downloadLocation"))

external_refs: List[ExternalPackageRef] = parse_field_or_log_error(logger, package_dict.get("externalRefs"),
Expand All @@ -73,19 +73,22 @@ def parse_package(self, package_dict: Dict) -> Package:
homepage: Optional[str] = package_dict.get("homepage")
license_comments: Optional[str] = package_dict.get("licenseComments")
license_concluded = parse_field_or_log_error(logger, package_dict.get("licenseConcluded"),
self.license_expression_parser.parse_license_expression, None)
lambda x: parse_field_or_no_assertion_or_none(x, self.license_expression_parser.parse_license_expression), None)

license_declared: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error(
logger, package_dict.get("licenseDeclared"), self.license_expression_parser.parse_license_expression)
logger, package_dict.get("licenseDeclared"), lambda x: parse_field_or_no_assertion_or_none(x, self.license_expression_parser.parse_license_expression))

license_info_from_file: Optional[
Union[List[LicenseExpression], SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error(logger,
package_dict.get(
"licenseInfoFromFiles"),
self.license_expression_parser.parse_license_expression)
lambda x: parse_field_or_no_assertion_or_none(x, self.license_expression_parser.parse_license_expressions))
originator: Optional[Union[Actor, SpdxNoAssertion]] = parse_field_or_log_error(logger,
package_dict.get("originator"),
self.actor_parser.parse_actor_or_no_assertion)
lambda
x: parse_field_or_no_assertion(
x,
self.actor_parser.parse_actor))
package_file_name: Optional[str] = package_dict.get("packageFileName")

package_verification_code: Optional[
Expand All @@ -100,7 +103,10 @@ def parse_package(self, package_dict: Dict) -> Package:
summary: Optional[str] = package_dict.get("summary")
supplier: Optional[Union[Actor, SpdxNoAssertion]] = parse_field_or_log_error(logger,
package_dict.get("supplier"),
self.actor_parser.parse_actor_or_no_assertion)
lambda
x: parse_field_or_no_assertion(
x,
self.actor_parser.parse_actor))
valid_until_date: Optional[datetime] = parse_field_or_log_error(logger, package_dict.get("validUntilDate"),
datetime_from_str)

Expand Down Expand Up @@ -177,10 +183,3 @@ def parse_primary_package_purpose(primary_package_purpose: str) -> PackagePurpos
except KeyError:
raise SPDXParsingError([f"Invalid PrimaryPackagePurpose: {primary_package_purpose}"])

@staticmethod
def parse_download_location(download_location: str) -> Union[str, SpdxNoAssertion, SpdxNone]:
if download_location == SpdxNone().__str__():
return SpdxNone()
if download_location == SpdxNoAssertion().__str__():
return SpdxNoAssertion()
return download_location
16 changes: 12 additions & 4 deletions src/parser/json/snippet_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from src.model.spdx_none import SpdxNone
from src.parser.error import SPDXParsingError
from src.parser.json.dict_parsing_functions import construct_or_raise_parsing_error, parse_field_or_log_error, \
raise_parsing_error_if_logger_has_messages, append_parsed_field_or_log_error
raise_parsing_error_if_logger_has_messages, append_parsed_field_or_log_error, parse_field_or_no_assertion_or_none

from src.parser.json.license_expression_parser import LicenseExpressionParser
from src.parser.logger import Logger
Expand Down Expand Up @@ -59,11 +59,19 @@ def parse_snippet(self, snippet_dict: Dict) -> Snippet:
license_comment: Optional[str] = snippet_dict.get("licenseComments")
concluded_license: Optional[Union[
LicenseExpression, SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error(logger, snippet_dict.get(
"licenseConcluded"), self.license_expression_parser.parse_license_expression)
"licenseConcluded"),
lambda
x: parse_field_or_no_assertion_or_none(
x,
self.license_expression_parser.parse_license_expression))

license_info: Optional[Union[List[
LicenseExpression], SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error(logger, snippet_dict.get(
"licenseInfoInSnippets"), self.license_expression_parser.parse_license_expression)
"licenseInfoInSnippets"),
lambda
x: parse_field_or_no_assertion_or_none(
x,
self.license_expression_parser.parse_license_expressions))
if logger.has_messages():
raise SPDXParsingError([f"Error while parsing snippet: {logger.get_messages()}"])

Expand Down Expand Up @@ -117,7 +125,7 @@ def validate_range_and_get_type(self, range_dict: Dict) -> RangeType:
@staticmethod
def validate_pointer_and_get_type(pointer: Dict) -> RangeType:
if "offset" in pointer and "lineNumber" in pointer:
raise ValueError ('Couldn\'t determine type of pointer: "offset" and "lineNumber" provided as key.')
raise ValueError('Couldn\'t determine type of pointer: "offset" and "lineNumber" provided as key.')
if "offset" not in pointer and "lineNumber" not in pointer:
raise ValueError('Couldn\'t determine type of pointer: neither "offset" nor "lineNumber" provided as key.')
return RangeType.BYTE if "offset" in pointer else RangeType.LINE
Loading
0