Compare commits

...

3 Commits

Author SHA1 Message Date
8d70ced693
Add myself as code owner for ruff.toml
Some checks are pending
0ad-freebsd/pipeline/pr-main This commit looks good
0ad-macos/pipeline/pr-main Build started...
checkrefs / checkrefs (pull_request) Successful in 1m2s
pre-commit / build (pull_request) Successful in 1m22s
0ad-linux/pipeline/pr-main This commit looks good
0ad-windows/pipeline/pr-main This commit looks good
0ad-freebsd/pipeline/head This commit looks good
checkrefs / checkrefs (push) Successful in 1m0s
pre-commit / build (push) Successful in 1m19s
0ad-linux/pipeline/head This commit looks good
0ad-windows/pipeline/head This commit looks good
0ad-macos/pipeline/head This commit looks good
2024-09-21 20:54:32 +02:00
0ea6d32fa5
Enable various ruff rules
This commit enables a bunch of unrelated ruff rules, which only require
minimal changes to the code base to enable them.

The rules enabled by this commit are:

- check the use of datetime objects without timezone (DTZ005)
- check the performance of try-except in loops (PERF203)
- check the number of function arguments (PLR0913)
- check for mutable class defaults (RUF012)
- check for the use of secure hashing algorithms (S324)
- check for raising base exceptions (TRY002)
- check for raising other exceptions where TypeErrors should be raised
  (TRY004)
2024-09-21 20:54:30 +02:00
c0232c6b5f
Specify the Python target version in ruff.toml
This ensures the same Python target version used for `ruff format`
is used for `ruff check` as well. It also allows ruff, even if it's not
run through pre-commit, to use the correct target Python version.
2024-09-21 20:54:24 +02:00
16 changed files with 30 additions and 34 deletions

View File

@ -3,6 +3,7 @@
\\.gitea/.* @Stan @Itms
## Linting
\\.pre-commit-config\\.yaml @Dunedan
ruff\\.toml @Dunedan
## == Build & Libraries
(build|libraries)/.* @Itms @Stan

View File

@ -30,8 +30,6 @@ repos:
- id: ruff-format
args:
- --check
- --target-version
- py311
exclude: ^source/tools/webservices/
- repo: local
hooks:

View File

@ -1,5 +1,7 @@
line-length = 99
target-version = "py311"
[format]
line-ending = "lf"
@ -10,36 +12,29 @@ ignore = [
"C90",
"COM812",
"D10",
"DTZ005",
"EM",
"FA",
"FIX",
"FBT",
"ISC001",
"N817",
"PERF203",
"PERF401",
"PLR0912",
"PLR0913",
"PLR0915",
"PLR2004",
"PLW2901",
"PT",
"PTH",
"RUF012",
"S101",
"S310",
"S314",
"S324",
"S320",
"S603",
"S607",
"T20",
"TD002",
"TD003",
"TRY002",
"TRY003",
"TRY004",
"UP038",
"W505"
]
@ -52,3 +47,6 @@ max-doc-length = 72
[lint.pydocstyle]
convention = "pep257"
[lint.pylint]
max-args = 8

View File

@ -8,7 +8,6 @@ from json import load, loads
from logging import INFO, WARNING, Filter, Formatter, StreamHandler, getLogger
from pathlib import Path
from struct import calcsize, unpack
from typing import Dict, List, Set, Tuple
from xml.etree import ElementTree as ET
from scriptlib import SimulTemplateEntity, find_files
@ -27,9 +26,9 @@ class SingleLevelFilter(Filter):
class CheckRefs:
def __init__(self):
self.files: List[Path] = []
self.roots: List[Path] = []
self.deps: List[Tuple[Path, Path]] = []
self.files: list[Path] = []
self.roots: list[Path] = []
self.deps: list[tuple[Path, Path]] = []
self.vfs_root = Path(__file__).resolve().parents[3] / "binaries" / "data" / "mods"
self.supportedTextureFormats = ("dds", "png")
self.supportedMeshesFormats = ("pmd", "dae")
@ -794,7 +793,7 @@ class CheckRefs:
uniq_files = {r.as_posix() for r in self.files}
lower_case_files = {f.lower(): f for f in uniq_files}
missing_files: Dict[str, Set[str]] = defaultdict(set)
missing_files: dict[str, set[str]] = defaultdict(set)
for parent, dep in self.deps:
dep_str = dep.as_posix()

View File

@ -7,7 +7,6 @@ import shutil
import sys
from pathlib import Path
from subprocess import CalledProcessError, run
from typing import Sequence
from xml.etree import ElementTree as ET
from scriptlib import SimulTemplateEntity, find_files
@ -50,7 +49,7 @@ errorch.setFormatter(logging.Formatter("%(levelname)s - %(message)s"))
logger.addHandler(errorch)
def main(argv: Sequence[str] | None = None) -> int:
def main() -> int:
parser = argparse.ArgumentParser(description="Validate templates")
parser.add_argument("-m", "--mod-name", required=True, help="The name of the mod to validate.")
parser.add_argument(
@ -73,7 +72,7 @@ def main(argv: Sequence[str] | None = None) -> int:
)
parser.add_argument("-v", "--verbose", help="Be verbose about the output.", default=False)
args = parser.parse_args(argv)
args = parser.parse_args()
if not args.relaxng_schema.exists():
logging.error(RELAXNG_SCHEMA_ERROR_MSG.format(args.relaxng_schema))

