1
0
mirror of https://github.com/godotengine/godot.git synced 2025-12-01 16:38:31 +00:00

SCons: Integrate annotations where relevant

• Expand Ruff linter to catch & upgrade legacy type-hint syntax
This commit is contained in:
Thaddeus Crews
2024-11-24 10:14:16 -06:00
parent 235a32ad11
commit 11fc998368
9 changed files with 116 additions and 104 deletions

View File

@@ -1,8 +1,9 @@
#!/usr/bin/env python
from __future__ import annotations
from misc.utility.scons_hints import *
import pathlib
from typing import Tuple
import profiling_builders
@@ -11,7 +12,7 @@ Import("env")
env.add_source_files(env.core_sources, "*.cpp")
def get_profiler_and_path_from_path(path: pathlib.Path) -> Tuple[str, pathlib.Path]:
def get_profiler_and_path_from_path(path: pathlib.Path) -> tuple[str, pathlib.Path]:
if not path.is_dir():
print("profiler_path must be empty or point to a directory.")
Exit(255)

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env python3
from __future__ import annotations
import fnmatch
import math
@@ -6,7 +7,6 @@ import os
import re
import sys
import xml.etree.ElementTree as ET
from typing import Dict, List, Set
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../"))
@@ -137,7 +137,7 @@ class ClassStatusProgress:
self.described: int = described
self.total: int = total
def __add__(self, other: "ClassStatusProgress"):
def __add__(self, other: ClassStatusProgress):
return ClassStatusProgress(self.described + other.described, self.total + other.total)
def increment(self, described: bool):
@@ -178,7 +178,7 @@ class ClassStatus:
self.name: str = name
self.has_brief_description: bool = True
self.has_description: bool = True
self.progresses: Dict[str, ClassStatusProgress] = {
self.progresses: dict[str, ClassStatusProgress] = {
"methods": ClassStatusProgress(),
"constants": ClassStatusProgress(),
"members": ClassStatusProgress(),
@@ -188,7 +188,7 @@ class ClassStatus:
"constructors": ClassStatusProgress(),
}
def __add__(self, other: "ClassStatus"):
def __add__(self, other: ClassStatus):
new_status = ClassStatus()
new_status.name = self.name
new_status.has_brief_description = self.has_brief_description and other.has_brief_description
@@ -213,8 +213,8 @@ class ClassStatus:
sum += self.progresses[k].total
return sum < 1
def make_output(self) -> Dict[str, str]:
output: Dict[str, str] = {}
def make_output(self) -> dict[str, str]:
output: dict[str, str] = {}
output["name"] = color("name", self.name)
ok_string = color("part_good", "OK")
@@ -295,8 +295,8 @@ class ClassStatus:
# Arguments #
################################################################################
input_file_list: List[str] = []
input_class_list: List[str] = []
input_file_list: list[str] = []
input_class_list: list[str] = []
merged_file: str = ""
for arg in sys.argv[1:]:
@@ -372,8 +372,8 @@ if len(input_file_list) < 1 or flags["h"]:
# Parse class list #
################################################################################
class_names: List[str] = []
classes: Dict[str, ET.Element] = {}
class_names: list[str] = []
classes: dict[str, ET.Element] = {}
for file in input_file_list:
tree = ET.parse(file)
@@ -389,7 +389,7 @@ class_names.sort()
if len(input_class_list) < 1:
input_class_list = ["*"]
filtered_classes_set: Set[str] = set()
filtered_classes_set: set[str] = set()
for pattern in input_class_list:
filtered_classes_set |= set(fnmatch.filter(class_names, pattern))
filtered_classes = list(filtered_classes_set)
@@ -419,7 +419,7 @@ for cn in filtered_classes:
continue
out = status.make_output()
row: List[str] = []
row: list[str] = []
for column in table_columns:
if column in out:
row.append(out[column])
@@ -456,7 +456,7 @@ if flags["a"]:
# without having to scroll back to the top.
table.append(table_column_names)
table_column_sizes: List[int] = []
table_column_sizes: list[int] = []
for row in table:
for cell_i, cell in enumerate(row):
if cell_i >= len(table_column_sizes):

113
doc/tools/make_rst.py Executable file → Normal file
View File

@@ -1,6 +1,7 @@
#!/usr/bin/env python3
# This script makes RST files from the XML class reference for use with the online docs.
from __future__ import annotations
import argparse
import os
@@ -8,7 +9,7 @@ import re
import sys
import xml.etree.ElementTree as ET
from collections import OrderedDict
from typing import Any, Dict, List, Optional, TextIO, Tuple, Union
from typing import Any, TextIO
sys.path.insert(0, root_directory := os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../"))
@@ -90,10 +91,10 @@ BASE_STRINGS = [
# See also `make_rst_class()` and `editor/doc/editor_help.cpp`.
"[b]Note:[/b] The returned array is [i]copied[/i] and any changes to it will not update the original property value. See [%s] for more details.",
]
strings_l10n: Dict[str, str] = {}
strings_l10n: dict[str, str] = {}
writing_translation = False
CLASS_GROUPS: Dict[str, str] = {
CLASS_GROUPS: dict[str, str] = {
"global": "Globals",
"node": "Nodes",
"resource": "Resources",
@@ -101,21 +102,21 @@ CLASS_GROUPS: Dict[str, str] = {
"editor": "Editor-only",
"variant": "Variant types",
}
CLASS_GROUPS_BASE: Dict[str, str] = {
CLASS_GROUPS_BASE: dict[str, str] = {
"node": "Node",
"resource": "Resource",
"object": "Object",
"variant": "Variant",
}
# Sync with editor\register_editor_types.cpp
EDITOR_CLASSES: List[str] = [
EDITOR_CLASSES: list[str] = [
"FileSystemDock",
"ScriptCreateDialog",
"ScriptEditor",
"ScriptEditorBase",
]
# Sync with the types mentioned in https://docs.godotengine.org/en/stable/tutorials/scripting/c_sharp/c_sharp_differences.html
CLASSES_WITH_CSHARP_DIFFERENCES: List[str] = [
CLASSES_WITH_CSHARP_DIFFERENCES: list[str] = [
"@GlobalScope",
"String",
"StringName",
@@ -147,7 +148,7 @@ CLASSES_WITH_CSHARP_DIFFERENCES: List[str] = [
"Variant",
]
PACKED_ARRAY_TYPES: List[str] = [
PACKED_ARRAY_TYPES: list[str] = [
"PackedByteArray",
"PackedColorArray",
"PackedFloat32Array",
@@ -425,7 +426,7 @@ class State:
self.current_class = ""
def parse_params(self, root: ET.Element, context: str) -> List["ParameterDef"]:
def parse_params(self, root: ET.Element, context: str) -> list[ParameterDef]:
param_elements = root.findall("param")
params: Any = [None] * len(param_elements)
@@ -443,7 +444,7 @@ class State:
params[index] = ParameterDef(param_name, type_name, default)
cast: List[ParameterDef] = params
cast: list[ParameterDef] = params
return cast
@@ -461,7 +462,7 @@ class TagState:
class TypeName:
def __init__(self, type_name: str, enum: Optional[str] = None, is_bitfield: bool = False) -> None:
def __init__(self, type_name: str, enum: str | None = None, is_bitfield: bool = False) -> None:
self.type_name = type_name
self.enum = enum
self.is_bitfield = is_bitfield
@@ -475,7 +476,7 @@ class TypeName:
return make_type(self.type_name, state)
@classmethod
def from_element(cls, element: ET.Element) -> "TypeName":
def from_element(cls, element: ET.Element) -> TypeName:
return cls(element.attrib["type"], element.get("enum"), element.get("is_bitfield") == "true")
@@ -487,8 +488,8 @@ class DefinitionBase:
) -> None:
self.definition_name = definition_name
self.name = name
self.deprecated: Optional[str] = None
self.experimental: Optional[str] = None
self.deprecated: str | None = None
self.experimental: str | None = None
class PropertyDef(DefinitionBase):
@@ -496,11 +497,11 @@ class PropertyDef(DefinitionBase):
self,
name: str,
type_name: TypeName,
setter: Optional[str],
getter: Optional[str],
text: Optional[str],
default_value: Optional[str],
overrides: Optional[str],
setter: str | None,
getter: str | None,
text: str | None,
default_value: str | None,
overrides: str | None,
) -> None:
super().__init__("property", name)
@@ -513,7 +514,7 @@ class PropertyDef(DefinitionBase):
class ParameterDef(DefinitionBase):
def __init__(self, name: str, type_name: TypeName, default_value: Optional[str]) -> None:
def __init__(self, name: str, type_name: TypeName, default_value: str | None) -> None:
super().__init__("parameter", name)
self.type_name = type_name
@@ -521,7 +522,7 @@ class ParameterDef(DefinitionBase):
class SignalDef(DefinitionBase):
def __init__(self, name: str, parameters: List[ParameterDef], description: Optional[str]) -> None:
def __init__(self, name: str, parameters: list[ParameterDef], description: str | None) -> None:
super().__init__("signal", name)
self.parameters = parameters
@@ -532,9 +533,9 @@ class AnnotationDef(DefinitionBase):
def __init__(
self,
name: str,
parameters: List[ParameterDef],
description: Optional[str],
qualifiers: Optional[str],
parameters: list[ParameterDef],
description: str | None,
qualifiers: str | None,
) -> None:
super().__init__("annotation", name)
@@ -548,9 +549,9 @@ class MethodDef(DefinitionBase):
self,
name: str,
return_type: TypeName,
parameters: List[ParameterDef],
description: Optional[str],
qualifiers: Optional[str],
parameters: list[ParameterDef],
description: str | None,
qualifiers: str | None,
) -> None:
super().__init__("method", name)
@@ -561,7 +562,7 @@ class MethodDef(DefinitionBase):
class ConstantDef(DefinitionBase):
def __init__(self, name: str, value: str, text: Optional[str], bitfield: bool) -> None:
def __init__(self, name: str, value: str, text: str | None, bitfield: bool) -> None:
super().__init__("constant", name)
self.value = value
@@ -580,7 +581,7 @@ class EnumDef(DefinitionBase):
class ThemeItemDef(DefinitionBase):
def __init__(
self, name: str, type_name: TypeName, data_name: str, text: Optional[str], default_value: Optional[str]
self, name: str, type_name: TypeName, data_name: str, text: str | None, default_value: str | None
) -> None:
super().__init__("theme property", name)
@@ -600,17 +601,17 @@ class ClassDef(DefinitionBase):
self.constants: OrderedDict[str, ConstantDef] = OrderedDict()
self.enums: OrderedDict[str, EnumDef] = OrderedDict()
self.properties: OrderedDict[str, PropertyDef] = OrderedDict()
self.constructors: OrderedDict[str, List[MethodDef]] = OrderedDict()
self.methods: OrderedDict[str, List[MethodDef]] = OrderedDict()
self.operators: OrderedDict[str, List[MethodDef]] = OrderedDict()
self.constructors: OrderedDict[str, list[MethodDef]] = OrderedDict()
self.methods: OrderedDict[str, list[MethodDef]] = OrderedDict()
self.operators: OrderedDict[str, list[MethodDef]] = OrderedDict()
self.signals: OrderedDict[str, SignalDef] = OrderedDict()
self.annotations: OrderedDict[str, List[AnnotationDef]] = OrderedDict()
self.annotations: OrderedDict[str, list[AnnotationDef]] = OrderedDict()
self.theme_items: OrderedDict[str, ThemeItemDef] = OrderedDict()
self.inherits: Optional[str] = None
self.brief_description: Optional[str] = None
self.description: Optional[str] = None
self.tutorials: List[Tuple[str, str]] = []
self.keywords: Optional[str] = None
self.inherits: str | None = None
self.brief_description: str | None = None
self.description: str | None = None
self.tutorials: list[tuple[str, str]] = []
self.keywords: str | None = None
# Used to match the class with XML source for output filtering purposes.
self.filepath: str = ""
@@ -656,7 +657,7 @@ class ClassDef(DefinitionBase):
# which don't necessarily need C# examples.
class ScriptLanguageParityCheck:
def __init__(self) -> None:
self.hit_map: OrderedDict[str, List[Tuple[DefinitionBase, str]]] = OrderedDict()
self.hit_map: OrderedDict[str, list[tuple[DefinitionBase, str]]] = OrderedDict()
self.hit_count = 0
def add_hit(self, class_name: str, context: DefinitionBase, error: str, state: State) -> None:
@@ -727,7 +728,7 @@ def main() -> None:
print("Checking for errors in the XML class reference...")
file_list: List[str] = []
file_list: list[str] = []
for path in args.path:
# Cut off trailing slashes so os.path.basename doesn't choke.
@@ -751,7 +752,7 @@ def main() -> None:
file_list.append(path)
classes: Dict[str, Tuple[ET.Element, str]] = {}
classes: dict[str, tuple[ET.Element, str]] = {}
state = State()
for cur_file in file_list:
@@ -784,7 +785,7 @@ def main() -> None:
print("Generating the RST class reference...")
grouped_classes: Dict[str, List[str]] = {}
grouped_classes: dict[str, list[str]] = {}
for class_name, class_def in state.classes.items():
if args.filter and not pattern.search(class_def.filepath):
@@ -947,7 +948,7 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
f.write("\n\n")
# Descendants
inherited: List[str] = []
inherited: list[str] = []
for c in state.classes.values():
if c.inherits and c.inherits.strip() == class_name:
inherited.append(c.name)
@@ -1008,7 +1009,7 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
### REFERENCE TABLES ###
# Reused container for reference tables.
ml: List[Tuple[Optional[str], ...]] = []
ml: list[tuple[str | None, ...]] = []
# Properties reference table
if len(class_def.properties) > 0:
@@ -1544,8 +1545,8 @@ def make_enum(t: str, is_bitfield: bool, state: State) -> str:
def make_method_signature(
class_def: ClassDef, definition: Union[AnnotationDef, MethodDef, SignalDef], ref_type: str, state: State
) -> Tuple[str, str]:
class_def: ClassDef, definition: AnnotationDef | MethodDef | SignalDef, ref_type: str, state: State
) -> tuple[str, str]:
ret_type = ""
if isinstance(definition, MethodDef):
@@ -1611,7 +1612,7 @@ def make_setter_signature(class_def: ClassDef, property_def: PropertyDef, state:
setter = class_def.methods[property_def.setter][0]
# Otherwise we fake it with the information we have available.
else:
setter_params: List[ParameterDef] = []
setter_params: list[ParameterDef] = []
setter_params.append(ParameterDef("value", property_def.type_name, None))
setter = MethodDef(property_def.setter, TypeName("void"), setter_params, None, None)
@@ -1628,7 +1629,7 @@ def make_getter_signature(class_def: ClassDef, property_def: PropertyDef, state:
getter = class_def.methods[property_def.getter][0]
# Otherwise we fake it with the information we have available.
else:
getter_params: List[ParameterDef] = []
getter_params: list[ParameterDef] = []
getter = MethodDef(property_def.getter, property_def.type_name, getter_params, None, None)
ret_type, signature = make_method_signature(class_def, getter, "", state)
@@ -1727,7 +1728,7 @@ def make_link(url: str, title: str) -> str:
return f"`{url} <{url}>`__"
def make_rst_index(grouped_classes: Dict[str, List[str]], dry_run: bool, output_dir: str) -> None:
def make_rst_index(grouped_classes: dict[str, list[str]], dry_run: bool, output_dir: str) -> None:
with open(
os.devnull if dry_run else os.path.join(output_dir, "index.rst"), "w", encoding="utf-8", newline="\n"
) as f:
@@ -1792,7 +1793,7 @@ RESERVED_CROSSLINK_TAGS = [
]
def is_in_tagset(tag_text: str, tagset: List[str]) -> bool:
def is_in_tagset(tag_text: str, tagset: list[str]) -> bool:
for tag in tagset:
# Complete match.
if tag_text == tag:
@@ -1834,7 +1835,7 @@ def get_tag_and_args(tag_text: str) -> TagState:
return TagState(tag_text, tag_name, arguments, closing)
def parse_link_target(link_target: str, state: State, context_name: str) -> List[str]:
def parse_link_target(link_target: str, state: State, context_name: str) -> list[str]:
if link_target.find(".") != -1:
return link_target.split(".")
else:
@@ -2082,7 +2083,7 @@ def format_text_block(
valid_param_context = isinstance(context, (MethodDef, SignalDef, AnnotationDef))
if valid_param_context:
context_params: List[ParameterDef] = context.parameters # type: ignore
context_params: list[ParameterDef] = context.parameters # type: ignore
for param_def in context_params:
if param_def.name == inside_code_text:
print_warning(
@@ -2242,7 +2243,7 @@ def format_text_block(
state,
)
else:
context_params: List[ParameterDef] = context.parameters # type: ignore
context_params: list[ParameterDef] = context.parameters # type: ignore
found = False
for param_def in context_params:
if param_def.name == link_target:
@@ -2407,7 +2408,7 @@ def format_text_block(
return text
def preformat_text_block(text: str, state: State) -> Optional[str]:
def preformat_text_block(text: str, state: State) -> str | None:
result = ""
codeblock_tag = ""
indent_level = 0
@@ -2457,7 +2458,7 @@ def preformat_text_block(text: str, state: State) -> Optional[str]:
return result
def format_context_name(context: Union[DefinitionBase, None]) -> str:
def format_context_name(context: DefinitionBase | None) -> str:
context_name: str = "unknown context"
if context is not None:
context_name = f'{context.definition_name} "{context.name}" description'
@@ -2499,7 +2500,7 @@ def escape_rst(text: str, until_pos: int = -1) -> str:
return text
def format_table(f: TextIO, data: List[Tuple[Optional[str], ...]], remove_empty_columns: bool = False) -> None:
def format_table(f: TextIO, data: list[tuple[str | None, ...]], remove_empty_columns: bool = False) -> None:
if len(data) == 0:
return
@@ -2544,7 +2545,7 @@ def format_table(f: TextIO, data: List[Tuple[Optional[str], ...]], remove_empty_
f.write("\n")
def sanitize_class_name(dirty_name: str, is_file_name=False) -> str:
def sanitize_class_name(dirty_name: str, is_file_name: bool = False) -> str:
if is_file_name:
return dirty_name.lower().replace('"', "").replace("/", "--")
else:

View File

@@ -1,3 +1,5 @@
from __future__ import annotations
import atexit
import contextlib
import glob
@@ -9,9 +11,9 @@ import sys
import textwrap
import zlib
from collections import OrderedDict
from io import StringIO, TextIOBase
from io import StringIO
from pathlib import Path
from typing import Generator, List, Optional, Union, cast
from typing import Generator, TextIO, cast
from misc.utility.color import print_error, print_info, print_warning
from platform_methods import detect_arch
@@ -1553,8 +1555,8 @@ def generate_copyright_header(filename: str) -> str:
@contextlib.contextmanager
def generated_wrapper(
path: str,
guard: Optional[bool] = None,
) -> Generator[TextIOBase, None, None]:
guard: bool | None = None,
) -> Generator[TextIO, None, None]:
"""
Wrapper class to automatically handle copyright headers and header guards
for generated scripts. Meant to be invoked via `with` statement similar to
@@ -1626,13 +1628,13 @@ def to_escaped_cstring(value: str) -> str:
return value.translate(C_ESCAPE_TABLE)
def to_raw_cstring(value: Union[str, List[str]]) -> str:
def to_raw_cstring(value: str | list[str]) -> str:
MAX_LITERAL = 16 * 1024
if isinstance(value, list):
value = "\n".join(value) + "\n"
split: List[bytes] = []
split: list[bytes] = []
offset = 0
encoded = value.encode()

View File

@@ -4,10 +4,11 @@
# the Unicode Character Database to the `char_range.inc` file.
# NOTE: This script is deliberately not integrated into the build system;
# you should run it manually whenever you want to update the data.
from __future__ import annotations
import os
import sys
from typing import Final, List, Tuple
from typing import Final
from urllib.request import urlopen
if __name__ == "__main__":
@@ -18,20 +19,20 @@ from methods import generate_copyright_header
URL: Final[str] = "https://www.unicode.org/Public/16.0.0/ucd/DerivedCoreProperties.txt"
xid_start: List[Tuple[int, int]] = []
xid_continue: List[Tuple[int, int]] = []
uppercase_letter: List[Tuple[int, int]] = []
lowercase_letter: List[Tuple[int, int]] = []
unicode_letter: List[Tuple[int, int]] = []
xid_start: list[tuple[int, int]] = []
xid_continue: list[tuple[int, int]] = []
uppercase_letter: list[tuple[int, int]] = []
lowercase_letter: list[tuple[int, int]] = []
unicode_letter: list[tuple[int, int]] = []
def merge_ranges(ranges: List[Tuple[int, int]]) -> None:
def merge_ranges(ranges: list[tuple[int, int]]) -> None:
if len(ranges) < 2:
return
last_start: int = ranges[0][0]
last_end: int = ranges[0][1]
original_ranges: List[Tuple[int, int]] = ranges[1:]
original_ranges: list[tuple[int, int]] = ranges[1:]
ranges.clear()
@@ -47,13 +48,13 @@ def merge_ranges(ranges: List[Tuple[int, int]]) -> None:
def parse_unicode_data() -> None:
lines: List[str] = [line.decode("utf-8") for line in urlopen(URL)]
lines: list[str] = [line.decode("utf-8") for line in urlopen(URL)]
for line in lines:
if line.startswith("#") or not line.strip():
continue
split_line: List[str] = line.split(";")
split_line: list[str] = line.split(";")
char_range: str = split_line[0].strip()
char_property: str = split_line[1].strip().split("#")[0].strip()
@@ -63,7 +64,7 @@ def parse_unicode_data() -> None:
if ".." in char_range:
range_start, range_end = char_range.split("..")
range_tuple: Tuple[int, int] = (int(range_start, 16), int(range_end, 16))
range_tuple: tuple[int, int] = (int(range_start, 16), int(range_end, 16))
if char_property == "XID_Start":
xid_start.append(range_tuple)
@@ -87,7 +88,7 @@ def parse_unicode_data() -> None:
merge_ranges(unicode_letter)
def make_array(array_name: str, range_list: List[Tuple[int, int]]) -> str:
def make_array(array_name: str, range_list: list[tuple[int, int]]) -> str:
result: str = f"\n\nconstexpr inline CharRange {array_name}[] = {{\n"
for start, end in range_list:

View File

@@ -4,10 +4,11 @@
# the Unicode Character Database to the `ucaps.h` file.
# NOTE: This script is deliberately not integrated into the build system;
# you should run it manually whenever you want to update the data.
from __future__ import annotations
import os
import sys
from typing import Final, List, Tuple
from typing import Final
from urllib.request import urlopen
if __name__ == "__main__":
@@ -18,15 +19,15 @@ from methods import generate_copyright_header
URL: Final[str] = "https://www.unicode.org/Public/16.0.0/ucd/UnicodeData.txt"
lower_to_upper: List[Tuple[str, str]] = []
upper_to_lower: List[Tuple[str, str]] = []
lower_to_upper: list[tuple[str, str]] = []
upper_to_lower: list[tuple[str, str]] = []
def parse_unicode_data() -> None:
lines: List[str] = [line.decode("utf-8") for line in urlopen(URL)]
lines: list[str] = [line.decode("utf-8") for line in urlopen(URL)]
for line in lines:
split_line: List[str] = line.split(";")
split_line: list[str] = line.split(";")
code_value: str = split_line[0].strip()
uppercase_mapping: str = split_line[12].strip()
@@ -38,7 +39,7 @@ def parse_unicode_data() -> None:
upper_to_lower.append((f"0x{code_value}", f"0x{lowercase_mapping}"))
def make_cap_table(table_name: str, len_name: str, table: List[Tuple[str, str]]) -> str:
def make_cap_table(table_name: str, len_name: str, table: list[tuple[str, str]]) -> str:
result: str = f"static const int {table_name}[{len_name}][2] = {{\n"
for first, second in table:

View File

@@ -4,10 +4,11 @@
# the Unicode Character Database to the `char_range.inc` file.
# NOTE: This script is deliberately not integrated into the build system;
# you should run it manually whenever you want to update the data.
from __future__ import annotations
import os
import sys
from typing import Final, List, Set, Tuple
from typing import Final
from urllib.request import urlopen
if __name__ == "__main__":
@@ -18,9 +19,9 @@ from methods import generate_copyright_header
URL: Final[str] = "https://www.unicode.org/Public/16.0.0/ucd/Blocks.txt"
ranges: List[Tuple[str, str, str]] = []
ranges: list[tuple[str, str, str]] = []
exclude_blocks: Set[str] = {
exclude_blocks: set[str] = {
"High Surrogates",
"High Private Use Surrogates",
"Low Surrogates",
@@ -33,13 +34,13 @@ exclude_blocks: Set[str] = {
def parse_unicode_data() -> None:
lines: List[str] = [line.decode("utf-8") for line in urlopen(URL)]
lines: list[str] = [line.decode("utf-8") for line in urlopen(URL)]
for line in lines:
if line.startswith("#") or not line.strip():
continue
split_line: List[str] = line.split(";")
split_line: list[str] = line.split(";")
char_range: str = split_line[0].strip()
block: str = split_line[1].strip()
@@ -52,7 +53,7 @@ def parse_unicode_data() -> None:
ranges.append((f"0x{range_start}", f"0x{range_end}", block))
def make_array(array_name: str, ranges: List[Tuple[str, str, str]]) -> str:
def make_array(array_name: str, ranges: list[tuple[str, str, str]]) -> str:
result: str = f"static UniRange {array_name}[] = {{\n"
for start, end, block in ranges:

View File

@@ -1,11 +1,11 @@
#!/usr/bin/python3
from __future__ import annotations
import os
import os.path
import shlex
import subprocess
from dataclasses import dataclass
from typing import List, Optional
def find_dotnet_cli():
@@ -151,7 +151,7 @@ def find_any_msbuild_tool(mono_prefix):
return None
def run_msbuild(tools: ToolsLocation, sln: str, chdir_to: str, msbuild_args: Optional[List[str]] = None):
def run_msbuild(tools: ToolsLocation, sln: str, chdir_to: str, msbuild_args: list[str] | None = None):
using_msbuild_mono = False
# Preference order: dotnet CLI > Standalone MSBuild > Mono's MSBuild

View File

@@ -20,8 +20,13 @@ target-version = "py38"
[tool.ruff.lint]
extend-select = [
"I", # isort
"I", # isort
"UP006", # Use {to} instead of {from} for type annotation
"UP007", # Use `X | Y` for type annotations
"UP037", # Remove quotes from type annotation
"FA", # Future annotations
]
extend-safe-fixes = ["UP006", "UP007", "FA"]
[tool.ruff.lint.per-file-ignores]
"{SConstruct,SCsub}" = [