From 5420f9baaf10af9eb7d436715d240c65e60f80fa Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 28 Oct 2025 07:21:11 +0100 Subject: [PATCH] Cleanup with ruff check (#963) * Implement improvements suggested by ruff check. * Add ruff check to CI. * Add changelog fragment. --- antsibull-nox.toml | 2 + changelogs/fragments/963-ruff.yml | 2 + plugins/module_utils/_acme/acme.py | 9 +--- plugins/module_utils/_acme/certificates.py | 2 +- plugins/module_utils/_acme/challenges.py | 10 ++--- plugins/module_utils/_acme/orders.py | 8 ++-- .../_crypto/cryptography_support.py | 15 +++---- .../_crypto/module_backends/certificate.py | 21 +++++----- .../module_backends/certificate_info.py | 18 ++++---- .../module_backends/certificate_ownca.py | 3 -- .../module_backends/certificate_selfsigned.py | 2 +- .../_crypto/module_backends/crl_info.py | 5 +-- .../_crypto/module_backends/csr.py | 32 +++++++------- .../_crypto/module_backends/csr_info.py | 3 +- .../_crypto/module_backends/privatekey.py | 42 ++++++++++--------- .../module_backends/privatekey_info.py | 6 +-- .../_crypto/module_backends/publickey_info.py | 2 +- plugins/module_utils/_cryptography_dep.py | 4 +- .../module_utils/_openssh/backends/common.py | 14 +++---- .../_openssh/backends/keypair_backend.py | 4 -- plugins/module_utils/_openssh/certificate.py | 4 +- plugins/module_utils/_openssh/cryptography.py | 12 +++--- plugins/module_utils/_openssh/utils.py | 2 +- plugins/modules/acme_account_info.py | 18 +++++--- plugins/modules/acme_certificate.py | 13 +++--- .../acme_certificate_order_finalize.py | 5 +-- plugins/modules/certificate_complete_chain.py | 20 ++++----- plugins/modules/crypto_info.py | 12 +++--- plugins/modules/get_certificate.py | 5 +-- plugins/modules/luks_device.py | 4 +- plugins/modules/openssl_dhparam.py | 2 +- plugins/modules/openssl_pkcs12.py | 12 +++--- plugins/modules/openssl_publickey.py | 6 +-- plugins/modules/openssl_signature.py | 11 ++--- plugins/modules/openssl_signature_info.py | 13 ++---- plugins/modules/x509_certificate_convert.py | 6 +-- plugins/modules/x509_crl.py | 11 ++--- ruff.toml | 31 ++++++++++++++ tests/unit/plugins/module_utils/test__time.py | 6 +-- 39 files changed, 198 insertions(+), 199 deletions(-) create mode 100644 changelogs/fragments/963-ruff.yml create mode 100644 ruff.toml diff --git a/antsibull-nox.toml b/antsibull-nox.toml index a0fab186..4b8ab380 100644 --- a/antsibull-nox.toml +++ b/antsibull-nox.toml @@ -16,6 +16,8 @@ stable_branches = [ "stable-*" ] run_isort = true isort_config = ".isort.cfg" run_black = true +run_ruff_check = true +ruff_check_config = "ruff.toml" run_flake8 = true flake8_config = ".flake8" run_pylint = true diff --git a/changelogs/fragments/963-ruff.yml b/changelogs/fragments/963-ruff.yml new file mode 100644 index 00000000..b59d54c2 --- /dev/null +++ b/changelogs/fragments/963-ruff.yml @@ -0,0 +1,2 @@ +bugfixes: + - "Smaller code cleanup (https://github.com/ansible-collections/community.crypto/pull/963)." diff --git a/plugins/module_utils/_acme/acme.py b/plugins/module_utils/_acme/acme.py index 289a38fe..2aa37c8a 100644 --- a/plugins/module_utils/_acme/acme.py +++ b/plugins/module_utils/_acme/acme.py @@ -56,9 +56,6 @@ if t.TYPE_CHECKING: from ansible.module_utils.basic import AnsibleModule # pragma: no cover - from ansible_collections.community.crypto.plugins.module_utils._acme.account import ( # pragma: no cover - ACMEAccount, - ) from ansible_collections.community.crypto.plugins.module_utils._acme.backends import ( # pragma: no cover CertificateInformation, CryptoBackend, @@ -132,12 +129,10 @@ def _is_failed( ) -> bool: if info["status"] < 200 or info["status"] >= 400: return True - if ( + return bool( expected_status_codes is not None and info["status"] not in expected_status_codes - ): - return True - return False + ) class ACMEDirectory: diff --git a/plugins/module_utils/_acme/certificates.py b/plugins/module_utils/_acme/certificates.py index 196fcacf..b7ea95b0 100644 --- a/plugins/module_utils/_acme/certificates.py +++ b/plugins/module_utils/_acme/certificates.py @@ -46,7 +46,7 @@ class CertificateChain: @classmethod def download( - cls: t.Type[_CertificateChain], *, client: ACMEClient, url: str + cls: type[_CertificateChain], *, client: ACMEClient, url: str ) -> _CertificateChain: content, info = client.get_request( url, diff --git a/plugins/module_utils/_acme/challenges.py b/plugins/module_utils/_acme/challenges.py index 2b0f7c8b..b2d312a9 100644 --- a/plugins/module_utils/_acme/challenges.py +++ b/plugins/module_utils/_acme/challenges.py @@ -82,7 +82,7 @@ class Challenge: @classmethod def from_json( - cls: t.Type[_Challenge], + cls: type[_Challenge], *, client: ACMEClient, data: dict[str, t.Any], @@ -188,7 +188,7 @@ class Authorization: @classmethod def from_json( - cls: t.Type[_Authorization], + cls: type[_Authorization], *, client: ACMEClient, data: dict[str, t.Any], @@ -200,7 +200,7 @@ class Authorization: @classmethod def from_url( - cls: t.Type[_Authorization], *, client: ACMEClient, url: str + cls: type[_Authorization], *, client: ACMEClient, url: str ) -> _Authorization: result = cls(url=url) result.refresh(client=client) @@ -208,7 +208,7 @@ class Authorization: @classmethod def create( - cls: t.Type[_Authorization], + cls: type[_Authorization], *, client: ACMEClient, identifier_type: str, @@ -384,7 +384,7 @@ class Authorization: @classmethod def deactivate_url( - cls: t.Type[_Authorization], *, client: ACMEClient, url: str + cls: type[_Authorization], *, client: ACMEClient, url: str ) -> _Authorization: """ Deactivates this authorization. diff --git a/plugins/module_utils/_acme/orders.py b/plugins/module_utils/_acme/orders.py index 554b7ce6..e6c68135 100644 --- a/plugins/module_utils/_acme/orders.py +++ b/plugins/module_utils/_acme/orders.py @@ -63,21 +63,21 @@ class Order: @classmethod def from_json( - cls: t.Type[_Order], *, client: ACMEClient, data: dict[str, t.Any], url: str + cls: type[_Order], *, client: ACMEClient, data: dict[str, t.Any], url: str ) -> _Order: result = cls(url=url) result._setup(client=client, data=data) return result @classmethod - def from_url(cls: t.Type[_Order], *, client: ACMEClient, url: str) -> _Order: + def from_url(cls: type[_Order], *, client: ACMEClient, url: str) -> _Order: result = cls(url=url) result.refresh(client=client) return result @classmethod def create( - cls: t.Type[_Order], + cls: type[_Order], *, client: ACMEClient, identifiers: list[tuple[str, str]], @@ -117,7 +117,7 @@ class Order: @classmethod def create_with_error_handling( - cls: t.Type[_Order], + cls: type[_Order], *, client: ACMEClient, identifiers: list[tuple[str, str]], diff --git a/plugins/module_utils/_crypto/cryptography_support.py b/plugins/module_utils/_crypto/cryptography_support.py index 1af3bcfb..c27c2964 100644 --- a/plugins/module_utils/_crypto/cryptography_support.py +++ b/plugins/module_utils/_crypto/cryptography_support.py @@ -114,19 +114,16 @@ if t.TYPE_CHECKING: PrivateKeyTypes, PublicKeyTypes, ) - from cryptography.hazmat.primitives.serialization.pkcs12 import ( # pragma: no cover - PKCS12KeyAndCertificates, - ) - CertificatePrivateKeyTypes = t.Union[ + CertificatePrivateKeyTypes = t.Union[ # noqa: UP007 CertificateIssuerPrivateKeyTypes, cryptography.hazmat.primitives.asymmetric.x25519.X25519PrivateKey, cryptography.hazmat.primitives.asymmetric.x448.X448PrivateKey, ] # pragma: no cover - PublicKeyTypesWOEdwards = t.Union[ # pylint: disable=invalid-name + PublicKeyTypesWOEdwards = t.Union[ # noqa: UP007 # pylint: disable=invalid-name DHPublicKey, DSAPublicKey, EllipticCurvePublicKey, RSAPublicKey ] # pragma: no cover - PrivateKeyTypesWOEdwards = t.Union[ # pylint: disable=invalid-name + PrivateKeyTypesWOEdwards = t.Union[ # noqa: UP007 # pylint: disable=invalid-name DHPrivateKey, DSAPrivateKey, EllipticCurvePrivateKey, RSAPrivateKey ] # pragma: no cover else: @@ -727,9 +724,9 @@ def cryptography_key_needs_digest_for_signing( key, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey ): return False - if isinstance(key, cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey): - return False - return True + return not isinstance( + key, cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey + ) def _compare_public_keys( diff --git a/plugins/module_utils/_crypto/module_backends/certificate.py b/plugins/module_utils/_crypto/module_backends/certificate.py index 1e8d9138..f0068742 100644 --- a/plugins/module_utils/_crypto/module_backends/certificate.py +++ b/plugins/module_utils/_crypto/module_backends/certificate.py @@ -41,9 +41,6 @@ if t.TYPE_CHECKING: import datetime # pragma: no cover from ansible.module_utils.basic import AnsibleModule # pragma: no cover - from cryptography.hazmat.primitives.asymmetric.types import ( # pragma: no cover - CertificateIssuerPrivateKeyTypes, - ) from ansible_collections.community.crypto.plugins.module_utils._crypto.cryptography_support import ( # pragma: no cover CertificatePrivateKeyTypes, @@ -324,15 +321,19 @@ class CertificateBackend(metaclass=abc.ABCMeta): return True # Check not before - if not_before is not None and not self.ignore_timestamps: - if get_not_valid_before(self.existing_certificate) != not_before: - return True + if ( + not_before is not None + and not self.ignore_timestamps + and get_not_valid_before(self.existing_certificate) != not_before + ): + return True # Check not after - if not_after is not None and not self.ignore_timestamps: - if get_not_valid_after(self.existing_certificate) != not_after: - return True - return False + return bool( + not_after is not None + and not self.ignore_timestamps + and get_not_valid_after(self.existing_certificate) != not_after + ) def dump(self, *, include_certificate: bool) -> dict[str, t.Any]: """Serialize the object into a dictionary.""" diff --git a/plugins/module_utils/_crypto/module_backends/certificate_info.py b/plugins/module_utils/_crypto/module_backends/certificate_info.py index 31bb082e..f3debf14 100644 --- a/plugins/module_utils/_crypto/module_backends/certificate_info.py +++ b/plugins/module_utils/_crypto/module_backends/certificate_info.py @@ -46,9 +46,6 @@ if t.TYPE_CHECKING: PublicKeyTypes, # pragma: no cover ) - from ansible_collections.community.crypto.plugins.module_utils._argspec import ( # pragma: no cover - ArgumentSpec, - ) from ansible_collections.community.crypto.plugins.plugin_utils._action_module import ( # pragma: no cover AnsibleActionModule, ) @@ -56,7 +53,7 @@ if t.TYPE_CHECKING: FilterModuleMock, ) - GeneralAnsibleModule = t.Union[ + GeneralAnsibleModule = t.Union[ # noqa: UP007 AnsibleModule, AnsibleActionModule, FilterModuleMock ] # pragma: no cover @@ -270,9 +267,11 @@ class CertificateInfoRetrieval: x509.AuthorityInformationAccess ) for desc in ext.value: - if desc.access_method == x509.oid.AuthorityInformationAccessOID.OCSP: - if isinstance(desc.access_location, x509.UniformResourceIdentifier): - return desc.access_location.value + if ( + desc.access_method == x509.oid.AuthorityInformationAccessOID.OCSP + and isinstance(desc.access_location, x509.UniformResourceIdentifier) + ): + return desc.access_location.value except x509.ExtensionNotFound: pass return None @@ -286,9 +285,8 @@ class CertificateInfoRetrieval: if ( desc.access_method == x509.oid.AuthorityInformationAccessOID.CA_ISSUERS - ): - if isinstance(desc.access_location, x509.UniformResourceIdentifier): - return desc.access_location.value + ) and isinstance(desc.access_location, x509.UniformResourceIdentifier): + return desc.access_location.value except x509.ExtensionNotFound: pass return None diff --git a/plugins/module_utils/_crypto/module_backends/certificate_ownca.py b/plugins/module_utils/_crypto/module_backends/certificate_ownca.py index 89239fc2..9c4ecb6c 100644 --- a/plugins/module_utils/_crypto/module_backends/certificate_ownca.py +++ b/plugins/module_utils/_crypto/module_backends/certificate_ownca.py @@ -45,9 +45,6 @@ if t.TYPE_CHECKING: import datetime # pragma: no cover from ansible.module_utils.basic import AnsibleModule # pragma: no cover - from cryptography.hazmat.primitives.asymmetric.types import ( # pragma: no cover - CertificateIssuerPrivateKeyTypes, - ) from ansible_collections.community.crypto.plugins.module_utils._argspec import ( # pragma: no cover ArgumentSpec, diff --git a/plugins/module_utils/_crypto/module_backends/certificate_selfsigned.py b/plugins/module_utils/_crypto/module_backends/certificate_selfsigned.py index 06b560c2..20f7e016 100644 --- a/plugins/module_utils/_crypto/module_backends/certificate_selfsigned.py +++ b/plugins/module_utils/_crypto/module_backends/certificate_selfsigned.py @@ -181,7 +181,7 @@ class SelfSignedCertificateBackendCryptography(CertificateBackend): assert self.existing_certificate is not None # Check whether certificate is signed by private key - if not cryptography_verify_certificate_signature( + if not cryptography_verify_certificate_signature( # noqa: SIM103 certificate=self.existing_certificate, signer_public_key=self.privatekey.public_key(), ): diff --git a/plugins/module_utils/_crypto/module_backends/crl_info.py b/plugins/module_utils/_crypto/module_backends/crl_info.py index d36576f8..44b80684 100644 --- a/plugins/module_utils/_crypto/module_backends/crl_info.py +++ b/plugins/module_utils/_crypto/module_backends/crl_info.py @@ -29,9 +29,6 @@ from ansible_collections.community.crypto.plugins.module_utils._cryptography_dep if t.TYPE_CHECKING: from ansible.module_utils.basic import AnsibleModule # pragma: no cover - from cryptography.hazmat.primitives.asymmetric.types import ( # pragma: no cover - PrivateKeyTypes, - ) from ansible_collections.community.crypto.plugins.plugin_utils._action_module import ( # pragma: no cover AnsibleActionModule, @@ -40,7 +37,7 @@ if t.TYPE_CHECKING: FilterModuleMock, ) - GeneralAnsibleModule = t.Union[ + GeneralAnsibleModule = t.Union[ # noqa: UP007 AnsibleModule, AnsibleActionModule, FilterModuleMock ] # pragma: no cover diff --git a/plugins/module_utils/_crypto/module_backends/csr.py b/plugins/module_utils/_crypto/module_backends/csr.py index f9636a05..e5b1963d 100644 --- a/plugins/module_utils/_crypto/module_backends/csr.py +++ b/plugins/module_utils/_crypto/module_backends/csr.py @@ -52,11 +52,6 @@ if t.TYPE_CHECKING: from ansible.module_utils.basic import AnsibleModule # pragma: no cover from cryptography.hazmat.primitives.asymmetric.types import ( # pragma: no cover CertificateIssuerPrivateKeyTypes, - PrivateKeyTypes, - ) - - from ansible_collections.community.crypto.plugins.module_utils._crypto.cryptography_support import ( # pragma: no cover - CertificatePrivateKeyTypes, ) _ET = t.TypeVar("_ET", bound="cryptography.x509.ExtensionType") # pragma: no cover @@ -533,10 +528,11 @@ class CertificateSigningRequestBackend: ) if set(altnames) != set(current_altnames): return False - if altnames and current_altnames_ext: - if current_altnames_ext.critical != self.subject_alt_name_critical: - return False - return True + return not ( + altnames + and current_altnames_ext + and current_altnames_ext.critical != self.subject_alt_name_critical + ) def _check_key_usage(extensions: cryptography.x509.Extensions) -> bool: current_keyusage_ext = _find_extension( @@ -578,10 +574,11 @@ class CertificateSigningRequestBackend: ) if set(current_usages) != set(usages): return False - if usages and current_usages_ext: - if current_usages_ext.critical != self.extended_key_usage_critical: - return False - return True + return not ( + usages + and current_usages_ext + and current_usages_ext.critical != self.extended_key_usage_critical + ) def _check_basic_constraints(extensions: cryptography.x509.Extensions) -> bool: bc_ext = _find_extension(extensions, cryptography.x509.BasicConstraints) @@ -652,10 +649,11 @@ class CertificateSigningRequestBackend: current_nc_excl ): return False - if (nc_perm or nc_excl) and current_nc_ext: - if current_nc_ext.critical != self.name_constraints_critical: - return False - return True + return not ( + (nc_perm or nc_excl) + and current_nc_ext + and current_nc_ext.critical != self.name_constraints_critical + ) def _check_subject_key_identifier( extensions: cryptography.x509.Extensions, diff --git a/plugins/module_utils/_crypto/module_backends/csr_info.py b/plugins/module_utils/_crypto/module_backends/csr_info.py index d7dd8948..521e03a5 100644 --- a/plugins/module_utils/_crypto/module_backends/csr_info.py +++ b/plugins/module_utils/_crypto/module_backends/csr_info.py @@ -35,7 +35,6 @@ if t.TYPE_CHECKING: from ansible.module_utils.basic import AnsibleModule # pragma: no cover from cryptography.hazmat.primitives.asymmetric.types import ( # pragma: no cover CertificatePublicKeyTypes, - PrivateKeyTypes, ) from ansible_collections.community.crypto.plugins.plugin_utils._action_module import ( # pragma: no cover @@ -45,7 +44,7 @@ if t.TYPE_CHECKING: FilterModuleMock, ) - GeneralAnsibleModule = t.Union[ + GeneralAnsibleModule = t.Union[ # noqa: UP007 AnsibleModule, AnsibleActionModule, FilterModuleMock ] # pragma: no cover diff --git a/plugins/module_utils/_crypto/module_backends/privatekey.py b/plugins/module_utils/_crypto/module_backends/privatekey.py index 112baacc..bdbbf944 100644 --- a/plugins/module_utils/_crypto/module_backends/privatekey.py +++ b/plugins/module_utils/_crypto/module_backends/privatekey.py @@ -47,7 +47,7 @@ if t.TYPE_CHECKING: AnsibleActionModule, ) - GeneralAnsibleModule = t.Union[ + GeneralAnsibleModule = t.Union[ # noqa: UP007 AnsibleModule, AnsibleActionModule ] # pragma: no cover @@ -495,26 +495,28 @@ class PrivateKeyBackend: " set to `full_idempotence` or `always`, or with `force=true`." ) self._ensure_existing_private_key_loaded() - if self.regenerate != "never": - if not self._check_size_and_type(): - if self.regenerate in ("partial_idempotence", "full_idempotence"): - return True - self.module.fail_json( - msg="Key has wrong type and/or size." - " Will not proceed. To force regeneration, call the module with `generate`" - " set to `partial_idempotence`, `full_idempotence` or `always`, or with `force=true`." - ) + if self.regenerate != "never" and not self._check_size_and_type(): + if self.regenerate in ("partial_idempotence", "full_idempotence"): + return True + self.module.fail_json( + msg="Key has wrong type and/or size." + " Will not proceed. To force regeneration, call the module with `generate`" + " set to `partial_idempotence`, `full_idempotence` or `always`, or with `force=true`." + ) # During generation step, regenerate if format does not match and format_mismatch == 'regenerate' - if self.format_mismatch == "regenerate" and self.regenerate != "never": - if not self._check_format(): - if self.regenerate in ("partial_idempotence", "full_idempotence"): - return True - self.module.fail_json( - msg="Key has wrong format." - " Will not proceed. To force regeneration, call the module with `generate`" - " set to `partial_idempotence`, `full_idempotence` or `always`, or with `force=true`." - " To convert the key, set `format_mismatch` to `convert`." - ) + if ( + self.format_mismatch == "regenerate" + and self.regenerate != "never" + and not self._check_format() + ): + if self.regenerate in ("partial_idempotence", "full_idempotence"): + return True + self.module.fail_json( + msg="Key has wrong format." + " Will not proceed. To force regeneration, call the module with `generate`" + " set to `partial_idempotence`, `full_idempotence` or `always`, or with `force=true`." + " To convert the key, set `format_mismatch` to `convert`." + ) return False def needs_conversion(self) -> bool: diff --git a/plugins/module_utils/_crypto/module_backends/privatekey_info.py b/plugins/module_utils/_crypto/module_backends/privatekey_info.py index 88b7afe9..6577fedb 100644 --- a/plugins/module_utils/_crypto/module_backends/privatekey_info.py +++ b/plugins/module_utils/_crypto/module_backends/privatekey_info.py @@ -47,7 +47,7 @@ if t.TYPE_CHECKING: FilterModuleMock, ) - GeneralAnsibleModule = t.Union[ + GeneralAnsibleModule = t.Union[ # noqa: UP007 AnsibleModule, AnsibleActionModule, FilterModuleMock ] # pragma: no cover @@ -122,9 +122,7 @@ def _check_dsa_consistency( if binary_exp_mod(g, x, m=p) != y: return False # Check (quickly) whether p or q are not primes - if quick_is_not_prime(q) or quick_is_not_prime(p): - return False - return True + return not (quick_is_not_prime(q) or quick_is_not_prime(p)) def _is_cryptography_key_consistent( diff --git a/plugins/module_utils/_crypto/module_backends/publickey_info.py b/plugins/module_utils/_crypto/module_backends/publickey_info.py index c9e48d33..8929cda4 100644 --- a/plugins/module_utils/_crypto/module_backends/publickey_info.py +++ b/plugins/module_utils/_crypto/module_backends/publickey_info.py @@ -35,7 +35,7 @@ if t.TYPE_CHECKING: FilterModuleMock, ) - GeneralAnsibleModule = t.Union[ + GeneralAnsibleModule = t.Union[ # noqa: UP007 AnsibleModule, AnsibleActionModule, FilterModuleMock ] # pragma: no cover diff --git a/plugins/module_utils/_cryptography_dep.py b/plugins/module_utils/_cryptography_dep.py index 35c1d5f3..c410e042 100644 --- a/plugins/module_utils/_cryptography_dep.py +++ b/plugins/module_utils/_cryptography_dep.py @@ -33,7 +33,7 @@ if t.TYPE_CHECKING: FilterModuleMock, ) - GeneralAnsibleModule = t.Union[ + GeneralAnsibleModule = t.Union[ # noqa: UP007 AnsibleModule, AnsibleActionModule, FilterModuleMock ] # pragma: no cover @@ -69,7 +69,7 @@ def assert_required_cryptography_version( msg=missing_required_lib(f"cryptography >= {minimum_cryptography_version}"), exception=_CRYPTOGRAPHY_IMP_ERR, ) - if CRYPTOGRAPHY_VERSION < LooseVersion(minimum_cryptography_version): + if LooseVersion(minimum_cryptography_version) > CRYPTOGRAPHY_VERSION: module.fail_json( msg=( f"Cannot detect the required Python library cryptography (>= {minimum_cryptography_version})." diff --git a/plugins/module_utils/_openssh/backends/common.py b/plugins/module_utils/_openssh/backends/common.py index d6543741..83dba6ce 100644 --- a/plugins/module_utils/_openssh/backends/common.py +++ b/plugins/module_utils/_openssh/backends/common.py @@ -21,10 +21,6 @@ from ansible_collections.community.crypto.plugins.module_utils._openssh.utils im if t.TYPE_CHECKING: from ansible.module_utils.basic import AnsibleModule # pragma: no cover - from cryptography.hazmat.primitives.asymmetric.types import ( # pragma: no cover - CertificateIssuerPrivateKeyTypes, - PrivateKeyTypes, - ) from ansible_collections.community.crypto.plugins.module_utils._openssh.certificate import ( # pragma: no cover OpensshCertificateTimeParameters, @@ -96,7 +92,7 @@ def _restore_all_on_failure( os.path.abspath(backup), os.path.abspath(destination) ) raise - for destination, backup in backups: + for dummy_destination, backup in backups: self.module.add_cleanup_file(backup) return backup_and_restore @@ -373,7 +369,9 @@ class PrivateKey: return self._format @classmethod - def from_string(cls: t.Type[_PrivateKey], string: str) -> _PrivateKey: + def from_string( + cls: t.Type[_PrivateKey], string: str # noqa: UP006 + ) -> _PrivateKey: properties = string.split() return cls( @@ -439,7 +437,7 @@ class PublicKey: return self._type_string @classmethod - def from_string(cls: t.Type[_PublicKey], string: str) -> _PublicKey: + def from_string(cls: type[_PublicKey], string: str) -> _PublicKey: properties = string.strip("\n").split(" ", 2) return cls( @@ -449,7 +447,7 @@ class PublicKey: ) @classmethod - def load(cls: t.Type[_PublicKey], path: str | os.PathLike) -> _PublicKey | None: + def load(cls: type[_PublicKey], path: str | os.PathLike) -> _PublicKey | None: with open(path, "r", encoding="utf-8") as f: properties = f.read().strip(" \n").split(" ", 2) diff --git a/plugins/module_utils/_openssh/backends/keypair_backend.py b/plugins/module_utils/_openssh/backends/keypair_backend.py index f047f435..28e7edb7 100644 --- a/plugins/module_utils/_openssh/backends/keypair_backend.py +++ b/plugins/module_utils/_openssh/backends/keypair_backend.py @@ -46,10 +46,6 @@ from ansible_collections.community.crypto.plugins.module_utils._version import ( if t.TYPE_CHECKING: from ansible.module_utils.basic import AnsibleModule # pragma: no cover - from cryptography.hazmat.primitives.asymmetric.types import ( # pragma: no cover - CertificateIssuerPrivateKeyTypes, - PrivateKeyTypes, - ) class KeypairBackend(OpensshModule, metaclass=abc.ABCMeta): diff --git a/plugins/module_utils/_openssh/certificate.py b/plugins/module_utils/_openssh/certificate.py index 1024cb0f..02532858 100644 --- a/plugins/module_utils/_openssh/certificate.py +++ b/plugins/module_utils/_openssh/certificate.py @@ -312,7 +312,7 @@ class OpensshCertificateOption: @classmethod def from_string( - cls: t.Type[_OpensshCertificateOption], option_string: str + cls: t.Type[_OpensshCertificateOption], option_string: str # noqa: UP006 ) -> _OpensshCertificateOption: if not isinstance(option_string, str): raise ValueError( @@ -573,7 +573,7 @@ class OpensshCertificate: @classmethod def load( - cls: t.Type[_OpensshCertificate], path: str | os.PathLike + cls: t.Type[_OpensshCertificate], path: str | os.PathLike # noqa: UP006 ) -> _OpensshCertificate: if not os.path.exists(path): raise ValueError(f"{path} is not a valid path.") diff --git a/plugins/module_utils/_openssh/cryptography.py b/plugins/module_utils/_openssh/cryptography.py index 2c7bb647..af430166 100644 --- a/plugins/module_utils/_openssh/cryptography.py +++ b/plugins/module_utils/_openssh/cryptography.py @@ -79,13 +79,13 @@ if t.TYPE_CHECKING: KeySerializationFormat = t.Literal["PEM", "DER", "SSH"] # pragma: no cover KeyType = t.Literal["rsa", "dsa", "ed25519", "ecdsa"] # pragma: no cover - PrivateKeyTypes = t.Union[ + PrivateKeyTypes = t.Union[ # noqa: UP007 rsa.RSAPrivateKey, dsa.DSAPrivateKey, ec.EllipticCurvePrivateKey, Ed25519PrivateKey, ] # pragma: no cover - PublicKeyTypes = t.Union[ + PublicKeyTypes = t.Union[ # noqa: UP007 rsa.RSAPublicKey, dsa.DSAPublicKey, ec.EllipticCurvePublicKey, Ed25519PublicKey ] # pragma: no cover @@ -149,7 +149,7 @@ class AsymmetricKeypair: @classmethod def generate( - cls: t.Type[_AsymmetricKeypair], + cls: type[_AsymmetricKeypair], *, keytype: KeyType = "rsa", size: int | None = None, @@ -213,7 +213,7 @@ class AsymmetricKeypair: @classmethod def load( - cls: t.Type[_AsymmetricKeypair], + cls: type[_AsymmetricKeypair], *, path: str | os.PathLike, passphrase: bytes | None = None, @@ -412,7 +412,7 @@ class OpensshKeypair: @classmethod def generate( - cls: t.Type[_OpensshKeypair], + cls: type[_OpensshKeypair], *, keytype: KeyType = "rsa", size: int | None = None, @@ -451,7 +451,7 @@ class OpensshKeypair: @classmethod def load( - cls: t.Type[_OpensshKeypair], + cls: type[_OpensshKeypair], *, path: str | os.PathLike, passphrase: bytes | None = None, diff --git a/plugins/module_utils/_openssh/utils.py b/plugins/module_utils/_openssh/utils.py index 9d29a3b8..7159d917 100644 --- a/plugins/module_utils/_openssh/utils.py +++ b/plugins/module_utils/_openssh/utils.py @@ -331,7 +331,7 @@ class _OpensshWriter: for name, data in value: writer.string(name) # SSH option data is encoded twice though this behavior is not documented - writer.string(_OpensshWriter().string(data).bytes() if data else bytes()) + writer.string(_OpensshWriter().string(data).bytes() if data else b"") self.string(writer.bytes()) diff --git a/plugins/modules/acme_account_info.py b/plugins/modules/acme_account_info.py index 4281644f..e9c7b8ac 100644 --- a/plugins/modules/acme_account_info.py +++ b/plugins/modules/acme_account_info.py @@ -227,6 +227,17 @@ if t.TYPE_CHECKING: from ansible.module_utils.basic import AnsibleModule # pragma: no cover +def _collect_next(info: dict[str, t.Any]) -> list[str]: + result: list[str] = [] + + def f(link: str, relation: str) -> None: + if relation == "next": + result.append(link) + + process_links(info=info, callback=f) + return result + + def get_orders_list( module: AnsibleModule, client: ACMEClient, orders_url: str ) -> list[str]: @@ -257,12 +268,7 @@ def get_orders_list( orders.extend(res["orders"]) # Extract URL of next part of results list new_orders_url: list[str | None] = [] - - def f(link: str, relation: str) -> None: - if relation == "next": - new_orders_url.append(link) - - process_links(info=info, callback=f) + new_orders_url.extend(_collect_next(info)) new_orders_url.append(None) previous_orders_url, next_orders_url = next_orders_url, new_orders_url.pop(0) if next_orders_url == previous_orders_url: diff --git a/plugins/modules/acme_certificate.py b/plugins/modules/acme_certificate.py index 92129866..44f0ea78 100644 --- a/plugins/modules/acme_certificate.py +++ b/plugins/modules/acme_certificate.py @@ -795,13 +795,12 @@ class ACMECertificateClient: raise ModuleFailException( f"Found no challenge of type '{self.challenge}' for identifier {type_identifier}!" ) - if self.challenge == "dns-01": - if self.challenge in challenges: - values = data_dns.get(challenges[self.challenge]["record"]) - if values is None: - values = [] - data_dns[challenges[self.challenge]["record"]] = values - values.append(challenges[self.challenge]["resource_value"]) + if self.challenge == "dns-01" and self.challenge in challenges: + values = data_dns.get(challenges[self.challenge]["record"]) + if values is None: + values = [] + data_dns[challenges[self.challenge]["record"]] = values + values.append(challenges[self.challenge]["resource_value"]) return data, data_dns def finish_challenges(self) -> None: diff --git a/plugins/modules/acme_certificate_order_finalize.py b/plugins/modules/acme_certificate_order_finalize.py index 6db4419d..e32e05bd 100644 --- a/plugins/modules/acme_certificate_order_finalize.py +++ b/plugins/modules/acme_certificate_order_finalize.py @@ -440,9 +440,8 @@ def main() -> t.NoReturn: module.params["deactivate_authzs"] == "always" or (module.params["deactivate_authzs"] == "on_success" and done) or (module.params["deactivate_authzs"] == "on_error" and not done) - ): - if order: - client.deactivate_authzs(order) + ) and order: + client.deactivate_authzs(order) module.exit_json( changed=changed, account_uri=client.client.account_uri, diff --git a/plugins/modules/certificate_complete_chain.py b/plugins/modules/certificate_complete_chain.py index ba37c5d1..36d2d9e4 100644 --- a/plugins/modules/certificate_complete_chain.py +++ b/plugins/modules/certificate_complete_chain.py @@ -206,11 +206,10 @@ def is_parent( ) elif isinstance( public_key, - cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey, - ): - public_key.verify(cert.cert.signature, cert.cert.tbs_certificate_bytes) - elif isinstance( - public_key, cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey + ( + cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey, + cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey, + ), ): public_key.verify(cert.cert.signature, cert.cert.tbs_certificate_bytes) else: @@ -365,13 +364,12 @@ def main() -> t.NoReturn: # Check chain for i, parent in enumerate(chain): - if i > 0: - if not is_parent(module, chain[i - 1], parent): - module.fail_json( - msg=( - f"Cannot verify input chain: certificate #{i + 1}: {format_cert(parent)} is not issuer of certificate #{i}: {format_cert(chain[i - 1])}" - ) + if i > 0 and not is_parent(module, chain[i - 1], parent): + module.fail_json( + msg=( + f"Cannot verify input chain: certificate #{i + 1}: {format_cert(parent)} is not issuer of certificate #{i}: {format_cert(chain[i - 1])}" ) + ) # Load intermediate certificates intermediates = CertificateSet(module) diff --git a/plugins/modules/crypto_info.py b/plugins/modules/crypto_info.py index 1be49f7f..5f1c13fc 100644 --- a/plugins/modules/crypto_info.py +++ b/plugins/modules/crypto_info.py @@ -222,7 +222,7 @@ def add_crypto_information(module: AnsibleModule) -> dict[str, t.Any]: has_dsa = True try: # added later in 1.5 - dsa.DSAPrivateKey.sign # pylint: disable=pointless-statement + dsa.DSAPrivateKey.sign # noqa: B018 # pylint: disable=pointless-statement has_dsa_sign = True except AttributeError: pass @@ -239,7 +239,7 @@ def add_crypto_information(module: AnsibleModule) -> dict[str, t.Any]: has_rsa = True try: # added later in 1.4 - rsa.RSAPrivateKey.sign # pylint: disable=pointless-statement + rsa.RSAPrivateKey.sign # noqa: B018 # pylint: disable=pointless-statement has_rsa_sign = True except AttributeError: pass @@ -261,7 +261,7 @@ def add_crypto_information(module: AnsibleModule) -> dict[str, t.Any]: has_ed25519 = True try: # added with the primitive in 2.6 - ed25519.Ed25519PrivateKey.sign # pylint: disable=pointless-statement + ed25519.Ed25519PrivateKey.sign # noqa: B018 # pylint: disable=pointless-statement has_ed25519_sign = True except AttributeError: pass @@ -283,7 +283,7 @@ def add_crypto_information(module: AnsibleModule) -> dict[str, t.Any]: has_ed448 = True try: # added with the primitive in 2.6 - ed448.Ed448PrivateKey.sign # pylint: disable=pointless-statement + ed448.Ed448PrivateKey.sign # noqa: B018 # pylint: disable=pointless-statement has_ed448_sign = True except AttributeError: pass @@ -299,7 +299,7 @@ def add_crypto_information(module: AnsibleModule) -> dict[str, t.Any]: try: # added later in 2.5 - x25519.X25519PrivateKey.private_bytes # pylint: disable=pointless-statement + x25519.X25519PrivateKey.private_bytes # noqa: B018 # pylint: disable=pointless-statement full = True except AttributeError: full = False @@ -344,7 +344,7 @@ def add_crypto_information(module: AnsibleModule) -> dict[str, t.Any]: has_ec = True try: # added later in 1.5 - ec.EllipticCurvePrivateKey.sign # pylint: disable=pointless-statement + ec.EllipticCurvePrivateKey.sign # noqa: B018 # pylint: disable=pointless-statement has_ec_sign = True except AttributeError: pass diff --git a/plugins/modules/get_certificate.py b/plugins/modules/get_certificate.py index 5087fd85..2993c2d7 100644 --- a/plugins/modules/get_certificate.py +++ b/plugins/modules/get_certificate.py @@ -376,9 +376,8 @@ def main() -> t.NoReturn: if timeout: setdefaulttimeout(timeout) - if ca_cert: - if not isfile(ca_cert): - module.fail_json(msg="ca_cert file does not exist") + if ca_cert and not isfile(ca_cert): + module.fail_json(msg="ca_cert file does not exist") verified_chain = None unverified_chain = None diff --git a/plugins/modules/luks_device.py b/plugins/modules/luks_device.py index d0a47977..6d5e45be 100644 --- a/plugins/modules/luks_device.py +++ b/plugins/modules/luks_device.py @@ -936,9 +936,7 @@ class ConditionsHandler(Handler): name = self.opened_luks_name(self.device) - if name is None: - return True - return False + return name is None def luks_close(self) -> bool: if ( diff --git a/plugins/modules/openssl_dhparam.py b/plugins/modules/openssl_dhparam.py index 7f438f1a..4317619a 100644 --- a/plugins/modules/openssl_dhparam.py +++ b/plugins/modules/openssl_dhparam.py @@ -391,7 +391,7 @@ def main() -> t.NoReturn: # Detection what is possible can_use_cryptography = ( CRYPTOGRAPHY_FOUND - and CRYPTOGRAPHY_VERSION >= LooseVersion(MINIMAL_CRYPTOGRAPHY_VERSION) + and LooseVersion(MINIMAL_CRYPTOGRAPHY_VERSION) <= CRYPTOGRAPHY_VERSION ) can_use_openssl = module.get_bin_path("openssl", False) is not None diff --git a/plugins/modules/openssl_pkcs12.py b/plugins/modules/openssl_pkcs12.py index f9a48691..20849d62 100644 --- a/plugins/modules/openssl_pkcs12.py +++ b/plugins/modules/openssl_pkcs12.py @@ -342,10 +342,10 @@ if t.TYPE_CHECKING: ) PKCS12 = tuple[ - t.Union[CertificateIssuerPrivateKeyTypes, None], - t.Union[cryptography.x509.Certificate, None], + t.Union[CertificateIssuerPrivateKeyTypes, None], # noqa: UP007 + t.Union[cryptography.x509.Certificate, None], # noqa: UP007 list[cryptography.x509.Certificate], - t.Union[bytes, None], + t.Union[bytes, None], # noqa: UP007 ] # pragma: no cover @@ -823,9 +823,9 @@ def main() -> t.NoReturn: changed = True file_args = module.load_file_common_arguments(module.params) - if module.check_file_absent_if_check_mode(file_args["path"]): - changed = True - elif module.set_fs_attributes_if_different(file_args, changed): + if module.check_file_absent_if_check_mode( + file_args["path"] + ) or module.set_fs_attributes_if_different(file_args, changed): changed = True else: if module.check_mode: diff --git a/plugins/modules/openssl_publickey.py b/plugins/modules/openssl_publickey.py index faa8ad38..d716dae6 100644 --- a/plugins/modules/openssl_publickey.py +++ b/plugins/modules/openssl_publickey.py @@ -325,9 +325,9 @@ class PublicKey(OpenSSLObject): passphrase=self.privatekey_passphrase, ) file_args = module.load_file_common_arguments(module.params) - if module.check_file_absent_if_check_mode(file_args["path"]): - self.changed = True - elif module.set_fs_attributes_if_different(file_args, False): + if module.check_file_absent_if_check_mode( + file_args["path"] + ) or module.set_fs_attributes_if_different(file_args, False): self.changed = True def check(self, module: AnsibleModule, *, perms_required: bool = True) -> bool: diff --git a/plugins/modules/openssl_signature.py b/plugins/modules/openssl_signature.py index d7188c72..b6b18882 100644 --- a/plugins/modules/openssl_signature.py +++ b/plugins/modules/openssl_signature.py @@ -200,13 +200,10 @@ class SignatureCryptography(SignatureBase): elif isinstance( private_key, - cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey, - ): - signature = private_key.sign(_in) - - elif isinstance( - private_key, - cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey, + ( + cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey, + cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey, + ), ): signature = private_key.sign(_in) diff --git a/plugins/modules/openssl_signature_info.py b/plugins/modules/openssl_signature_info.py index e3d6ee3f..3709b219 100644 --- a/plugins/modules/openssl_signature_info.py +++ b/plugins/modules/openssl_signature_info.py @@ -197,15 +197,10 @@ class SignatureInfoCryptography(SignatureInfoBase): elif isinstance( public_key, - cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey, - ): - public_key.verify(_signature, _in) - verified = True - valid = True - - elif isinstance( - public_key, - cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey, + ( + cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey, + cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey, + ), ): public_key.verify(_signature, _in) verified = True diff --git a/plugins/modules/x509_certificate_convert.py b/plugins/modules/x509_certificate_convert.py index 13034129..42b61148 100644 --- a/plugins/modules/x509_certificate_convert.py +++ b/plugins/modules/x509_certificate_convert.py @@ -244,9 +244,9 @@ class X509CertificateConvertModule(OpenSSLObject): return True if self.input != self.dest_content: return True - if self.format == "pem" and self.dest_content_pem_type != self.wanted_pem_type: - return True - return False + return bool( + self.format == "pem" and self.dest_content_pem_type != self.wanted_pem_type + ) def get_dest_certificate(self) -> bytes: if self.format == "der": diff --git a/plugins/modules/x509_crl.py b/plugins/modules/x509_crl.py index 2f3195ff..170cb2fc 100644 --- a/plugins/modules/x509_crl.py +++ b/plugins/modules/x509_crl.py @@ -823,10 +823,7 @@ class CRL(OpenSSLObject): if old_entries != new_entries: return False - if self.format != self.actual_format and not ignore_conversion: - return False - - return True + return not (self.format != self.actual_format and not ignore_conversion) def _generate_crl(self) -> bytes: crl = CertificateRevocationListBuilder() @@ -919,9 +916,9 @@ class CRL(OpenSSLObject): self.changed = True file_args = self.module.load_file_common_arguments(self.module.params) - if self.module.check_file_absent_if_check_mode(file_args["path"]): - self.changed = True - elif self.module.set_fs_attributes_if_different(file_args, False): + if self.module.check_file_absent_if_check_mode( + file_args["path"] + ) or self.module.set_fs_attributes_if_different(file_args, False): self.changed = True def dump(self, check_mode: bool = False) -> dict[str, t.Any]: diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 00000000..dca70302 --- /dev/null +++ b/ruff.toml @@ -0,0 +1,31 @@ +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later +# SPDX-FileCopyrightText: 2025 Felix Fontein + +line-length = 160 + +[lint] +# https://docs.astral.sh/ruff/rules/ + +select = ["A", "B", "E", "F", "FA", "FLY", "UP", "SIM"] +ignore = [ + # Better keep ignored (for now) + "F811", # Redefinition of unused `xxx` (happens a lot for fixtures in unit tests) + "E402", # Module level import not at top of file + "E741", # Ambiguous variable name + "UP012", # unnecessary-encode-utf8 + "UP015", # Unnecessary mode argument + "SIM105", # suppressible-exception + "SIM108", # if-else-block-instead-of-if-exp + # To fix later: + "B905", # zip-without-explicit-strict - needs Python 3.10+ + # To fix: + "UP024", # Replace aliased errors with `OSError` +] + +# Allow fix for all enabled rules (when `--fix`) is provided. +fixable = ["ALL"] +unfixable = [] + +# Allow unused variables when underscore-prefixed or starting with dummy +dummy-variable-rgx = "^(_|dummy).*$" diff --git a/tests/unit/plugins/module_utils/test__time.py b/tests/unit/plugins/module_utils/test__time.py index a12a1814..f298e141 100644 --- a/tests/unit/plugins/module_utils/test__time.py +++ b/tests/unit/plugins/module_utils/test__time.py @@ -37,9 +37,9 @@ if t.TYPE_CHECKING: def cartesian_product( - list1: list[_S], list2: "list[tuple[*_Ts]]" -) -> "list[tuple[_S, *_Ts]]": - result: "list[tuple[_S, *_Ts]]" = [] + list1: list[_S], list2: "list[tuple[*_Ts]]" # noqa: UP037 +) -> "list[tuple[_S, *_Ts]]": # noqa: UP037 + result: "list[tuple[_S, *_Ts]]" = [] # noqa: UP037 for item1 in list1: item1_tuple = (item1,) for item2 in list2: