Skip to content

gh-104504: Run mypy on cases_generator in CI (and blacken the code) #108090

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Aug 18, 2023
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ updates:
- "version-update:semver-minor"
- "version-update:semver-patch"
- package-ecosystem: "pip"
directory: "/Tools/clinic/"
directory: "/Tools/"
schedule:
interval: "monthly"
labels:
Expand Down
14 changes: 9 additions & 5 deletions .github/workflows/mypy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
pull_request:
paths:
- "Tools/clinic/**"
- "Tools/cases_generator/**"
- ".github/workflows/mypy.yml"
workflow_dispatch:

Expand All @@ -25,15 +26,18 @@ concurrency:

jobs:
mypy:
name: Run mypy on Tools/clinic/
strategy:
matrix:
target: ["Tools/cases_generator", "Tools/clinic"]
name: Run mypy on ${{ matrix.target }}
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.x"
python-version: "3.11"
cache: pip
cache-dependency-path: Tools/clinic/requirements-dev.txt
- run: pip install -r Tools/clinic/requirements-dev.txt
- run: mypy --config-file Tools/clinic/mypy.ini
cache-dependency-path: Tools/requirements-dev.txt
- run: pip install -r Tools/requirements-dev.txt
- run: mypy --config-file ${{ matrix.target }}/mypy.ini
17 changes: 8 additions & 9 deletions Tools/cases_generator/flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@ class InstructionFlags:
HAS_FREE_FLAG: bool
HAS_LOCAL_FLAG: bool

def __post_init__(self):
def __post_init__(self) -> None:
self.bitmask = {name: (1 << i) for i, name in enumerate(self.names())}

@staticmethod
def fromInstruction(instr: parsing.Node):

def fromInstruction(instr: parsing.Node) -> "InstructionFlags":
has_free = (
variable_used(instr, "PyCell_New")
or variable_used(instr, "PyCell_GET")
Expand All @@ -41,15 +40,15 @@ def fromInstruction(instr: parsing.Node):
)

@staticmethod
def newEmpty():
def newEmpty() -> "InstructionFlags":
return InstructionFlags(False, False, False, False, False, False)

def add(self, other: "InstructionFlags") -> None:
for name, value in dataclasses.asdict(other).items():
if value:
setattr(self, name, value)

def names(self, value=None) -> list[str]:
def names(self, value: bool | None = None) -> list[str]:
if value is None:
return list(dataclasses.asdict(self).keys())
return [n for n, v in dataclasses.asdict(self).items() if v == value]
Expand All @@ -62,7 +61,7 @@ def bitmap(self) -> int:
return flags

@classmethod
def emit_macros(cls, out: Formatter):
def emit_macros(cls, out: Formatter) -> None:
flags = cls.newEmpty()
for name, value in flags.bitmask.items():
out.emit(f"#define {name} ({value})")
Expand Down Expand Up @@ -90,9 +89,9 @@ def variable_used_unspecialized(node: parsing.Node, name: str) -> bool:
text = "".join(token.text.split())
# TODO: Handle nested #if
if text == "#if":
if (
i + 1 < len(node.tokens)
and node.tokens[i + 1].text in ("ENABLE_SPECIALIZATION", "TIER_ONE")
if i + 1 < len(node.tokens) and node.tokens[i + 1].text in (
"ENABLE_SPECIALIZATION",
"TIER_ONE",
):
skipping = True
elif text in ("#else", "#endif"):
Expand Down
11 changes: 6 additions & 5 deletions Tools/cases_generator/formatting.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import contextlib
import re
import typing
from collections.abc import Iterator

from parsing import StackEffect, Family

Expand Down Expand Up @@ -58,13 +59,13 @@ def reset_lineno(self) -> None:
self.set_lineno(self.lineno + 1, self.filename)

@contextlib.contextmanager
def indent(self):
def indent(self) -> Iterator[None]:
self.prefix += " "
yield
self.prefix = self.prefix[:-4]

@contextlib.contextmanager
def block(self, head: str, tail: str = ""):
def block(self, head: str, tail: str = "") -> Iterator[None]:
if head:
self.emit(head + " {")
else:
Expand All @@ -77,7 +78,7 @@ def stack_adjust(
self,
input_effects: list[StackEffect],
output_effects: list[StackEffect],
):
) -> None:
shrink, isym = list_effect_size(input_effects)
grow, osym = list_effect_size(output_effects)
diff = grow - shrink
Expand All @@ -90,7 +91,7 @@ def stack_adjust(
if osym and osym != isym:
self.emit(f"STACK_GROW({osym});")

def declare(self, dst: StackEffect, src: StackEffect | None):
def declare(self, dst: StackEffect, src: StackEffect | None) -> None:
if dst.name == UNUSED or dst.cond == "0":
return
typ = f"{dst.type}" if dst.type else "PyObject *"
Expand All @@ -107,7 +108,7 @@ def declare(self, dst: StackEffect, src: StackEffect | None):
sepa = "" if typ.endswith("*") else " "
self.emit(f"{typ}{sepa}{dst.name}{init};")

def assign(self, dst: StackEffect, src: StackEffect):
def assign(self, dst: StackEffect, src: StackEffect) -> None:
if src.name == UNUSED or dst.name == UNUSED:
return
cast = self.cast(dst, src)
Expand Down
Loading