build: typecheck the python code (#5269)
continuous-integration/drone/push Build is passing

add pyright to project,
add it to pre-commit
fix all errors it detects

Co-authored-by: Darragh Elliott <me@delliott.net>
Reviewed-on: #5269
This commit was merged in pull request #5269.
This commit is contained in:
2025-08-30 17:11:44 +00:00
co-authored by Darragh Elliott
parent f03b3c2c4c
commit c8f54f19cb
23 changed files with 158 additions and 69 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ from fsfe_website_build.lib.misc import get_basename, get_version, lang_from_fil
logger = logging.getLogger(__name__)
def _get_xmls(file: Path, parser: etree.XMLParser) -> etree.Element:
def _get_xmls(file: Path, parser: etree.XMLParser) -> list:
"""
include second level elements of a given XML file
this emulates the behaviour of the original
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import logging
import multiprocessing
import multiprocessing.pool
from itertools import product
from pathlib import Path
@@ -24,7 +24,7 @@ def _do_symlinking(link_type: str, lang: str) -> None:
source.symlink_to(target.relative_to(source.parent))
def global_symlinks(languages: list[str], pool: multiprocessing.Pool) -> None:
def global_symlinks(languages: list[str], pool: multiprocessing.pool.Pool) -> None:
"""
After this step, the following symlinks will exist:
* global/data/texts/.texts.<lang>.xml for each language
@@ -19,7 +19,7 @@ def prepare_early_subdirectories(source_dir: Path, processes: int) -> None:
sys.path.append(str(subdir_path.resolve()))
# Ignore this very sensible warning, as we do evil things
# here for out subdir scripts
import early_subdir # noqa: PLC0415
import early_subdir # noqa: PLC0415 # pyright: ignore [reportMissingImports]
early_subdir.run(processes, subdir_path)
# Remove its path from where things can be imported
@@ -6,7 +6,7 @@
import json
import logging
import multiprocessing
import multiprocessing.pool
from pathlib import Path
import iso639
@@ -74,7 +74,7 @@ def _process_file(file: Path, stopwords: set[str]) -> dict:
def index_websites(
source_dir: Path,
languages: list[str],
pool: multiprocessing.Pool,
pool: multiprocessing.pool.Pool,
) -> None:
"""
Generate a search index for all sites that have a search/search.js file
@@ -23,7 +23,7 @@ def prepare_subdirectories(
sys.path.append(str(subdir_path.resolve()))
# Ignore this very sensible warning, as we do evil things
# here for out subdir scripts
import subdir # noqa: PLC0415
import subdir # noqa: PLC0415 # pyright: ignore [reportMissingImports]
subdir.run(languages, processes, subdir_path)
# Remove its path from where things can be imported
+3 -3
View File
@@ -11,7 +11,7 @@
# directory tree and does not touch the target directory tree at all.
# -----------------------------------------------------------------------------
import logging
import multiprocessing
import multiprocessing.pool
from pathlib import Path
from .index_website import index_websites
@@ -28,9 +28,9 @@ logger = logging.getLogger(__name__)
def phase1_run(
source_dir: Path,
languages: list[str] or None,
languages: list[str],
processes: int,
pool: multiprocessing.Pool,
pool: multiprocessing.pool.Pool,
) -> None:
"""
Run all the necessary sub functions for phase1.
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import logging
import multiprocessing
import multiprocessing.pool
from pathlib import Path
logger = logging.getLogger(__name__)
@@ -22,7 +22,7 @@ def _do_symlinking(directory: Path) -> None:
)
def update_defaultxsls(source_dir: Path, pool: multiprocessing.Pool) -> None:
def update_defaultxsls(source_dir: Path, pool: multiprocessing.pool.Pool) -> None:
"""
Place a .default.xsl into each directory containing source files for
HTML pages (*.xhtml). These .default.xsl are symlinks to the first
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import logging
import multiprocessing
import multiprocessing.pool
from pathlib import Path
from lxml import etree
@@ -32,9 +32,9 @@ def _write_localmenus(
version = etree.SubElement(page, "version")
version.text = "1"
for source_file in filter(
lambda path: path is not None,
(
for source_file in [
path
for path in (
base_file.with_suffix(f".{lang}.xhtml")
if base_file.with_suffix(f".{lang}.xhtml").exists()
else (
@@ -43,8 +43,9 @@ def _write_localmenus(
else None
)
for base_file in base_files
),
):
)
if path is not None
]:
for localmenu in etree.parse(source_file).xpath("//localmenu"):
etree.SubElement(
page,
@@ -77,7 +78,7 @@ def _write_localmenus(
def update_localmenus(
source_dir: Path,
languages: list[str],
pool: multiprocessing.Pool,
pool: multiprocessing.pool.Pool,
) -> None:
"""
Update all the .localmenu.*.xml files containing the local menus.
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import logging
import multiprocessing
import multiprocessing.pool
import re
from pathlib import Path
@@ -19,17 +19,16 @@ def _update_sheet(file: Path) -> None:
Update a given xsl file if any of its dependant xsl files have been updated
"""
xslt_root = etree.parse(file)
imports = (
imports = [
file.parent.joinpath(imp.get("href")).resolve().relative_to(Path.cwd())
for imp in xslt_root.xpath(
"//xsl:import",
namespaces={"xsl": "http://www.w3.org/1999/XSL/Transform"},
"//xsl:import", namespaces={"xsl": "http://www.w3.org/1999/XSL/Transform"}
)
)
]
touch_if_newer_dep(file, imports)
def update_stylesheets(source_dir: Path, pool: multiprocessing.Pool) -> None:
def update_stylesheets(source_dir: Path, pool: multiprocessing.pool.Pool) -> None:
"""
This script is called from the phase 1 Makefile and touches all XSL files
which depend on another XSL file that has changed since the last build run.
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import logging
import multiprocessing
import multiprocessing.pool
from pathlib import Path
from xml.sax.saxutils import escape
@@ -77,7 +77,7 @@ def _update_tag_sets(
def update_tags(
source_dir: Path,
languages: list[str],
pool: multiprocessing.Pool,
pool: multiprocessing.pool.Pool,
) -> None:
"""
Update Tag pages, xmllists and xmls
@@ -5,7 +5,7 @@
import datetime
import fnmatch
import logging
import multiprocessing
import multiprocessing.pool
import re
from pathlib import Path
@@ -48,10 +48,9 @@ def _update_for_base(
if len(pattern) <= 0:
logger.debug("Pattern too short, continue!")
continue
search_result = re.search(r":\[(.*)\]", line)
tag = (
re.search(r":\[(.*)\]", line).group(1).strip()
if re.search(r":\[(.*)\]", line) is not None
else ""
search_result.group(1).strip() if search_result is not None else ""
)
for xml_file in filter(
@@ -94,7 +93,7 @@ def _update_for_base(
def _update_module_xmllists(
source_dir: Path,
languages: list[str],
pool: multiprocessing.Pool,
pool: multiprocessing.pool.Pool,
) -> None:
"""
Update .xmllist files for .sources and .xhtml containing <module>s
@@ -142,7 +141,7 @@ def _check_xmllist_deps(file: Path) -> None:
def _touch_xmllists_with_updated_deps(
source_dir: Path,
pool: multiprocessing.Pool,
pool: multiprocessing.pool.Pool,
) -> None:
"""
Touch all .xmllist files where one of the contained files has changed
@@ -154,7 +153,7 @@ def _touch_xmllists_with_updated_deps(
def update_xmllists(
source_dir: Path,
languages: list[str],
pool: multiprocessing.Pool,
pool: multiprocessing.pool.Pool,
) -> None:
"""
Update XML filelists (*.xmllist)
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import logging
import multiprocessing
import multiprocessing.pool
import shutil
from pathlib import Path
@@ -23,7 +23,7 @@ def _copy_file(target: Path, source_dir: Path, source_file: Path) -> None:
shutil.copymode(source_file, target_file)
def copy_files(source_dir: Path, pool: multiprocessing.Pool, target: Path) -> None:
def copy_files(source_dir: Path, pool: multiprocessing.pool.Pool, target: Path) -> None:
"""
Copy images, docments etc
"""
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import logging
import multiprocessing
import multiprocessing.pool
from pathlib import Path
from fsfe_website_build.lib.misc import get_basename
@@ -20,7 +20,7 @@ def _do_symlinking(target: Path) -> None:
def create_index_symlinks(
pool: multiprocessing.Pool,
pool: multiprocessing.pool.Pool,
target: Path,
) -> None:
"""
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import logging
import multiprocessing
import multiprocessing.pool
from pathlib import Path
logger = logging.getLogger(__name__)
@@ -16,7 +16,7 @@ def _do_symlinking(target: Path) -> None:
def create_language_symlinks(
pool: multiprocessing.Pool,
pool: multiprocessing.pool.Pool,
target: Path,
) -> None:
"""
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import logging
import multiprocessing
import multiprocessing.pool
from pathlib import Path
from fsfe_website_build.lib.misc import get_basepath
@@ -89,7 +89,7 @@ def _process_stylesheet(
def process_files(
source_dir: Path,
languages: list[str],
pool: multiprocessing.Pool,
pool: multiprocessing.pool.Pool,
target: Path,
) -> None:
"""
+2 -2
View File
@@ -6,7 +6,7 @@
# script for FSFE website build, phase 2
# -----------------------------------------------------------------------------
import logging
import multiprocessing
import multiprocessing.pool
from pathlib import Path
from .copy_files import copy_files
@@ -20,7 +20,7 @@ logger = logging.getLogger(__name__)
def phase2_run(
source_dir: Path,
languages: list[str],
pool: multiprocessing.Pool,
pool: multiprocessing.pool.Pool,
target: Path,
) -> None:
"""
@@ -27,7 +27,7 @@ def _run_webserver(path: str, port: int) -> None:
httpd.serve_forever()
def serve_websites(serve_dir: str, base_port: int, increment_number: int) -> None:
def serve_websites(serve_dir: Path, base_port: int, increment_number: int) -> None:
"""
Takes a target directory, a base port and a number to increment port by per dir
It then serves all directories over http on localhost
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import logging
import multiprocessing
import multiprocessing.pool
from pathlib import Path
from fsfe_website_build.lib.misc import run_command
@@ -32,7 +32,9 @@ def _rsync(stagedir: Path, target: str, port: int) -> None:
)
def stage_to_target(stagedir: Path, targets: str, pool: multiprocessing.Pool) -> None:
def stage_to_target(
stagedir: Path, targets: str, pool: multiprocessing.pool.Pool
) -> None:
"""
Use a multithreaded rsync to copy the stage dir to all targets.
"""
@@ -24,8 +24,6 @@ def keys_exists_test() -> None:
def keys_exists_bad_input_test() -> None:
with pytest.raises(TypeError):
keys_exists([], "a")
assert keys_exists({}, "a") is False