From f6d04a30765cec05cece1b0b1da932535caaabbf Mon Sep 17 00:00:00 2001 From: Miguel Sousa Date: Mon, 3 Aug 2026 17:54:06 -0700 Subject: [PATCH] Fix lint/format errors surfaced by ruff 0.16 default rules ruff 0.16.0 expanded its default rule selection (adding I, UP, SIM and RUF categories) and now formats Python code blocks in Markdown. This broke CI on previously-clean code, since `ruff` is unpinned in requirements.txt. Adopt the new defaults instead of pinning: - apply auto-fixes for I001 (import sorting), UP032 (f-strings), SIM117 (combined with-statements), SIM118 (dict-keys) and RUF100 (unused `# noqa: E501` directives) - annotate setuptools Command attributes with typing.ClassVar (RUF012) - reformat the code samples in README.md via `ruff format` --- README.md | 5 ++- build_ots.py | 10 ++--- setup.py | 67 ++++++++++++++++---------------- tests/test_compare_ots_python.py | 4 +- tests/test_ots_suite.py | 4 +- 5 files changed, 45 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 892e9fd..b4f83cb 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,8 @@ If you wish to run tests comparing results from `ots-python` against `pyots`, be Simplest case: ```python import pyots -result = pyots.sanitize('/path/to/font/file.ttf') + +result = pyots.sanitize("/path/to/font/file.ttf") ``` `result` is an `OTSResult` object with 3 attributes: @@ -51,7 +52,7 @@ from pathlib import Path for filename in Path("src/ots/tests/fonts/good").rglob("*"): result = pyots.sanitize(filename.absolute()) if not result.sanitized: - print(f'{filename}:\n{", ".join([m for m in result.messages])}') + print(f"{filename}:\n{', '.join([m for m in result.messages])}") ``` ### Options for `sanitize()` diff --git a/build_ots.py b/build_ots.py index 2c10cd6..4c847a1 100755 --- a/build_ots.py +++ b/build_ots.py @@ -3,13 +3,13 @@ Run meson and ninja to build the ots static libs from source. """ -import sys -from pathlib import Path +import argparse +import errno import os -import subprocess import shutil -import errno -import argparse +import subprocess +import sys +from pathlib import Path ROOT = Path(__file__).parent.resolve() BUILD_ROOT = ROOT / "src" / "ots" / "build" diff --git a/setup.py b/setup.py index a83b116..74d1282 100644 --- a/setup.py +++ b/setup.py @@ -3,14 +3,16 @@ import os import re import shutil +import subprocess +import sys from pathlib import Path -from setuptools import setup, Extension, Command +from typing import ClassVar + +from setuptools import Command, Extension, setup from setuptools.command import build_py from setuptools.command.build_ext import build_ext from setuptools.command.egg_info import egg_info from setuptools.errors import SetupError -import subprocess -import sys PY = sys.executable @@ -135,7 +137,7 @@ def _get_sources(): # woff2 sources sp.append(SRC_SUB_DIR / f"woff2-{WOFF2_TAG}" / "src" / "table_tags.cc") - sp.append(SRC_SUB_DIR / f"woff2-{WOFF2_TAG}" / "src" / "variable_length.cc") # noqa: E501 + sp.append(SRC_SUB_DIR / f"woff2-{WOFF2_TAG}" / "src" / "variable_length.cc") sp.append(SRC_SUB_DIR / f"woff2-{WOFF2_TAG}" / "src" / "woff2_common.cc") sp.append(SRC_SUB_DIR / f"woff2-{WOFF2_TAG}" / "src" / "woff2_dec.cc") sp.append(SRC_SUB_DIR / f"woff2-{WOFF2_TAG}" / "src" / "woff2_out.cc") @@ -149,7 +151,7 @@ class BuildStaticLibs(Command): """ description = "Build ots static libs from source with meson/ninja" - user_options = [] + user_options: ClassVar[list] = [] def run(self): cmd = [PY, "build_ots.py"] @@ -194,13 +196,13 @@ def run(self): class Download(Command): - user_options = [ + user_options: ClassVar[list] = [ ("version=", None, "ots source version number to download"), ("sha256=", None, "expected SHA-256 hash of the source archive"), ("download-dir=", "d", "where to unpack the 'ots' dir (default: src)"), ("clean", None, "remove existing directory before downloading"), ] - boolean_options = ["clean"] + boolean_options: ClassVar[list] = ["clean"] URL_TEMPLATE = "https://github.com/khaledhosny/ots/releases/download/v{version}/ots-{version}.tar.xz" @@ -223,27 +225,27 @@ def finalize_options(self): self.url = self.URL_TEMPLATE.format(**vars(self)) def run(self): - from urllib.request import urlopen - import tarfile - import lzma import hashlib + import lzma + import tarfile + from urllib.request import urlopen output_dir = os.path.join(self.download_dir, "ots") if self.clean and os.path.isdir(output_dir): - log.info("removing '{}'".format(output_dir)) + log.info(f"removing '{output_dir}'") if not self.dry_run: shutil.rmtree(output_dir) if os.path.isdir(output_dir): - log.info("{} was already downloaded".format(output_dir)) + log.info(f"{output_dir} was already downloaded") else: archive_name = self.url.rsplit("/", 1)[-1] - log.info("creating '{}'".format(self.download_dir)) + log.info(f"creating '{self.download_dir}'") if not self.dry_run: os.makedirs(self.download_dir, exist_ok=True) - log.info("downloading {}".format(self.url)) + log.info(f"downloading {self.url}") if not self.dry_run: # response is not seekable so we first download *.tar.xz to an # in-memory file, and then extract all files to the output_dir @@ -256,28 +258,25 @@ def run(self): actual_sha256 = hashlib.sha256(f.getvalue()).hexdigest() if actual_sha256 != self.sha256: raise SetupError( - "invalid SHA-256 checksum:\nactual: {}\nexpected: {}".format( - actual_sha256, self.sha256 - ) + f"invalid SHA-256 checksum:\nactual: {actual_sha256}\nexpected: {self.sha256}" ) - log.info("unarchiving {} to {}".format(archive_name, output_dir)) - with lzma.open(f) as xz: - with tarfile.open(fileobj=xz) as tar: - filelist = tar.getmembers() - first = filelist[0] - if not (first.isdir() and first.name.startswith("ots")): # noqa: E501 - raise SetupError( - "The downloaded archive is not recognized as a valid ots source tarball" - ) - # strip the root 'ots-X.X.X' directory first - rootdir = first.name + "/" - to_extract = [] - for member in filelist[1:]: - if member.name.startswith(rootdir): - member.name = member.name[len(rootdir) :] - to_extract.append(member) - tar.extractall(output_dir, members=to_extract) + log.info(f"unarchiving {archive_name} to {output_dir}") + with lzma.open(f) as xz, tarfile.open(fileobj=xz) as tar: + filelist = tar.getmembers() + first = filelist[0] + if not (first.isdir() and first.name.startswith("ots")): + raise SetupError( + "The downloaded archive is not recognized as a valid ots source tarball" + ) + # strip the root 'ots-X.X.X' directory first + rootdir = first.name + "/" + to_extract = [] + for member in filelist[1:]: + if member.name.startswith(rootdir): + member.name = member.name[len(rootdir) :] + to_extract.append(member) + tar.extractall(output_dir, members=to_extract) log.info("writing custom meson.build") diff --git a/tests/test_compare_ots_python.py b/tests/test_compare_ots_python.py index 174504c..cdb2002 100644 --- a/tests/test_compare_ots_python.py +++ b/tests/test_compare_ots_python.py @@ -5,8 +5,8 @@ """ import functools -from pathlib import Path import timeit +from pathlib import Path import pytest @@ -85,7 +85,7 @@ def cmp_times(): "pyots": functools.partial(pyots.sanitize, quiet=False), "ots-python": functools.partial(ots.sanitize, capture_output=True), } - rd = {k: 0.0 for k in fd.keys()} + rd = {k: 0.0 for k in fd} for name, sanitize_method in fd.items(): start = timeit.default_timer() diff --git a/tests/test_ots_suite.py b/tests/test_ots_suite.py index d53358c..71930a0 100644 --- a/tests/test_ots_suite.py +++ b/tests/test_ots_suite.py @@ -29,7 +29,7 @@ def test_ots_good(): count += 1 print("[good] unexpected failure on", f, "\n".join(r.messages)) - assert not count, f"{count} file{'s' if count != 1 else ''} failed when expected to be sanitized." # noqa: E501 + assert not count, f"{count} file{'s' if count != 1 else ''} failed when expected to be sanitized." def test_ots_bad(): @@ -49,7 +49,7 @@ def test_ots_bad(): assert not count, ( f"{count} file{'s were' if count != 1 else 'was'} sanitized successfully when expected to fail." - ) # noqa: E501 + ) def test_ots_fuzzing():