From d9f8ef68df1df8cf88d484fc22995f55a9c3f9aa Mon Sep 17 00:00:00 2001 From: Jakub Marcowski Date: Tue, 21 May 2024 15:14:59 +0200 Subject: [PATCH] Update pre-commit hooks configuration to use `ruff` instead of `black` --- .pre-commit-config.yaml | 10 +-- SConstruct | 24 +++---- core/SCsub | 14 ++--- core/core_builders.py | 12 ++-- core/extension/SCsub | 2 +- core/extension/make_wrappers.py | 2 - core/input/SCsub | 1 - doc/tools/doc_status.py | 8 +-- doc/tools/make_rst.py | 11 ++-- editor/SCsub | 7 ++- editor/editor_builders.py | 1 + editor/icons/SCsub | 2 +- editor/themes/SCsub | 2 +- gles3_builders.py | 13 ++-- glsl_builders.py | 9 +-- methods.py | 55 ++++++++-------- misc/scripts/install_d3d12_sdk_windows.py | 4 +- modules/SCsub | 3 +- .../mono/build_scripts/build_assemblies.py | 10 +-- modules/mono/build_scripts/mono_configure.py | 4 -- modules/mono/config.py | 2 +- .../gdextension_build/SConstruct | 7 ++- .../gdextension_build/methods.py | 62 +++++++++---------- .../gdextension_build/SConstruct | 5 +- .../gdextension_build/methods.py | 62 +++++++++---------- platform/SCsub | 3 +- platform/android/SCsub | 3 +- platform/android/detect.py | 5 +- platform/ios/SCsub | 6 +- platform/ios/detect.py | 4 +- platform/linuxbsd/detect.py | 6 +- platform/macos/SCsub | 10 +-- platform/macos/detect.py | 8 +-- platform/web/SCsub | 3 +- platform/web/detect.py | 11 ++-- platform/web/emscripten_helpers.py | 7 ++- platform/web/serve.py | 8 +-- platform/windows/SCsub | 1 + platform/windows/detect.py | 14 ++--- platform/windows/platform_windows_builders.py | 4 +- platform_methods.py | 16 ++--- pyproject.toml | 17 ++++- scene/theme/SCsub | 1 - scene/theme/icons/SCsub | 1 - scu_builders.py | 21 +++---- tests/python_build/test_gles3_builder.py | 2 +- tests/python_build/test_glsl_builder.py | 2 +- 47 files changed, 244 insertions(+), 241 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5a0e919c476..cff3d2a22e9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,12 +17,12 @@ repos: platform/android/java/lib/src/com/.* ) - - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.2.0 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.4.4 hooks: - - id: black - files: (\.py$|SConstruct|SCsub) - types_or: [text] + - id: ruff + args: [--fix] + - id: ruff-format - repo: https://github.com/pre-commit/mirrors-mypy rev: v0.971 diff --git a/SConstruct b/SConstruct index afa44fef4a4..7e51ef4fc45 100644 --- a/SConstruct +++ b/SConstruct @@ -10,11 +10,11 @@ import os import pickle import sys import time -from types import ModuleType from collections import OrderedDict -from importlib.util import spec_from_file_location, module_from_spec -from SCons import __version__ as scons_raw_version +from importlib.util import module_from_spec, spec_from_file_location +from types import ModuleType +from SCons import __version__ as scons_raw_version # Explicitly resolve the helper modules, this is done to avoid clash with # modules of the same name that might be randomly added (e.g. someone adding @@ -53,12 +53,12 @@ _helper_module("core.core_builders", "core/core_builders.py") _helper_module("main.main_builders", "main/main_builders.py") # Local -import methods -import glsl_builders import gles3_builders +import glsl_builders +import methods import scu_builders -from methods import print_warning, print_error -from platform_methods import architectures, architecture_aliases +from methods import print_error, print_warning +from platform_methods import architecture_aliases, architectures if ARGUMENTS.get("target", "editor") == "editor": _helper_module("editor.editor_builders", "editor/editor_builders.py") @@ -68,7 +68,7 @@ if ARGUMENTS.get("target", "editor") == "editor": # if sys.stdout.isatty() and sys.platform == "win32": try: - from ctypes import windll, byref, WinError # type: ignore + from ctypes import WinError, byref, windll # type: ignore from ctypes.wintypes import DWORD # type: ignore stdout_handle = windll.kernel32.GetStdHandle(DWORD(-11)) @@ -562,7 +562,7 @@ if env["build_profile"] != "": dbo = ft["disabled_build_options"] for c in dbo: env[c] = dbo[c] - except: + except json.JSONDecodeError: print_error('Failed to open feature build profile: "{}"'.format(env["build_profile"])) Exit(255) @@ -570,7 +570,7 @@ if env["build_profile"] != "": # These can sometimes override default options. flag_list = platform_flags[env["platform"]] for f in flag_list: - if not (f[0] in ARGUMENTS) or ARGUMENTS[f[0]] == "auto": # Allow command line to override platform flags + if f[0] not in ARGUMENTS or ARGUMENTS[f[0]] == "auto": # Allow command line to override platform flags env[f[0]] = f[1] # 'dev_mode' and 'production' are aliases to set default options if they haven't been @@ -591,7 +591,7 @@ if env["production"]: # Run SCU file generation script if in a SCU build. if env["scu_build"]: max_includes_per_scu = 8 - if env.dev_build == True: + if env.dev_build: max_includes_per_scu = 1024 read_scu_limit = int(env["scu_limit"]) @@ -984,7 +984,7 @@ GLSL_BUILDERS = { env.Append(BUILDERS=GLSL_BUILDERS) scons_cache_path = os.environ.get("SCONS_CACHE") -if scons_cache_path != None: +if scons_cache_path is not None: CacheDir(scons_cache_path) print("Scons cache enabled... (path: '" + scons_cache_path + "')") diff --git a/core/SCsub b/core/SCsub index a61c0b5fc23..52f3506416b 100644 --- a/core/SCsub +++ b/core/SCsub @@ -2,10 +2,12 @@ Import("env") -import core_builders -import methods import os +import core_builders + +import methods + env.core_sources = [] # Add required thirdparty code. @@ -188,9 +190,7 @@ def version_info_builder(target, source, env): #define VERSION_WEBSITE "{website}" #define VERSION_DOCS_BRANCH "{docs_branch}" #define VERSION_DOCS_URL "https://docs.godotengine.org/en/" VERSION_DOCS_BRANCH -""".format( - **env.version_info - ) +""".format(**env.version_info) ) @@ -206,9 +206,7 @@ def version_hash_builder(target, source, env): const char *const VERSION_HASH = "{git_hash}"; const uint64_t VERSION_TIMESTAMP = {git_timestamp}; -""".format( - **env.version_info - ) +""".format(**env.version_info) ) diff --git a/core/core_builders.py b/core/core_builders.py index a401f036939..a3dc935b791 100644 --- a/core/core_builders.py +++ b/core/core_builders.py @@ -180,7 +180,7 @@ def make_license_header(target, source, env): return line def next_tag(self): - if not ":" in self.current: + if ":" not in self.current: return ("", []) tag, line = self.current.split(":", 1) lines = [line.strip()] @@ -206,7 +206,7 @@ def make_license_header(target, source, env): if not tag or not reader.current: # end of a paragraph start a new part - if "License" in part and not "Files" in part: + if "License" in part and "Files" not in part: # no Files tag in this one, so assume standalone license license_list.append(part["License"]) part = {} @@ -298,13 +298,13 @@ def make_license_header(target, source, env): f.write("const int LICENSE_COUNT = " + str(len(license_list)) + ";\n") f.write("const char *const LICENSE_NAMES[] = {\n") - for l in license_list: - f.write('\t"' + escape_string(l[0]) + '",\n') + for license in license_list: + f.write('\t"' + escape_string(license[0]) + '",\n') f.write("};\n\n") f.write("const char *const LICENSE_BODIES[] = {\n\n") - for l in license_list: - for line in l[1:]: + for license in license_list: + for line in license[1:]: if line == ".": f.write('\t"\\n"\n') else: diff --git a/core/extension/SCsub b/core/extension/SCsub index 901ceec1e8d..6ab2d2b0a67 100644 --- a/core/extension/SCsub +++ b/core/extension/SCsub @@ -2,8 +2,8 @@ Import("env") -import make_wrappers import make_interface_dumper +import make_wrappers env.CommandNoCache(["ext_wrappers.gen.inc"], "make_wrappers.py", env.Run(make_wrappers.run)) env.CommandNoCache( diff --git a/core/extension/make_wrappers.py b/core/extension/make_wrappers.py index 655b90d2b17..54f4fd5579d 100644 --- a/core/extension/make_wrappers.py +++ b/core/extension/make_wrappers.py @@ -10,7 +10,6 @@ _FORCE_INLINE_ virtual $RETVAL m_name($FUNCARGS) $CONST override { \\ def generate_mod_version(argcount, const=False, returns=False): s = proto_mod sproto = str(argcount) - method_info = "" if returns: sproto += "R" s = s.replace("$RETTYPE", "m_ret, ") @@ -68,7 +67,6 @@ virtual $RETVAL m_name($FUNCARGS) $CONST override { \\ def generate_ex_version(argcount, const=False, returns=False): s = proto_ex sproto = str(argcount) - method_info = "" if returns: sproto += "R" s = s.replace("$RETTYPE", "m_ret, ") diff --git a/core/input/SCsub b/core/input/SCsub index da296371357..d8e6f33156b 100644 --- a/core/input/SCsub +++ b/core/input/SCsub @@ -4,7 +4,6 @@ Import("env") import input_builders - # Order matters here. Higher index controller database files write on top of lower index database files. controller_databases = [ "gamecontrollerdb.txt", diff --git a/doc/tools/doc_status.py b/doc/tools/doc_status.py index a23c11b585d..57c03bfdeef 100755 --- a/doc/tools/doc_status.py +++ b/doc/tools/doc_status.py @@ -1,11 +1,11 @@ #!/usr/bin/env python3 import fnmatch -import os -import sys -import re import math +import os import platform +import re +import sys import xml.etree.ElementTree as ET from typing import Dict, List, Set @@ -286,7 +286,7 @@ class ClassStatus: status.progresses[tag.tag].increment(is_deprecated or is_experimental or has_descr) elif tag.tag in ["constants", "members", "theme_items"]: for sub_tag in list(tag): - if not sub_tag.text is None: + if sub_tag.text is not None: is_deprecated = "deprecated" in sub_tag.attrib is_experimental = "experimental" in sub_tag.attrib has_descr = len(sub_tag.text.strip()) > 0 diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py index 43e1afe7205..bc379f85535 100755 --- a/doc/tools/make_rst.py +++ b/doc/tools/make_rst.py @@ -4,17 +4,16 @@ import argparse import os -import platform import re import sys import xml.etree.ElementTree as ET from collections import OrderedDict -from typing import List, Dict, TextIO, Tuple, Optional, Any, Union +from typing import Any, Dict, List, Optional, TextIO, Tuple, Union # Import hardcoded version information from version.py root_directory = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../") sys.path.append(root_directory) # Include the root directory -import version +import version # noqa: E402 # $DOCS_URL/path/to/page.html(#fragment-tag) GODOT_DOCS_PATTERN = re.compile(r"^\$DOCS_URL/(.*)\.html(#.*)?$") @@ -706,7 +705,7 @@ def main() -> None: # if should_color and sys.stdout.isatty() and sys.platform == "win32": try: - from ctypes import windll, byref, WinError # type: ignore + from ctypes import WinError, byref, windll # type: ignore from ctypes.wintypes import DWORD # type: ignore stdout_handle = windll.kernel32.GetStdHandle(DWORD(-11)) @@ -1413,7 +1412,7 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir: operator_anchor = f".. _class_{class_name}_operator_{sanitize_operator_name(m.name, state)}" for parameter in m.parameters: operator_anchor += f"_{parameter.type_name.type_name}" - operator_anchor += f":\n\n" + operator_anchor += ":\n\n" f.write(operator_anchor) f.write(".. rst-class:: classref-operator\n\n") @@ -1553,7 +1552,7 @@ def make_method_signature( out += f":ref:`{op_name}`" + out += ">`" elif ref_type == "method": ref_type_qualifier = "" if definition.name.startswith("_"): diff --git a/editor/SCsub b/editor/SCsub index e613a712388..029048969ad 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -4,11 +4,12 @@ Import("env") env.editor_sources = [] -import os import glob -import editor_builders -import methods +import os +import editor_builders + +import methods if env.editor_build: # Generate doc data paths diff --git a/editor/editor_builders.py b/editor/editor_builders.py index cfe6e56b493..625d5706666 100644 --- a/editor/editor_builders.py +++ b/editor/editor_builders.py @@ -7,6 +7,7 @@ import subprocess import tempfile import uuid import zlib + from methods import print_warning diff --git a/editor/icons/SCsub b/editor/icons/SCsub index d2d752cff45..0d9ac43c467 100644 --- a/editor/icons/SCsub +++ b/editor/icons/SCsub @@ -3,8 +3,8 @@ Import("env") import os -import editor_icons_builders +import editor_icons_builders env["BUILDERS"]["MakeEditorIconsBuilder"] = Builder( action=env.Run(editor_icons_builders.make_editor_icons_action), diff --git a/editor/themes/SCsub b/editor/themes/SCsub index 65cfb6a8be2..e8f96e42994 100644 --- a/editor/themes/SCsub +++ b/editor/themes/SCsub @@ -3,8 +3,8 @@ Import("env") import glob -import editor_theme_builders +import editor_theme_builders # Fonts flist = glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.ttf") diff --git a/gles3_builders.py b/gles3_builders.py index 1491927febb..a4928c81c5c 100644 --- a/gles3_builders.py +++ b/gles3_builders.py @@ -1,9 +1,10 @@ """Functions used to generate source files during build time""" import os.path -from methods import print_error from typing import Optional +from methods import print_error + class GLES3HeaderStruct: def __init__(self): @@ -91,11 +92,11 @@ def include_file_in_gles3_header(filename: str, header_data: GLES3HeaderStruct, includeline = line.replace("#include ", "").strip()[1:-1] included_file = os.path.relpath(os.path.dirname(filename) + "/" + includeline) - if not included_file in header_data.vertex_included_files and header_data.reading == "vertex": + if included_file not in header_data.vertex_included_files and header_data.reading == "vertex": header_data.vertex_included_files += [included_file] if include_file_in_gles3_header(included_file, header_data, depth + 1) is None: print_error(f'In file "{filename}": #include "{includeline}" could not be found!"') - elif not included_file in header_data.fragment_included_files and header_data.reading == "fragment": + elif included_file not in header_data.fragment_included_files and header_data.reading == "fragment": header_data.fragment_included_files += [included_file] if include_file_in_gles3_header(included_file, header_data, depth + 1) is None: print_error(f'In file "{filename}": #include "{includeline}" could not be found!"') @@ -121,7 +122,7 @@ def include_file_in_gles3_header(filename: str, header_data: GLES3HeaderStruct, # unfiorm array x = x[: x.find("[")] - if not x in header_data.texunit_names: + if x not in header_data.texunit_names: header_data.texunits += [(x, texunit)] header_data.texunit_names += [x] @@ -142,7 +143,7 @@ def include_file_in_gles3_header(filename: str, header_data: GLES3HeaderStruct, # unfiorm array x = x[: x.find("[")] - if not x in header_data.ubo_names: + if x not in header_data.ubo_names: header_data.ubos += [(x, ubo)] header_data.ubo_names += [x] @@ -157,7 +158,7 @@ def include_file_in_gles3_header(filename: str, header_data: GLES3HeaderStruct, # unfiorm array x = x[: x.find("[")] - if not x in header_data.uniforms: + if x not in header_data.uniforms: header_data.uniforms += [x] if (line.strip().find("out ") == 0 or line.strip().find("flat ") == 0) and line.find("tfb:") != -1: diff --git a/glsl_builders.py b/glsl_builders.py index 22f4de74b1f..05aab3acbb3 100644 --- a/glsl_builders.py +++ b/glsl_builders.py @@ -1,8 +1,9 @@ """Functions used to generate source files during build time""" import os.path +from typing import Iterable, Optional + from methods import print_error -from typing import Optional, Iterable def generate_inline_code(input_lines: Iterable[str], insert_newline: bool = True): @@ -77,15 +78,15 @@ def include_file_in_rd_header(filename: str, header_data: RDHeaderStruct, depth: else: included_file = os.path.relpath(os.path.dirname(filename) + "/" + includeline) - if not included_file in header_data.vertex_included_files and header_data.reading == "vertex": + if included_file not in header_data.vertex_included_files and header_data.reading == "vertex": header_data.vertex_included_files += [included_file] if include_file_in_rd_header(included_file, header_data, depth + 1) is None: print_error(f'In file "{filename}": #include "{includeline}" could not be found!"') - elif not included_file in header_data.fragment_included_files and header_data.reading == "fragment": + elif included_file not in header_data.fragment_included_files and header_data.reading == "fragment": header_data.fragment_included_files += [included_file] if include_file_in_rd_header(included_file, header_data, depth + 1) is None: print_error(f'In file "{filename}": #include "{includeline}" could not be found!"') - elif not included_file in header_data.compute_included_files and header_data.reading == "compute": + elif included_file not in header_data.compute_included_files and header_data.reading == "compute": header_data.compute_included_files += [included_file] if include_file_in_rd_header(included_file, header_data, depth + 1) is None: print_error(f'In file "{filename}": #include "{includeline}" could not be found!"') diff --git a/methods.py b/methods.py index da221cc0ea3..7600e6d4456 100644 --- a/methods.py +++ b/methods.py @@ -1,17 +1,14 @@ -import os -import sys -import re -import glob -import subprocess import contextlib +import glob +import os +import re +import subprocess +import sys from collections import OrderedDict -from collections.abc import Mapping from enum import Enum -from typing import Generator, Optional -from io import TextIOWrapper, StringIO +from io import StringIO, TextIOWrapper from pathlib import Path -from os.path import normpath, basename - +from typing import Generator, Optional # Get the "Godot" folder name ahead of time base_folder_path = str(os.path.abspath(Path(__file__).parent)) + "/" @@ -199,7 +196,7 @@ def add_module_version_string(self, s): def get_version_info(module_version_string="", silent=False): build_name = "custom_build" - if os.getenv("BUILD_NAME") != None: + if os.getenv("BUILD_NAME") is not None: build_name = str(os.getenv("BUILD_NAME")) if not silent: print(f"Using custom build name: '{build_name}'.") @@ -221,7 +218,7 @@ def get_version_info(module_version_string="", silent=False): # For dev snapshots (alpha, beta, RC, etc.) we do not commit status change to Git, # so this define provides a way to override it without having to modify the source. - if os.getenv("GODOT_VERSION_STATUS") != None: + if os.getenv("GODOT_VERSION_STATUS") is not None: version_info["status"] = str(os.getenv("GODOT_VERSION_STATUS")) if not silent: print(f"Using version status '{version_info['status']}', overriding the original '{version.status}'.") @@ -435,7 +432,7 @@ def module_check_dependencies(self, module): required_deps = self.module_dependencies[module][0] if module in self.module_dependencies else [] for dep in required_deps: opt = "module_{}_enabled".format(dep) - if not opt in self or not self[opt]: + if opt not in self or not self[opt]: missing_deps.append(dep) if missing_deps != []: @@ -450,7 +447,6 @@ def module_check_dependencies(self, module): def sort_module_list(env): - out = OrderedDict() deps = {k: v[0] + list(filter(lambda x: x in env.module_list, v[1])) for k, v in env.module_dependencies.items()} frontier = list(env.module_list.keys()) @@ -650,7 +646,7 @@ def detect_visual_c_compiler_version(tools_env): def find_visual_c_batch_file(env): - from SCons.Tool.MSCommon.vc import get_default_version, get_host_target, find_batch_file, find_vc_pdir + from SCons.Tool.MSCommon.vc import find_batch_file, find_vc_pdir, get_default_version, get_host_target msvc_version = get_default_version(env) @@ -696,10 +692,7 @@ def glob_recursive(pattern, node="."): def add_to_vs_project(env, sources): for x in sources: - if type(x) == type(""): - fname = env.File(x).path - else: - fname = env.File(x)[0].path + fname = env.File(x).path if isinstance(x, str) else env.File(x)[0].path pieces = fname.split(".") if len(pieces) > 0: basename = pieces[0] @@ -884,7 +877,8 @@ def show_progress(env): return import sys - from SCons.Script import Progress, Command, AlwaysBuild + + from SCons.Script import AlwaysBuild, Command, Progress screen = sys.stdout # Progress reporting is not available in non-TTY environments since it @@ -895,7 +889,8 @@ def show_progress(env): node_count_interval = 1 node_count_fname = str(env.Dir("#")) + "/.scons_node_count" - import time, math + import math + import time class cache_progress: # The default is 1 GB cache and 12 hours half life @@ -903,7 +898,7 @@ def show_progress(env): self.path = path self.limit = limit self.exponent_scale = math.log(2) / half_life - if env["verbose"] and path != None: + if env["verbose"] and path is not None: screen.write( "Current cache limit is {} (used: {})\n".format( self.convert_size(limit), self.convert_size(self.get_size(path)) @@ -1049,11 +1044,11 @@ def generate_vs_project(env, original_args, project_name="godot"): if type(f) is Node.FS.Dir: results += glob_recursive_2(pattern, dirs, f) r = Glob(str(node) + "/" + pattern, source=True) - if len(r) > 0 and not str(node) in dirs: + if len(r) > 0 and str(node) not in dirs: d = "" for part in str(node).split("\\"): d += part - if not d in dirs: + if d not in dirs: dirs.append(d) d += "\\" results += r @@ -1066,7 +1061,7 @@ def generate_vs_project(env, original_args, project_name="godot"): if val is not None: try: return _text2bool(val) - except: + except (ValueError, AttributeError): return default else: return default @@ -1239,13 +1234,13 @@ def generate_vs_project(env, original_args, project_name="godot"): others_active = [] for x in envsources: fname = "" - if type(x) == type(""): + if isinstance(x, str): fname = env.File(x).path else: # Some object files might get added directly as a File object and not a list. try: fname = env.File(x)[0].path - except: + except Exception: fname = x.path pass @@ -1324,7 +1319,7 @@ def generate_vs_project(env, original_args, project_name="godot"): itemlist = {} for item in activeItems: key = os.path.dirname(item).replace("\\", "_") - if not key in itemlist: + if key not in itemlist: itemlist[key] = [item] else: itemlist[key] += [item] @@ -1465,14 +1460,14 @@ def generate_vs_project(env, original_args, project_name="godot"): if godot_platform != "windows": configurations += [ f'', - f" editor", + " editor", f" {proj_plat}", "", ] properties += [ f"", - f" editor", + " editor", f" {proj_plat}", "", ] diff --git a/misc/scripts/install_d3d12_sdk_windows.py b/misc/scripts/install_d3d12_sdk_windows.py index aed80d81a46..d7574e6222b 100755 --- a/misc/scripts/install_d3d12_sdk_windows.py +++ b/misc/scripts/install_d3d12_sdk_windows.py @@ -1,15 +1,15 @@ #!/usr/bin/env python import os -import urllib.request import shutil import subprocess import sys +import urllib.request # Enable ANSI escape code support on Windows 10 and later (for colored console output). # if sys.platform == "win32": - from ctypes import windll, c_int, byref + from ctypes import byref, c_int, windll stdout_handle = windll.kernel32.GetStdHandle(c_int(-11)) mode = c_int(0) diff --git a/modules/SCsub b/modules/SCsub index 739c5de0b55..db0e563dc4d 100644 --- a/modules/SCsub +++ b/modules/SCsub @@ -1,8 +1,9 @@ #!/usr/bin/env python -import methods import os +import methods + Import("env") env_modules = env.Clone() diff --git a/modules/mono/build_scripts/build_assemblies.py b/modules/mono/build_scripts/build_assemblies.py index f9709362ebc..efbf298f990 100755 --- a/modules/mono/build_scripts/build_assemblies.py +++ b/modules/mono/build_scripts/build_assemblies.py @@ -5,7 +5,7 @@ import os.path import shlex import subprocess from dataclasses import dataclass -from typing import Optional, List +from typing import List, Optional def find_dotnet_cli(): @@ -304,9 +304,7 @@ def generate_sdk_package_versions(): {1} -""".format( - version_str, ";".join(version_defines) - ) +""".format(version_str, ";".join(version_defines)) # We write in ../SdkPackageVersions.props. with open(os.path.join(dirname(script_path), "SdkPackageVersions.props"), "w", encoding="utf-8", newline="\n") as f: @@ -323,9 +321,7 @@ def generate_sdk_package_versions(): public const string VersionDocsUrl = "https://docs.godotengine.org/en/{docs_branch}"; }} }} -""".format( - **version_info - ) +""".format(**version_info) generators_dir = os.path.join( dirname(script_path), diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py index e5469c4980c..98c50dcc228 100644 --- a/modules/mono/build_scripts/mono_configure.py +++ b/modules/mono/build_scripts/mono_configure.py @@ -1,7 +1,3 @@ -import os -import os.path - - def is_desktop(platform): return platform in ["windows", "macos", "linuxbsd"] diff --git a/modules/mono/config.py b/modules/mono/config.py index 3d087c9e27b..5ebdb83b366 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -12,7 +12,7 @@ def configure(env): # Check if the platform has marked mono as supported. supported = env.get("supported", []) - if not "mono" in supported: + if "mono" not in supported: raise RuntimeError("This module does not currently support building for this platform") env.add_module_version_string("mono") diff --git a/modules/text_server_adv/gdextension_build/SConstruct b/modules/text_server_adv/gdextension_build/SConstruct index 58e1868e31f..2f7a175d918 100644 --- a/modules/text_server_adv/gdextension_build/SConstruct +++ b/modules/text_server_adv/gdextension_build/SConstruct @@ -1,14 +1,15 @@ #!/usr/bin/env python import atexit import sys -import methods import time +import methods + # Enable ANSI escape code support on Windows 10 and later (for colored console output). # if sys.stdout.isatty() and sys.platform == "win32": try: - from ctypes import windll, byref, WinError # type: ignore + from ctypes import WinError, byref, windll # type: ignore from ctypes.wintypes import DWORD # type: ignore stdout_handle = windll.kernel32.GetStdHandle(DWORD(-11)) @@ -720,7 +721,7 @@ if env["static_icu_data"]: env.Append(CXXFLAGS=["-DICU_STATIC_DATA"]) env.Append(CPPPATH=["../../../thirdparty/icu4c/"]) else: - thirdparty_sources += ["../icu_data/icudata_stub.cpp"] + thirdparty_icu_sources += ["../icu_data/icudata_stub.cpp"] env_icu.Append(CPPPATH=["../../../thirdparty/icu4c/common/", "../../../thirdparty/icu4c/i18n/"]) env_icu.Append( diff --git a/modules/text_server_adv/gdextension_build/methods.py b/modules/text_server_adv/gdextension_build/methods.py index 3453c3e8f02..43bf56abfee 100644 --- a/modules/text_server_adv/gdextension_build/methods.py +++ b/modules/text_server_adv/gdextension_build/methods.py @@ -81,9 +81,9 @@ def disable_warnings(self): self.Append(CCFLAGS=["/w"]) self.Append(CFLAGS=["/w"]) self.Append(CXXFLAGS=["/w"]) - self["CCFLAGS"] = [x for x in self["CCFLAGS"] if not x in warn_flags] - self["CFLAGS"] = [x for x in self["CFLAGS"] if not x in warn_flags] - self["CXXFLAGS"] = [x for x in self["CXXFLAGS"] if not x in warn_flags] + self["CCFLAGS"] = [x for x in self["CCFLAGS"] if x not in warn_flags] + self["CFLAGS"] = [x for x in self["CFLAGS"] if x not in warn_flags] + self["CXXFLAGS"] = [x for x in self["CXXFLAGS"] if x not in warn_flags] else: self.Append(CCFLAGS=["-w"]) self.Append(CFLAGS=["-w"]) @@ -117,31 +117,31 @@ def make_icu_data(target, source, env): def write_macos_plist(target, binary_name, identifier, name): os.makedirs(f"{target}/Resource/", exist_ok=True) with open(f"{target}/Resource/Info.plist", "w", encoding="utf-8", newline="\n") as f: - f.write(f'\n') - f.write( - f'\n' - ) - f.write(f'\n') - f.write(f"\n") - f.write(f"\tCFBundleExecutable\n") - f.write(f"\t{binary_name}\n") - f.write(f"\tCFBundleIdentifier\n") - f.write(f"\t{identifier}\n") - f.write(f"\tCFBundleInfoDictionaryVersion\n") - f.write(f"\t6.0\n") - f.write(f"\tCFBundleName\n") - f.write(f"\t{name}\n") - f.write(f"\tCFBundlePackageType\n") - f.write(f"\tFMWK\n") - f.write(f"\tCFBundleShortVersionString\n") - f.write(f"\t1.0.0\n") - f.write(f"\tCFBundleSupportedPlatforms\n") - f.write(f"\t\n") - f.write(f"\t\tMacOSX\n") - f.write(f"\t\n") - f.write(f"\tCFBundleVersion\n") - f.write(f"\t1.0.0\n") - f.write(f"\tLSMinimumSystemVersion\n") - f.write(f"\t10.14\n") - f.write(f"\n") - f.write(f"\n") + f.write(f"""\ + + + + + CFBundleExecutable + {binary_name} + CFBundleIdentifier + {identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + {name} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1.0.0 + LSMinimumSystemVersion + 10.14 + + +""") diff --git a/modules/text_server_fb/gdextension_build/SConstruct b/modules/text_server_fb/gdextension_build/SConstruct index 9326a53026e..f6ae7149bee 100644 --- a/modules/text_server_fb/gdextension_build/SConstruct +++ b/modules/text_server_fb/gdextension_build/SConstruct @@ -1,14 +1,15 @@ #!/usr/bin/env python import atexit import sys -import methods import time +import methods + # Enable ANSI escape code support on Windows 10 and later (for colored console output). # if sys.stdout.isatty() and sys.platform == "win32": try: - from ctypes import windll, byref, WinError # type: ignore + from ctypes import WinError, byref, windll # type: ignore from ctypes.wintypes import DWORD # type: ignore stdout_handle = windll.kernel32.GetStdHandle(DWORD(-11)) diff --git a/modules/text_server_fb/gdextension_build/methods.py b/modules/text_server_fb/gdextension_build/methods.py index 3453c3e8f02..43bf56abfee 100644 --- a/modules/text_server_fb/gdextension_build/methods.py +++ b/modules/text_server_fb/gdextension_build/methods.py @@ -81,9 +81,9 @@ def disable_warnings(self): self.Append(CCFLAGS=["/w"]) self.Append(CFLAGS=["/w"]) self.Append(CXXFLAGS=["/w"]) - self["CCFLAGS"] = [x for x in self["CCFLAGS"] if not x in warn_flags] - self["CFLAGS"] = [x for x in self["CFLAGS"] if not x in warn_flags] - self["CXXFLAGS"] = [x for x in self["CXXFLAGS"] if not x in warn_flags] + self["CCFLAGS"] = [x for x in self["CCFLAGS"] if x not in warn_flags] + self["CFLAGS"] = [x for x in self["CFLAGS"] if x not in warn_flags] + self["CXXFLAGS"] = [x for x in self["CXXFLAGS"] if x not in warn_flags] else: self.Append(CCFLAGS=["-w"]) self.Append(CFLAGS=["-w"]) @@ -117,31 +117,31 @@ def make_icu_data(target, source, env): def write_macos_plist(target, binary_name, identifier, name): os.makedirs(f"{target}/Resource/", exist_ok=True) with open(f"{target}/Resource/Info.plist", "w", encoding="utf-8", newline="\n") as f: - f.write(f'\n') - f.write( - f'\n' - ) - f.write(f'\n') - f.write(f"\n") - f.write(f"\tCFBundleExecutable\n") - f.write(f"\t{binary_name}\n") - f.write(f"\tCFBundleIdentifier\n") - f.write(f"\t{identifier}\n") - f.write(f"\tCFBundleInfoDictionaryVersion\n") - f.write(f"\t6.0\n") - f.write(f"\tCFBundleName\n") - f.write(f"\t{name}\n") - f.write(f"\tCFBundlePackageType\n") - f.write(f"\tFMWK\n") - f.write(f"\tCFBundleShortVersionString\n") - f.write(f"\t1.0.0\n") - f.write(f"\tCFBundleSupportedPlatforms\n") - f.write(f"\t\n") - f.write(f"\t\tMacOSX\n") - f.write(f"\t\n") - f.write(f"\tCFBundleVersion\n") - f.write(f"\t1.0.0\n") - f.write(f"\tLSMinimumSystemVersion\n") - f.write(f"\t10.14\n") - f.write(f"\n") - f.write(f"\n") + f.write(f"""\ + + + + + CFBundleExecutable + {binary_name} + CFBundleIdentifier + {identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + {name} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1.0.0 + LSMinimumSystemVersion + 10.14 + + +""") diff --git a/platform/SCsub b/platform/SCsub index b24c1898484..b07023efedc 100644 --- a/platform/SCsub +++ b/platform/SCsub @@ -1,9 +1,10 @@ #!/usr/bin/env python -import methods from glob import glob from pathlib import Path +import methods + Import("env") env.platform_sources = [] diff --git a/platform/android/SCsub b/platform/android/SCsub index 4d76ffb1800..bc1b5e9200b 100644 --- a/platform/android/SCsub +++ b/platform/android/SCsub @@ -1,7 +1,8 @@ #!/usr/bin/env python -import sys import subprocess +import sys + from methods import print_warning Import("env") diff --git a/platform/android/detect.py b/platform/android/detect.py index 6a8c4ed86d6..485f31dee20 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -1,10 +1,11 @@ import os -import sys import platform import subprocess -from methods import print_warning, print_error +import sys from typing import TYPE_CHECKING +from methods import print_error, print_warning + if TYPE_CHECKING: from SCons.Script.SConscript import SConsEnvironment diff --git a/platform/ios/SCsub b/platform/ios/SCsub index f38914434b2..cff7dcc1fd1 100644 --- a/platform/ios/SCsub +++ b/platform/ios/SCsub @@ -2,11 +2,11 @@ Import("env") -import os, json -from platform_methods import architectures, lipo, get_build_version, detect_mvk -import subprocess +import os import shutil +from platform_methods import detect_mvk, lipo + def generate_bundle(target, source, env): bin_dir = Dir("#bin").abspath diff --git a/platform/ios/detect.py b/platform/ios/detect.py index e3bac4ec5ce..eb233a5d547 100644 --- a/platform/ios/detect.py +++ b/platform/ios/detect.py @@ -1,9 +1,9 @@ import os import sys -from methods import print_error, detect_darwin_sdk_path - from typing import TYPE_CHECKING +from methods import detect_darwin_sdk_path, print_error + if TYPE_CHECKING: from SCons.Script.SConscript import SConsEnvironment diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index 47f3bcadc97..28825038ca4 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -1,11 +1,11 @@ import os import platform import sys -from methods import print_warning, print_error, get_compiler_version, using_gcc -from platform_methods import detect_arch - from typing import TYPE_CHECKING +from methods import get_compiler_version, print_error, print_warning, using_gcc +from platform_methods import detect_arch + if TYPE_CHECKING: from SCons.Script.SConscript import SConsEnvironment diff --git a/platform/macos/SCsub b/platform/macos/SCsub index 59ef4ee85c4..eb8524826f3 100644 --- a/platform/macos/SCsub +++ b/platform/macos/SCsub @@ -2,11 +2,13 @@ Import("env") -import os, json -from platform_methods import architectures, lipo, get_build_version -import platform_macos_builders -import subprocess +import os import shutil +import subprocess + +import platform_macos_builders + +from platform_methods import get_build_version, lipo def generate_bundle(target, source, env): diff --git a/platform/macos/detect.py b/platform/macos/detect.py index a5ef29e34f3..f02f693dd96 100644 --- a/platform/macos/detect.py +++ b/platform/macos/detect.py @@ -1,10 +1,10 @@ import os import sys -from methods import print_error, detect_darwin_sdk_path, get_compiler_version, is_vanilla_clang -from platform_methods import detect_arch, detect_mvk - from typing import TYPE_CHECKING +from methods import detect_darwin_sdk_path, get_compiler_version, is_vanilla_clang, print_error +from platform_methods import detect_arch, detect_mvk + if TYPE_CHECKING: from SCons.Script.SConscript import SConsEnvironment @@ -107,7 +107,7 @@ def configure(env: "SConsEnvironment"): env.Append(CCFLAGS=["-fobjc-arc"]) - if not "osxcross" in env: # regular native build + if "osxcross" not in env: # regular native build if env["macports_clang"] != "no": mpprefix = os.environ.get("MACPORTS_PREFIX", "/opt/local") mpclangver = env["macports_clang"] diff --git a/platform/web/SCsub b/platform/web/SCsub index bc5893ab3ad..fea2fa7df95 100644 --- a/platform/web/SCsub +++ b/platform/web/SCsub @@ -6,9 +6,10 @@ Import("env") # The HTTP server "targets". Run with "scons p=web serve", or "scons p=web run" if "serve" in COMMAND_LINE_TARGETS or "run" in COMMAND_LINE_TARGETS: - from serve import serve import os + from serve import serve + port = os.environ.get("GODOT_WEB_TEST_PORT", 8060) try: port = int(port) diff --git a/platform/web/detect.py b/platform/web/detect.py index ccd884b2255..524ff44f4d7 100644 --- a/platform/web/detect.py +++ b/platform/web/detect.py @@ -1,18 +1,19 @@ import os import sys +from typing import TYPE_CHECKING from emscripten_helpers import ( - run_closure_compiler, - create_engine_file, + add_js_externs, add_js_libraries, add_js_pre, - add_js_externs, + create_engine_file, create_template_zip, get_template_zip_path, + run_closure_compiler, ) -from methods import print_warning, print_error, get_compiler_version from SCons.Util import WhereIs -from typing import TYPE_CHECKING + +from methods import get_compiler_version, print_error, print_warning if TYPE_CHECKING: from SCons.Script.SConscript import SConsEnvironment diff --git a/platform/web/emscripten_helpers.py b/platform/web/emscripten_helpers.py index 3ba133c9a10..745b2457fa7 100644 --- a/platform/web/emscripten_helpers.py +++ b/platform/web/emscripten_helpers.py @@ -1,4 +1,5 @@ -import os, json +import json +import os from SCons.Util import WhereIs @@ -24,13 +25,13 @@ def get_build_version(): import version name = "custom_build" - if os.getenv("BUILD_NAME") != None: + if os.getenv("BUILD_NAME") is not None: name = os.getenv("BUILD_NAME") v = "%d.%d" % (version.major, version.minor) if version.patch > 0: v += ".%d" % version.patch status = version.status - if os.getenv("GODOT_VERSION_STATUS") != None: + if os.getenv("GODOT_VERSION_STATUS") is not None: status = str(os.getenv("GODOT_VERSION_STATUS")) v += ".%s.%s" % (status, name) return v diff --git a/platform/web/serve.py b/platform/web/serve.py index 89dff63ca30..f0b0ec96227 100755 --- a/platform/web/serve.py +++ b/platform/web/serve.py @@ -1,13 +1,13 @@ #!/usr/bin/env python3 -from http.server import HTTPServer, SimpleHTTPRequestHandler, test # type: ignore -from pathlib import Path -import os -import sys import argparse import contextlib +import os import socket import subprocess +import sys +from http.server import HTTPServer, SimpleHTTPRequestHandler, test # type: ignore +from pathlib import Path # See cpython GH-17851 and GH-17864. diff --git a/platform/windows/SCsub b/platform/windows/SCsub index 435c501956c..1c2bfb9b75e 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -4,6 +4,7 @@ Import("env") import os from pathlib import Path + import platform_windows_builders sources = [] diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 93eb34001e9..b66cdadc41d 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -1,12 +1,12 @@ -import methods import os import subprocess import sys -from methods import print_warning, print_error -from platform_methods import detect_arch - from typing import TYPE_CHECKING +import methods +from methods import print_error, print_warning +from platform_methods import detect_arch + if TYPE_CHECKING: from SCons.Script.SConscript import SConsEnvironment @@ -178,7 +178,7 @@ def get_opts(): caller_frame = inspect.stack()[1] caller_script_dir = os.path.dirname(os.path.abspath(caller_frame[1])) d3d12_deps_folder = os.path.join(caller_script_dir, "bin", "build_deps") - except: # Give up. + except Exception: # Give up. d3d12_deps_folder = "" return [ @@ -523,7 +523,7 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config): env.Append(CXXFLAGS=["/bigobj"]) # PIX - if not env["arch"] in ["x86_64", "arm64"] or env["pix_path"] == "" or not os.path.exists(env["pix_path"]): + if env["arch"] not in ["x86_64", "arm64"] or env["pix_path"] == "" or not os.path.exists(env["pix_path"]): env["use_pix"] = False if env["use_pix"]: @@ -750,7 +750,7 @@ def configure_mingw(env: "SConsEnvironment"): env.Append(LIBS=["dxgi", "dxguid"]) # PIX - if not env["arch"] in ["x86_64", "arm64"] or env["pix_path"] == "" or not os.path.exists(env["pix_path"]): + if env["arch"] not in ["x86_64", "arm64"] or env["pix_path"] == "" or not os.path.exists(env["pix_path"]): env["use_pix"] = False if env["use_pix"]: diff --git a/platform/windows/platform_windows_builders.py b/platform/windows/platform_windows_builders.py index 729d55cea61..3fd9e1a5813 100644 --- a/platform/windows/platform_windows_builders.py +++ b/platform/windows/platform_windows_builders.py @@ -1,8 +1,8 @@ """Functions used to generate source files during build time""" import os -from detect import get_mingw_bin_prefix -from detect import try_cmd + +from detect import get_mingw_bin_prefix, try_cmd def make_debug_mingw(target, source, env): diff --git a/platform_methods.py b/platform_methods.py index 5326e36077f..2b157da22b7 100644 --- a/platform_methods.py +++ b/platform_methods.py @@ -1,10 +1,7 @@ import os -import sys -import json import platform -import uuid -import functools import subprocess + import methods # NOTE: The multiprocessing module is not compatible with SCons due to conflict on cPickle @@ -47,14 +44,14 @@ def get_build_version(short): import version name = "custom_build" - if os.getenv("BUILD_NAME") != None: + if os.getenv("BUILD_NAME") is not None: name = os.getenv("BUILD_NAME") v = "%d.%d" % (version.major, version.minor) if version.patch > 0: v += ".%d" % version.patch status = version.status if not short: - if os.getenv("GODOT_VERSION_STATUS") != None: + if os.getenv("GODOT_VERSION_STATUS") is not None: status = str(os.getenv("GODOT_VERSION_STATUS")) v += ".%s.%s" % (status, name) return v @@ -86,7 +83,7 @@ def get_mvk_sdk_path(osname): def int_or_zero(i): try: return int(i) - except: + except (TypeError, ValueError): return 0 def ver_parse(a): @@ -140,9 +137,8 @@ def detect_mvk(env, osname): ) for mvk_path in mvk_list: - if mvk_path and os.path.isfile(os.path.join(mvk_path, osname + "/libMoltenVK.a")): - mvk_found = True - print("MoltenVK found at: " + mvk_path) + if mvk_path and os.path.isfile(os.path.join(mvk_path, f"{osname}/libMoltenVK.a")): + print(f"MoltenVK found at: {mvk_path}") return mvk_path return "" diff --git a/pyproject.toml b/pyproject.toml index f1ea10fbaec..34ae075f2ba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,6 +11,19 @@ namespace_packages = true explicit_package_bases = true exclude = ["thirdparty/"] -[tool.black] +[tool.ruff] +extend-exclude = ["thirdparty"] +extend-include = ["SConstruct", "SCsub"] line-length = 120 -extend-exclude = ".*thirdparty/.*" +target-version = "py37" + +[tool.ruff.lint] +extend-select = [ + "I", # isort +] + +[tool.ruff.lint.per-file-ignores] +"{SConstruct,SCsub}" = [ + "E402", # Module level import not at top of file + "F821", # Undefined name +] diff --git a/scene/theme/SCsub b/scene/theme/SCsub index 5f62ae4b05a..2372d1820a5 100644 --- a/scene/theme/SCsub +++ b/scene/theme/SCsub @@ -4,7 +4,6 @@ Import("env") import default_theme_builders - env.add_source_files(env.scene_sources, "*.cpp") SConscript("icons/SCsub") diff --git a/scene/theme/icons/SCsub b/scene/theme/icons/SCsub index 46133ccceb9..1f3b7f6d178 100644 --- a/scene/theme/icons/SCsub +++ b/scene/theme/icons/SCsub @@ -4,7 +4,6 @@ Import("env") import default_theme_icons_builders - env["BUILDERS"]["MakeDefaultThemeIconsBuilder"] = Builder( action=env.Run(default_theme_icons_builders.make_default_theme_icons_action), suffix=".h", diff --git a/scu_builders.py b/scu_builders.py index a9ae4282228..fc5461196f9 100644 --- a/scu_builders.py +++ b/scu_builders.py @@ -1,11 +1,11 @@ -"""Functions used to generate scu build source files during build time -""" +"""Functions used to generate scu build source files during build time""" -import glob, os +import glob import math -from methods import print_error +import os from pathlib import Path -from os.path import normpath, basename + +from methods import print_error base_folder_path = str(Path(__file__).parent) + "/" base_folder_only = os.path.basename(os.path.normpath(base_folder_path)) @@ -25,7 +25,7 @@ def clear_out_stale_files(output_folder, extension, fresh_files): for file in glob.glob(output_folder + "/*." + extension): file = Path(file) - if not file in fresh_files: + if file not in fresh_files: # print("removed stale file: " + str(file)) os.remove(file) @@ -56,7 +56,7 @@ def find_files_in_folder(folder, sub_folder, include_list, extension, sought_exc li = '#include "' + folder + "/" + sub_folder_slashed + file + '"' - if not simple_name in sought_exceptions: + if simple_name not in sought_exceptions: include_list.append(li) else: found_exceptions.append(li) @@ -78,9 +78,9 @@ def write_output_file(file_count, include_list, start_line, end_line, output_fol file_text = "" - for l in range(start_line, end_line): - if l < len(include_list): - line = include_list[l] + for i in range(start_line, end_line): + if i < len(include_list): + line = include_list[i] li = line + "\n" file_text += li @@ -221,7 +221,6 @@ def process_folder(folders, sought_exceptions=[], includes_per_scu=0, extension= lines_per_file = max(lines_per_file, 1) start_line = 0 - file_number = 0 # These do not vary throughout the loop output_folder = abs_main_folder + "/scu/" diff --git a/tests/python_build/test_gles3_builder.py b/tests/python_build/test_gles3_builder.py index 6f16139eb97..b34d33bde7e 100644 --- a/tests/python_build/test_gles3_builder.py +++ b/tests/python_build/test_gles3_builder.py @@ -2,7 +2,7 @@ import json import pytest -from gles3_builders import build_gles3_header, GLES3HeaderStruct +from gles3_builders import GLES3HeaderStruct, build_gles3_header @pytest.mark.parametrize( diff --git a/tests/python_build/test_glsl_builder.py b/tests/python_build/test_glsl_builder.py index 348ef8441cd..9f548855ffc 100644 --- a/tests/python_build/test_glsl_builder.py +++ b/tests/python_build/test_glsl_builder.py @@ -2,7 +2,7 @@ import json import pytest -from glsl_builders import build_raw_header, RAWHeaderStruct, build_rd_header, RDHeaderStruct +from glsl_builders import RAWHeaderStruct, RDHeaderStruct, build_raw_header, build_rd_header @pytest.mark.parametrize(