mirror of
https://github.com/theupdateframework/python-tuf
synced 2026-05-24 10:08:28 +00:00
Add to linting Configuration:
- adpot changes in dependabot.yml and remove --diff from ruff check. - select pydocstyle, isort, pyflakes, pep8-naming, pycodestyle for ruff and ignore some small issues / add inline comments. - adjust docstring length to 80 in various files Signed-off-by: E3E <ntanzill@purdue.edu>
This commit is contained in:
parent
cd543c9947
commit
206c9424f1
11 changed files with 87 additions and 46 deletions
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
|
|
@ -16,12 +16,10 @@ updates:
|
|||
# Python dependencies that are only pinned to ensure test reproducibility
|
||||
patterns:
|
||||
- "bandit"
|
||||
- "black"
|
||||
- "coverage"
|
||||
- "isort"
|
||||
- "mypy"
|
||||
- "pydocstyle"
|
||||
- "pylint"
|
||||
- "ruff"
|
||||
- "tox"
|
||||
dependencies:
|
||||
# Python (developer) runtime dependencies. Also any new dependencies not
|
||||
|
|
|
|||
|
|
@ -112,7 +112,9 @@ def _get_verification_result(
|
|||
)
|
||||
|
||||
def open(self, role: str) -> Metadata:
|
||||
"""Return current Metadata for role from 'storage' (or create a new one)"""
|
||||
"""Return current Metadata for role from 'storage'
|
||||
(or create a new one)
|
||||
"""
|
||||
|
||||
if role not in self.role_cache:
|
||||
signed_init = _signed_init.get(role, Targets)
|
||||
|
|
|
|||
|
|
@ -81,11 +81,21 @@ dev-mode-dirs = ["."]
|
|||
line-length=80
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = [
|
||||
"D", # pydocstyle
|
||||
"I", # isort
|
||||
"F", # pyflakes
|
||||
"N", # pep8-naming
|
||||
"E" # pycodestyle
|
||||
]
|
||||
ignore = ["D400","D415","D213","D205","D202","D107","D407","D413","D212","D104","D406","D105","D411","D401","D200","D203"]
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"tests/*" = ["D", "E"]
|
||||
"examples/*/*" = ["D"]
|
||||
"tuf/repository/__init__.py" = ["F401"]
|
||||
"tuf/api/exceptions.py" = ["F401"]
|
||||
"tuf/repository/_repository.py" = ["N818"]
|
||||
"verify_release" = ["F401", "D103", "E501"]
|
||||
|
||||
# Pylint section
|
||||
|
||||
|
|
|
|||
4
tox.ini
4
tox.ini
|
|
@ -47,12 +47,12 @@ deps =
|
|||
--editable {toxinidir}
|
||||
lint_dirs = tuf examples tests verify_release
|
||||
commands =
|
||||
ruff check --diff {[testenv:lint]lint_dirs}
|
||||
ruff check {[testenv:lint]lint_dirs}
|
||||
ruff format --diff {[testenv:lint]lint_dirs}
|
||||
pylint -j 0 --rcfile=pyproject.toml {[testenv:lint]lint_dirs}
|
||||
|
||||
mypy {[testenv:lint]lint_dirs}
|
||||
|
||||
|
||||
bandit -r tuf
|
||||
|
||||
[testenv:docs]
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#### Repository errors ####
|
||||
|
||||
# pylint: disable=unused-import
|
||||
# ruff: disable unused-inport
|
||||
from securesystemslib.exceptions import StorageError
|
||||
|
||||
|
||||
|
|
@ -23,7 +24,9 @@ class RepositoryError(Exception):
|
|||
|
||||
|
||||
class UnsignedMetadataError(RepositoryError):
|
||||
"""An error about metadata object with insufficient threshold of signatures."""
|
||||
"""An error about metadata object with insufficient threshold of
|
||||
signatures.
|
||||
"""
|
||||
|
||||
|
||||
class BadVersionNumberError(RepositoryError):
|
||||
|
|
|
|||
|
|
@ -19,9 +19,10 @@
|
|||
|
||||
The above principle means that a ``Metadata`` object represents a single
|
||||
metadata file, and has a ``signed`` attribute that is an instance of one of the
|
||||
four top level signed classes (``Root``, ``Timestamp``, ``Snapshot`` and ``Targets``).
|
||||
To make Python type annotations useful ``Metadata`` can be type constrained: e.g. the
|
||||
signed attribute of ``Metadata[Root]`` is known to be ``Root``.
|
||||
four top level signed classes (``Root``, ``Timestamp``, ``Snapshot`` and
|
||||
``Targets``). To make Python type annotations useful ``Metadata`` can be
|
||||
type constrained: e.g. the signed attribute of ``Metadata[Root]``
|
||||
is known to be ``Root``.
|
||||
|
||||
Currently Metadata API supports JSON as the file format.
|
||||
|
||||
|
|
@ -101,8 +102,8 @@ class Metadata(Generic[T]):
|
|||
|
||||
Using a type constraint is not required but not doing so means T is not a
|
||||
specific type so static typing cannot happen. Note that the type constraint
|
||||
``[Root]`` is not validated at runtime (as pure annotations are not available
|
||||
then).
|
||||
``[Root]`` is not validated at runtime (as pure annotations are not
|
||||
available then).
|
||||
|
||||
New Metadata instances can be created from scratch with::
|
||||
|
||||
|
|
@ -227,6 +228,7 @@ def from_file(
|
|||
storage_backend: Object that implements
|
||||
``securesystemslib.storage.StorageBackendInterface``.
|
||||
Default is ``FilesystemBackend`` (i.e. a local file).
|
||||
|
||||
Raises:
|
||||
StorageError: The file cannot be read.
|
||||
tuf.api.serialization.DeserializationError:
|
||||
|
|
@ -357,9 +359,10 @@ def sign(
|
|||
"""Create signature over ``signed`` and assigns it to ``signatures``.
|
||||
|
||||
Args:
|
||||
signer: A ``securesystemslib.signer.Signer`` object that provides a private
|
||||
key and signing implementation to generate the signature. A standard
|
||||
implementation is available in ``securesystemslib.signer.SSlibSigner``.
|
||||
signer: A ``securesystemslib.signer.Signer`` object that provides a
|
||||
private key and signing implementation to generate the signature. A
|
||||
standard implementation is available in
|
||||
``securesystemslib.signer.SSlibSigner``.
|
||||
append: ``True`` if the signature should be appended to
|
||||
the list of signatures or replace any existing signatures. The
|
||||
default behavior is to replace signatures.
|
||||
|
|
@ -403,7 +406,8 @@ def verify_delegate(
|
|||
threshold of keys for ``delegated_role``.
|
||||
|
||||
.. deprecated:: 3.1.0
|
||||
Please use ``Root.verify_delegate()`` or ``Targets.verify_delegate()``.
|
||||
Please use ``Root.verify_delegate()`` or
|
||||
``Targets.verify_delegate()``.
|
||||
"""
|
||||
|
||||
if self.signed.type not in ["root", "targets"]:
|
||||
|
|
@ -522,7 +526,9 @@ def to_dict(self) -> Dict[str, Any]:
|
|||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def from_dict(cls, signed_dict: Dict[str, Any]) -> "Signed":
|
||||
"""Deserialization helper, creates object from json/dict representation."""
|
||||
"""Deserialization helper, creates object from json/dict
|
||||
representation.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
|
|
@ -533,7 +539,8 @@ def _common_fields_from_dict(
|
|||
representation, and returns an ordered list to be passed as leading
|
||||
positional arguments to a subclass constructor.
|
||||
|
||||
See ``{Root, Timestamp, Snapshot, Targets}.from_dict`` methods for usage.
|
||||
See ``{Root, Timestamp, Snapshot, Targets}.from_dict``
|
||||
methods for usage.
|
||||
|
||||
"""
|
||||
_type = signed_dict.pop("_type")
|
||||
|
|
@ -551,7 +558,8 @@ def _common_fields_from_dict(
|
|||
return version, spec_version, expires
|
||||
|
||||
def _common_fields_to_dict(self) -> Dict[str, Any]:
|
||||
"""Return a dict representation of common fields of ``Signed`` instances.
|
||||
"""Return a dict representation of common fields of
|
||||
``Signed`` instances.
|
||||
|
||||
See ``{Root, Timestamp, Snapshot, Targets}.to_dict`` methods for usage.
|
||||
|
||||
|
|
@ -700,19 +708,27 @@ def __bool__(self) -> bool:
|
|||
|
||||
@property
|
||||
def verified(self) -> bool:
|
||||
"""True if threshold of signatures is met in both underlying VerificationResults."""
|
||||
"""True if threshold of signatures is met in both underlying
|
||||
VerificationResults.
|
||||
"""
|
||||
return self.first.verified and self.second.verified
|
||||
|
||||
@property
|
||||
def signed(self) -> Dict[str, Key]:
|
||||
"""Dictionary of all signing keys that have signed, from both VerificationResults"""
|
||||
# return a union of all signed (in python<3.9 this requires dict unpacking)
|
||||
"""Dictionary of all signing keys that have signed, from both
|
||||
VerificationResults.
|
||||
return a union of all signed (in python<3.9 this requires
|
||||
dict unpacking)
|
||||
"""
|
||||
return {**self.first.signed, **self.second.signed}
|
||||
|
||||
@property
|
||||
def unsigned(self) -> Dict[str, Key]:
|
||||
"""Dictionary of all signing keys that have not signed, from both VerificationResults"""
|
||||
# return a union of all unsigned (in python<3.9 this requires dict unpacking)
|
||||
"""Dictionary of all signing keys that have not signed, from both
|
||||
VerificationResults.
|
||||
return a union of all unsigned (in python<3.9 this requires
|
||||
dict unpacking)
|
||||
"""
|
||||
return {**self.first.unsigned, **self.second.unsigned}
|
||||
|
||||
|
||||
|
|
@ -828,8 +844,8 @@ class Root(Signed, _DelegatorMixin):
|
|||
roles: Dictionary of role names to Roles. Defines which keys are
|
||||
required to sign the metadata for a specific role. Default is
|
||||
a dictionary of top level roles without keys and threshold of 1.
|
||||
consistent_snapshot: ``True`` if repository supports consistent snapshots.
|
||||
Default is True.
|
||||
consistent_snapshot: ``True`` if repository supports consistent
|
||||
snapshots. Default is True.
|
||||
unrecognized_fields: Dictionary of all attributes that are not managed
|
||||
by TUF Metadata API
|
||||
|
||||
|
|
@ -1191,6 +1207,7 @@ def from_data(
|
|||
data: Metadata bytes that the metafile represents.
|
||||
hash_algorithms: Hash algorithms to create the hashes with. If not
|
||||
specified, the securesystemslib default hash algorithm is used.
|
||||
|
||||
Raises:
|
||||
ValueError: The hash algorithms list contains an unsupported
|
||||
algorithm.
|
||||
|
|
@ -1234,7 +1251,8 @@ class Timestamp(Signed):
|
|||
"""A container for the signed part of timestamp metadata.
|
||||
|
||||
TUF file format uses a dictionary to contain the snapshot information:
|
||||
this is not the case with ``Timestamp.snapshot_meta`` which is a ``MetaFile``.
|
||||
this is not the case with ``Timestamp.snapshot_meta`` which is a
|
||||
``MetaFile``.
|
||||
|
||||
*All parameters named below are not just constructor arguments but also
|
||||
instance attributes.*
|
||||
|
|
@ -1366,12 +1384,13 @@ class DelegatedRole(Role):
|
|||
|
||||
A delegation can happen in two ways:
|
||||
|
||||
- ``paths`` is set: delegates targets matching any path pattern in ``paths``
|
||||
- ``path_hash_prefixes`` is set: delegates targets whose target path hash
|
||||
starts with any of the prefixes in ``path_hash_prefixes``
|
||||
- ``paths`` is set: delegates targets matching any path pattern in
|
||||
``paths``
|
||||
- ``path_hash_prefixes`` is set: delegates targets whose target path
|
||||
hash starts with any of the prefixes in ``path_hash_prefixes``
|
||||
|
||||
``paths`` and ``path_hash_prefixes`` are mutually exclusive: both cannot be
|
||||
set, at least one of them must be set.
|
||||
``paths`` and ``path_hash_prefixes`` are mutually exclusive:
|
||||
both cannot be set, at least one of them must be set.
|
||||
|
||||
*All parameters named below are not just constructor arguments but also
|
||||
instance attributes.*
|
||||
|
|
@ -1491,10 +1510,10 @@ def is_delegated_path(self, target_filepath: str) -> bool:
|
|||
"""Determine whether the given ``target_filepath`` is in one of
|
||||
the paths that ``DelegatedRole`` is trusted to provide.
|
||||
|
||||
The ``target_filepath`` and the ``DelegatedRole`` paths are expected to be
|
||||
in their canonical forms, so e.g. "a/b" instead of "a//b" . Only "/" is
|
||||
supported as target path separator. Leading separators are not handled
|
||||
as special cases (see `TUF specification on targetpath
|
||||
The ``target_filepath`` and the ``DelegatedRole`` paths are expected to
|
||||
be in their canonical forms, so e.g. "a/b" instead of "a//b" . Only "/"
|
||||
is supported as target path separator. Leading separators are not
|
||||
handled as special cases (see `TUF specification on targetpath
|
||||
<https://theupdateframework.github.io/specification/latest/#targetpath>`_).
|
||||
|
||||
Args:
|
||||
|
|
@ -1613,7 +1632,8 @@ def to_dict(self) -> Dict[str, Any]:
|
|||
}
|
||||
|
||||
def get_role_for_target(self, target_filepath: str) -> str:
|
||||
"""Calculate the name of the delegated role responsible for ``target_filepath``.
|
||||
"""Calculate the name of the delegated role responsible for
|
||||
``target_filepath``.
|
||||
|
||||
The target at path ``target_filepath`` is assigned to a bin by casting
|
||||
the left-most ``bit_length`` of bits of the file path hash digest to
|
||||
|
|
@ -1897,6 +1917,7 @@ def from_file(
|
|||
local_path: Local path to target file content.
|
||||
hash_algorithms: Hash algorithms to calculate hashes with. If not
|
||||
specified the securesystemslib default hash algorithm is used.
|
||||
|
||||
Raises:
|
||||
FileNotFoundError: The file doesn't exist.
|
||||
ValueError: The hash algorithms list contains an unsupported
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
# Copyright 2021, New York University and the TUF contributors
|
||||
# SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
|
||||
"""Provides an implementation of ``FetcherInterface`` using the Requests HTTP library.
|
||||
"""Provides an implementation of ``FetcherInterface`` using the Requests HTTP
|
||||
library.
|
||||
"""
|
||||
|
||||
# requests_fetcher is public but comes from _internal for now (because
|
||||
|
|
@ -117,7 +118,8 @@ def _chunks(self, response: "requests.Response") -> Iterator[bytes]:
|
|||
response.close()
|
||||
|
||||
def _get_session(self, url: str) -> requests.Session:
|
||||
"""Return a different customized requests.Session per schema+hostname combination.
|
||||
"""Return a different customized requests.Session per schema+hostname
|
||||
combination.
|
||||
|
||||
Raises:
|
||||
exceptions.DownloadError: When there is a problem parsing the url.
|
||||
|
|
|
|||
|
|
@ -73,9 +73,10 @@
|
|||
class TrustedMetadataSet(abc.Mapping):
|
||||
"""Internal class to keep track of trusted metadata in ``Updater``.
|
||||
|
||||
``TrustedMetadataSet`` ensures that the collection of metadata in it is valid
|
||||
and trusted through the whole client update workflow. It provides easy ways
|
||||
to update the metadata with the caller making decisions on what is updated.
|
||||
``TrustedMetadataSet`` ensures that the collection of metadata in it is
|
||||
valid and trusted through the whole client update workflow. It provides
|
||||
easy ways to update the metadata with the caller making decisions on
|
||||
what is updated.
|
||||
"""
|
||||
|
||||
def __init__(self, root_data: bytes):
|
||||
|
|
@ -107,7 +108,9 @@ def __len__(self) -> int:
|
|||
return len(self._trusted_set)
|
||||
|
||||
def __iter__(self) -> Iterator[Metadata]:
|
||||
"""Return iterator over ``Metadata`` objects in ``TrustedMetadataSet``."""
|
||||
"""Return iterator over ``Metadata`` objects in
|
||||
``TrustedMetadataSet``.
|
||||
"""
|
||||
return iter(self._trusted_set.values())
|
||||
|
||||
# Helper properties for top level metadata
|
||||
|
|
|
|||
|
|
@ -10,4 +10,5 @@
|
|||
The repository module is not considered part of the stable python-tuf API yet.
|
||||
"""
|
||||
|
||||
# ruff: disable unused-inport
|
||||
from tuf.repository._repository import AbortEdit, Repository
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# ruff: ignore N818 `Exception name should have Error suffix`
|
||||
class AbortEdit(Exception):
|
||||
"""Raise to exit the edit() contextmanager without saving changes"""
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ from tempfile import TemporaryDirectory
|
|||
from typing import Optional
|
||||
|
||||
try:
|
||||
import build as _ # type: ignore
|
||||
import build as _
|
||||
import requests
|
||||
except ImportError:
|
||||
print("Error: verify_release requires modules 'requests' and 'build':")
|
||||
|
|
|
|||
Loading…
Reference in a new issue