From 05c4f67b06bb4848a3748393a5f1bbc5cbe46a97 Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Fri, 9 Jan 2026 11:41:14 +0200 Subject: [PATCH 01/10] fix: add ignore for RUF067 --- pyproject.toml | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index edbc7cf16..ab0ea20b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,21 +83,22 @@ extend-select = [ "NPY", # numpy "Q", # flake8-quotes "RUF", # ruff + "TC", # flake8-type-checking "UP", # pyupgrade "W", # pycodestyle - "TC", ] extend-ignore = [ - "C90", # McCabe complexity - "E226", # missing whitespace around arithmetic operator - "E402", # module level import not at the top of file - "N802", # function name should be lowercase - "N803", # argument name should be lowercase - "N806", # variable name should be lowercase - "RUF012", # ClassVar for mutable class attributes - "RUF022", # __all__ is not sorted - "UP031", # use f-strings instead of % - "UP032", # use f-strings instead of .format + "C90", # McCabe complexity + "E226", # missing whitespace around arithmetic operator + "E402", # module level import not at the top of file + "N802", # function name should be lowercase + "N803", # argument name should be lowercase + "N806", # variable name should be lowercase + "RUF012", # ClassVar for mutable class attributes + "RUF022", # __all__ is not sorted + "RUF067", # non-empty-init-module + "UP031", # use f-strings instead of % + "UP032", # use f-strings instead of .format ] exclude = [ "experiments/*.py", From 827cb3d1635f8036a220086cbb7e15d386c074e6 Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Fri, 9 Jan 2026 11:44:02 +0200 Subject: [PATCH 02/10] feat: enable RUF022 --- pyproject.toml | 1 - pytential/__init__.py | 2 +- pytential/linalg/__init__.py | 6 ++++-- pytential/qbx/__init__.py | 14 +++++++------- pytential/symbolic/primitives.py | 2 +- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ab0ea20b7..9a2ce2fb9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -95,7 +95,6 @@ extend-ignore = [ "N803", # argument name should be lowercase "N806", # variable name should be lowercase "RUF012", # ClassVar for mutable class attributes - "RUF022", # __all__ is not sorted "RUF067", # non-empty-init-module "UP031", # use f-strings instead of % "UP032", # use f-strings instead of .format diff --git a/pytential/__init__.py b/pytential/__init__.py index b66e40b91..72042e127 100644 --- a/pytential/__init__.py +++ b/pytential/__init__.py @@ -141,4 +141,4 @@ def norm( raise ValueError(f"unsupported norm order: {p}") -__all__ = ["sym", "bind", "GeometryCollection"] +__all__ = ("GeometryCollection", "bind", "integral", "norm", "sym") diff --git a/pytential/linalg/__init__.py b/pytential/linalg/__init__.py index 1869399ce..65cff7bc5 100644 --- a/pytential/linalg/__init__.py +++ b/pytential/linalg/__init__.py @@ -33,7 +33,9 @@ __all__ = ( - "IndexList", "TargetAndSourceClusterList", - "make_index_list", "make_index_cluster_cartesian_product", + "IndexList", + "TargetAndSourceClusterList", "interp_decomp", + "make_index_cluster_cartesian_product", + "make_index_list", ) diff --git a/pytential/qbx/__init__.py b/pytential/qbx/__init__.py index a5dce852d..31ec56cf8 100644 --- a/pytential/qbx/__init__.py +++ b/pytential/qbx/__init__.py @@ -1067,12 +1067,12 @@ def get_flat_strengths_from_densities( # }}} -__all__ = [ - "QBXLayerPotentialSource", - "QBXTargetAssociationFailedError", - "QBXDefaultExpansionFactory", - "ExpansionFactoryBase", - "LocalExpansionBase", - ] +__all__ = ( + "ExpansionFactoryBase", + "LocalExpansionBase", + "QBXDefaultExpansionFactory", + "QBXLayerPotentialSource", + "QBXTargetAssociationFailedError", +) # vim: fdm=marker diff --git a/pytential/symbolic/primitives.py b/pytential/symbolic/primitives.py index f1d98c731..3ca0b84c6 100644 --- a/pytential/symbolic/primitives.py +++ b/pytential/symbolic/primitives.py @@ -370,7 +370,7 @@ .. autofunction:: pretty """ -__all__ = ( +__all__ = ( # noqa: RUF022 # re-export from pymbolic "Variable", "cse", From 382d7486a880ff591c8e73e868c9afdde44e2bbb Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Fri, 9 Jan 2026 11:54:36 +0200 Subject: [PATCH 03/10] feat(typing): add type annotations to extra_curve_data --- test/extra_curve_data.py | 62 +++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/test/extra_curve_data.py b/test/extra_curve_data.py index 7bff9fb10..4a9c4170e 100644 --- a/test/extra_curve_data.py +++ b/test/extra_curve_data.py @@ -23,22 +23,30 @@ THE SOFTWARE. """ +from typing import Any, TypeAlias + import numpy as np import numpy.linalg as la +from typing_extensions import override + + +Array1D: TypeAlias = np.ndarray[tuple[int], np.dtype[np.floating]] +Array2D: TypeAlias = np.ndarray[tuple[int, int], np.dtype[np.floating]] class Curve: - def plot(self, npoints=50): + def plot(self, npoints: int = 50) -> None: import matplotlib.pyplot as plt x, y = self(np.linspace(0, 1, npoints)) + plt.plot(x, y, marker=".", lw=0) plt.axis("equal") plt.show() - def __add__(self, other): + def __add__(self, other: Curve) -> Curve: return CompositeCurve(self, other) - def __call__(self, ts): + def __call__(self, ts: Array1D) -> Array2D: raise NotImplementedError @@ -47,33 +55,41 @@ class CompositeCurve(Curve): Parametrization of two or more curves combined. """ - def __init__(self, *objs): - curves = [] + curves: tuple[Curve, ...] + + def __init__(self, *objs: Curve) -> None: + curves: list[Curve] = [] for obj in objs: if isinstance(obj, CompositeCurve): curves.extend(obj.curves) else: curves.append(obj) - self.curves = curves - def __call__(self, ts): + self.curves = tuple(curves) + + @override + def __call__(self, ts: Array1D) -> Array2D: from itertools import pairwise ranges = np.linspace(0, 1, len(self.curves) + 1) ts_argsort = np.argsort(ts) ts_sorted = ts[ts_argsort] ts_split_points = np.searchsorted(ts_sorted, ranges) + # Make sure the last entry = len(ts), otherwise if ts finishes with a # trail of 1s, then they won't be forwarded to the last curve. ts_split_points[-1] = len(ts) - result = [] + + result: list[Array2D] = [] subranges = [slice(*pair) for pair in pairwise(ts_split_points)] for curve, subrange, (start, end) in zip( self.curves, subranges, pairwise(ranges), strict=True): ts_mapped = (ts_sorted[subrange] - start) / (end - start) result.append(curve(ts_mapped)) + final = np.concatenate(result, axis=-1) assert len(final[0]) == len(ts) + return final @@ -82,11 +98,14 @@ class Segment(Curve): Represents a line segment. """ - def __init__(self, start, end): - self.start = np.array(start) - self.end = np.array(end) + def __init__(self, + start: tuple[float, float], + end: tuple[float, float]) -> None: + self.start: Array1D = np.array(start) + self.end: Array1D = np.array(end) - def __call__(self, ts): + @override + def __call__(self, ts: Array1D) -> Array2D: return ( self.start[:, np.newaxis] + ts * (self.end - self.start)[:, np.newaxis]) @@ -97,7 +116,16 @@ class Arc(Curve): Represents an arc of a circle. """ - def __init__(self, start, mid, end): + r: np.floating[Any] + center: Array1D + + theta_range: Array1D + theta_increasing: bool + + def __init__(self, + start: tuple[float, float], + mid: tuple[float, float], + end: tuple[float, float]) -> None: """ :arg start: starting point of the arc :arg mid: any point along the arc @@ -135,15 +163,17 @@ def __init__(self, start, mid, end): self.theta_range = np.array(sorted([theta_start, theta_end])) self.theta_increasing = theta_start <= theta_end - def __call__(self, t): + @override + def __call__(self, ts: Array1D) -> Array2D: if self.theta_increasing: thetas = ( self.theta_range[0] - + t * (self.theta_range[1] - self.theta_range[0])) + + ts * (self.theta_range[1] - self.theta_range[0])) else: thetas = ( self.theta_range[1] - - t * (self.theta_range[1] - self.theta_range[0])) + - ts * (self.theta_range[1] - self.theta_range[0])) + val = (self.r * np.exp(1j * thetas)) + self.center return np.array([val.real, val.imag]) From de6140f4e36e35e43fe2c378fe97cf478bf96dea Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Fri, 9 Jan 2026 15:13:47 +0200 Subject: [PATCH 04/10] feat(typing): add more types to array_context --- pytential/array_context.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/pytential/array_context.py b/pytential/array_context.py index c6dbbfaac..e322c58ee 100644 --- a/pytential/array_context.py +++ b/pytential/array_context.py @@ -23,6 +23,10 @@ THE SOFTWARE. """ +from typing import TYPE_CHECKING, ClassVar + +from typing_extensions import override + from arraycontext.pytest import ( _PytestPyOpenCLArrayContextFactoryWithClass, register_pytest_array_context_factory, @@ -33,6 +37,10 @@ ) +if TYPE_CHECKING: + import loopy as lp + from arraycontext import ArrayContext + __doc__ = """ .. autoclass:: PyOpenCLArrayContext """ @@ -41,7 +49,8 @@ # {{{ PyOpenCLArrayContext class PyOpenCLArrayContext(PyOpenCLArrayContextBase): - def transform_loopy_program(self, t_unit): + @override + def transform_loopy_program(self, t_unit: lp.TranslationUnit) -> lp.TranslationUnit: kernel = t_unit.default_entrypoint options = kernel.options @@ -68,7 +77,7 @@ def transform_loopy_program(self, t_unit): # {{{ pytest -def _acf(): +def _acf() -> PyOpenCLArrayContext: # pyright: ignore[reportUnusedFunction] import pyopencl as cl ctx = cl.create_some_context() queue = cl.CommandQueue(ctx) @@ -78,9 +87,10 @@ def _acf(): class PytestPyOpenCLArrayContextFactory( _PytestPyOpenCLArrayContextFactoryWithClass): - actx_class = PyOpenCLArrayContext + actx_class: ClassVar[ArrayContext] = PyOpenCLArrayContext - def __call__(self): + @override + def __call__(self) -> ArrayContext: # NOTE: prevent any cache explosions during testing! from sympy.core.cache import clear_cache clear_cache() From 1b27dab06c99702280ecb8d212c4a1fb7c0103fe Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Fri, 9 Jan 2026 15:14:06 +0200 Subject: [PATCH 05/10] feat(typing): add type annotations to extra_int_eq_data --- test/extra_int_eq_data.py | 177 +++++++++++++++++++++++++------------- 1 file changed, 115 insertions(+), 62 deletions(-) diff --git a/test/extra_int_eq_data.py b/test/extra_int_eq_data.py index b6e304afe..59a4738b3 100644 --- a/test/extra_int_eq_data.py +++ b/test/extra_int_eq_data.py @@ -25,32 +25,48 @@ """ import logging +from abc import ABC, abstractmethod from dataclasses import dataclass, field -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, Literal, TypeAlias import numpy as np +from typing_extensions import override +from meshmode.discretization import Discretization, ElementGroupFactory from meshmode.discretization.poly_element import InterpolatoryQuadratureGroupFactory -from meshmode.mesh import MeshElementGroup, SimplexElementGroup +from meshmode.mesh import Mesh, MeshElementGroup, SimplexElementGroup from pytools import memoize_method from pytential import sym +from pytential.qbx import FMMBackend, QBXLayerPotentialSource +from pytential.source import PointPotentialSource +from pytential.target import PointsTarget if TYPE_CHECKING: from collections.abc import Callable - from meshmode.discretization import ElementGroupFactory + from arraycontext import ArrayContext + from boxtree.tree_build import ExtentNorm from sumpy.kernel import Kernel + from pytential.array_context import PyOpenCLArrayContext + from pytential.symbolic.pde.scalar import L2WeightedPDEOperator logger = logging.getLogger(__name__) +Array1D: TypeAlias = np.ndarray[tuple[int], np.dtype[np.floating]] +Array2D: TypeAlias = np.ndarray[tuple[int, int], np.dtype[np.floating]] + # {{{ make_circular_point_group -def make_circular_point_group(ambient_dim, npoints, radius, - center=None, func=lambda x: x): +def make_circular_point_group( + ambient_dim: int, + npoints: int, + radius: np.floating[Any], + center: Array1D | None = None, + func: Callable[[Array1D], Array1D] = lambda x: x) -> Array2D: if center is None: center = np.array([0., 0.]) t = func(np.linspace(0, 1, npoints, endpoint=False)) * (2 * np.pi) @@ -61,8 +77,13 @@ def make_circular_point_group(ambient_dim, npoints, radius, def make_source_and_target_points( - actx, side, inner_radius, outer_radius, ambient_dim, - nsources=10, ntargets=20): + actx: PyOpenCLArrayContext, + side: Literal[1] | Literal[-1] | Literal["scat"], + inner_radius: np.floating[Any], + outer_radius: np.floating[Any], + ambient_dim: int, + nsources: int = 10, + ntargets: int = 20) -> tuple[PointPotentialSource, PointsTarget]: if side == -1: test_src_geo_radius = outer_radius test_tgt_geo_radius = inner_radius @@ -75,14 +96,12 @@ def make_source_and_target_points( else: raise ValueError(f"unknown side: {side}") - from pytential.source import PointPotentialSource point_sources = make_circular_point_group( ambient_dim, nsources, test_src_geo_radius, func=lambda x: x**1.5) point_source = PointPotentialSource( actx.freeze(actx.from_numpy(point_sources))) - from pytential.target import PointsTarget test_targets = make_circular_point_group( ambient_dim, ntargets, test_tgt_geo_radius) point_target = PointsTarget( @@ -96,12 +115,12 @@ def make_source_and_target_points( # {{{ IntegralEquationTestCase @dataclass -class IntegralEquationTestCase: - name: str | None = None - ambient_dim: int | None = None +class IntegralEquationTestCase(ABC): + name: str = "case" + ambient_dim: int = -1 # operator - knl_class_or_helmholtz_k: type[Kernel] | float = 0 + knl_class_or_helmholtz_k: type[Kernel] | int | float = 0 knl_kwargs: dict[str, Any] = field(default_factory=dict) bc_type: str = "dirichlet" side: int = -1 @@ -109,13 +128,13 @@ class IntegralEquationTestCase: # qbx qbx_order: int | None = None source_ovsmp: int = 4 - target_order: int | None = None + target_order: int = 4 use_refinement: bool = True group_cls: type[MeshElementGroup] = SimplexElementGroup group_factory_cls: type[ElementGroupFactory] = InterpolatoryQuadratureGroupFactory # fmm - fmm_backend: str | None = "sumpy" + fmm_backend: FMMBackend | None = "sumpy" fmm_order: int | None = None fmm_tol: float | None = None disable_fft: bool = False @@ -130,14 +149,14 @@ class IntegralEquationTestCase: check_tangential_deriv: bool = True check_gradient: bool = False - box_extent_norm: str | None = None + box_extent_norm: ExtentNorm | None = None from_sep_smaller_crit: str | None = None # {{{ symbolic @property @memoize_method - def knl_class(self): + def knl_class(self) -> type[Kernel]: if isinstance(self.knl_class_or_helmholtz_k, type): return self.knl_class_or_helmholtz_k @@ -150,7 +169,7 @@ def knl_class(self): @property @memoize_method - def knl_concrete_kwargs(self): + def knl_concrete_kwargs(self) -> dict[str, Any]: if isinstance(self.knl_class_or_helmholtz_k, type): return self.knl_kwargs @@ -162,16 +181,16 @@ def knl_concrete_kwargs(self): @property @memoize_method - def knl_sym_kwargs(self): + def knl_sym_kwargs(self) -> dict[str, Any]: return {k: sym.var(k) for k in self.knl_concrete_kwargs} - def get_operator(self, ambient_dim): + def get_operator(self, ambient_dim: int) -> L2WeightedPDEOperator: sign = +1 if self.side in [+1, "scat"] else -1 knl = self.knl_class(ambient_dim) if self.bc_type == "dirichlet": from pytential.symbolic.pde.scalar import DirichletOperator - op = DirichletOperator(knl, sign, + op: L2WeightedPDEOperator = DirichletOperator(knl, sign, use_l2_weighting=True, kernel_arguments=self.knl_sym_kwargs) elif self.bc_type == "neumann": @@ -192,24 +211,37 @@ def get_operator(self, ambient_dim): # {{{ geometry - def get_mesh(self, resolution, mesh_order): - raise NotImplementedError + @abstractmethod + def get_mesh(self, resolution: int | float, mesh_order: int) -> Mesh: + pass - def get_discretization(self, actx, resolution, mesh_order): + def get_discretization(self, + actx: ArrayContext, + resolution: int | float, + mesh_order: int) -> Discretization: mesh = self.get_mesh(resolution, mesh_order) return self._get_discretization(actx, mesh) - def _get_discretization(self, actx, mesh): - from meshmode.discretization import Discretization + def _get_discretization(self, actx: ArrayContext, mesh: Mesh) -> Discretization: return Discretization(actx, mesh, self.group_factory_cls(self.target_order)) - def get_layer_potential(self, actx, resolution, mesh_order): + def get_layer_potential(self, + actx: ArrayContext, + resolution: int | float, + mesh_order: int) -> QBXLayerPotentialSource: pre_density_discr = self.get_discretization(actx, resolution, mesh_order) from sumpy.expansion.level_to_order import SimpleExpansionOrderFinder + + qbx_order = self.qbx_order + if qbx_order is None: + qbx_order = self.target_order + + fmm_backend = self.fmm_backend fmm_kwargs = {} - if self.fmm_backend is None: + if fmm_backend is None: + fmm_backend = "sumpy" fmm_kwargs["fmm_order"] = False else: if self.fmm_tol is not None: @@ -217,18 +249,17 @@ def get_layer_potential(self, actx, resolution, mesh_order): elif self.fmm_order is not None: fmm_kwargs["fmm_order"] = self.fmm_order else: - fmm_kwargs["fmm_order"] = self.qbx_order + 5 + fmm_kwargs["fmm_order"] = qbx_order + 5 if self.disable_fft: from pytential.qbx import NonFFTExpansionFactory fmm_kwargs["expansion_factory"] = NonFFTExpansionFactory() - from pytential.qbx import QBXLayerPotentialSource return QBXLayerPotentialSource( pre_density_discr, fine_order=self.source_ovsmp * self.target_order, qbx_order=self.qbx_order, - fmm_backend=self.fmm_backend, **fmm_kwargs, + fmm_backend=fmm_backend, **fmm_kwargs, _disable_refinement=not self.use_refinement, _box_extent_norm=self.box_extent_norm, @@ -238,7 +269,8 @@ def get_layer_potential(self, actx, resolution, mesh_order): # }}} - def __str__(self): + @override + def __str__(self) -> str: from dataclasses import fields attrs = {f.name: getattr(self, f.name) for f in fields(self)} @@ -273,16 +305,21 @@ class CurveTestCase(IntegralEquationTestCase): fmm_backend: str | None = None # test case - curve_fn: Callable[[np.ndarray], np.ndarray] | None = None + curve_fn: Callable[[Array1D], Array2D] | None = None inner_radius: float = 0.1 outer_radius: float = 2 resolutions: list[int] = field(default_factory=lambda: [40, 50, 60]) - def _curve_fn(self, t): + def _curve_fn(self, t: Array1D) -> Array2D: + if self.curve_fn is None: + raise ValueError(f"no 'curve_fn' provided to {type(self)}") return self.curve_fn(t) - def get_mesh(self, resolution, mesh_order): + @override + def get_mesh(self, resolution: int | float, mesh_order: int) -> Mesh: from meshmode.mesh.generation import make_curve_mesh + + assert isinstance(resolution, int) return make_curve_mesh( self._curve_fn, np.linspace(0, 1, resolution + 1), @@ -295,7 +332,8 @@ class EllipseTestCase(CurveTestCase): aspect_ratio: float = 3.0 radius: float = 1.0 - def _curve_fn(self, t): + @override + def _curve_fn(self, t: Array1D) -> Array2D: from meshmode.mesh.generation import ellipse return self.radius * ellipse(self.aspect_ratio, t) @@ -312,7 +350,8 @@ class WobbleCircleTestCase(CurveTestCase): name: str = "wobble-circle" resolutions: list[int] = field(default_factory=lambda: [2000, 3000, 4000]) - def _curve_fn(self, t): + @override + def _curve_fn(self, t: Array1D) -> Array2D: from meshmode.mesh.generation import WobblyCircle return WobblyCircle.random(30, seed=30)(t) @@ -329,7 +368,8 @@ class StarfishTestCase(CurveTestCase): resolutions: list[int] = field(default_factory=lambda: [30, 50, 70, 90]) - def _curve_fn(self, t): + @override + def _curve_fn(self, t: Array1D) -> Array2D: from meshmode.mesh.generation import NArmedStarfish return NArmedStarfish(self.n_arms, self.amplitude)(t) @@ -339,7 +379,7 @@ def _curve_fn(self, t): # {{{ 3d surfaces @dataclass -class Helmholtz3DTestCase(IntegralEquationTestCase): +class Helmholtz3DTestCase(IntegralEquationTestCase, ABC): ambient_dim: int = 3 # qbx @@ -364,13 +404,13 @@ class HelmholtzEllisoidTestCase(Helmholtz3DTestCase): fmm_order: int = 13 # test case - resolutions: list[int] = field( - default_factory=lambda: [2.0, 0.8]) + resolutions: list[int] = field(default_factory=lambda: [2.0, 0.8]) inner_radius: float = 0.4 outer_radius: float = 5.0 check_gradient: bool = True - def get_mesh(self, resolution, mesh_order): + @override + def get_mesh(self, resolution: int | float, mesh_order: int) -> Mesh: from meshmode.mesh.io import FileSource, generate_gmsh mesh = generate_gmsh( FileSource("ellipsoid.step"), 2, order=mesh_order, @@ -409,8 +449,11 @@ class SphereTestCase(IntegralEquationTestCase): inner_radius: float = 0.4 outer_radius: float = 5.0 - def get_mesh(self, resolution, mesh_order): + @override + def get_mesh(self, resolution: int | float, mesh_order: int) -> Mesh: from meshmode.mesh.generation import generate_sphere + + assert isinstance(resolution, int) return generate_sphere(self.radius, mesh_order, uniform_refinement_rounds=resolution, group_cls=self.group_cls) @@ -421,7 +464,8 @@ class SpheroidTestCase(SphereTestCase): name: str = "spheroid" aspect_ratio: float = 2.0 - def get_mesh(self, resolution, mesh_order): + @override + def get_mesh(self, resolution: int | float, mesh_order: int) -> Mesh: mesh = super().get_mesh(resolution, mesh_order) from meshmode.mesh.processing import affine_map @@ -435,9 +479,12 @@ class QuadSpheroidTestCase(SphereTestCase): name: str = "quadspheroid" aspect_ratio: float = 2.0 - def get_mesh(self, resolution, mesh_order): + @override + def get_mesh(self, resolution: int | float, mesh_order: int) -> Mesh: from meshmode.mesh import TensorProductElementGroup from meshmode.mesh.generation import generate_sphere + + assert isinstance(resolution, int) mesh = generate_sphere(1.0, mesh_order, uniform_refinement_rounds=resolution, group_cls=TensorProductElementGroup) @@ -454,10 +501,10 @@ class GMSHSphereTestCase(SphereTestCase): name: str = "gmsphere" radius: float = 1.5 - resolutions: list[int] = field( - default_factory=lambda: [0.4]) + resolutions: list[int] = field(default_factory=lambda: [0.4]) - def get_mesh(self, resolution, mesh_order): + @override + def get_mesh(self, resolution: int | float, mesh_order: int) -> Mesh: from meshmode.mesh import SimplexElementGroup, TensorProductElementGroup from meshmode.mesh.io import ScriptSource if issubclass(self.group_cls, SimplexElementGroup): @@ -513,7 +560,10 @@ class TorusTestCase(IntegralEquationTestCase): # test case resolutions: list[int] = field(default_factory=lambda: [0, 1, 2]) - def get_mesh(self, resolution, mesh_order): + @override + def get_mesh(self, resolution: int | float, mesh_order: int) -> Mesh: + assert isinstance(resolution, int) + from meshmode.mesh.generation import generate_torus mesh = generate_torus(self.r_major, self.r_minor, order=mesh_order, group_cls=self.group_cls) @@ -530,18 +580,18 @@ class MergedCubesTestCase(Helmholtz3DTestCase): use_refinement: bool = True # test case - resolutions: list[int] = field( - default_factory=lambda: [1.4]) + resolutions: list[int] = field(default_factory=lambda: [1.4]) inner_radius: float = 0.4 outer_radius: float = 12.0 - def get_mesh(self, resolution, mesh_order): + @override + def get_mesh(self, resolution: int | float, mesh_order: int) -> Mesh: from meshmode.mesh.io import FileSource, generate_gmsh mesh = generate_gmsh( FileSource("merged-cubes.step"), 2, order=mesh_order, other_options=[ "-string", - "Mesh.CharacteristicLengthMax = %g;" % resolution]) + f"Mesh.CharacteristicLengthMax = {resolution};"]) # Flip elements--gmsh generates inside-out geometry. from meshmode.mesh.processing import perform_flips @@ -563,13 +613,14 @@ class ManyEllipsoidTestCase(Helmholtz3DTestCase): ny: int = 2 nz: int = 2 - def get_mesh(self, resolution, mesh_order): + @override + def get_mesh(self, resolution: int | float, mesh_order: int) -> Mesh: from meshmode.mesh.io import FileSource, generate_gmsh base_mesh = generate_gmsh( FileSource("ellipsoid.step"), 2, order=mesh_order, other_options=[ "-string", - "Mesh.CharacteristicLengthMax = %g;" % resolution]) + f"Mesh.CharacteristicLengthMax = {resolution};"]) from meshmode.mesh.processing import perform_flips base_mesh = perform_flips(base_mesh, np.ones(base_mesh.nelements, np.bool)) @@ -579,6 +630,8 @@ def get_mesh(self, resolution, mesh_order): meshes = [ affine_map( base_mesh, + # FIXME: this should take the rng from somewhere to allow + # for reproducible tests A=rand_rotation_matrix(3), b=self.pitch*np.array([ (i_x-self.nx//2), @@ -611,8 +664,7 @@ class EllipticPlaneTestCase(IntegralEquationTestCase): fmm_tol: float = 1.0e-4 # test case - resolutions: list[int] = field( - default_factory=lambda: [0.1]) + resolutions: list[int] = field(default_factory=lambda: [0.1]) inner_radius: float = 0.2 outer_radius: float = 12 # was '-13' in some large-scale run (?) check_gradient: bool = False @@ -626,7 +678,8 @@ class EllipticPlaneTestCase(IntegralEquationTestCase): box_extent_norm: str = "l2" from_sep_smaller_crit: str = "static_l2" - def get_mesh(self, resolution, mesh_order): + @override + def get_mesh(self, resolution: int | float, mesh_order: int) -> Mesh: from pytools import download_from_web_if_not_present download_from_web_if_not_present( @@ -643,7 +696,7 @@ def get_mesh(self, resolution, mesh_order): # now centered at origin and extends to -1,1 from meshmode.mesh.processing import perform_flips - return perform_flips(mesh, np.ones(mesh.nelements), dtype=np.bool) + return perform_flips(mesh, np.ones(mesh.nelements, dtype=np.bool)) @dataclass @@ -661,8 +714,7 @@ class BetterPlaneTestCase(IntegralEquationTestCase): use_refinement: bool = True # test case - resolutions: list[int] = field( - default_factory=lambda: [0.2]) + resolutions: list[int] = field(default_factory=lambda: [0.2]) inner_radius: float = 0.2 outer_radius: float = 15 check_gradient: bool = False @@ -681,7 +733,8 @@ class BetterPlaneTestCase(IntegralEquationTestCase): # scaled_max_curvature_threshold = 1 expansion_disturbance_tolerance: float = 0.3 - def get_mesh(self, resolution, target_order): + @override + def get_mesh(self, resolution: int | float, mesh_order: int) -> Mesh: from pytools import download_from_web_if_not_present download_from_web_if_not_present( From 61b4044fcd2e03d6b6fa4891e08058eed29991c3 Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Fri, 9 Jan 2026 15:37:50 +0200 Subject: [PATCH 06/10] feat(typing): add type annotations to refine_geometry_collection --- pytential/qbx/refinement.py | 42 +++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/pytential/qbx/refinement.py b/pytential/qbx/refinement.py index 6fbe865aa..4a33bcb85 100644 --- a/pytential/qbx/refinement.py +++ b/pytential/qbx/refinement.py @@ -27,7 +27,7 @@ """ import logging -from typing import cast +from typing import TYPE_CHECKING, Any, cast import numpy as np @@ -42,11 +42,18 @@ from pytential.qbx.utils import ( QBX_TREE_C_PREAMBLE, QBX_TREE_MAKO_DEFS, + TreeCodeContainer, TreeCodeContainerMixin, TreeWranglerBase, ) +if TYPE_CHECKING: + from meshmode.discretization import ElementGroupFactory + + from pytential.collection import GeometryCollection + from pytential.symbolic.dof_desc import DiscretizationStage + logger = logging.getLogger(__name__) @@ -224,8 +231,10 @@ # {{{ code container class RefinerCodeContainer(TreeCodeContainerMixin): + array_context: PyOpenCLArrayContext + tree_code_container: TreeCodeContainer - def __init__(self, actx: PyOpenCLArrayContext): + def __init__(self, actx: PyOpenCLArrayContext) -> None: self.array_context = actx from pytential.qbx.utils import tree_code_container @@ -233,8 +242,13 @@ def __init__(self, actx: PyOpenCLArrayContext): @memoize_method def expansion_disk_undisturbed_by_sources_checker( - self, dimensions, coord_dtype, box_id_dtype, peer_list_idx_dtype, - particle_id_dtype, max_levels): + self, + dimensions: int, + coord_dtype: np.dtype[np.floating[Any]], + box_id_dtype: np.dtype[np.integer[Any]], + peer_list_idx_dtype: np.dtype[np.integer[Any]], + particle_id_dtype: np.dtype[np.integer[Any]], + max_levels: int) -> int: return EXPANSION_DISK_UNDISTURBED_BY_SOURCES_CHECKER.generate( self.array_context.context, dimensions, coord_dtype, box_id_dtype, peer_list_idx_dtype, @@ -935,15 +949,17 @@ def get_from_cache(from_ds, to_ds): # {{{ refine_geometry_collection -def refine_geometry_collection(places, - group_factory=None, - refine_discr_stage=None, - kernel_length_scale=None, - force_stage2_uniform_refinement_rounds=None, - scaled_max_curvature_threshold=None, - expansion_disturbance_tolerance=None, - maxiter=None, - debug=None, visualize=False): +def refine_geometry_collection( + places: GeometryCollection, + group_factory: ElementGroupFactory | None = None, + refine_discr_stage: DiscretizationStage | None = None, + kernel_length_scale: float | np.floating[Any] | None = None, + force_stage2_uniform_refinement_rounds: int | None = None, + scaled_max_curvature_threshold: float | None = None, + expansion_disturbance_tolerance: float | None = None, + maxiter: int | None = None, + debug: bool | None = None, + visualize: bool = False) -> GeometryCollection: """Entry point for refining all the :class:`~pytential.qbx.QBXLayerPotentialSource` in the given collection. The :class:`~pytential.collection.GeometryCollection` performs From 39ec6e46f38d0ee961109710ab5a1d20f5d51986 Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Fri, 9 Jan 2026 15:38:06 +0200 Subject: [PATCH 07/10] feat(typing): add type annotations to test_layer_pot_identity.py --- test/test_layer_pot_identity.py | 146 +++++++++++++++++++++----------- 1 file changed, 95 insertions(+), 51 deletions(-) diff --git a/test/test_layer_pot_identity.py b/test/test_layer_pot_identity.py index ce2363064..eef7d8bb9 100644 --- a/test/test_layer_pot_identity.py +++ b/test/test_layer_pot_identity.py @@ -24,11 +24,15 @@ """ import logging +from abc import ABC, abstractmethod +from dataclasses import dataclass, field +from typing import TYPE_CHECKING, ClassVar import extra_int_eq_data as ied import numpy as np import numpy.linalg as la import pytest +from typing_extensions import override from arraycontext import ( ArrayContextFactory, @@ -38,13 +42,16 @@ ) # from sumpy.visualization import FieldPlotter -from sumpy.kernel import HelmholtzKernel, LaplaceKernel +from sumpy.kernel import HelmholtzKernel, Kernel, LaplaceKernel from pytential import GeometryCollection, bind, norm, sym from pytential.array_context import PytestPyOpenCLArrayContextFactory from pytential.utils import pytest_teardown_function as teardown_function # noqa: F401 +if TYPE_CHECKING: + from pytential.qbx import FMMBackend + logger = logging.getLogger(__name__) pytest_generate_tests = pytest_generate_tests_for_array_contexts([ PytestPyOpenCLArrayContextFactory, @@ -54,21 +61,33 @@ d2 = sym.Derivative() +@dataclass class SphereTestCase(ied.SphereTestCase): - resolutions = [0, 1] + resolutions: list[int] = field(default_factory=lambda: [0, 1]) +@dataclass class QuadSphereTestCase(ied.QuadSpheroidTestCase): - name = "sphere-quad" - aspect_ratio = 1 - resolutions = [0, 1] + name: str = "sphere-quad" + aspect_ratio: float = 1 + resolutions: list[int] = field(default_factory=lambda: [0, 1]) + + +class IdentityExpr(ABC): + zero_op_name: ClassVar[str] + order_drop: ClassVar[int] + + @abstractmethod + def get_zero_op(self, kernel: Kernel, **knl_kwargs: sym.Operand) -> sym.Operand: + pass -class GreenExpr: - zero_op_name = "green" - order_drop = 0 +class GreenExpr(IdentityExpr): + zero_op_name: ClassVar[str] = "green" + order_drop: ClassVar[int] = 0 - def get_zero_op(self, kernel, **knl_kwargs): + @override + def get_zero_op(self, kernel: Kernel, **knl_kwargs: sym.Operand) -> sym.Operand: u_sym = sym.var("u") dn_u_sym = sym.var("dn_u") @@ -78,11 +97,12 @@ def get_zero_op(self, kernel, **knl_kwargs): - 0.5*u_sym) -class GradGreenExpr: - zero_op_name = "grad_green" - order_drop = 1 +class GradGreenExpr(IdentityExpr): + zero_op_name: ClassVar[str] = "grad_green" + order_drop: ClassVar[int] = 1 - def get_zero_op(self, kernel, **knl_kwargs): + @override + def get_zero_op(self, kernel: Kernel, **knl_kwargs: sym.Operand) -> sym.Operand: d = kernel.dim u_sym = sym.var("u") grad_u_sym = sym.make_sym_mv("grad_u", d) @@ -97,11 +117,12 @@ def get_zero_op(self, kernel, **knl_kwargs): ).as_vector() -class ZeroCalderonExpr: - zero_op_name = "calderon" - order_drop = 1 +class ZeroCalderonExpr(IdentityExpr): + zero_op_name: ClassVar[str] = "calderon" + order_drop: ClassVar[int] = 1 - def get_zero_op(self, kernel, **knl_kwargs): + @override + def get_zero_op(self, kernel: Kernel, **knl_kwargs: sym.Operand) -> sym.Operand: assert isinstance(kernel, LaplaceKernel) assert not knl_kwargs @@ -119,56 +140,76 @@ def get_zero_op(self, kernel, **knl_kwargs): class StaticTestCase: - def check(self): + def check(self) -> None: pass +@dataclass class StarfishGreenTest(StaticTestCase): - expr = GreenExpr() - geometry = ied.StarfishTestCase() - k = 0 - qbx_order = 5 - fmm_order = 15 + expr: IdentityExpr = field(default_factory=lambda: GreenExpr()) + geometry: ied.IntegralEquationTestCase = field( + default_factory=lambda: ied.StarfishTestCase()) + + k: float = 0 + qbx_order: int = 5 + fmm_order: int = 15 - resolutions = [30, 50] + resolutions: list[int] = field(default_factory=lambda: [30, 50]) - _expansion_stick_out_factor = 0.5 + _expansion_stick_out_factor: float = 0.5 - fmm_backend = "fmmlib" + fmm_backend: FMMBackend = "fmmlib" +@dataclass class WobblyCircleGreenTest(StaticTestCase): - expr = GreenExpr() - geometry = ied.WobbleCircleTestCase() - k = 0 - qbx_order = 3 - fmm_order = 10 + expr: IdentityExpr = field(default_factory=lambda: GreenExpr()) + geometry: ied.IntegralEquationTestCase = field( + default_factory=lambda: ied.WobbleCircleTestCase()) - _expansion_stick_out_factor = 0.5 + k: float = 0 + qbx_order: int = 3 + fmm_order: int = 10 - fmm_backend = "sumpy" + _expansion_stick_out_factor: float = 0.5 + fmm_backend: FMMBackend = "sumpy" + +@dataclass class SphereGreenTest(StaticTestCase): - expr = GreenExpr() - geometry = SphereTestCase() - k = 0 - qbx_order = 3 - fmm_order = 10 + expr: IdentityExpr = field(default_factory=lambda: GreenExpr()) + geometry: ied.IntegralEquationTestCase = field( + default_factory=lambda: ied.SphereTestCase()) - resolutions = [0, 1] + k: float = 0 + qbx_order: int = 3 + fmm_order: int = 10 - _expansion_stick_out_factor = 0.5 + resolutions: list[int] = field(default_factory=lambda: [0, 1]) - fmm_backend = "fmmlib" + _expansion_stick_out_factor: float = 0.5 + fmm_backend: FMMBackend = "fmmlib" -class DynamicTestCase: - fmm_backend = "sumpy" - def __init__(self, geometry, expr, k, fmm_backend="sumpy", fmm_order=None): - self.geometry = geometry +class DynamicTestCase: + expr: IdentityExpr + geometry: ied.IntegralEquationTestCase + + k: float + qbx_order: int + fmm_order: int + fmm_backend: FMMBackend = "sumpy" + + def __init__(self, + geometry: ied.IntegralEquationTestCase, + expr: IdentityExpr, + k: float, + fmm_backend: FMMBackend = "sumpy", + fmm_order: int | None = None) -> None: self.expr = expr + self.geometry = geometry self.k = k self.qbx_order = 5 if geometry.ambient_dim == 2 else 3 self.fmm_backend = fmm_backend @@ -186,10 +227,11 @@ def __init__(self, geometry, expr, k, fmm_backend="sumpy", fmm_order=None): self.fmm_order = fmm_order @property - def resolutions(self): + def resolutions(self) -> list[int]: + assert self.geometry.resolutions is not None return self.geometry.resolutions - def check(self): + def check(self) -> None: if (self.geometry.name == "sphere" and self.k != 0 and self.fmm_backend == "sumpy"): @@ -208,7 +250,8 @@ def check(self): @pytest.mark.parametrize("case", [ DynamicTestCase(SphereTestCase(), GreenExpr(), 0), ]) -def test_identity_convergence_slow(actx_factory: ArrayContextFactory, case): +def test_identity_convergence_slow(actx_factory: ArrayContextFactory, + case: DynamicTestCase): test_identity_convergence(actx_factory, case) @@ -231,9 +274,12 @@ def test_identity_convergence_slow(actx_factory: ArrayContextFactory, case): DynamicTestCase(SphereTestCase(), GreenExpr(), 1.2, fmm_backend="fmmlib"), DynamicTestCase(QuadSphereTestCase(), GreenExpr(), 0, fmm_backend="fmmlib"), ]) -def test_identity_convergence(actx_factory: ArrayContextFactory, case, visualize=False): +def test_identity_convergence(actx_factory: ArrayContextFactory, + case: DynamicTestCase, + visualize: bool = False) -> None: if case.fmm_backend == "fmmlib": pytest.importorskip("pyfmmlib") + case.check() actx = actx_factory() target_order = 8 @@ -243,8 +289,6 @@ def test_identity_convergence(actx_factory: ArrayContextFactory, case, visualize for resolution in case.resolutions: mesh = case.geometry.get_mesh(resolution, target_order) - if mesh is None: - break d = mesh.ambient_dim k = case.k From 35d2e2c3a1c7e5d9cecaf1a380eb544b3491818f Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Fri, 9 Jan 2026 15:39:14 +0200 Subject: [PATCH 08/10] fix: enable RUF012 --- pyproject.toml | 1 - pytential/qbx/cost.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9a2ce2fb9..019348dbb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -94,7 +94,6 @@ extend-ignore = [ "N802", # function name should be lowercase "N803", # argument name should be lowercase "N806", # variable name should be lowercase - "RUF012", # ClassVar for mutable class attributes "RUF067", # non-empty-init-module "UP031", # use f-strings instead of % "UP032", # use f-strings instead of .format diff --git a/pytential/qbx/cost.py b/pytential/qbx/cost.py index 18fabc396..7e172a8ad 100644 --- a/pytential/qbx/cost.py +++ b/pytential/qbx/cost.py @@ -30,7 +30,7 @@ import logging from abc import abstractmethod from functools import partial -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, ClassVar import numpy as np from mako.template import Template @@ -515,7 +515,7 @@ def get_unit_calibration_params(): return calibration_params - _QBX_STAGE_TO_CALIBRATION_PARAMETER = { + _QBX_STAGE_TO_CALIBRATION_PARAMETER: ClassVar[dict[str, str]] = { "form_global_qbx_locals": "c_p2qbxl", "translate_box_multipoles_to_qbx_local": "c_m2qbxl", "translate_box_local_to_qbx_local": "c_l2qbxl", From a2ea17acf32c66ac9cde921cb1d20a904593014d Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Fri, 9 Jan 2026 15:55:19 +0200 Subject: [PATCH 09/10] docs: add ElementGroupFactory to redirects --- doc/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/conf.py b/doc/conf.py index 3feeb9925..256dd5e87 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -88,6 +88,7 @@ # meshmode "Discretization": "class:meshmode.discretization.Discretization", "DOFArray": "class:meshmode.dof_array.DOFArray", + "ElementGroupFactory": "class:meshmode.discretization.ElementGroupFactory", # boxtree "FromSepSmallerCrit": "obj:boxtree.traversal.FromSepSmallerCrit", "TimingResult": "class:boxtree.timing.TimingResult", From 6d1c5f80e0e0fcab536796cd297db4224691c59a Mon Sep 17 00:00:00 2001 From: Alexandru Fikl Date: Fri, 9 Jan 2026 15:41:27 +0200 Subject: [PATCH 10/10] chore: update baseline --- .basedpyright/baseline.json | 498 ++---------------------------------- 1 file changed, 22 insertions(+), 476 deletions(-) diff --git a/.basedpyright/baseline.json b/.basedpyright/baseline.json index 29693c192..c2cdbf7a2 100644 --- a/.basedpyright/baseline.json +++ b/.basedpyright/baseline.json @@ -1577,30 +1577,6 @@ "lineCount": 1 } }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 8, - "endColumn": 31, - "lineCount": 1 - } - }, - { - "code": "reportImplicitOverride", - "range": { - "startColumn": 8, - "endColumn": 31, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 38, - "endColumn": 44, - "lineCount": 1 - } - }, { "code": "reportUnknownVariableType", "range": { @@ -1617,22 +1593,6 @@ "lineCount": 1 } }, - { - "code": "reportUnusedFunction", - "range": { - "startColumn": 4, - "endColumn": 8, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 14, - "lineCount": 1 - } - }, { "code": "reportIncompatibleMethodOverride", "range": { @@ -1644,16 +1604,8 @@ { "code": "reportAssignmentType", "range": { - "startColumn": 17, - "endColumn": 37, - "lineCount": 1 - } - }, - { - "code": "reportImplicitOverride", - "range": { - "startColumn": 8, - "endColumn": 16, + "startColumn": 41, + "endColumn": 61, "lineCount": 1 } }, @@ -8877,14 +8829,6 @@ "lineCount": 1 } }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 4, - "endColumn": 39, - "lineCount": 1 - } - }, { "code": "reportUnknownParameterType", "range": { @@ -21257,126 +21201,6 @@ } ], "./pytential/qbx/refinement.py": [ - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 13, - "endColumn": 26, - "lineCount": 1 - } - }, - { - "code": "reportUnannotatedClassAttribute", - "range": { - "startColumn": 13, - "endColumn": 32, - "lineCount": 1 - } - }, - { - "code": "reportAny", - "range": { - "startColumn": 8, - "endColumn": 53, - "lineCount": 1 - } - }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 18, - "endColumn": 28, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 18, - "endColumn": 28, - "lineCount": 1 - } - }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 30, - "endColumn": 41, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 30, - "endColumn": 41, - "lineCount": 1 - } - }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 43, - "endColumn": 55, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 43, - "endColumn": 55, - "lineCount": 1 - } - }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 57, - "endColumn": 76, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 57, - "endColumn": 76, - "lineCount": 1 - } - }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 12, - "endColumn": 29, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 12, - "endColumn": 29, - "lineCount": 1 - } - }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 31, - "endColumn": 41, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 31, - "endColumn": 41, - "lineCount": 1 - } - }, { "code": "reportUnknownMemberType", "range": { @@ -21393,46 +21217,6 @@ "lineCount": 5 } }, - { - "code": "reportUnknownArgumentType", - "range": { - "startColumn": 16, - "endColumn": 26, - "lineCount": 1 - } - }, - { - "code": "reportUnknownArgumentType", - "range": { - "startColumn": 28, - "endColumn": 39, - "lineCount": 1 - } - }, - { - "code": "reportUnknownArgumentType", - "range": { - "startColumn": 41, - "endColumn": 53, - "lineCount": 1 - } - }, - { - "code": "reportUnknownArgumentType", - "range": { - "startColumn": 55, - "endColumn": 74, - "lineCount": 1 - } - }, - { - "code": "reportUnknownArgumentType", - "range": { - "startColumn": 16, - "endColumn": 26, - "lineCount": 1 - } - }, { "code": "reportAny", "range": { @@ -25369,246 +25153,6 @@ "lineCount": 1 } }, - { - "code": "reportUnknownVariableType", - "range": { - "startColumn": 11, - "endColumn": 17, - "lineCount": 1 - } - }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 4, - "endColumn": 30, - "lineCount": 1 - } - }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 31, - "endColumn": 37, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 31, - "endColumn": 37, - "lineCount": 1 - } - }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 8, - "endColumn": 21, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 8, - "endColumn": 21, - "lineCount": 1 - } - }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 8, - "endColumn": 26, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 8, - "endColumn": 26, - "lineCount": 1 - } - }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 8, - "endColumn": 27, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 8, - "endColumn": 27, - "lineCount": 1 - } - }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 8, - "endColumn": 46, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 8, - "endColumn": 46, - "lineCount": 1 - } - }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 8, - "endColumn": 38, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 8, - "endColumn": 38, - "lineCount": 1 - } - }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 8, - "endColumn": 39, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 8, - "endColumn": 39, - "lineCount": 1 - } - }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 8, - "endColumn": 15, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 8, - "endColumn": 15, - "lineCount": 1 - } - }, - { - "code": "reportUnknownParameterType", - "range": { - "startColumn": 8, - "endColumn": 13, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 8, - "endColumn": 13, - "lineCount": 1 - } - }, - { - "code": "reportMissingParameterType", - "range": { - "startColumn": 20, - "endColumn": 29, - "lineCount": 1 - } - }, - { - "code": "reportUnknownVariableType", - "range": { - "startColumn": 4, - "endColumn": 10, - "lineCount": 1 - } - }, - { - "code": "reportUnknownMemberType", - "range": { - "startColumn": 13, - "endColumn": 24, - "lineCount": 1 - } - }, - { - "code": "reportUnknownVariableType", - "range": { - "startColumn": 8, - "endColumn": 16, - "lineCount": 1 - } - }, - { - "code": "reportUnknownMemberType", - "range": { - "startColumn": 20, - "endColumn": 33, - "lineCount": 1 - } - }, - { - "code": "reportUnknownArgumentType", - "range": { - "startColumn": 33, - "endColumn": 41, - "lineCount": 1 - } - }, - { - "code": "reportUnknownArgumentType", - "range": { - "startColumn": 28, - "endColumn": 46, - "lineCount": 1 - } - }, - { - "code": "reportUnknownVariableType", - "range": { - "startColumn": 8, - "endColumn": 19, - "lineCount": 1 - } - }, - { - "code": "reportUnknownMemberType", - "range": { - "startColumn": 22, - "endColumn": 41, - "lineCount": 1 - } - }, - { - "code": "reportUnknownArgumentType", - "range": { - "startColumn": 31, - "endColumn": 37, - "lineCount": 1 - } - }, { "code": "reportUnknownVariableType", "range": { @@ -47090,26 +46634,10 @@ ], "./test/extra_int_eq_data.py": [ { - "code": "reportOptionalOperand", - "range": { - "startColumn": 42, - "endColumn": 56, - "lineCount": 1 - } - }, - { - "code": "reportOptionalCall", - "range": { - "startColumn": 15, - "endColumn": 31, - "lineCount": 1 - } - }, - { - "code": "reportIncompatibleMethodOverride", + "code": "reportUnreachable", "range": { "startColumn": 8, - "endColumn": 16, + "endColumn": 49, "lineCount": 1 } } @@ -47123,6 +46651,14 @@ "lineCount": 1 } }, + { + "code": "reportIncompatibleVariableOverride", + "range": { + "startColumn": 6, + "endColumn": 19, + "lineCount": 1 + } + }, { "code": "reportIncompatibleMethodOverride", "range": { @@ -47140,6 +46676,16 @@ } } ], + "./test/test_layer_pot_identity.py": [ + { + "code": "reportReturnType", + "range": { + "startColumn": 15, + "endColumn": 29, + "lineCount": 7 + } + } + ], "./test/test_linalg_skeletonization.py": [ { "code": "reportConstantRedefinition",