Fix ruff 0.16 findings; bump dependency minimums to match
- pyproject [tool.ruff.lint]: ignore RUF022/RUF023 (deliberately grouped __all__/__slots__), SIM117, BLE001 (blind except is intentional at CFFI callback boundaries) - Legit fixes: dict/tuple instead of typing.Dict/Tuple in generate.py, unquoted annotations in raf.py, Self return for __enter__ methods, explicit check=False on subprocess.run, collapsed nested ifs, sorted test imports, unused-unpacked-variable in test_raises - Bump minimum versions to the synced toolchain: cffi 2.1.1, ruff 0.16.10, pytest 9.1.1, auditwheel 6.8.2, setuptools 84.0.0, setuptools-scm 10.3.4 (project deps and build-system requires)
This commit is contained in:
1 parent
1eb0b6e8c0
commit
b4404b42e6
10 files changed
+52
-40
No files matched your search
+19
-7
@@ -1,5 +1,5 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=61.0", "cffi>=2.0.0", "setuptools-scm>=8.0"]
|
||||
requires = ["setuptools>=84.0.0", "cffi>=2.1.1", "setuptools-scm>=10.3.4"]
|
||||
build-backend = "build_backend"
|
||||
backend-path = ["tools"]
|
||||
|
||||
@@ -16,7 +16,7 @@ classifiers = [
|
||||
"Topic :: Security :: Cryptography",
|
||||
]
|
||||
dependencies = [
|
||||
"cffi>=2.0.0",
|
||||
"cffi>=2.1.1",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
@@ -25,11 +25,11 @@ Repository = "https://github.com/LeoVasanko/aegis-python"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"auditwheel>=6.5.0",
|
||||
"pytest>=8.4.2",
|
||||
"ruff>=0.14.4",
|
||||
"setuptools>=80.9.0",
|
||||
"setuptools-scm>=9.2.2",
|
||||
"auditwheel>=6.8.2",
|
||||
"pytest>=9.1.1",
|
||||
"ruff>=0.16.10",
|
||||
"setuptools>=84.0.0",
|
||||
"setuptools-scm>=10.3.4",
|
||||
]
|
||||
|
||||
[tool.setuptools]
|
||||
@@ -39,4 +39,16 @@ packages = ["aeg"]
|
||||
[tool.setuptools.package-data]
|
||||
aeg = ["*.h"]
|
||||
|
||||
[tool.ruff]
|
||||
# Disable formatting in Markdown files
|
||||
extend-exclude = ["*.md"]
|
||||
|
||||
[tool.ruff.lint]
|
||||
ignore = [
|
||||
"RUF022", # __all__ is deliberately grouped with comments
|
||||
"RUF023", # __slots__ is deliberately grouped
|
||||
"SIM117", # nested with-statements are sometimes clearer
|
||||
"BLE001", # blind except is intentional at CFFI callback boundaries
|
||||
]
|
||||
|
||||
[tool.setuptools_scm]
|
||||
+9
-9
@@ -18,7 +18,7 @@ import hashlib
|
||||
import io as io_module
|
||||
import os
|
||||
import threading
|
||||
from typing import NamedTuple, Protocol, runtime_checkable
|
||||
from typing import NamedTuple, Protocol, Self, runtime_checkable
|
||||
|
||||
from . import cipher as _cipher_for_name
|
||||
from . import random as _random
|
||||
@@ -163,7 +163,7 @@ class FileStorage:
|
||||
os.close(self._fd)
|
||||
self._closed = True
|
||||
|
||||
def __enter__(self) -> FileStorage:
|
||||
def __enter__(self) -> Self:
|
||||
return self
|
||||
|
||||
def __exit__(self, *args) -> None:
|
||||
@@ -213,7 +213,7 @@ class BytesIOStorage:
|
||||
"""Return the entire buffer contents."""
|
||||
return bytes(self._data)
|
||||
|
||||
def __enter__(self) -> BytesIOStorage:
|
||||
def __enter__(self) -> Self:
|
||||
return self
|
||||
|
||||
def __exit__(self, *args) -> None:
|
||||
@@ -272,7 +272,7 @@ class StreamStorage:
|
||||
if hasattr(self._stream, "flush"):
|
||||
self._stream.flush()
|
||||
|
||||
def __enter__(self) -> StreamStorage:
|
||||
def __enter__(self) -> Self:
|
||||
return self
|
||||
|
||||
def __exit__(self, *args) -> None:
|
||||
@@ -588,8 +588,8 @@ def create(
|
||||
truncate: bool = False,
|
||||
merkle: bool | MerkleHasher = False,
|
||||
merkle_max_chunks: int = 16384,
|
||||
rng: "_random.RandomSource | None" = None,
|
||||
) -> "Raf":
|
||||
rng: _random.RandomSource | None = None,
|
||||
) -> Raf:
|
||||
"""Create a new encrypted file.
|
||||
|
||||
Args:
|
||||
@@ -641,8 +641,8 @@ def open(
|
||||
*,
|
||||
merkle: bool | MerkleHasher = False,
|
||||
merkle_max_chunks: int = 16384,
|
||||
rng: "_random.RandomSource | None" = None,
|
||||
) -> "Raf":
|
||||
rng: _random.RandomSource | None = None,
|
||||
) -> Raf:
|
||||
"""Open an existing encrypted file.
|
||||
|
||||
The header is probed to size internal buffers and its alg_id is checked
|
||||
@@ -922,7 +922,7 @@ class Raf:
|
||||
"""True if the file has been closed."""
|
||||
return self._closed
|
||||
|
||||
def __enter__(self) -> "Raf":
|
||||
def __enter__(self) -> Self:
|
||||
return self
|
||||
|
||||
def __exit__(self, *args) -> None:
|
||||
|
||||
@@ -17,6 +17,7 @@ import ctypes
|
||||
import mmap
|
||||
import os
|
||||
from contextlib import suppress
|
||||
from typing import Self
|
||||
|
||||
from .util import wipe
|
||||
|
||||
@@ -104,7 +105,7 @@ class SecureBuffer:
|
||||
def __len__(self) -> int:
|
||||
return len(self._mmap)
|
||||
|
||||
def __enter__(self) -> "SecureBuffer":
|
||||
def __enter__(self) -> Self:
|
||||
return self
|
||||
|
||||
def __exit__(self, *args) -> None:
|
||||
|
||||
@@ -12,8 +12,7 @@ import random
|
||||
|
||||
import pytest
|
||||
|
||||
from aeg import aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4
|
||||
from aeg import raf
|
||||
from aeg import aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4, raf
|
||||
from aeg.raf import BytesIOStorage, FileStorage
|
||||
|
||||
CIPHERS = [aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4]
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
import pytest
|
||||
|
||||
from aeg import aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4
|
||||
from aeg import raf
|
||||
from aeg import aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4, raf
|
||||
from aeg import random as aeg_random
|
||||
|
||||
CIPHERS = [aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4]
|
||||
|
||||
@@ -12,8 +12,7 @@ import hashlib
|
||||
|
||||
import pytest
|
||||
|
||||
from aeg import aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4
|
||||
from aeg import raf
|
||||
from aeg import aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4, raf
|
||||
from aeg.raf import (
|
||||
BytesIOStorage,
|
||||
FileStorage,
|
||||
|
||||
@@ -252,6 +252,7 @@ class TestDecryptorFinalization:
|
||||
|
||||
# Encrypt empty message
|
||||
ct, tag = aegis256x4.encrypt_detached(key, nonce, b"")
|
||||
del ct
|
||||
|
||||
# Decrypt without any updates
|
||||
decryptor = aegis256x4.Decryptor(key, nonce)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import random
|
||||
|
||||
|
||||
_rng = random.SystemRandom()
|
||||
|
||||
|
||||
|
||||
+17
-15
@@ -5,7 +5,6 @@ import pathlib
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import Dict, Tuple
|
||||
|
||||
|
||||
def preprocess_content(content: str) -> str:
|
||||
@@ -58,15 +57,17 @@ def format_declaration(decl: str, max_width: int = 100) -> str:
|
||||
if len(decl) <= max_width:
|
||||
return decl
|
||||
|
||||
if "(" in decl and ")" in decl:
|
||||
if match := re.match(r"(.*?\s+\w+\s*)\((.*)\)(.*)", decl):
|
||||
if (
|
||||
"(" in decl
|
||||
and ")" in decl
|
||||
and (match := re.match(r"(.*?\s+\w+\s*)\((.*)\)(.*)", decl))
|
||||
):
|
||||
prefix, params, suffix = match.groups()
|
||||
if len(prefix) + len(params) + 2 > max_width:
|
||||
param_list = [p.strip() for p in params.split(",")]
|
||||
if len(param_list) > 1:
|
||||
formatted_params = (",\n" + " " * (len(prefix) + 1)).join(
|
||||
param_list
|
||||
)
|
||||
if (
|
||||
len(prefix) + len(params) + 2 > max_width
|
||||
and len(param_list := [p.strip() for p in params.split(",")]) > 1
|
||||
):
|
||||
formatted_params = (",\n" + " " * (len(prefix) + 1)).join(param_list)
|
||||
return f"{prefix}({formatted_params}){suffix}"
|
||||
|
||||
return decl
|
||||
@@ -108,7 +109,7 @@ def generate_cdef(include_dir: pathlib.Path) -> str:
|
||||
|
||||
def extract_constants(
|
||||
common_h_path: pathlib.Path, header_path: pathlib.Path, raf_h_path: pathlib.Path
|
||||
) -> Dict[str, int]:
|
||||
) -> dict[str, int]:
|
||||
"""Extract constants from common.h (ALIGNMENT, RATE), main header (KEYBYTES, NPUBBYTES, ABYTES_*), and aegis_raf.h (RAF_ALG_ID)."""
|
||||
constants = {}
|
||||
|
||||
@@ -151,7 +152,7 @@ def extract_constants(
|
||||
|
||||
def extract_all_constants(
|
||||
libaegis_src_dir: pathlib.Path, include_dir: pathlib.Path
|
||||
) -> Dict[str, Dict[str, int]]:
|
||||
) -> dict[str, dict[str, int]]:
|
||||
variants = [
|
||||
"aegis128l",
|
||||
"aegis128x2",
|
||||
@@ -195,7 +196,7 @@ def algo_label(name: str) -> str:
|
||||
return "AEGIS-" + name[5:].upper()
|
||||
|
||||
|
||||
def generate_variant(template_src: str, variant: str, constants: Dict[str, int]) -> str:
|
||||
def generate_variant(template_src: str, variant: str, constants: dict[str, int]) -> str:
|
||||
"""Generate a variant module from the template with substituted constants."""
|
||||
s = template_src.replace("aegis256x4", variant).replace(
|
||||
"AEGIS-256X4", algo_label(variant)
|
||||
@@ -238,8 +239,8 @@ def generate_variant(template_src: str, variant: str, constants: Dict[str, int])
|
||||
def generate_python_modules(
|
||||
template_path: pathlib.Path,
|
||||
output_dir: pathlib.Path,
|
||||
constants: Dict[str, Dict[str, int]],
|
||||
) -> Tuple[list[pathlib.Path], list[pathlib.Path]]:
|
||||
constants: dict[str, dict[str, int]],
|
||||
) -> tuple[list[pathlib.Path], list[pathlib.Path]]:
|
||||
if not template_path.exists():
|
||||
raise FileNotFoundError(f"Template not found: {template_path}")
|
||||
|
||||
@@ -295,7 +296,7 @@ def generate_python_modules(
|
||||
return updated, unchanged
|
||||
|
||||
|
||||
def generate_ciphers_module(constants: Dict[str, Dict[str, int]]) -> str:
|
||||
def generate_ciphers_module(constants: dict[str, dict[str, int]]) -> str:
|
||||
labels = [algo_label(variant) for variant in constants]
|
||||
literal_items = ", ".join(f'"{label}"' for label in labels)
|
||||
lines = [
|
||||
@@ -381,6 +382,7 @@ def main() -> int:
|
||||
["uv", "run", "ruff", "format", str(pyaegis_dir)],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print(f"Error formatting generated files: {result.stderr}", file=sys.stderr)
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ def get_next_version(current_version):
|
||||
def is_working_copy_clean():
|
||||
"""Check if git working copy is clean."""
|
||||
result = subprocess.run(
|
||||
["git", "status", "--porcelain"], capture_output=True, text=True
|
||||
["git", "status", "--porcelain"], capture_output=True, text=True, check=False
|
||||
)
|
||||
return result.returncode == 0 and not result.stdout.strip()
|
||||
|
||||
|
||||
Reference in new issue
Block a user