Skip to content

Commit

Permalink
style: streamline code quality (#472)
Browse files Browse the repository at this point in the history
- raised some dev tools
- added more quality checkers and rules
- documented and applied additional code standards

---------

Signed-off-by: Jan Kowalleck <[email protected]>
  • Loading branch information
jkowalleck authored Oct 20, 2023
1 parent d09ac36 commit bb0f7a5
Show file tree
Hide file tree
Showing 35 changed files with 237 additions and 219 deletions.
20 changes: 20 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[flake8]
## https://flake8.pycqa.org/en/latest/user/configuration.html
## keep in sync with isort config - in `isort.cfg` file

exclude =
build,dist,__pycache__,.eggs,*.egg-info*,
*_cache,*.cache,
.git,.tox,.venv,venv,.venv*,venv*,
_OLD,_TEST,
docs

max-line-length = 120

max-complexity = 20

ignore =
# ignore `self`, `cls` markers of flake8-annotations>=2.0
ANN101,ANN102
# ignore ANN401 for dynamically typed *args and **kwargs
ANN401
2 changes: 1 addition & 1 deletion .isort.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[settings]
## read the docs: https://pycqa.github.io/isort/docs/configuration/options.html
## keep in sync with flake8 config - in `tox.ini` file
## keep in sync with flake8 config - in `.flake8` file
known_first_party = cyclonedx
skip_gitignore = false
skip_glob =
Expand Down
4 changes: 4 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ poetry run isort .
poetry run autopep8 -ir cyclonedx/ tests/ typings/ examples/
```

This project prefers `f'strings'` over `'string'.format()`.
This project prefers `'single quotes'` over `"double quotes"`.
This project prefers `lower_snake_case` variable names.

## Documentation

This project uses [Sphinx] to generate documentation which is automatically published to [readthedocs.io].
Expand Down
1 change: 1 addition & 0 deletions cyclonedx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@

# !! version is managed by semantic_release
# do not use typing here, or else `semantic_release` might have issues finding the variable
# flake8: noqa
__version__ = "5.0.0-rc.1"
4 changes: 2 additions & 2 deletions cyclonedx/exception/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@
"""


class CycloneDxException(Exception):
class CycloneDxException(Exception): # noqa: N818
"""
Root exception thrown by this library.
"""
pass


class MissingOptionalDependencyException(CycloneDxException):
class MissingOptionalDependencyException(CycloneDxException): # noqa: N818
"""Validation did not happen, due to missing dependencies."""
pass
34 changes: 17 additions & 17 deletions cyclonedx/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import serializable
from sortedcontainers import SortedSet

from .. import __version__ as __ThisToolVersion
from .. import __version__ as __ThisToolVersion # noqa: N812
from ..exception.model import (
InvalidLocaleTypeException,
InvalidUriException,
Expand Down Expand Up @@ -57,7 +57,7 @@ def sha1sum(filename: str) -> str:
"""
h = sha1()
with open(filename, 'rb') as f:
for byte_block in iter(lambda: f.read(4096), b""):
for byte_block in iter(lambda: f.read(4096), b''):
h.update(byte_block)
return h.hexdigest()

Expand Down Expand Up @@ -102,10 +102,10 @@ class DataFlow(str, Enum):
.. note::
See the CycloneDX Schema: https://cyclonedx.org/docs/1.4/xml/#type_dataFlowType
"""
INBOUND = "inbound"
OUTBOUND = "outbound"
BI_DIRECTIONAL = "bi-directional"
UNKNOWN = "unknown"
INBOUND = 'inbound'
OUTBOUND = 'outbound'
BI_DIRECTIONAL = 'bi-directional'
UNKNOWN = 'unknown'


@serializable.serializable_class
Expand Down Expand Up @@ -325,16 +325,16 @@ def from_composite_str(composite_hash: str) -> 'HashType':
)
elif algorithm_prefix[0:3] == 'sha':
return HashType(
alg=getattr(HashAlgorithm, 'SHA_{}'.format(algorithm_prefix[3:])),
alg=getattr(HashAlgorithm, f'SHA_{algorithm_prefix[3:]}'),
content=parts[1].lower()
)
elif algorithm_prefix[0:6] == 'blake2':
return HashType(
alg=getattr(HashAlgorithm, 'BLAKE2b_{}'.format(algorithm_prefix[6:])),
alg=getattr(HashAlgorithm, f'BLAKE2b_{algorithm_prefix[6:]}'),
content=parts[1].lower()
)

raise UnknownHashTypeException(f"Unable to determine hash type from '{composite_hash}'")
raise UnknownHashTypeException(f'Unable to determine hash type from {composite_hash!r}')

def __init__(self, *, alg: HashAlgorithm, content: str) -> None:
self.alg = alg
Expand Down Expand Up @@ -542,7 +542,7 @@ def type(self, type: ExternalReferenceType) -> None:
@serializable.view(SchemaVersion1Dot3)
@serializable.view(SchemaVersion1Dot4)
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'hash')
def hashes(self) -> "SortedSet[HashType]":
def hashes(self) -> 'SortedSet[HashType]':
"""
The hashes of the external reference (if applicable).
Expand Down Expand Up @@ -779,9 +779,9 @@ def locale(self, locale: Optional[str]) -> None:
if not re.search(Note._LOCALE_TYPE_REGEX, locale):
self._locale = None
raise InvalidLocaleTypeException(
f"Supplied locale '{locale}' is not a valid locale. "
f"Locale string should be formatted as the ISO-639 (or higher) language code and optional "
f"ISO-3166 (or higher) country code. according to ISO-639 format. Examples include: 'en', 'en-US'."
f'Supplied locale {locale!r} is not a valid locale.'
' Locale string should be formatted as the ISO-639 (or higher) language code and optional'
" ISO-3166 (or higher) country code. according to ISO-639 format. Examples include: 'en', 'en-US'."
)

def __eq__(self, other: object) -> bool:
Expand Down Expand Up @@ -922,7 +922,7 @@ def name(self, name: Optional[str]) -> None:
@serializable.json_name('url')
@serializable.xml_array(serializable.XmlArraySerializationType.FLAT, 'url')
@serializable.xml_sequence(2)
def urls(self) -> "SortedSet[XsUri]":
def urls(self) -> 'SortedSet[XsUri]':
"""
Get a list of URLs of the organization. Multiple URLs are allowed.
Expand All @@ -939,7 +939,7 @@ def urls(self, urls: Iterable[XsUri]) -> None:
@serializable.json_name('contact')
@serializable.xml_array(serializable.XmlArraySerializationType.FLAT, 'contact')
@serializable.xml_sequence(3)
def contacts(self) -> "SortedSet[OrganizationalContact]":
def contacts(self) -> 'SortedSet[OrganizationalContact]':
"""
Get a list of contact person at the organization. Multiple contacts are allowed.
Expand Down Expand Up @@ -1037,7 +1037,7 @@ def version(self, version: Optional[str]) -> None:
@property
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'hash')
@serializable.xml_sequence(4)
def hashes(self) -> "SortedSet[HashType]":
def hashes(self) -> 'SortedSet[HashType]':
"""
The hashes of the tool (if applicable).
Expand All @@ -1054,7 +1054,7 @@ def hashes(self, hashes: Iterable[HashType]) -> None:
@serializable.view(SchemaVersion1Dot4)
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'reference')
@serializable.xml_sequence(5)
def external_references(self) -> "SortedSet[ExternalReference]":
def external_references(self) -> 'SortedSet[ExternalReference]':
"""
External References provide a way to document systems, sites, and information that may be relevant but which
are not included with the BOM.
Expand Down
22 changes: 11 additions & 11 deletions cyclonedx/model/bom.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def timestamp(self, timestamp: datetime) -> None:
@property
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'tool')
@serializable.xml_sequence(2)
def tools(self) -> "SortedSet[Tool]":
def tools(self) -> 'SortedSet[Tool]':
"""
Tools used to create this BOM.
Expand All @@ -110,7 +110,7 @@ def tools(self, tools: Iterable[Tool]) -> None:
@property
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'author')
@serializable.xml_sequence(3)
def authors(self) -> "SortedSet[OrganizationalContact]":
def authors(self) -> 'SortedSet[OrganizationalContact]':
"""
The person(s) who created the BOM.
Expand Down Expand Up @@ -207,7 +207,7 @@ def licenses(self, licenses: Iterable[License]) -> None:
@serializable.view(SchemaVersion1Dot4)
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'property')
@serializable.xml_sequence(8)
def properties(self) -> "SortedSet[Property]":
def properties(self) -> 'SortedSet[Property]':
"""
Provides the ability to document properties in a key/value store. This provides flexibility to include data not
officially supported in the standard without having to use additional namespaces or create extensions.
Expand Down Expand Up @@ -335,7 +335,7 @@ def metadata(self, metadata: BomMetaData) -> None:
@serializable.include_none(SchemaVersion1Dot1)
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'component')
@serializable.xml_sequence(2)
def components(self) -> "SortedSet[Component]":
def components(self) -> 'SortedSet[Component]':
"""
Get all the Components currently in this Bom.
Expand All @@ -348,7 +348,7 @@ def components(self) -> "SortedSet[Component]":
def components(self, components: Iterable[Component]) -> None:
self._components = SortedSet(components)

def get_component_by_purl(self, purl: Optional["PackageURL"]) -> Optional[Component]:
def get_component_by_purl(self, purl: Optional['PackageURL']) -> Optional[Component]:
"""
Get a Component already in the Bom by its PURL
Expand Down Expand Up @@ -394,7 +394,7 @@ def has_component(self, component: Component) -> bool:
@serializable.view(SchemaVersion1Dot4)
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'service')
@serializable.xml_sequence(3)
def services(self) -> "SortedSet[Service]":
def services(self) -> 'SortedSet[Service]':
"""
Get all the Services currently in this Bom.
Expand All @@ -414,7 +414,7 @@ def services(self, services: Iterable[Service]) -> None:
@serializable.view(SchemaVersion1Dot4)
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'reference')
@serializable.xml_sequence(4)
def external_references(self) -> "SortedSet[ExternalReference]":
def external_references(self) -> 'SortedSet[ExternalReference]':
"""
Provides the ability to document external references related to the BOM or to the project the BOM describes.
Expand All @@ -438,7 +438,7 @@ def _get_all_components(self) -> Set[Component]:

return components

def get_vulnerabilities_for_bom_ref(self, bom_ref: BomRef) -> "SortedSet[Vulnerability]":
def get_vulnerabilities_for_bom_ref(self, bom_ref: BomRef) -> 'SortedSet[Vulnerability]':
"""
Get all known Vulnerabilities that affect the supplied bom_ref.
Expand Down Expand Up @@ -469,7 +469,7 @@ def has_vulnerabilities(self) -> bool:
@serializable.view(SchemaVersion1Dot4)
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'vulnerability')
@serializable.xml_sequence(8)
def vulnerabilities(self) -> "SortedSet[Vulnerability]":
def vulnerabilities(self) -> 'SortedSet[Vulnerability]':
"""
Get all the Vulnerabilities in this BOM.
Expand Down Expand Up @@ -497,7 +497,7 @@ def version(self, version: int) -> None:
@serializable.view(SchemaVersion1Dot4)
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'dependency')
@serializable.xml_sequence(5)
def dependencies(self) -> "SortedSet[Dependency]":
def dependencies(self) -> 'SortedSet[Dependency]':
return self._dependencies

@dependencies.setter
Expand Down Expand Up @@ -564,7 +564,7 @@ def validate(self) -> bool:
f'The Component this BOM is describing {self.metadata.component.purl} has no defined dependencies '
f'which means the Dependency Graph is incomplete - you should add direct dependencies to this '
f'"root" Component to complete the Dependency Graph data.',
UserWarning
category=UserWarning, stacklevel=1
)

# 3. If a LicenseExpression is set, then there must be no other license.
Expand Down
Loading

0 comments on commit bb0f7a5

Please sign in to comment.