diff --git a/pymbolic/algorithm.py b/pymbolic/algorithm.py index 8f92085bfcb64a9eb81e934a9b19ceda06e69ac3..a3ae005f729b348e6f999ce908897fb9eb328115 100644 --- a/pymbolic/algorithm.py +++ b/pymbolic/algorithm.py @@ -155,7 +155,7 @@ def fft(x, sign=1, "instead. wrap_intermediate will stop working in 2023.", DeprecationWarning, stacklevel=2) - def wrap_intermediate_with_level(level, x): # pylint: disable=function-redefined # noqa: E501 + def wrap_intermediate_with_level(level, x): # pylint: disable=function-redefined return wrap_intermediate(x) if wrap_intermediate_with_level is None: @@ -272,7 +272,7 @@ def csr_matrix_multiply(S, x): # noqa result = numpy.empty_like(x) for i in range(h): - result[i] = sum(S.data[idx]*x[S.indices[idx]] # noqa pylint:disable=unsupported-assignment-operation + result[i] = sum(S.data[idx]*x[S.indices[idx]] # pylint:disable=unsupported-assignment-operation for idx in range(S.indptr[i], S.indptr[i+1])) return result @@ -326,7 +326,7 @@ def gaussian_elimination(mat, rhs): for i in range(m): g = gcd_many(*( [a for a in mat[i] if a] - + # noqa: W504 + + [a for a in rhs[i] if a])) mat[i] //= g diff --git a/pymbolic/geometric_algebra/mapper.py b/pymbolic/geometric_algebra/mapper.py index b143c5cb1c58324e8dea680b36f236bb3e351471..6d4edcbcc6df3d07731852e5a9e3c28eb80be803 100644 --- a/pymbolic/geometric_algebra/mapper.py +++ b/pymbolic/geometric_algebra/mapper.py @@ -23,6 +23,7 @@ THE SOFTWARE. # This is experimental, undocumented, and could go away any second. # Consider yourself warned. +from typing import ClassVar, Dict from pymbolic.geometric_algebra import MultiVector import pymbolic.geometric_algebra.primitives as prim @@ -104,7 +105,7 @@ class EvaluationMapper(EvaluationMapperBase): class StringifyMapper(StringifyMapperBase): - AXES = {0: "x", 1: "y", 2: "z"} + AXES: ClassVar[Dict[int, str]] = {0: "x", 1: "y", 2: "z"} def map_nabla(self, expr, enclosing_prec): return f"∇[{expr.nabla_id}]" diff --git a/pymbolic/geometric_algebra/primitives.py b/pymbolic/geometric_algebra/primitives.py index 2c56d960fe46ea6ad0f88f07d8f72301832d1133..4d4e15cc0e14e4205053026422c9cb92bd852d78 100644 --- a/pymbolic/geometric_algebra/primitives.py +++ b/pymbolic/geometric_algebra/primitives.py @@ -23,6 +23,8 @@ THE SOFTWARE. # This is experimental, undocumented, and could go away any second. # Consider yourself warned. +from typing import ClassVar, List + from pymbolic.primitives import Expression, Variable @@ -84,7 +86,7 @@ class Derivative: .. automethod:: dnabla .. automethod:: resolve """ - _next_id = [0] + _next_id: ClassVar[List[int]] = [0] def __init__(self): self.my_id = f"id{self._next_id[0]}" diff --git a/pymbolic/interop/ast.py b/pymbolic/interop/ast.py index df2a49dcb43a040dc148e312d69edbc9bf85cbfc..1fdadfe70a629360e50b29a79f4019aa77e8a357 100644 --- a/pymbolic/interop/ast.py +++ b/pymbolic/interop/ast.py @@ -24,8 +24,9 @@ THE SOFTWARE. """ import ast +from typing import Any, ClassVar, Dict, List, Tuple, Type + import pymbolic.primitives as p -from typing import Tuple, List, Any from pymbolic.typing import ExpressionT, ScalarT from pymbolic.mapper import CachedMapper @@ -112,7 +113,7 @@ def _neg(x): class ASTToPymbolic(ASTMapper): - bin_op_map = { + bin_op_map: ClassVar[Dict[Type[ast.operator], Any]] = { ast.Add: _add, ast.Sub: _sub, ast.Mult: _mult, @@ -138,7 +139,7 @@ class ASTToPymbolic(ASTMapper): return op_constructor(self.rec(expr.left), self.rec(expr.right)) - unary_op_map = { + unary_op_map: ClassVar[Dict[Type[ast.unaryop], Any]] = { ast.Invert: _neg, ast.Not: p.LogicalNot, # ast.UAdd: @@ -159,7 +160,7 @@ class ASTToPymbolic(ASTMapper): # (expr test, expr body, expr orelse) return p.If(self.rec(expr.test), self.rec(expr.body), self.rec(expr.orelse)) - comparison_op_map = { + comparison_op_map: ClassVar[Dict[Type[ast.cmpop], str]] = { ast.Eq: "==", ast.NotEq: "!=", ast.Lt: "<", @@ -279,15 +280,10 @@ class PymbolicToASTMapper(CachedMapper): return self._map_multi_children_op(expr.children, ast.Mult()) def map_constant(self, expr: ScalarT) -> ast.expr: - import sys if isinstance(expr, bool): return ast.NameConstant(expr) else: - # needed because of https://bugs.python.org/issue36280 - if sys.version_info < (3, 8): - return ast.Num(expr) - else: - return ast.Constant(expr, None) + return ast.Constant(expr, None) def map_call(self, expr: p.Call) -> ast.expr: return ast.Call( diff --git a/pymbolic/interop/common.py b/pymbolic/interop/common.py index bb7529e3b0897f13d94a5754724d1e9efd0ac5a4..1ad83cdac1d61ee3243e99e14647c735bf58b1c0 100644 --- a/pymbolic/interop/common.py +++ b/pymbolic/interop/common.py @@ -109,7 +109,7 @@ class SympyLikeToPymbolicMapper(SympyLikeMapperBase): def map_UnevaluatedExpr(self, expr): # noqa return self.rec(expr.args[0]) - def not_supported(self, expr): # noqa + def not_supported(self, expr): if isinstance(expr, int): return expr elif getattr(expr, "is_Function", False): diff --git a/pymbolic/interop/maxima.py b/pymbolic/interop/maxima.py index b9038f7496a8170c7ffe9885207a8abbac75a0b4..82812a24241b0f52a8d0536af293f3d216b7e53b 100644 --- a/pymbolic/interop/maxima.py +++ b/pymbolic/interop/maxima.py @@ -35,10 +35,13 @@ __doc__ = """ # http://trac.sagemath.org/sage_trac/browser/sage/interfaces/maxima.py import re -import pytools +from sys import intern +from typing import ClassVar, List, Tuple + import numpy as np -from sys import intern +import pytools + from pymbolic.mapper.stringifier import StringifyMapper from pymbolic.parser import Parser as ParserBase, FinalizedTuple @@ -92,11 +95,12 @@ class MaximaParser(ParserBase): imag_unit = intern("imag_unit") euler_number = intern("euler_number") - lex_table = [ + lex_table: ClassVar[List[Tuple[str, str]]] = [ (power_sym, pytools.lex.RE(r"\^")), (imag_unit, pytools.lex.RE(r"%i")), (euler_number, pytools.lex.RE(r"%e")), - ] + ParserBase.lex_table + *ParserBase.lex_table + ] def parse_prefix(self, pstate): pstate.expect_not_end() @@ -212,7 +216,7 @@ class MaximaParser(ParserBase): new_el = self.parse_expression(pstate, p._PREC_COMMA) if isinstance(left_exp, tuple) \ and not isinstance(left_exp, FinalizedTuple): - left_exp = left_exp + (new_el,) + left_exp = (*left_exp, new_el) else: left_exp = (left_exp, new_el) diff --git a/pymbolic/interop/symengine.py b/pymbolic/interop/symengine.py index 431671eb84d97708757bebd6f43127f9e28f571b..f6152a1d57ca2bfaa05457798e5a88c5b6b43e6f 100644 --- a/pymbolic/interop/symengine.py +++ b/pymbolic/interop/symengine.py @@ -81,7 +81,7 @@ class SymEngineToPymbolicMapper(SympyLikeToPymbolicMapper): # For builtin functions return type(expr).__name__ - def not_supported(self, expr): # noqa + def not_supported(self, expr): from symengine.lib.symengine_wrapper import \ PyFunction # pylint: disable=E0611 if isinstance(expr, PyFunction) and \ diff --git a/pymbolic/interop/sympy.py b/pymbolic/interop/sympy.py index 22f4569ebf433334e9e4be82489a4f4f6408642d..85a79267d56914857d17301f19aa0d7f93624718 100644 --- a/pymbolic/interop/sympy.py +++ b/pymbolic/interop/sympy.py @@ -98,7 +98,7 @@ class PymbolicToSympyMapper(PymbolicToSympyLikeMapper): sym = sympy def raise_conversion_error(self, expr): - raise RuntimeError("do not know how to translate '{expr}' to sympy") + raise RuntimeError(f"do not know how to translate '{expr}' to sympy") def map_subscript(self, expr): return self.sym.Indexed( diff --git a/pymbolic/mapper/__init__.py b/pymbolic/mapper/__init__.py index 34589b9676095cd8dc998d0c574734f03c17bf83..034cc755a03ed51aa329cda99e945f7e09d66f27 100644 --- a/pymbolic/mapper/__init__.py +++ b/pymbolic/mapper/__init__.py @@ -22,9 +22,12 @@ THE SOFTWARE. from abc import ABC, abstractmethod from typing import Any, Dict -import pymbolic.primitives as primitives + from immutabledict import immutabledict +import pymbolic.primitives as primitives + + __doc__ = """ Basic dispatch -------------- @@ -305,23 +308,18 @@ class CombineMapper(RecursiveMapper): raise NotImplementedError def map_call(self, expr, *args, **kwargs): - return self.combine( - (self.rec(expr.function, *args, **kwargs),) - + tuple([ - self.rec(child, *args, **kwargs) for child in expr.parameters - ]) - ) + return self.combine(( + self.rec(expr.function, *args, **kwargs), + *[self.rec(child, *args, **kwargs) for child in expr.parameters] + )) def map_call_with_kwargs(self, expr, *args, **kwargs): - return self.combine( - (self.rec(expr.function, *args, **kwargs),) - + tuple([ - self.rec(child, *args, **kwargs) - for child in expr.parameters]) - + tuple([ - self.rec(child, *args, **kwargs) - for child in expr.kw_parameters.values()]) - ) + return self.combine(( + self.rec(expr.function, *args, **kwargs), + *[self.rec(child, *args, **kwargs) for child in expr.parameters], + *[self.rec(child, *args, **kwargs) + for child in expr.kw_parameters.values()] + )) def map_subscript(self, expr, *args, **kwargs): return self.combine( @@ -351,12 +349,10 @@ class CombineMapper(RecursiveMapper): self.rec(expr.exponent, *args, **kwargs))) def map_polynomial(self, expr, *args, **kwargs): - return self.combine( - (self.rec(expr.base, *args, **kwargs),) - + tuple([ - self.rec(coeff, *args, **kwargs) for exp, coeff in expr.data - ]) - ) + return self.combine(( + self.rec(expr.base, *args, **kwargs), + *[self.rec(coeff, *args, **kwargs) for exp, coeff in expr.data] + )) def map_left_shift(self, expr, *args, **kwargs): return self.combine(( diff --git a/pymbolic/mapper/constant_folder.py b/pymbolic/mapper/constant_folder.py index e8ab531b79bbf7ae4cc8f65ebd1ddaac20cd983e..da32d3b8527887343f90eec58686db98d147963a 100644 --- a/pymbolic/mapper/constant_folder.py +++ b/pymbolic/mapper/constant_folder.py @@ -67,7 +67,7 @@ class ConstantFoldingMapperBase: if constants: from functools import reduce constant = reduce(op, constants) - return constructor(tuple([constant]+nonconstants)) + return constructor((constant, *nonconstants)) else: return constructor(tuple(nonconstants)) diff --git a/pymbolic/mapper/optimize.py b/pymbolic/mapper/optimize.py index 54bd9fc2c851f820a9940039a519e26e44346f70..d56e24596b6c0b189708831900215fada4b46a7f 100644 --- a/pymbolic/mapper/optimize.py +++ b/pymbolic/mapper/optimize.py @@ -46,7 +46,7 @@ def _get_def_from_ast_container(container, name, node_type): @lru_cache def _get_ast_for_file(filename): - with open(filename, "r") as inf: + with open(filename) as inf: return ast.parse(inf.read(), filename) diff --git a/pymbolic/mapper/stringifier.py b/pymbolic/mapper/stringifier.py index e49fcc4f9103956afccdf05c56975847d3e8ee4a..e2632bcd5b3fc15c7e53f6d3fd225157a9553977 100644 --- a/pymbolic/mapper/stringifier.py +++ b/pymbolic/mapper/stringifier.py @@ -20,8 +20,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -from pymbolic.mapper import Mapper, CachedMapper +from typing import ClassVar, Dict + import pymbolic.primitives as p +from pymbolic.mapper import Mapper, CachedMapper + __doc__ = """ .. _prec-constants: @@ -161,7 +164,7 @@ class StringifyMapper(Mapper): self.rec(ch, PREC_NONE, *args, **kwargs) for ch in expr.parameters ]) - + # noqa: W504 + + tuple([ "{}={}".format(name, self.rec(ch, PREC_NONE, *args, **kwargs)) for name, ch in expr.kw_parameters.items() @@ -623,7 +626,7 @@ class SimplifyingSortingStringifyMapper(StringifyMapper): class LaTeXMapper(StringifyMapper): - COMPARISON_OP_TO_LATEX = { + COMPARISON_OP_TO_LATEX: ClassVar[Dict[str, str]] = { "==": r"=", "!=": r"\ne", "<=": r"\le", diff --git a/pymbolic/mapper/unifier.py b/pymbolic/mapper/unifier.py index 577b6efb735d18afeaf375a2f01ce568a7f4b552..2d9a7d2e0e76e1f36a6da9ee829ca0f5ca6e7a24 100644 --- a/pymbolic/mapper/unifier.py +++ b/pymbolic/mapper/unifier.py @@ -391,7 +391,7 @@ class UnidirectionalUnifier(UnifierBase): return for subset in map(set, subsets(s, len(s) - k + 1)): for partition in partitions(s - subset, k - 1): - yield [subset] + partition + yield [subset, *partition] for partition in partitions( other_leftovers, len(plain_var_candidates)): @@ -410,9 +410,10 @@ class UnidirectionalUnifier(UnifierBase): # urecs was not merged in, do it here. yield from unify_many(urecs, result) - for urec in match_children( - UnificationRecord([]), 0, set(range(len(other.children)))): - yield urec + yield from match_children( + UnificationRecord([]), + 0, + set(range(len(other.children)))) def map_sum(self, expr, other, unis): from pymbolic.primitives import flattened_sum diff --git a/pymbolic/parser.py b/pymbolic/parser.py index e885c7d21663a93f4f139fced104c65d85d27b28..5ce3347fc4c0f15e013e2ab999889a06a85adfb1 100644 --- a/pymbolic/parser.py +++ b/pymbolic/parser.py @@ -20,9 +20,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ +from sys import intern +from typing import ClassVar, Dict, List, Tuple + import pytools.lex from pytools import memoize_method -from sys import intern + _imaginary = intern("imaginary") _float = intern("float") @@ -91,7 +94,7 @@ _PREC_CALL = 250 def _join_to_slice(left, right): from pymbolic.primitives import Slice if isinstance(right, Slice): - return Slice((left,) + right.children) + return Slice((left, *right.children)) else: return Slice((left, right)) @@ -117,7 +120,7 @@ class FinalizedList(list, FinalizedContainer): class Parser: - lex_table = [ + lex_table: ClassVar[List[Tuple[str, str]]] = [ (_equal, pytools.lex.RE(r"==")), (_notequal, pytools.lex.RE(r"!=")), (_equal, pytools.lex.RE(r"==")), @@ -182,7 +185,7 @@ class Parser: (_colon, pytools.lex.RE(r"\:")), ] - _COMP_TABLE = { + _COMP_TABLE: ClassVar[Dict[str, str]] = { _greater: ">", _greaterequal: ">=", _less: "<", @@ -246,7 +249,7 @@ class Parser: left_exp = self.parse_expression(pstate, _PREC_UNARY) elif pstate.is_next(_minus): pstate.advance() - left_exp = -self.parse_expression(pstate, _PREC_UNARY) # noqa pylint:disable=invalid-unary-operand-type + left_exp = -self.parse_expression(pstate, _PREC_UNARY) # pylint:disable=invalid-unary-operand-type elif pstate.is_next(_not): pstate.advance() from pymbolic.primitives import LogicalNot @@ -363,7 +366,7 @@ class Parser: pstate.advance() right_exp = self.parse_expression(pstate, _PREC_PLUS) if isinstance(left_exp, primitives.Sum): - left_exp = primitives.Sum(left_exp.children + (right_exp,)) + left_exp = primitives.Sum((*left_exp.children, right_exp)) else: left_exp = primitives.Sum((left_exp, right_exp)) @@ -374,13 +377,13 @@ class Parser: if isinstance(left_exp, primitives.Sum): left_exp = primitives.Sum(left_exp.children + ((-right_exp),)) # noqa pylint:disable=invalid-unary-operand-type else: - left_exp = primitives.Sum((left_exp, -right_exp)) # noqa pylint:disable=invalid-unary-operand-type + left_exp = primitives.Sum((left_exp, -right_exp)) # pylint:disable=invalid-unary-operand-type did_something = True elif next_tag is _times and _PREC_TIMES > min_precedence: pstate.advance() right_exp = self.parse_expression(pstate, _PREC_PLUS) if isinstance(left_exp, primitives.Product): - left_exp = primitives.Product(left_exp.children + (right_exp,)) + left_exp = primitives.Product((*left_exp.children, right_exp)) else: left_exp = primitives.Product((left_exp, right_exp)) did_something = True @@ -494,7 +497,7 @@ class Parser: new_el = self.parse_expression(pstate, _PREC_COMMA) if isinstance(left_exp, (tuple, list)) \ and not isinstance(left_exp, FinalizedContainer): - left_exp = left_exp + (new_el,) + left_exp = (*left_exp, new_el) else: left_exp = (left_exp, new_el) diff --git a/pymbolic/primitives.py b/pymbolic/primitives.py index 621073fb2e7c89af92c1333c950e87ee732514ef..49fb9194eff817b809bea1946b09574fdf71c2ac 100644 --- a/pymbolic/primitives.py +++ b/pymbolic/primitives.py @@ -20,8 +20,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -from sys import intern from abc import ABC, abstractmethod +from sys import intern +from typing import ClassVar, Dict + import pymbolic.traits as traits @@ -260,7 +262,7 @@ class Expression(ABC): if is_nonzero(other): if self: if isinstance(other, Sum): - return Sum((self,) + other.children) + return Sum((self, *other.children)) else: return Sum((self, other)) else: @@ -580,7 +582,7 @@ class Expression(ABC): and self.__getinitargs__() == other.__getinitargs__()) def get_hash(self): - return hash((type(self).__name__,) + self.__getinitargs__()) + return hash((type(self).__name__, *self.__getinitargs__())) # }}} @@ -952,7 +954,7 @@ class Sum(_MultiChildExpression): return Sum(self.children + other.children) if not other: return self - return Sum(self.children + (other,)) + return Sum((*self.children, other)) def __radd__(self, other): if not is_constant(other): @@ -962,7 +964,7 @@ class Sum(_MultiChildExpression): return Sum(other.children + self.children) if not other: return self - return Sum((other,) + self.children) + return Sum((other, *self.children)) def __sub__(self, other): if not is_valid_operand(other): @@ -970,7 +972,7 @@ class Sum(_MultiChildExpression): if not other: return self - return Sum(self.children + (-other,)) + return Sum((*self.children, -other)) def __bool__(self): if len(self.children) == 0: @@ -1002,7 +1004,7 @@ class Product(_MultiChildExpression): return 0 if is_zero(other-1): return self - return Product(self.children + (other,)) + return Product((*self.children, other)) def __rmul__(self, other): if not is_constant(other): @@ -1013,7 +1015,7 @@ class Product(_MultiChildExpression): return 0 if is_zero(other-1): return self - return Product((other,) + self.children) + return Product((other, *self.children)) def __bool__(self): for i in self.children: @@ -1205,7 +1207,7 @@ class Comparison(Expression): init_arg_names = ("left", "operator", "right") - operator_to_name = { + operator_to_name: ClassVar[Dict[str, str]] = { "==": "eq", "!=": "ne", ">=": "ge", @@ -1213,7 +1215,9 @@ class Comparison(Expression): "<=": "le", "<": "lt", } - name_to_operator = {name: op for op, name in operator_to_name.items()} + name_to_operator: ClassVar[Dict[str, str]] = { + name: op for op, name in operator_to_name.items() + } def __init__(self, left, operator, right): """ diff --git a/pyproject.toml b/pyproject.toml index b416c1947a2d194fd7fdf0a7275b862cb3f53004..36fd7d30b2318017a6b48f5efcc1e78a1420d76e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,14 +61,17 @@ preview = true [tool.ruff.lint] extend-select = [ - "B", # flake8-bugbear - "C", # flake8-comprehensions - "E", # pycodestyle - "F", # pyflakes + "B", # flake8-bugbear + "C", # flake8-comprehensions + "E", # pycodestyle + "F", # pyflakes + "G", # flake8-logging-format # "I", # flake8-isort - "N", # pep8-naming - "Q", # flake8-quotes - "W", # pycodestyle + "N", # pep8-naming + "Q", # flake8-quotes + "RUF", # ruff + "UP", # pyupgrade + "W", # pycodestyle ] extend-ignore = [ "C90", # McCabe complexity @@ -76,6 +79,8 @@ extend-ignore = [ "E241", # multiple spaces after comma "E242", # tab after comma "E402", # module level import not at the top of file + "UP031", # use f-strings instead of % + "UP032", # use f-strings instead of .format ] exclude = [ "pymbolic/polynomial.py", diff --git a/test/test_maxima.py b/test/test_maxima.py index 7a2257df572c6aabcab13449305b29fa7868761a..33b40f125737c574e581bcb2b8dd5409a6cfddce 100644 --- a/test/test_maxima.py +++ b/test/test_maxima.py @@ -118,7 +118,7 @@ def test_lax_round_trip(knl): knl.clean_eval_str_with_setup(k_setup, "result")) assert knl.clean_eval_expr_with_setup( - k_setup + [("result2", parsed)], + [*k_setup, ("result2", parsed)], "ratsimp(result-result2)") == 0 diff --git a/test/test_pymbolic.py b/test/test_pymbolic.py index 12be1e6700e5297325f498c808a4cb2d03ce0a29..b8e4e57aac7304300494ede6b27295a26740c7a4 100644 --- a/test/test_pymbolic.py +++ b/test/test_pymbolic.py @@ -456,7 +456,7 @@ def test_geometric_algebra(dims): assert (c << c.I.rev()).close_to(c | c.I.rev()) # inverse - for div in list(b.gen_blades()) + [vec1, vec1.I]: + for div in [*b.gen_blades(), vec1, vec1.I]: assert (div.inv()*div).close_to(1) assert (div*div.inv()).close_to(1) assert ((1/div)*div).close_to(1) @@ -543,7 +543,7 @@ def test_compile(): def test_unifier(): from pymbolic import var from pymbolic.mapper.unifier import UnidirectionalUnifier - a, b, c, d, e, f = [var(s) for s in "abcdef"] + a, b, c, d, e, f = (var(s) for s in "abcdef") def match_found(records, eqns): for record in records: @@ -586,7 +586,7 @@ def test_long_sympy_mapping(): sp = pytest.importorskip("sympy") from pymbolic.interop.sympy import SympyToPymbolicMapper SympyToPymbolicMapper()(sp.sympify(int(10**20))) - SympyToPymbolicMapper()(sp.sympify(int(10))) + SympyToPymbolicMapper()(sp.sympify(10)) # }}}