View File

@ -1,7 +1,10 @@
# Adapted from http://cairographics.org/freetypepython/
# ruff: noqa: TRY002
import ctypes
import sys
from typing import ClassVar
import cairo
@ -40,7 +43,7 @@ _surface = cairo.ImageSurface(cairo.FORMAT_A8, 0, 0)
class PycairoContext(ctypes.Structure):
_fields_ = [
_fields_: ClassVar = [
("PyObject_HEAD", ctypes.c_byte * object.__basicsize__),
("ctx", ctypes.c_void_p),
("base", ctypes.c_void_p),

View File

@ -22,7 +22,6 @@ import io
import os
import subprocess
from itertools import islice
from typing import List
from i18n_helper import PROJECT_ROOT_DIRECTORY
@ -38,7 +37,7 @@ def get_diff():
return io.StringIO(diff_process.stdout.decode("utf-8"))
def check_diff(diff: io.StringIO) -> List[str]:
def check_diff(diff: io.StringIO) -> list[str]:
"""Check a diff of .po files for meaningful changes.
Run through a diff of .po files and check that some of the changes
@ -87,7 +86,7 @@ def check_diff(diff: io.StringIO) -> List[str]:
return list(files.difference(keep))
def revert_files(files: List[str], verbose=False):
def revert_files(files: list[str], verbose=False):
def batched(iterable, n):
"""Split an iterable in equally sized chunks.

View File

@ -1,6 +1,6 @@
"""Wrapper around babel Catalog / .po handling."""
from datetime import datetime
from datetime import UTC, datetime
from babel.messages.catalog import Catalog as BabelCatalog
from babel.messages.pofile import read_po, write_po
@ -10,7 +10,7 @@ class Catalog(BabelCatalog):
"""Wraps a BabelCatalog for convenience."""
def __init__(self, *args, project=None, copyright_holder=None, **other_kwargs):
date = datetime.now()
date = datetime.now(tz=UTC)
super().__init__(
*args,
header_comment=(

View File

@ -1,12 +1,11 @@
"""Utils to list .po."""
import os
from typing import List, Optional
from i18n_helper.catalog import Catalog
def get_catalogs(input_file_path, filters: Optional[List[str]] = None) -> List[Catalog]:
def get_catalogs(input_file_path, filters: list[str] | None = None) -> list[Catalog]:
"""Return a list of "real" catalogs (.po) in the given folder."""
existing_translation_catalogs = []
l10n_folder_path = os.path.dirname(input_file_path)

View File

@ -97,7 +97,7 @@ PATCHES_EXPECT_REVERT = [
]
@pytest.fixture(params=zip(PATCHES, PATCHES_EXPECT_REVERT))
@pytest.fixture(params=zip(PATCHES, PATCHES_EXPECT_REVERT, strict=False))
def patch(request):
return [io.StringIO(request.param[0]), request.param[1]]

View File

@ -7,11 +7,11 @@ import zero_ad
def dist(p1, p2):
return math.sqrt(sum(math.pow(x2 - x1, 2) for (x1, x2) in zip(p1, p2)))
return math.sqrt(sum(math.pow(x2 - x1, 2) for (x1, x2) in zip(p1, p2, strict=False)))
def center(units):
sum_position = map(sum, zip(*(u.position() for u in units)))
sum_position = map(sum, zip(*(u.position() for u in units), strict=False))
return [x / len(units) for x in sum_position]

View File

@ -11,11 +11,11 @@ with open(path.join(scriptdir, "..", "samples", "arcadia.json"), encoding="utf-8
def dist(p1, p2):
return math.sqrt(sum(math.pow(x2 - x1, 2) for (x1, x2) in zip(p1, p2)))
return math.sqrt(sum(math.pow(x2 - x1, 2) for (x1, x2) in zip(p1, p2, strict=False)))
def center(units):
sum_position = map(sum, zip(*(u.position() for u in units)))
sum_position = map(sum, zip(*(u.position() for u in units), strict=False))
return [x / len(units) for x in sum_position]

View File

@ -26,7 +26,7 @@ class RLAPI:
def get_templates(self, names):
post_data = "\n".join(names)
response = self.post("templates", post_data)
return zip(names, response.decode().split("\n"))
return zip(names, response.decode().split("\n"), strict=False)
def evaluate(self, code):
response = self.post("evaluate", code)

View File

@ -17,7 +17,7 @@ class ZeroAD:
actions = []
player_ids = cycle([self.player_id]) if player is None else cycle(player)
cmds = zip(player_ids, actions)
cmds = zip(player_ids, actions, strict=False)
cmds = ((player, action) for (player, action) in cmds if action is not None)
state_json = self.api.step(cmds)
self.current_state = GameState(json.loads(state_json), self)

View File

@ -46,7 +46,7 @@ def execute(command):
def calculate_hash(path):
assert os.path.isfile(path)
with open(path, "rb") as handle:
return hashlib.sha1(handle.read()).hexdigest()
return hashlib.sha256(handle.read()).hexdigest()
def resolve_if(defines, expression):

View File

@ -201,7 +201,7 @@ class RelaxNGValidator:
try:
doc = lxml.etree.parse(str(file[1]))
relaxng.assertValid(doc)
except Exception:
except (lxml.etree.DocumentInvalid, lxml.etree.XMLSyntaxError):
error_count = error_count + 1
self.logger.exception(file[1])