Skip to content

Commit

Permalink
Merge pull request #429 from neutrinoceros/typ/mypy_strict
Browse files Browse the repository at this point in the history
  • Loading branch information
neutrinoceros authored Jan 20, 2025
2 parents e45670e + 6ef1749 commit 1a25410
Show file tree
Hide file tree
Showing 13 changed files with 46 additions and 36 deletions.
5 changes: 2 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,10 @@ exclude_lines = [

[tool.mypy]
python_version = '3.10'
strict = true
show_error_codes = true
warn_unused_configs = true
warn_unused_ignores = true
warn_unreachable = true
show_error_context = true
warn_unused_ignores = true

[tool.pytest.ini_options]
minversion = "6.0"
Expand Down
2 changes: 2 additions & 0 deletions src/idefix_cli/_backports.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# type: ignore

import os
import sys

Expand Down
2 changes: 1 addition & 1 deletion src/idefix_cli/_commands/clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def add_arguments(parser: ArgumentParser) -> None:


def command(
directory, clean_all: bool = False, dry: bool = False, confirm: bool = True
directory: str, clean_all: bool = False, dry: bool = False, confirm: bool = True
) -> int:
origin = os.path.abspath(os.curdir)
with chdir(directory):
Expand Down
12 changes: 7 additions & 5 deletions src/idefix_cli/_commands/clone.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import os
import shutil
import sys
from argparse import ArgumentParser
from collections.abc import Generator, Sequence
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import TYPE_CHECKING
Expand Down Expand Up @@ -81,14 +83,14 @@ def exists(self) -> bool:
return self._path.exists()

@property
def parent(self):
def parent(self) -> Path:
return self._path.parent

@property
def parents(self):
def parents(self) -> Sequence[Path]:
return self._path.parents

def glob(self, *args):
def glob(self, *args: str) -> Generator[Path, None, None]:
return self._path.glob(*args)

def __str__(self) -> str:
Expand All @@ -105,7 +107,7 @@ def get_include_from_conf() -> list[str]:
return raw.split()


def add_arguments(parser) -> None:
def add_arguments(parser: ArgumentParser) -> None:
parser.add_argument(
"source",
default="",
Expand Down Expand Up @@ -156,7 +158,7 @@ def command(
include = []

files_and_dirs_to_copy = files_from_patterns(
str(source),
Path(str(source)),
*BASE_INCLUDE,
*include,
*get_include_from_conf(),
Expand Down
2 changes: 1 addition & 1 deletion src/idefix_cli/_commands/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ def substitute_cmake_args(args: list[str]) -> list[str]:
return args


def add_arguments(parser) -> None:
def add_arguments(parser: ArgumentParser) -> None:
parser.add_argument("--dir", dest="directory", default=".", help="target directory")

parser.add_argument(
Expand Down
8 changes: 4 additions & 4 deletions src/idefix_cli/_commands/digest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
from argparse import ArgumentParser
from pathlib import Path
from time import monotonic_ns
from typing import Any
from typing import Any, TextIO

from idefix_cli.lib import print_error

_LOG_LINE_REGEXP = re.compile(r"^(?P<trailer>TimeIntegrator:)(?P<data>.*\|.*)")


def _log_to_data(log: list[str]):
def _log_to_data(log: list[str]) -> dict[str, list[Any]]:
columns: dict[str, list[Any]] = {name.strip(): [] for name in log[0].split("|")}
tokenized_log = [line.replace("N/A", "NaN").split("|") for line in log[1:]]
for i, name in enumerate(columns.keys()):
Expand Down Expand Up @@ -87,11 +87,11 @@ def add_arguments(parser: ArgumentParser) -> None:
def command(
dir: str,
input_: list[str] | None = None,
output=sys.stdout,
output: TextIO = sys.stdout,
all_files: bool = False,
timeit: bool = False,
*,
_log_line_regexp=_LOG_LINE_REGEXP,
_log_line_regexp: re.Pattern[str] = _LOG_LINE_REGEXP,
) -> int:
pdir = Path(dir)
if not pdir.is_dir():
Expand Down
3 changes: 2 additions & 1 deletion src/idefix_cli/_commands/read.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
from __future__ import annotations

import json
from argparse import ArgumentParser
from pathlib import Path

import inifix

from idefix_cli.lib import print_error


def add_arguments(parser) -> None:
def add_arguments(parser: ArgumentParser) -> None:
parser.add_argument("inifile", type=str, help="target inifile")
parser.add_argument(
"--indent", type=int, help="indentation in spaces (default is flat output)"
Expand Down
15 changes: 8 additions & 7 deletions src/idefix_cli/_commands/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import re
import subprocess
import sys
from argparse import ArgumentParser
from copy import deepcopy
from enum import auto
from math import prod
Expand Down Expand Up @@ -38,7 +39,7 @@
else:
from typing_extensions import assert_never

from idefix_cli._backports import StrEnum
from idefix_cli._backports import StrEnum # type: ignore [attr-defined]
from idefix_cli.lib import chdir

MAIN_LOG_FILE = "idefix.0.log"
Expand Down Expand Up @@ -124,7 +125,7 @@ def get_command(
return cmd


class RebuildMode(StrEnum):
class RebuildMode(StrEnum): # type: ignore [misc]
ALWAYS = auto()
PROMPT = auto()

Expand Down Expand Up @@ -156,11 +157,11 @@ def get_cpu_count() -> int:


def get_highest_power_of_two(n_max: int) -> int:
return 2 ** (n_max.bit_length() - 1)
return 1 << (n_max.bit_length() - 1)


@requires_idefix()
def build_idefix(directory) -> int:
def build_idefix(directory: str) -> int:
ncpus = min(8, get_highest_power_of_two(get_cpu_count()))
cmd = ["make", "-j", str(ncpus)]
return run_subcommand(cmd, loc=Path(directory), err="failed to build idefix")
Expand Down Expand Up @@ -189,7 +190,7 @@ def parse_ncycles(unknown_args: tuple[str, ...], ncycles: int) -> tuple[str, ...
return unknown_args


def add_arguments(parser) -> None:
def add_arguments(parser: ArgumentParser) -> None:
parser.add_argument("--dir", dest="directory", default=".", help="target directory")
parser.add_argument(
"-i",
Expand Down Expand Up @@ -358,11 +359,11 @@ def command(
rebuild_mode = RebuildMode(rebuild_mode_str)
except ValueError:
print_warning(
f"Expected [idfx run].recompile to be any of {[str(_) for _ in RebuildMode]}"
f"Expected [idfx run].recompile to be any of {[str(_) for _ in RebuildMode]}" # type: ignore [attr-defined]
f"Got {rebuild_mode_str!r} from {get_config_file()}\n"
)
print_warning("Falling back to 'prompt' mode.")
rebuild_mode = RebuildMode.PROMPT
rebuild_mode = RebuildMode.PROMPT # type: ignore [assignment]

build_is_required: bool = True
if rebuild_mode is RebuildMode.ALWAYS:
Expand Down
3 changes: 2 additions & 1 deletion src/idefix_cli/_commands/switch.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
"""switch git branch in $IDEFIX_DIR using git checkout"""

import os
from argparse import ArgumentParser
from pathlib import Path

from idefix_cli.lib import print_error, requires_idefix, run_subcommand


def add_arguments(parser):
def add_arguments(parser: ArgumentParser) -> None:
parser.add_argument(
"branch",
default="-",
Expand Down
3 changes: 2 additions & 1 deletion src/idefix_cli/_commands/write.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import json
import sys
from argparse import ArgumentParser
from contextlib import ExitStack
from io import TextIOBase
from pathlib import Path
Expand All @@ -11,7 +12,7 @@
from idefix_cli.lib import print_error


def add_arguments(parser) -> None:
def add_arguments(parser: ArgumentParser) -> None:
parser.add_argument("dest", type=str, help="dest inifile")
parser.add_argument(
"source",
Expand Down
5 changes: 3 additions & 2 deletions src/idefix_cli/_theme.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import sys
import unicodedata
from collections.abc import Generator
from contextlib import contextmanager
from dataclasses import dataclass
from typing import Literal, TypedDict
Expand Down Expand Up @@ -34,7 +35,7 @@ def register(
symbols: SymbolSet,
enter: str | None = None,
exit: str | None = None,
):
) -> None:
self._registry[name] = Theme(
name=name, symbols=symbols, enter_msg=enter, exit_msg=exit
)
Expand Down Expand Up @@ -79,7 +80,7 @@ def get_symbol(key: Literal["LAUNCH", "SUCCESS", "WARNING", "ERROR", "HINT"]) ->


@contextmanager
def theme_ctx(name: str):
def theme_ctx(name: str) -> Generator[None, None, None]:
global THEME
old_name = THEME.name
THEME = themes[name]
Expand Down
18 changes: 9 additions & 9 deletions src/idefix_cli/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
if sys.version_info >= (3, 11):
from enum import StrEnum
else:
from idefix_cli._backports import StrEnum
from idefix_cli._backports import StrEnum # type: ignore[attr-defined]

# workaround mypy not being confortable around decorator preserving signatures
# adapted from
Expand Down Expand Up @@ -53,14 +53,14 @@
__all__.append("chdir")


class _WindowsTree(StrEnum):
class _WindowsTree(StrEnum): # type: ignore [misc]
TRUNK = "|"
FORK = "|-"
ANGLE = "'-"
BRANCH = "-"


class _PosixTree(StrEnum):
class _PosixTree(StrEnum): # type: ignore [misc]
TRUNK = "│"
FORK = "├"
ANGLE = "└"
Expand Down Expand Up @@ -102,7 +102,7 @@ class requires_idefix:

def __call__(self, f: TFun) -> TFun:
@wraps(f)
def wrapper(*args, **kwargs) -> Any:
def wrapper(*args: Any, **kwargs: Any) -> Any:
if (IDEFIX_DIR := os.getenv("IDEFIX_DIR")) is None:
print_error(
"this functionality requires $IDEFIX_DIR to be defined",
Expand Down Expand Up @@ -260,8 +260,8 @@ def run_subcommand(


def files_from_patterns(
source,
*patterns,
source: os.PathLike[str],
*patterns: str,
recursive: bool = False,
excludes: list[str] | None = None,
) -> list[str]:
Expand Down Expand Up @@ -447,17 +447,17 @@ def prompt_ask(prompt: str, /) -> bool:
print("Please enter y or n", file=sys.stderr)


def __getattr__(attr: str):
def __getattr__(attr: str) -> Any:
# avoid leaking more than intended from the standard library
if attr == "chdir":
if sys.version_info >= (3, 11):
from contextlib import chdir
else:
from idefix_cli._backports import chdir
from idefix_cli._backports import chdir # type: ignore [attr-defined]
return chdir
else:
raise AttributeError(f"Unknown attribute {attr!r}")


def __dir__():
def __dir__() -> list[str]:
return list(globals()) + ["chdir"]
4 changes: 3 additions & 1 deletion tests/test_app_structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ def test_plugins(isolated_conf_dir, tmp_path, capsys):
dedent(
"""
'test extension command'
def add_arguments(parser) -> None:
from argparse import ArgumentParser
def add_arguments(parser: ArgumentParser) -> None:
return
def command() -> int:
Expand Down

0 comments on commit 1a25410

Please sign in to comment.