Skip to content
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

refactor: configure mypy to strict mode #339

Merged
merged 8 commits into from
Jan 4, 2025
Merged
5 changes: 3 additions & 2 deletions cdxev/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import shutil
import sys
import textwrap
import typing as t
from collections.abc import MutableSequence
from dataclasses import dataclass
from pathlib import Path
Expand Down Expand Up @@ -42,7 +43,7 @@ class Status(enum.IntEnum):
VALIDATION_ERROR = 4


def main() -> int:
def main() -> t.Union[int, t.Any]:
"""Main entry point for this tool."""
args = parse_cli()

Expand Down Expand Up @@ -93,7 +94,7 @@ def read_sbom(sbom_file: Path, file_type: Optional[str] = None) -> Tuple[dict, s
return sbom, file_type


def load_json(path: Path) -> dict:
def load_json(path: Path) -> t.Any:
"""Loads a JSON file into a dictionary."""
try:
with path.open(encoding="utf-8-sig") as file:
Expand Down
14 changes: 10 additions & 4 deletions cdxev/amend/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,9 @@ class LicenseNameToId(Operation):

license_map: dict[str, str] = {}

def prepare(self, sbom: dict) -> None:
def prepare(self, sbom: dict) -> None: # type: ignore
license_mapping_file = (
importlib.resources.files(__spec__.parent) / "license_name_spdx_id_map.json" # type: ignore[name-defined, arg-type] # noqa: E501
importlib.resources.files(__spec__.parent) / "license_name_spdx_id_map.json" # type: ignore[arg-type] # noqa: E501
)
license_mapping_json = license_mapping_file.read_text(encoding="utf-8-sig")
license_mapping = json.loads(license_mapping_json)
Expand Down Expand Up @@ -446,10 +446,16 @@ class DeleteAmbiguousLicenses(Operation):
"""

def _has_text(self, license: dict) -> bool:
return license.get("text", {}).get("content", "") != ""
if license.get("text", {}).get("content", "") != "":
return True
else:
return False

def _has_url(self, license: dict) -> bool:
return license.get("url", "") != ""
if license.get("url", "") != "":
return True
else:
return False

def _has_name_only(self, license: dict) -> bool:
# Any fields other than name, text, or url mean the license shouldn't be deleted.
Expand Down
4 changes: 2 additions & 2 deletions cdxev/auxiliary/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ class SWID(dict):
"""

def __str__(self) -> str:
return "tagId: " + self["tagId"]
return "tagId: " + str(self["tagId"])

def __eq__(self, other: object) -> bool:
return isinstance(other, SWID) and self["tagId"] == other["tagId"]

def __hash__(self) -> int: # type: ignore[override]
return self["tagId"].__hash__()
return self["tagId"].__hash__() # type: ignore


@dataclass(init=True, frozen=True, eq=True)
Expand Down
12 changes: 10 additions & 2 deletions cdxev/auxiliary/sbomFunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from cyclonedx.model.component import Component
from dateutil.parser import parse

from cdxev.error import AppError

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -415,8 +417,14 @@ def deserialize(sbom: dict) -> Bom:
sbom.pop(
"compositions"
) # compositions need to be removed till the model supports those
deserialized_bom = Bom.from_json(data=sbom) # type: ignore
return deserialized_bom
deserialized_bom = Bom.from_json(data=sbom) # type:ignore[attr-defined]
if isinstance(deserialized_bom, Bom):
return deserialized_bom
else:
raise AppError(
"Failed deserialization",
("Deserialization of the SBOM into the CycloneDX Python Library failed."),
)


def extract_cyclonedx_components(
Expand Down
21 changes: 7 additions & 14 deletions cdxev/initialize_sbom.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,14 @@
from typing import Any, Union
from uuid import uuid4

from cyclonedx.model import ( # type: ignore
ExternalReference,
ExternalReferenceType,
XsUri,
)
from cyclonedx.model.bom import Bom, BomMetaData # type: ignore
from cyclonedx.model.bom_ref import BomRef # type: ignore
from cyclonedx.model.component import Component, ComponentType # type: ignore
from cyclonedx.model.contact import ( # type: ignore
OrganizationalContact,
OrganizationalEntity,
)
from cyclonedx.model.dependency import Dependency # type: ignore
from cyclonedx.model import ExternalReference, ExternalReferenceType, XsUri
from cyclonedx.model.bom import Bom, BomMetaData
from cyclonedx.model.bom_ref import BomRef
from cyclonedx.model.component import Component, ComponentType
from cyclonedx.model.contact import OrganizationalContact, OrganizationalEntity
from cyclonedx.model.dependency import Dependency
from cyclonedx.model.tool import Tool
from cyclonedx.output.json import JsonV1Dot6 # type: ignore
from cyclonedx.output.json import JsonV1Dot6

from cdxev import pkg

Expand Down
29 changes: 10 additions & 19 deletions cdxev/list_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,18 @@
logger = logging.getLogger(__name__)


def print_license(license: dict) -> str:
if license.get("expression", ""):
return license.get("expression", "")
elif license.get("license", {}).get("id", ""):
return license.get("license", {}).get("id", "")
else:
return license.get("license", {}).get("name", "")


def extract_string_from_license(license: License) -> str:
if isinstance(license, DisjunctiveLicense):
if license.id is not None:
return license.id
return str(license.id)
elif license.name is not None:
return license.name
return str(license.name)
else:
return ""

elif isinstance(license, LicenseExpression):
if license.value is not None:
return license.value
return str(license.value)
else:
return ""
else:
Expand All @@ -48,7 +39,7 @@ def extract_license_strings_from_licenses(licenses: list[License]) -> list[str]:
return license_list


def extract_metadata_license_information(metadata: BomMetaData) -> dict:
def extract_metadata_license_information(metadata: BomMetaData) -> dict[str, Any]:
if metadata.component is not None:
metadata_component = metadata.component
software_information: dict[str, Any] = {}
Expand Down Expand Up @@ -115,7 +106,7 @@ def write_list_to_str(str_list: list[str], division_character: str = "\n") -> st
return string


def write_license_dict_to_txt(info_dict: dict) -> str:
def write_license_dict_to_txt(info_dict: dict[str, Any]) -> str:
string = ""

if info_dict.get("name", ""):
Expand All @@ -137,7 +128,7 @@ def write_license_dict_to_txt(info_dict: dict) -> str:
return string


def write_license_dict_to_csv(info_dict: dict) -> str:
def write_license_dict_to_csv(info_dict: dict[str, Any]) -> str:
string = ""

string += '"' + info_dict.get("name", "") + '"'
Expand All @@ -153,7 +144,7 @@ def write_license_dict_to_csv(info_dict: dict) -> str:


def write_license_information_to_txt(
software_information: dict, component_information: list[dict]
software_information: dict[str, Any], component_information: list[dict[str, Any]]
) -> str:

string = write_license_dict_to_txt(software_information)
Expand All @@ -176,8 +167,8 @@ def write_license_information_to_txt(


def write_license_information_to_csv(
software_information: dict,
component_information: list[dict],
software_information: dict[str, Any],
component_information: list[dict[str, Any]],
) -> str:
string = "Name,Copyright,Licenses"

Expand Down Expand Up @@ -293,7 +284,7 @@ def list_components(sbom: Bom, format: str = "txt") -> str:
return string


def list_command(sbom: dict, operation: str, format: str = "txt") -> str:
def list_command(sbom: dict, operation: str, format: str = "txt") -> str: # type: ignore
"""
Lists specific content of the SBOM.

Expand Down
2 changes: 1 addition & 1 deletion cdxev/merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def merge_components(governing_sbom: dict, sbom_to_be_merged: dict) -> t.List[di
)
list_of_merged_components.append(component)
list_of_merged_bom_refs.append(new_bom_ref)
return list_of_merged_components
return list_of_merged_components # type:ignore [no-any-return]


def merge_dependency(
Expand Down
6 changes: 3 additions & 3 deletions cdxev/set.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import typing as t
from dataclasses import dataclass, field, fields

import univers.version_range # type:ignore
import univers.versions # type:ignore
import univers.version_range # type:ignore[import-untyped]
import univers.versions # type:ignore[import-untyped]

from cdxev.auxiliary.identity import ComponentIdentity, Coordinates, Key, KeyType
from cdxev.auxiliary.sbomFunctions import walk_components
Expand Down Expand Up @@ -150,7 +150,7 @@ def create(
group=component.get("group"),
version_range=component.get("version-range", ""),
)
return UpdateIdentity(coordinates) # type:ignore
return UpdateIdentity(coordinates)

else:
return super().create(component, allow_unsafe)
Expand Down
20 changes: 17 additions & 3 deletions cdxev/validator/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def open_schema(
"Path does not exist or is not a file: " + str(schema_path),
)
with schema_path.open() as fp:
return json.load(fp)
return json.load(fp) # type:ignore [no-any-return]
except OSError as e:
raise AppError("Schema not loaded", str(e)) from e
except json.JSONDecodeError as e:
Expand All @@ -55,15 +55,29 @@ def _get_builtin_schema(schema_type: str, spec_version: str) -> dict:
f"schema type '{schema_type}'.",
)
schema_json = schema_file.read_text()
return json.loads(schema_json)
schema = json.loads(schema_json)
if isinstance(schema, dict):
return schema
else:
raise AppError(
"Schema error",
("Loaded builtin schema is not of type dict"),
)


def load_spdx_schema() -> dict:
path_to_embedded_schema = (
resources.files("cdxev.auxiliary.schema") / "spdx.schema.json"
)
with path_to_embedded_schema.open() as f:
return json.load(f)
schema = json.load(f)
if isinstance(schema, dict):
return schema
else:
raise AppError(
"SPDX schema error",
("Loaded SPDX schema is not type dict"),
)


def validate_filename(
Expand Down
10 changes: 6 additions & 4 deletions cdxev/validator/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,11 @@ def validate_sbom(
)
for error in sorted(v.iter_errors(sbom), key=str):
try:
if error.validator == "required" and error.validator_value == [
"this_is_an_externally_described_component"
]:
if (
error.validator == "required" # type: ignore[comparison-overlap]
and error.validator_value
== ["this_is_an_externally_described_component"]
):
# This requirement in the schema allows us to produce warnings.
comp = t.cast(dict, error.instance)
if "bom-ref" in comp:
Expand Down Expand Up @@ -202,7 +204,7 @@ def validate_sbom(
errors.append(
f"{error_path}'{error.absolute_path[-1]}' should not be empty"
)
elif error.validator == "pattern":
elif error.validator == "pattern": # type: ignore[comparison-overlap]
errors.append(error_path + error.message.replace("\\", ""))
else:
errors.append(error_path + error.message)
Expand Down
Loading
Loading