From ee59dcc0b9a23891d3540236ffac5e4a648b4235 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Mon, 8 Jul 2024 12:21:29 -0500 Subject: [PATCH 01/18] Add ruff.isort config --- pyproject.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index f416506..57cc6ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -91,3 +91,10 @@ extend-ignore = [ inline-quotes = "double" docstring-quotes = "double" multiline-quotes = "double" + +[tool.ruff.lint.isort] +known-first-party = ["pytools"] +known-local-folder = ["pymbolic"] +lines-after-imports = 2 +combine-as-imports = true + From 8483d50c34e0ca49582c9cca3ae78417b63a7ce2 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Thu, 12 Jan 2023 19:59:06 -0600 Subject: [PATCH 02/18] Base expressions on dataclasses --- doc/index.rst | 14 +- pymbolic/parser.py | 5 +- pymbolic/primitives.py | 710 +++++++++++++++++++---------------------- 3 files changed, 336 insertions(+), 393 deletions(-) diff --git a/doc/index.rst b/doc/index.rst index fb159ba..040693e 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -69,13 +69,13 @@ You can also easily define your own objects to use inside an expression: .. doctest:: - >>> from pymbolic.primitives import Expression - >>> class FancyOperator(Expression): - ... def __init__(self, operand): - ... self.operand = operand - ... - ... def __getinitargs__(self): - ... return (self.operand,) + >>> from pymbolic.primitives import Expression, augment_expression_dataclass + >>> from dataclasses import dataclass + >>> + >>> @augment_expression_dataclass + ... @dataclass(frozen=True) + ... class FancyOperator(Expression): + ... operand: Expression ... ... mapper_method = "map_fancy_operator" ... diff --git a/pymbolic/parser.py b/pymbolic/parser.py index 5ce3347..1bc7c93 100644 --- a/pymbolic/parser.py +++ b/pymbolic/parser.py @@ -23,6 +23,8 @@ from sys import intern from typing import ClassVar, Dict, List, Tuple +from immutabledict import immutabledict + import pytools.lex from pytools import memoize_method @@ -333,7 +335,8 @@ def parse_postfix(self, pstate, min_precedence, left_exp): args, kwargs = self.parse_arglist(pstate) if kwargs: - left_exp = primitives.CallWithKwargs(left_exp, args, kwargs) + left_exp = primitives.CallWithKwargs( + left_exp, args, immutabledict(kwargs)) else: left_exp = primitives.Call(left_exp, args) diff --git a/pymbolic/primitives.py b/pymbolic/primitives.py index 49fb919..8fb4c3b 100644 --- a/pymbolic/primitives.py +++ b/pymbolic/primitives.py @@ -1,3 +1,6 @@ +from __future__ import annotations + + __copyright__ = "Copyright (C) 2009-2013 Andreas Kloeckner" __license__ = """ @@ -20,19 +23,42 @@ THE SOFTWARE. """ -from abc import ABC, abstractmethod +from dataclasses import dataclass, fields from sys import intern -from typing import ClassVar, Dict +from typing import Any, Callable, ClassVar, Mapping, Tuple, Union +from warnings import warn import pymbolic.traits as traits +# FIXME: This is a lie. Many more constant types (e.g. numpy and such) +# are in practical use and completely fine. We cannot really add in numpy +# as a special case (because pymbolic doesn't have a hard numpy dependency), +# and there isn't a usable numerical tower that we could rely on. As such, +# code abusing what constants are allowable will have to type-ignore those +# statements. Better ideas would be most welcome. +# +# References: +# https://github.com/python/mypy/issues/3186 +# https://discuss.python.org/t/numeric-generics-where-do-we-go-from-pep-3141-and-present-day-mypy/17155/14 +_ConstantT = Union[int, float, complex] +ExpressionT = Union[_ConstantT, "Expression", Tuple["ExpressionT", ...]] + + __doc__ = """ Expression base class --------------------- .. autoclass:: Expression +.. class:: ExpressionT + + A type that can be used in type annotations whenever an expression + is desired. A :class:`typing.Union` of :class:`Expression` and + built-in scalar types. + +.. autofunction:: augment_expression_dataclass + Sums, products and such ----------------------- @@ -188,7 +214,7 @@ def disable_subscript_by_getitem(): pass -class Expression(ABC): +class Expression: """Superclass for parts of a mathematical expression. Overrides operators to implicitly construct :class:`Sum`, :class:`Product` and other expressions. @@ -215,9 +241,7 @@ class Expression(ABC): .. automethod:: make_stringifier .. automethod:: __eq__ - .. automethod:: is_equal .. automethod:: __hash__ - .. automethod:: get_hash .. automethod:: __str__ .. automethod:: __repr__ @@ -239,9 +263,8 @@ class Expression(ABC): # {{{ init arg names (override by subclass) - @abstractmethod def __getinitargs__(self): - pass + raise NotImplementedError @classmethod @property @@ -440,7 +463,8 @@ def __pos__(self): def __call__(self, *args, **kwargs): if kwargs: - return CallWithKwargs(self, args, kwargs) + from immutabledict import immutabledict + return CallWithKwargs(self, args, immutabledict(kwargs)) else: return Call(self, args) @@ -538,10 +562,13 @@ def __repr__(self): def __eq__(self, other): """Provides equality testing with quick positive and negative paths based on :func:`id` and :meth:`__hash__`. - - Subclasses should generally not override this method, but instead - provide an implementation of :meth:`is_equal`. """ + from warnings import warn + warn(f"Expression.__eq__ is used by {self.__class__}. This is deprecated. " + "Use equality comparison supplied by augment_expression_dataclass " + "instead. " + "This will stop working in 2025.", + DeprecationWarning, stacklevel=2) if self is other: return True elif hash(self) != hash(other): @@ -554,10 +581,13 @@ def __ne__(self, other): def __hash__(self): """Provides caching for hash values. - - Subclasses should generally not override this method, but instead - provide an implementation of :meth:`get_hash`. """ + from warnings import warn + warn(f"Expression.__hash__ is used by {self.__class__}. This is deprecated. " + "Use hash functions supplied by augment_expression_dataclass instead. " + "This will stop working in 2025.", + DeprecationWarning, stacklevel=2) + try: return self._hash_value except AttributeError: @@ -571,7 +601,7 @@ def __setstate__(self, state): # Can't use trivial pickling: _hash_value cache must stay unset assert len(self.init_arg_names) == len(state), type(self) for name, value in zip(self.init_arg_names, state): - setattr(self, name, value) + object.__setattr__(self, name, value) # }}} @@ -683,6 +713,116 @@ def __iter__(self): raise TypeError("expression types are not iterable") +# {{{ dataclasses support + +def augment_expression_dataclass(cls: type[Expression]) -> type[Expression]: + """A class decorator for :func:`dataclasses.dataclass`-derived + :class:`Expression` nodes. It adds cached hashing, equality comparisons + with ``self is other`` shortcuts as well as some methods/attributes + for backward compatibility (e.g. ``__getinitargs__``, ``init_arg_names``) + """ + attr_tuple = ", ".join(f"self.{fld.name}" for fld in fields(cls)) + if attr_tuple: + attr_tuple = f"({attr_tuple},)" + else: + attr_tuple = "()" + + fld_name_tuple = ", ".join(f"'{fld.name}'" for fld in fields(cls)) + if fld_name_tuple: + fld_name_tuple = f"({fld_name_tuple},)" + else: + fld_name_tuple = "()" + + comparison = " and ".join( + f"self.{fld.name} == other.{fld.name}" + for fld in fields(cls)) + + if not comparison: + comparison = "True" + + from pytools.codegen import remove_common_indentation + augment_code = remove_common_indentation( + f""" + from warnings import warn + + + def {cls.__name__}_eq(self, other): + if self is other: + return True + if self.__class__ is not other.__class__: + return False + if hash(self) != hash(other): + return False + if self.__class__ is not cls and self.init_arg_names != {fld_name_tuple}: + warn(f"{{self.__class__}} is derived from {cls}, which is now " + f"a dataclass. {{self.__class__}} should be converted to being " + "a dataclass as well. Non-dataclass subclasses " + "will stop working in 2025.", + DeprecationWarning) + + return self.is_equal(other) + + return self.__class__ == other.__class__ and {comparison} + + cls.__eq__ = {cls.__name__}_eq + + + def {cls.__name__}_hash(self): + try: + return self._hash_value + except AttributeError: + pass + + if self.__class__ is not cls and self.init_arg_names != {fld_name_tuple}: + warn(f"{{self.__class__}} is derived from {cls}, which is now " + f"a dataclass. {{self.__class__}} should be converted to being " + "a dataclass as well. Non-dataclass subclasses " + "will stop working in 2025.", + DeprecationWarning) + + hash_val = self.get_hash() + else: + hash_val = hash({attr_tuple}) + + object.__setattr__(self, "_hash_value", hash_val) + return hash_val + + cls.__hash__ = {cls.__name__}_hash + + + def {cls.__name__}_init_arg_names(self): + warn("__getinitargs__ is deprecated and will be removed in 2025. " + "Use dataclasses.fields instead.", + DeprecationWarning, stacklevel=2) + + return {fld_name_tuple} + + cls.init_arg_names = property({cls.__name__}_init_arg_names) + + + def {cls.__name__}_getinitargs(self): + warn("__getinitargs__ is deprecated and will be removed in 2025. " + "Use dataclasses.fields instead.", + DeprecationWarning, stacklevel=2) + + return {attr_tuple} + + cls.__getinitargs__ = {cls.__name__}_getinitargs + + + # FIXME Also implement pickling, with fallback + """) + + exec_dict = {"cls": cls, "_MODULE_SOURCE_CODE": augment_code} + exec(compile(augment_code, + f"", "exec"), + exec_dict) + + return cls + +# }}} + + class AlgebraicLeaf(Expression): """An expression that serves as a leaf for arithmetic evaluation. This may end up having child nodes still, but they're not reached by @@ -696,73 +836,50 @@ class Leaf(AlgebraicLeaf): pass +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class Variable(Leaf): """ .. attribute:: name """ - init_arg_names = ("name",) + name: str - def __init__(self, name): - assert name - self.name = intern(name) - - def __getinitargs__(self): - return self.name, - - def __lt__(self, other): - if isinstance(other, Variable): - return self.name.__lt__(other.name) - else: - return NotImplemented - - def __setstate__(self, val): - super().__setstate__(val) - - self.name = intern(self.name) + # FIXME: Missing intern(): does it matter? mapper_method = intern("map_variable") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class Wildcard(Leaf): - def __getinitargs__(self): - return () - mapper_method = intern("map_wildcard") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class DotWildcard(Leaf): """ A wildcard that can be substituted for a single expression. """ - init_arg_names = ("name",) - - def __init__(self, name): - assert isinstance(name, str) - self.name = name - - def __getinitargs__(self): - return self.name, + name: str mapper_method = intern("map_dot_wildcard") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class StarWildcard(Leaf): """ A wildcard that can be substituted by a sequence of expressions of non-negative length. """ - init_arg_names = ("name",) - - def __init__(self, name): - assert isinstance(name, str) - self.name = name - - def __getinitargs__(self): - return self.name, + name: str mapper_method = intern("map_star_wildcard") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class FunctionSymbol(AlgebraicLeaf): """Represents the name of a function. @@ -770,14 +887,13 @@ class FunctionSymbol(AlgebraicLeaf): allow `Call` to check the number of arguments. """ - def __getinitargs__(self): - return () - mapper_method = intern("map_function_symbol") # {{{ structural primitives +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class Call(AlgebraicLeaf): """A function invocation. @@ -791,29 +907,14 @@ class Call(AlgebraicLeaf): of which is a :class:`Expression` or a constant. """ - - init_arg_names = ("function", "parameters",) - - def __init__(self, function, parameters): - self.function = function - self.parameters = parameters - - try: - arg_count = self.function.arg_count - except AttributeError: - pass - else: - if len(self.parameters) != arg_count: - raise TypeError( - f"{self.function} called with wrong number of arguments " - f"(need {arg_count}, got {len(parameters)})") - - def __getinitargs__(self): - return self.function, self.parameters + function: ExpressionT + parameters: tuple[ExpressionT, ...] mapper_method = intern("map_call") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class CallWithKwargs(AlgebraicLeaf): """A function invocation with keyword arguments. @@ -834,48 +935,15 @@ class CallWithKwargs(AlgebraicLeaf): constructor. """ - init_arg_names = ("function", "parameters", "kw_parameters") - - def __init__(self, function, parameters, kw_parameters): - self.function = function - self.parameters = parameters - - if isinstance(kw_parameters, dict): - self.kw_parameters = kw_parameters - else: - self.kw_parameters = dict(kw_parameters) - - try: - arg_count = self.function.arg_count - except AttributeError: - pass - else: - if len(self.parameters) != arg_count: - raise TypeError( - f"{self.function} called with wrong number of arguments " - f"(need {arg_count}, got {len(parameters)})") - - def __getinitargs__(self): - return (self.function, - self.parameters, - tuple(sorted(self.kw_parameters.items(), key=lambda item: item[0]))) - - def __setstate__(self, state): - # CallWithKwargs must override __setstate__ because during pickling the - # kw_parameters are converted to tuple, which needs to be converted - # back to dict. - assert len(self.init_arg_names) == len(state) - function, parameters, kw_parameters = state - - self.function = function - self.parameters = parameters - if not isinstance(kw_parameters, dict): - kw_parameters = dict(kw_parameters) - self.kw_parameters = kw_parameters + function: ExpressionT + parameters: tuple[ExpressionT, ...] + kw_parameters: Mapping[str, ExpressionT] mapper_method = intern("map_call_with_kwargs") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class Subscript(AlgebraicLeaf): """An array subscript. @@ -886,15 +954,8 @@ class Subscript(AlgebraicLeaf): Return :attr:`index` wrapped in a single-element tuple, if it is not already a tuple. """ - - init_arg_names = ("aggregate", "index",) - - def __init__(self, aggregate, index): - self.aggregate = aggregate - self.index = index - - def __getinitargs__(self): - return self.aggregate, self.index + aggregate: ExpressionT + index: ExpressionT @property def index_tuple(self): @@ -906,19 +967,15 @@ def index_tuple(self): mapper_method = intern("map_subscript") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class Lookup(AlgebraicLeaf): """Access to an attribute of an *aggregate*, such as an attribute of a class. """ - init_arg_names = ("aggregate", "name",) - - def __init__(self, aggregate, name): - self.aggregate = aggregate - self.name = name - - def __getinitargs__(self): - return self.aggregate, self.name + aggregate: ExpressionT + name: str mapper_method = intern("map_lookup") @@ -927,25 +984,17 @@ def __getinitargs__(self): # {{{ arithmetic primitives -class _MultiChildExpression(Expression): - init_arg_names = ("children",) - - def __init__(self, children): - assert isinstance(children, tuple) - - self.children = children - - def __getinitargs__(self): - return self.children, - - -class Sum(_MultiChildExpression): +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) +class Sum(Expression): """ .. attribute:: children A :class:`tuple`. """ + children: tuple[ExpressionT, ...] + def __add__(self, other): if not is_valid_operand(other): return NotImplemented @@ -988,13 +1037,17 @@ def __bool__(self): mapper_method = intern("map_sum") -class Product(_MultiChildExpression): +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) +class Product(Expression): """ .. attribute:: children A :class:`tuple`. """ + children: tuple[ExpressionT, ...] + def __mul__(self, other): if not is_valid_operand(other): return NotImplemented @@ -1028,15 +1081,11 @@ def __bool__(self): mapper_method = intern("map_product") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class QuotientBase(Expression): - init_arg_names = ("numerator", "denominator",) - - def __init__(self, numerator, denominator=1): - self.numerator = numerator - self.denominator = denominator - - def __getinitargs__(self): - return self.numerator, self.denominator + numerator: ExpressionT + denominator: ExpressionT @property def num(self): @@ -1052,21 +1101,19 @@ def __bool__(self): __nonzero__ = __bool__ +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class Quotient(QuotientBase): """ .. attribute:: numerator .. attribute:: denominator """ - def is_equal(self, other): - from pymbolic.rational import Rational - return isinstance(other, (Rational, Quotient)) \ - and (self.numerator == other.numerator) \ - and (self.denominator == other.denominator) - mapper_method = intern("map_quotient") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class FloorDiv(QuotientBase): """ .. attribute:: numerator @@ -1076,6 +1123,8 @@ class FloorDiv(QuotientBase): mapper_method = intern("map_floor_div") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class Remainder(QuotientBase): """ .. attribute:: numerator @@ -1085,20 +1134,16 @@ class Remainder(QuotientBase): mapper_method = intern("map_remainder") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class Power(Expression): """ .. attribute:: base .. attribute:: exponent """ - init_arg_names = ("base", "exponent",) - - def __init__(self, base, exponent): - self.base = base - self.exponent = exponent - - def __getinitargs__(self): - return self.base, self.exponent + base: ExpressionT + exponent: ExpressionT mapper_method = intern("map_power") @@ -1107,17 +1152,15 @@ def __getinitargs__(self): # {{{ shift operators +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class _ShiftOperator(Expression): - init_arg_names = ("shiftee", "shift",) - - def __init__(self, shiftee, shift): - self.shiftee = shiftee - self.shift = shift - - def __getinitargs__(self): - return self.shiftee, self.shift + shiftee: ExpressionT + shift: ExpressionT +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class LeftShift(_ShiftOperator): """ .. attribute:: shiftee @@ -1127,6 +1170,8 @@ class LeftShift(_ShiftOperator): mapper_method = intern("map_left_shift") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class RightShift(_ShiftOperator): """ .. attribute:: shiftee @@ -1140,48 +1185,54 @@ class RightShift(_ShiftOperator): # {{{ bitwise operators +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class BitwiseNot(Expression): """ .. attribute:: child """ - init_arg_names = ("child",) - - def __init__(self, child): - self.child = child - - def __getinitargs__(self): - return (self.child,) + child: ExpressionT mapper_method = intern("map_bitwise_not") -class BitwiseOr(_MultiChildExpression): +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) +class BitwiseOr(Expression): """ .. attribute:: children A :class:`tuple`. """ + children: tuple[ExpressionT, ...] + mapper_method = intern("map_bitwise_or") -class BitwiseXor(_MultiChildExpression): +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) +class BitwiseXor(Expression): """ .. attribute:: children A :class:`tuple`. """ + children: tuple[ExpressionT, ...] mapper_method = intern("map_bitwise_xor") -class BitwiseAnd(_MultiChildExpression): +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) +class BitwiseAnd(Expression): """ .. attribute:: children A :class:`tuple`. """ + children: tuple[ExpressionT, ...] mapper_method = intern("map_bitwise_and") @@ -1190,6 +1241,8 @@ class BitwiseAnd(_MultiChildExpression): # {{{ comparisons, logic, conditionals +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class Comparison(Expression): """ .. attribute:: left @@ -1203,11 +1256,16 @@ class Comparison(Expression): Unlike other expressions, comparisons are not implicitly constructed by comparing :class:`Expression` objects. See :meth:`Expression.eq`. + + .. attribute:: operator_to_name + .. attribute:: name_to_operator """ - init_arg_names = ("left", "operator", "right") + left: ExpressionT + operator: str + right: ExpressionT - operator_to_name: ClassVar[Dict[str, str]] = { + operator_to_name: ClassVar[dict[str, str]] = { "==": "eq", "!=": "ne", ">=": "ge", @@ -1215,70 +1273,69 @@ class Comparison(Expression): "<=": "le", "<": "lt", } - name_to_operator: ClassVar[Dict[str, str]] = { + name_to_operator: ClassVar[dict[str, str]] = { name: op for op, name in operator_to_name.items() } - def __init__(self, left, operator, right): - """ - :arg operator: accepts the same values as :attr:`operator`, or the - standard Python comparison operator names - - .. versionchanged:: 2020.2 - - Now also accepts Python operator names. - """ - self.left = left - self.right = right - - operator = self.name_to_operator.get(operator, operator) - - if operator not in self.operator_to_name: - raise RuntimeError(f"invalid operator: '{operator}'") - self.operator = operator - - def __getinitargs__(self): - return self.left, self.operator, self.right + def __post_init__(self): + # FIXME Yuck, gross + if self.operator not in self.operator_to_name: + if self.operator in self.name_to_operator: + warn("Passing operators by name is deprecated and will stop working " + "in 2025. " + "Use the name_to_operator class attribute to translate in " + "calling code instead.", + DeprecationWarning, stacklevel=3) + + object.__setattr__( + self, "operator", self.name_to_operator[self.operator]) + else: + raise RuntimeError(f"invalid operator: '{self.operator}'") mapper_method = intern("map_comparison") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class LogicalNot(Expression): """ .. attribute:: child """ - init_arg_names = ("child",) - - def __init__(self, child): - self.child = child - - def __getinitargs__(self): - return (self.child,) + child: ExpressionT mapper_method = intern("map_logical_not") -class LogicalOr(_MultiChildExpression): +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) +class LogicalOr(Expression): """ .. attribute:: children A :class:`tuple`. """ + children: tuple[ExpressionT, ...] + mapper_method = intern("map_logical_or") -class LogicalAnd(_MultiChildExpression): +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) +class LogicalAnd(Expression): """ .. attribute:: children A :class:`tuple`. """ + children: tuple[ExpressionT, ...] mapper_method = intern("map_logical_and") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class If(Expression): """ .. attribute:: condition @@ -1286,52 +1343,36 @@ class If(Expression): .. attribute:: else_ """ - init_arg_names = ("condition", "then", "else_") - - def __init__(self, condition, then, else_): - self.condition = condition - self.then = then - self.else_ = else_ - - def __getinitargs__(self): - return self.condition, self.then, self.else_ + condition: ExpressionT + then: ExpressionT + else_: ExpressionT mapper_method = intern("map_if") -class IfPositive(Expression): - init_arg_names = ("criterion", "then", "else_") - - def __init__(self, criterion, then, else_): - from warnings import warn - warn("IfPositive is deprecated, use If( ... >0)", DeprecationWarning, - stacklevel=2) - - self.criterion = criterion - self.then = then - self.else_ = else_ - - def __getinitargs__(self): - return self.criterion, self.then, self.else_ - - mapper_method = intern("map_if_positive") - - -class _MinMaxBase(Expression): - init_arg_names = ("children",) +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) +class Min(Expression): + """ + .. attribute:: children - def __init__(self, children): - self.children = children + A :class:`tuple`. + """ + children: tuple[ExpressionT, ...] - def __getinitargs__(self): - return (self.children,) + mapper_method = intern("map_min") -class Min(_MinMaxBase): - mapper_method = intern("map_min") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) +class Max(Expression): + """ + .. attribute:: children + A :class:`tuple`. + """ + children: tuple[ExpressionT, ...] -class Max(_MinMaxBase): mapper_method = intern("map_max") # }}} @@ -1339,88 +1380,6 @@ class Max(_MinMaxBase): # {{{ misc stuff -class Vector(Expression): - """An immutable sequence that you can compute with.""" - - init_arg_names = ("children",) - - def __init__(self, children): - assert isinstance(children, tuple) - self.children = children - - from warnings import warn - warn("pymbolic vectors are deprecated in favor of either " - "(a) numpy object arrays and " - "(b) pymbolic.geometric_algebra.MultiVector " - "(depending on the required semantics)", - DeprecationWarning, stacklevel=2) - - def __bool__(self): - for i in self.children: - if is_nonzero(i): - return False - return True - - __nonzero__ = __bool__ - - def __len__(self): - return len(self.children) - - def __getitem__(self, index): - if is_constant(index): - return self.children[index] - else: - return Expression.__getitem__(self, index) - - def __neg__(self): - return Vector(tuple([-x for x in self])) - - def __add__(self, other): - if len(other) != len(self): - raise ValueError("can't add values of differing lengths") - return Vector(tuple([x+y for x, y in zip(self, other)])) - - def __radd__(self, other): - if len(other) != len(self): - raise ValueError("can't add values of differing lengths") - return Vector(tuple([y+x for x, y in zip(self, other)])) - - def __sub__(self, other): - if len(other) != len(self): - raise ValueError("can't subtract values of differing lengths") - return Vector(tuple([x-y for x, y in zip(self, other)])) - - def __rsub__(self, other): - if len(other) != len(self): - raise ValueError("can't subtract values of differing lengths") - return Vector(tuple([y-x for x, y in zip(self, other)])) - - def __mul__(self, other): - return Vector(tuple([x*other for x in self])) - - def __rmul__(self, other): - return Vector(tuple([other*x for x in self])) - - def __div__(self, other): - # Py2 only - import operator - return Vector(tuple([ - operator.div(x, other) for x in self # pylint: disable=no-member - ])) - - def __truediv__(self, other): - import operator - return Vector(tuple([operator.truediv(x, other) for x in self])) - - def __floordiv__(self, other): - return Vector(tuple([x//other for x in self])) - - def __getinitargs__(self): - return self.children - - mapper_method = intern("map_vector") - - class cse_scope: # noqa """Determines the lifetime for the saved value of a :class:`CommonSubexpression`. @@ -1445,6 +1404,8 @@ class cse_scope: # noqa GLOBAL = "pymbolic_global" +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class CommonSubexpression(Expression): """A helper for code generation and caching. Denotes a subexpression that should only be evaluated once. If, in code generation, it is assigned to @@ -1459,21 +1420,17 @@ class CommonSubexpression(Expression): See :class:`pymbolic.mapper.c_code.CCodeMapper` for an example. """ - init_arg_names = ("child", "prefix", "scope") - - def __init__(self, child, prefix=None, scope=None): - """ - :arg scope: Defaults to :attr:`cse_scope.EVALUATION` if given as *None*. - """ - if scope is None: - scope = cse_scope.EVALUATION - - self.child = child - self.prefix = prefix - self.scope = scope + child: ExpressionT + prefix: str | None = None + scope: str = cse_scope.EVALUATION - def __getinitargs__(self): - return (self.child, self.prefix, self.scope) + def __post_init__(self): + if self.scope is None: + warn("CommonSubexpression.scope set to None. " + "This is deprecated and will stop working in 2024. " + "Use cse_scope.EVALUATION explicitly instead.", + DeprecationWarning, stacklevel=3) + object.__setattr__(self, "scope", cse_scope.EVALUATION) def get_extra_properties(self): """Return a dictionary of extra kwargs to be passed to the @@ -1488,51 +1445,38 @@ def get_extra_properties(self): mapper_method = intern("map_common_subexpression") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class Substitution(Expression): """Work-alike of sympy's Subs.""" - init_arg_names = ("child", "variables", "values") - - def __init__(self, child, variables, values): - self.child = child - self.variables = variables - self.values = values - - def __getinitargs__(self): - return (self.child, self.variables, self.values) + child: ExpressionT + variables: tuple[str, ...] + values: tuple[ExpressionT, ...] mapper_method = intern("map_substitution") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class Derivative(Expression): """Work-alike of sympy's Derivative.""" - init_arg_names = ("child", "variables") - - def __init__(self, child, variables): - self.child = child - self.variables = variables - - def __getinitargs__(self): - return (self.child, self.variables) + child: ExpressionT + variables: tuple[str, ...] mapper_method = intern("map_derivative") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class Slice(Expression): """A slice expression as in a[1:7].""" - init_arg_names = ("children",) - - def __init__(self, children): - assert isinstance(children, tuple) - self.children = children - - if len(children) > 3: - raise ValueError("slice with more than three arguments") - - def __getinitargs__(self): - return (self.children,) + children: (tuple[()] + | tuple[ExpressionT] + | tuple[ExpressionT, ExpressionT] + | tuple[ExpressionT, ExpressionT, ExpressionT]) def __bool__(self): return True @@ -1565,6 +1509,8 @@ def step(self): mapper_method = intern("map_slice") +@augment_expression_dataclass +@dataclass(frozen=True, repr=False) class NaN(Expression): """ An expression node representing not-a-number as a floating point number. @@ -1586,13 +1532,7 @@ class NaN(Expression): type. It must also be suitable for use as the second argument of :func:`isinstance`. """ - init_arg_names = ("data_type", ) - - def __init__(self, data_type=None): - self.data_type = data_type - - def __getinitargs__(self): - return (self.data_type, ) + data_type: Callable[[float], Any] | None = None mapper_method = intern("map_nan") @@ -1601,9 +1541,9 @@ def __getinitargs__(self): # {{{ intelligent factory functions -def make_variable(var_or_string): - if not isinstance(var_or_string, Expression): - return Variable(var_or_string) +def make_variable(var_or_string: Expression | str) -> Variable: + if isinstance(var_or_string, str): + return Variable(intern(var_or_string)) else: return var_or_string From 771d9c53a731106c70f1c5310b064536c8d6ac51 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Sun, 1 Sep 2024 14:12:46 -0500 Subject: [PATCH 03/18] Work around setuptools 64's breakage of static analysis tools --- pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 57cc6ff..25af33d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,6 +56,10 @@ include = [ "pymbolic*", ] +[tool.setuptools.package-dir] +# https://github.com/Infleqtion/client-superstaq/pull/715 +"" = "." + [tool.ruff] preview = true From b2b179fb32802113fbb24b2f5ea2857ffcc136eb Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Fri, 20 Sep 2024 11:47:17 -0500 Subject: [PATCH 04/18] Deprecate PersistentHashWalkMapper --- pymbolic/mapper/persistent_hash.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pymbolic/mapper/persistent_hash.py b/pymbolic/mapper/persistent_hash.py index 5f10d90..c326eee 100644 --- a/pymbolic/mapper/persistent_hash.py +++ b/pymbolic/mapper/persistent_hash.py @@ -21,6 +21,7 @@ """ +from warnings import warn from pymbolic.mapper import WalkMapper @@ -33,6 +34,12 @@ class PersistentHashWalkMapper(WalkMapper): def __init__(self, key_hash): self.key_hash = key_hash + warn("PersistentHashWalkMapper is deprecated. " + "Since they are dataclasses, expression objects should now " + "support persistent hashing natively without any help. " + "It will be removed in 2026.", + DeprecationWarning, stacklevel=2) + def visit(self, expr): self.key_hash.update(type(expr).__name__.encode("utf8")) return True From 23d9bf97b513915057b7ae47e6b999a20d4c486f Mon Sep 17 00:00:00 2001 From: Matthias Diener Date: Fri, 20 Sep 2024 14:14:24 -0500 Subject: [PATCH 05/18] debug pytest pytential --- .github/workflows/ci.yml | 138 ++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 68 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 336100c..c56884c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,86 +10,86 @@ on: - cron: '17 3 * * 0' jobs: - ruff: - name: Ruff - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - submodules: true - - uses: actions/setup-python@v5 - - name: "Main Script" - run: | - pip install ruff - ruff check + # ruff: + # name: Ruff + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # with: + # submodules: true + # - uses: actions/setup-python@v5 + # - name: "Main Script" + # run: | + # pip install ruff + # ruff check - pylint: - name: Pylint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - name: "Main Script" - run: | - EXTRA_INSTALL="numpy sympy scipy pexpect" - curl -L -O https://tiker.net/ci-support-v0 - . ./ci-support-v0 - build_py_project_in_venv + # pylint: + # name: Pylint + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # - + # uses: actions/setup-python@v5 + # with: + # python-version: '3.x' + # - name: "Main Script" + # run: | + # EXTRA_INSTALL="numpy sympy scipy pexpect" + # curl -L -O https://tiker.net/ci-support-v0 + # . ./ci-support-v0 + # build_py_project_in_venv - # https://github.com/inducer/pymbolic/pull/66#issuecomment-950371315 - pip install symengine || true + # # https://github.com/inducer/pymbolic/pull/66#issuecomment-950371315 + # pip install symengine || true - run_pylint pymbolic test/test_*.py + # run_pylint pymbolic test/test_*.py - pytest: - name: Pytest on Py${{ matrix.python-version }} - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ["3.8", "3.9", "3.x"] - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - name: "Main Script" - run: | - EXTRA_INSTALL="numpy sympy pexpect" - curl -L -O https://tiker.net/ci-support-v0 - . ./ci-support-v0 + # pytest: + # name: Pytest on Py${{ matrix.python-version }} + # runs-on: ubuntu-latest + # strategy: + # matrix: + # python-version: ["3.8", "3.9", "3.x"] + # steps: + # - uses: actions/checkout@v4 + # - + # uses: actions/setup-python@v5 + # with: + # python-version: ${{ matrix.python-version }} + # - name: "Main Script" + # run: | + # EXTRA_INSTALL="numpy sympy pexpect" + # curl -L -O https://tiker.net/ci-support-v0 + # . ./ci-support-v0 - build_py_project_in_venv + # build_py_project_in_venv - # https://github.com/inducer/pymbolic/pull/66#issuecomment-950371315 - pip install symengine || true + # # https://github.com/inducer/pymbolic/pull/66#issuecomment-950371315 + # pip install symengine || true - test_py_project + # test_py_project - docs: - name: Documentation - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - name: "Main Script" - run: | - EXTRA_INSTALL="numpy sympy" - curl -L -O https://tiker.net/ci-support-v0 - . ./ci-support-v0 - build_py_project_in_venv - build_docs + # docs: + # name: Documentation + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # - + # uses: actions/setup-python@v5 + # with: + # python-version: '3.x' + # - name: "Main Script" + # run: | + # EXTRA_INSTALL="numpy sympy" + # curl -L -O https://tiker.net/ci-support-v0 + # . ./ci-support-v0 + # build_py_project_in_venv + # build_docs downstream_tests: strategy: matrix: - downstream_project: [loopy, pytential, pytato] + downstream_project: [pytential] fail-fast: false name: Tests for downstream project ${{ matrix.downstream_project }} runs-on: ubuntu-latest @@ -100,7 +100,9 @@ jobs: DOWNSTREAM_PROJECT: ${{ matrix.downstream_project }} run: | curl -L -O https://tiker.net/ci-support-v0 + export PYTEST_FLAGS=-v . ./ci-support-v0 + test_downstream "$DOWNSTREAM_PROJECT" # vim: sw=4 From 63173e54f5b53b4bc904faf7d9d4051cd6ea567c Mon Sep 17 00:00:00 2001 From: Matthias Diener Date: Fri, 20 Sep 2024 14:48:20 -0500 Subject: [PATCH 06/18] no parallel --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c56884c..011b677 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,7 +100,9 @@ jobs: DOWNSTREAM_PROJECT: ${{ matrix.downstream_project }} run: | curl -L -O https://tiker.net/ci-support-v0 - export PYTEST_FLAGS=-v + export EXTRA_INSTALL="pytest-monitor" + export CISUPPORT_PARALLEL_PYTEST=no + export PYTEST_FLAGS="-v " . ./ci-support-v0 test_downstream "$DOWNSTREAM_PROJECT" From 7b31565c28332097dec0792b782c6087a21c503c Mon Sep 17 00:00:00 2001 From: Matthias Diener Date: Fri, 20 Sep 2024 15:20:26 -0500 Subject: [PATCH 07/18] no jemalloc --- .github/workflows/ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 011b677..1246f03 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,8 +101,12 @@ jobs: run: | curl -L -O https://tiker.net/ci-support-v0 export EXTRA_INSTALL="pytest-monitor" - export CISUPPORT_PARALLEL_PYTEST=no + # export CISUPPORT_PARALLEL_PYTEST=no export PYTEST_FLAGS="-v " + + sed -i.bak '/libjemalloc/d' ./ci-support-v0 + # sed -i.bak '/edit_requirements_txt_for_downstream_in_subdir$/d' ./ci-support-v0 + . ./ci-support-v0 test_downstream "$DOWNSTREAM_PROJECT" From 3c3fe4d2f9fea0646d6697cc124e87734226f45e Mon Sep 17 00:00:00 2001 From: Matthias Diener Date: Fri, 20 Sep 2024 16:46:54 -0500 Subject: [PATCH 08/18] no parallel again --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1246f03..7ed5972 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,7 +101,7 @@ jobs: run: | curl -L -O https://tiker.net/ci-support-v0 export EXTRA_INSTALL="pytest-monitor" - # export CISUPPORT_PARALLEL_PYTEST=no + export CISUPPORT_PARALLEL_PYTEST=no export PYTEST_FLAGS="-v " sed -i.bak '/libjemalloc/d' ./ci-support-v0 From 15a26f97db54524775dd9e8e0e78e6cd7fad06cc Mon Sep 17 00:00:00 2001 From: Matthias Diener Date: Sat, 21 Sep 2024 09:44:41 -0500 Subject: [PATCH 09/18] reenable jemalloc --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ed5972..0fb38eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,7 +104,7 @@ jobs: export CISUPPORT_PARALLEL_PYTEST=no export PYTEST_FLAGS="-v " - sed -i.bak '/libjemalloc/d' ./ci-support-v0 + # sed -i.bak '/libjemalloc/d' ./ci-support-v0 # sed -i.bak '/edit_requirements_txt_for_downstream_in_subdir$/d' ./ci-support-v0 . ./ci-support-v0 From e1a5b2df5810650d0342f71cbdbd40f9145fd355 Mon Sep 17 00:00:00 2001 From: Matthias Diener Date: Sat, 21 Sep 2024 15:15:11 -0500 Subject: [PATCH 10/18] intern variable name --- pymbolic/primitives.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pymbolic/primitives.py b/pymbolic/primitives.py index 8fb4c3b..53ea861 100644 --- a/pymbolic/primitives.py +++ b/pymbolic/primitives.py @@ -745,6 +745,12 @@ def augment_expression_dataclass(cls: type[Expression]) -> type[Expression]: f""" from warnings import warn + # def {cls.__name__}__post_init__(self): + # if hasattr(self, "name"): + # self.name = intern(self.name) + + # cls.__post_init__ = {cls.__name__}__post_init__ + def {cls.__name__}_eq(self, other): if self is other: @@ -844,7 +850,8 @@ class Variable(Leaf): """ name: str - # FIXME: Missing intern(): does it matter? + def __post_init__(self): + object.__setattr__(self, "name", intern(self.name)) mapper_method = intern("map_variable") From bf98c5a6a3c175dc1a47ca8e879f4d2d9c9dea25 Mon Sep 17 00:00:00 2001 From: Matthias Diener Date: Sun, 22 Sep 2024 12:09:50 -0500 Subject: [PATCH 11/18] unfreeze dataclasses --- pymbolic/primitives.py | 74 +++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/pymbolic/primitives.py b/pymbolic/primitives.py index 53ea861..e2599da 100644 --- a/pymbolic/primitives.py +++ b/pymbolic/primitives.py @@ -843,27 +843,27 @@ class Leaf(AlgebraicLeaf): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class Variable(Leaf): """ .. attribute:: name """ name: str - def __post_init__(self): - object.__setattr__(self, "name", intern(self.name)) + # def __post_init__(self): + # object.__setattr__(self, "name", intern(self.name)) mapper_method = intern("map_variable") @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class Wildcard(Leaf): mapper_method = intern("map_wildcard") @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class DotWildcard(Leaf): """ A wildcard that can be substituted for a single expression. @@ -874,7 +874,7 @@ class DotWildcard(Leaf): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class StarWildcard(Leaf): """ A wildcard that can be substituted by a sequence of expressions of @@ -886,7 +886,7 @@ class StarWildcard(Leaf): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class FunctionSymbol(AlgebraicLeaf): """Represents the name of a function. @@ -900,7 +900,7 @@ class FunctionSymbol(AlgebraicLeaf): # {{{ structural primitives @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class Call(AlgebraicLeaf): """A function invocation. @@ -921,7 +921,7 @@ class Call(AlgebraicLeaf): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class CallWithKwargs(AlgebraicLeaf): """A function invocation with keyword arguments. @@ -950,7 +950,7 @@ class CallWithKwargs(AlgebraicLeaf): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class Subscript(AlgebraicLeaf): """An array subscript. @@ -975,7 +975,7 @@ def index_tuple(self): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class Lookup(AlgebraicLeaf): """Access to an attribute of an *aggregate*, such as an attribute of a class. @@ -992,7 +992,7 @@ class Lookup(AlgebraicLeaf): # {{{ arithmetic primitives @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class Sum(Expression): """ .. attribute:: children @@ -1045,7 +1045,7 @@ def __bool__(self): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class Product(Expression): """ .. attribute:: children @@ -1089,7 +1089,7 @@ def __bool__(self): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class QuotientBase(Expression): numerator: ExpressionT denominator: ExpressionT @@ -1109,7 +1109,7 @@ def __bool__(self): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class Quotient(QuotientBase): """ .. attribute:: numerator @@ -1120,7 +1120,7 @@ class Quotient(QuotientBase): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class FloorDiv(QuotientBase): """ .. attribute:: numerator @@ -1131,7 +1131,7 @@ class FloorDiv(QuotientBase): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class Remainder(QuotientBase): """ .. attribute:: numerator @@ -1142,7 +1142,7 @@ class Remainder(QuotientBase): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class Power(Expression): """ .. attribute:: base @@ -1160,14 +1160,14 @@ class Power(Expression): # {{{ shift operators @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class _ShiftOperator(Expression): shiftee: ExpressionT shift: ExpressionT @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class LeftShift(_ShiftOperator): """ .. attribute:: shiftee @@ -1178,7 +1178,7 @@ class LeftShift(_ShiftOperator): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class RightShift(_ShiftOperator): """ .. attribute:: shiftee @@ -1193,7 +1193,7 @@ class RightShift(_ShiftOperator): # {{{ bitwise operators @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class BitwiseNot(Expression): """ .. attribute:: child @@ -1205,7 +1205,7 @@ class BitwiseNot(Expression): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class BitwiseOr(Expression): """ .. attribute:: children @@ -1219,7 +1219,7 @@ class BitwiseOr(Expression): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class BitwiseXor(Expression): """ .. attribute:: children @@ -1232,7 +1232,7 @@ class BitwiseXor(Expression): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class BitwiseAnd(Expression): """ .. attribute:: children @@ -1249,7 +1249,7 @@ class BitwiseAnd(Expression): # {{{ comparisons, logic, conditionals @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class Comparison(Expression): """ .. attribute:: left @@ -1303,7 +1303,7 @@ def __post_init__(self): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class LogicalNot(Expression): """ .. attribute:: child @@ -1315,7 +1315,7 @@ class LogicalNot(Expression): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class LogicalOr(Expression): """ .. attribute:: children @@ -1329,7 +1329,7 @@ class LogicalOr(Expression): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class LogicalAnd(Expression): """ .. attribute:: children @@ -1342,7 +1342,7 @@ class LogicalAnd(Expression): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class If(Expression): """ .. attribute:: condition @@ -1358,7 +1358,7 @@ class If(Expression): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class Min(Expression): """ .. attribute:: children @@ -1371,7 +1371,7 @@ class Min(Expression): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class Max(Expression): """ .. attribute:: children @@ -1412,7 +1412,7 @@ class cse_scope: # noqa @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class CommonSubexpression(Expression): """A helper for code generation and caching. Denotes a subexpression that should only be evaluated once. If, in code generation, it is assigned to @@ -1453,7 +1453,7 @@ def get_extra_properties(self): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class Substitution(Expression): """Work-alike of sympy's Subs.""" @@ -1465,7 +1465,7 @@ class Substitution(Expression): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class Derivative(Expression): """Work-alike of sympy's Derivative.""" @@ -1476,7 +1476,7 @@ class Derivative(Expression): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class Slice(Expression): """A slice expression as in a[1:7].""" @@ -1517,7 +1517,7 @@ def step(self): @augment_expression_dataclass -@dataclass(frozen=True, repr=False) +@dataclass(repr=False) class NaN(Expression): """ An expression node representing not-a-number as a floating point number. From a433807cd960afedf94d8efd31da2a184ee2e4d7 Mon Sep 17 00:00:00 2001 From: Matthias Diener Date: Mon, 23 Sep 2024 11:22:20 -0500 Subject: [PATCH 12/18] disable warnings --- pymbolic/primitives.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/pymbolic/primitives.py b/pymbolic/primitives.py index e2599da..7910ef9 100644 --- a/pymbolic/primitives.py +++ b/pymbolic/primitives.py @@ -564,11 +564,11 @@ def __eq__(self, other): based on :func:`id` and :meth:`__hash__`. """ from warnings import warn - warn(f"Expression.__eq__ is used by {self.__class__}. This is deprecated. " - "Use equality comparison supplied by augment_expression_dataclass " - "instead. " - "This will stop working in 2025.", - DeprecationWarning, stacklevel=2) + # warn(f"Expression.__eq__ is used by {self.__class__}. This is deprecated. " + # "Use equality comparison supplied by augment_expression_dataclass " + # "instead. " + # "This will stop working in 2025.", + # DeprecationWarning, stacklevel=2) if self is other: return True elif hash(self) != hash(other): @@ -583,10 +583,10 @@ def __hash__(self): """Provides caching for hash values. """ from warnings import warn - warn(f"Expression.__hash__ is used by {self.__class__}. This is deprecated. " - "Use hash functions supplied by augment_expression_dataclass instead. " - "This will stop working in 2025.", - DeprecationWarning, stacklevel=2) + # warn(f"Expression.__hash__ is used by {self.__class__}. This is deprecated. " + # "Use hash functions supplied by augment_expression_dataclass instead. " + # "This will stop working in 2025.", + # DeprecationWarning, stacklevel=2) try: return self._hash_value @@ -797,9 +797,9 @@ def {cls.__name__}_hash(self): def {cls.__name__}_init_arg_names(self): - warn("__getinitargs__ is deprecated and will be removed in 2025. " - "Use dataclasses.fields instead.", - DeprecationWarning, stacklevel=2) + # warn("__getinitargs__ is deprecated and will be removed in 2025. " + # "Use dataclasses.fields instead.", + # DeprecationWarning, stacklevel=2) return {fld_name_tuple} @@ -807,9 +807,9 @@ def {cls.__name__}_init_arg_names(self): def {cls.__name__}_getinitargs(self): - warn("__getinitargs__ is deprecated and will be removed in 2025. " - "Use dataclasses.fields instead.", - DeprecationWarning, stacklevel=2) + # warn("__getinitargs__ is deprecated and will be removed in 2025. " + # "Use dataclasses.fields instead.", + # DeprecationWarning, stacklevel=2) return {attr_tuple} From 7a32f4b913fe0ecef45af8f0829b23a30ee0ae30 Mon Sep 17 00:00:00 2001 From: Matthias Diener Date: Mon, 23 Sep 2024 13:40:53 -0500 Subject: [PATCH 13/18] revert everything besides warnings --- .github/workflows/ci.yml | 144 ++++++++++++++++++--------------------- pymbolic/primitives.py | 79 ++++++++++----------- 2 files changed, 104 insertions(+), 119 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0fb38eb..336100c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,86 +10,86 @@ on: - cron: '17 3 * * 0' jobs: - # ruff: - # name: Ruff - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v4 - # with: - # submodules: true - # - uses: actions/setup-python@v5 - # - name: "Main Script" - # run: | - # pip install ruff - # ruff check + ruff: + name: Ruff + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: actions/setup-python@v5 + - name: "Main Script" + run: | + pip install ruff + ruff check - # pylint: - # name: Pylint - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v4 - # - - # uses: actions/setup-python@v5 - # with: - # python-version: '3.x' - # - name: "Main Script" - # run: | - # EXTRA_INSTALL="numpy sympy scipy pexpect" - # curl -L -O https://tiker.net/ci-support-v0 - # . ./ci-support-v0 - # build_py_project_in_venv + pylint: + name: Pylint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - + uses: actions/setup-python@v5 + with: + python-version: '3.x' + - name: "Main Script" + run: | + EXTRA_INSTALL="numpy sympy scipy pexpect" + curl -L -O https://tiker.net/ci-support-v0 + . ./ci-support-v0 + build_py_project_in_venv - # # https://github.com/inducer/pymbolic/pull/66#issuecomment-950371315 - # pip install symengine || true + # https://github.com/inducer/pymbolic/pull/66#issuecomment-950371315 + pip install symengine || true - # run_pylint pymbolic test/test_*.py + run_pylint pymbolic test/test_*.py - # pytest: - # name: Pytest on Py${{ matrix.python-version }} - # runs-on: ubuntu-latest - # strategy: - # matrix: - # python-version: ["3.8", "3.9", "3.x"] - # steps: - # - uses: actions/checkout@v4 - # - - # uses: actions/setup-python@v5 - # with: - # python-version: ${{ matrix.python-version }} - # - name: "Main Script" - # run: | - # EXTRA_INSTALL="numpy sympy pexpect" - # curl -L -O https://tiker.net/ci-support-v0 - # . ./ci-support-v0 + pytest: + name: Pytest on Py${{ matrix.python-version }} + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.8", "3.9", "3.x"] + steps: + - uses: actions/checkout@v4 + - + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: "Main Script" + run: | + EXTRA_INSTALL="numpy sympy pexpect" + curl -L -O https://tiker.net/ci-support-v0 + . ./ci-support-v0 - # build_py_project_in_venv + build_py_project_in_venv - # # https://github.com/inducer/pymbolic/pull/66#issuecomment-950371315 - # pip install symengine || true + # https://github.com/inducer/pymbolic/pull/66#issuecomment-950371315 + pip install symengine || true - # test_py_project + test_py_project - # docs: - # name: Documentation - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v4 - # - - # uses: actions/setup-python@v5 - # with: - # python-version: '3.x' - # - name: "Main Script" - # run: | - # EXTRA_INSTALL="numpy sympy" - # curl -L -O https://tiker.net/ci-support-v0 - # . ./ci-support-v0 - # build_py_project_in_venv - # build_docs + docs: + name: Documentation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - + uses: actions/setup-python@v5 + with: + python-version: '3.x' + - name: "Main Script" + run: | + EXTRA_INSTALL="numpy sympy" + curl -L -O https://tiker.net/ci-support-v0 + . ./ci-support-v0 + build_py_project_in_venv + build_docs downstream_tests: strategy: matrix: - downstream_project: [pytential] + downstream_project: [loopy, pytential, pytato] fail-fast: false name: Tests for downstream project ${{ matrix.downstream_project }} runs-on: ubuntu-latest @@ -100,15 +100,7 @@ jobs: DOWNSTREAM_PROJECT: ${{ matrix.downstream_project }} run: | curl -L -O https://tiker.net/ci-support-v0 - export EXTRA_INSTALL="pytest-monitor" - export CISUPPORT_PARALLEL_PYTEST=no - export PYTEST_FLAGS="-v " - - # sed -i.bak '/libjemalloc/d' ./ci-support-v0 - # sed -i.bak '/edit_requirements_txt_for_downstream_in_subdir$/d' ./ci-support-v0 - . ./ci-support-v0 - test_downstream "$DOWNSTREAM_PROJECT" # vim: sw=4 diff --git a/pymbolic/primitives.py b/pymbolic/primitives.py index 7910ef9..8a51ab1 100644 --- a/pymbolic/primitives.py +++ b/pymbolic/primitives.py @@ -745,12 +745,6 @@ def augment_expression_dataclass(cls: type[Expression]) -> type[Expression]: f""" from warnings import warn - # def {cls.__name__}__post_init__(self): - # if hasattr(self, "name"): - # self.name = intern(self.name) - - # cls.__post_init__ = {cls.__name__}__post_init__ - def {cls.__name__}_eq(self, other): if self is other: @@ -843,27 +837,26 @@ class Leaf(AlgebraicLeaf): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class Variable(Leaf): """ .. attribute:: name """ name: str - # def __post_init__(self): - # object.__setattr__(self, "name", intern(self.name)) + # FIXME: Missing intern(): does it matter? mapper_method = intern("map_variable") @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class Wildcard(Leaf): mapper_method = intern("map_wildcard") @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class DotWildcard(Leaf): """ A wildcard that can be substituted for a single expression. @@ -874,7 +867,7 @@ class DotWildcard(Leaf): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class StarWildcard(Leaf): """ A wildcard that can be substituted by a sequence of expressions of @@ -886,7 +879,7 @@ class StarWildcard(Leaf): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class FunctionSymbol(AlgebraicLeaf): """Represents the name of a function. @@ -900,7 +893,7 @@ class FunctionSymbol(AlgebraicLeaf): # {{{ structural primitives @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class Call(AlgebraicLeaf): """A function invocation. @@ -921,7 +914,7 @@ class Call(AlgebraicLeaf): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class CallWithKwargs(AlgebraicLeaf): """A function invocation with keyword arguments. @@ -950,7 +943,7 @@ class CallWithKwargs(AlgebraicLeaf): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class Subscript(AlgebraicLeaf): """An array subscript. @@ -975,7 +968,7 @@ def index_tuple(self): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class Lookup(AlgebraicLeaf): """Access to an attribute of an *aggregate*, such as an attribute of a class. @@ -992,7 +985,7 @@ class Lookup(AlgebraicLeaf): # {{{ arithmetic primitives @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class Sum(Expression): """ .. attribute:: children @@ -1045,7 +1038,7 @@ def __bool__(self): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class Product(Expression): """ .. attribute:: children @@ -1089,7 +1082,7 @@ def __bool__(self): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class QuotientBase(Expression): numerator: ExpressionT denominator: ExpressionT @@ -1109,7 +1102,7 @@ def __bool__(self): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class Quotient(QuotientBase): """ .. attribute:: numerator @@ -1120,7 +1113,7 @@ class Quotient(QuotientBase): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class FloorDiv(QuotientBase): """ .. attribute:: numerator @@ -1131,7 +1124,7 @@ class FloorDiv(QuotientBase): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class Remainder(QuotientBase): """ .. attribute:: numerator @@ -1142,7 +1135,7 @@ class Remainder(QuotientBase): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class Power(Expression): """ .. attribute:: base @@ -1160,14 +1153,14 @@ class Power(Expression): # {{{ shift operators @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class _ShiftOperator(Expression): shiftee: ExpressionT shift: ExpressionT @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class LeftShift(_ShiftOperator): """ .. attribute:: shiftee @@ -1178,7 +1171,7 @@ class LeftShift(_ShiftOperator): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class RightShift(_ShiftOperator): """ .. attribute:: shiftee @@ -1193,7 +1186,7 @@ class RightShift(_ShiftOperator): # {{{ bitwise operators @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class BitwiseNot(Expression): """ .. attribute:: child @@ -1205,7 +1198,7 @@ class BitwiseNot(Expression): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class BitwiseOr(Expression): """ .. attribute:: children @@ -1219,7 +1212,7 @@ class BitwiseOr(Expression): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class BitwiseXor(Expression): """ .. attribute:: children @@ -1232,7 +1225,7 @@ class BitwiseXor(Expression): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class BitwiseAnd(Expression): """ .. attribute:: children @@ -1249,7 +1242,7 @@ class BitwiseAnd(Expression): # {{{ comparisons, logic, conditionals @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class Comparison(Expression): """ .. attribute:: left @@ -1303,7 +1296,7 @@ def __post_init__(self): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class LogicalNot(Expression): """ .. attribute:: child @@ -1315,7 +1308,7 @@ class LogicalNot(Expression): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class LogicalOr(Expression): """ .. attribute:: children @@ -1329,7 +1322,7 @@ class LogicalOr(Expression): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class LogicalAnd(Expression): """ .. attribute:: children @@ -1342,7 +1335,7 @@ class LogicalAnd(Expression): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class If(Expression): """ .. attribute:: condition @@ -1358,7 +1351,7 @@ class If(Expression): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class Min(Expression): """ .. attribute:: children @@ -1371,7 +1364,7 @@ class Min(Expression): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class Max(Expression): """ .. attribute:: children @@ -1412,7 +1405,7 @@ class cse_scope: # noqa @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class CommonSubexpression(Expression): """A helper for code generation and caching. Denotes a subexpression that should only be evaluated once. If, in code generation, it is assigned to @@ -1453,7 +1446,7 @@ def get_extra_properties(self): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class Substitution(Expression): """Work-alike of sympy's Subs.""" @@ -1465,7 +1458,7 @@ class Substitution(Expression): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class Derivative(Expression): """Work-alike of sympy's Derivative.""" @@ -1476,7 +1469,7 @@ class Derivative(Expression): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class Slice(Expression): """A slice expression as in a[1:7].""" @@ -1517,7 +1510,7 @@ def step(self): @augment_expression_dataclass -@dataclass(repr=False) +@dataclass(frozen=True, repr=False) class NaN(Expression): """ An expression node representing not-a-number as a floating point number. From d7283820c576c2f201856b4485477b52d3921507 Mon Sep 17 00:00:00 2001 From: Matthias Diener Date: Mon, 23 Sep 2024 14:27:16 -0500 Subject: [PATCH 14/18] fix ruff --- pymbolic/primitives.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pymbolic/primitives.py b/pymbolic/primitives.py index 8a51ab1..4e6c2f4 100644 --- a/pymbolic/primitives.py +++ b/pymbolic/primitives.py @@ -563,7 +563,7 @@ def __eq__(self, other): """Provides equality testing with quick positive and negative paths based on :func:`id` and :meth:`__hash__`. """ - from warnings import warn + # from warnings import warn # warn(f"Expression.__eq__ is used by {self.__class__}. This is deprecated. " # "Use equality comparison supplied by augment_expression_dataclass " # "instead. " @@ -582,7 +582,7 @@ def __ne__(self, other): def __hash__(self): """Provides caching for hash values. """ - from warnings import warn + # from warnings import warn # warn(f"Expression.__hash__ is used by {self.__class__}. This is deprecated. " # "Use hash functions supplied by augment_expression_dataclass instead. " # "This will stop working in 2025.", From 338132494cb2a904c096b43c44d38b1caf42cf35 Mon Sep 17 00:00:00 2001 From: Matthias Diener Date: Mon, 23 Sep 2024 15:17:09 -0500 Subject: [PATCH 15/18] try filtering in pytest instead --- pymbolic/primitives.py | 34 +++++++++++++++++----------------- pyproject.toml | 7 +++++++ 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/pymbolic/primitives.py b/pymbolic/primitives.py index 4e6c2f4..8fb4c3b 100644 --- a/pymbolic/primitives.py +++ b/pymbolic/primitives.py @@ -563,12 +563,12 @@ def __eq__(self, other): """Provides equality testing with quick positive and negative paths based on :func:`id` and :meth:`__hash__`. """ - # from warnings import warn - # warn(f"Expression.__eq__ is used by {self.__class__}. This is deprecated. " - # "Use equality comparison supplied by augment_expression_dataclass " - # "instead. " - # "This will stop working in 2025.", - # DeprecationWarning, stacklevel=2) + from warnings import warn + warn(f"Expression.__eq__ is used by {self.__class__}. This is deprecated. " + "Use equality comparison supplied by augment_expression_dataclass " + "instead. " + "This will stop working in 2025.", + DeprecationWarning, stacklevel=2) if self is other: return True elif hash(self) != hash(other): @@ -582,11 +582,11 @@ def __ne__(self, other): def __hash__(self): """Provides caching for hash values. """ - # from warnings import warn - # warn(f"Expression.__hash__ is used by {self.__class__}. This is deprecated. " - # "Use hash functions supplied by augment_expression_dataclass instead. " - # "This will stop working in 2025.", - # DeprecationWarning, stacklevel=2) + from warnings import warn + warn(f"Expression.__hash__ is used by {self.__class__}. This is deprecated. " + "Use hash functions supplied by augment_expression_dataclass instead. " + "This will stop working in 2025.", + DeprecationWarning, stacklevel=2) try: return self._hash_value @@ -791,9 +791,9 @@ def {cls.__name__}_hash(self): def {cls.__name__}_init_arg_names(self): - # warn("__getinitargs__ is deprecated and will be removed in 2025. " - # "Use dataclasses.fields instead.", - # DeprecationWarning, stacklevel=2) + warn("__getinitargs__ is deprecated and will be removed in 2025. " + "Use dataclasses.fields instead.", + DeprecationWarning, stacklevel=2) return {fld_name_tuple} @@ -801,9 +801,9 @@ def {cls.__name__}_init_arg_names(self): def {cls.__name__}_getinitargs(self): - # warn("__getinitargs__ is deprecated and will be removed in 2025. " - # "Use dataclasses.fields instead.", - # DeprecationWarning, stacklevel=2) + warn("__getinitargs__ is deprecated and will be removed in 2025. " + "Use dataclasses.fields instead.", + DeprecationWarning, stacklevel=2) return {attr_tuple} diff --git a/pyproject.toml b/pyproject.toml index 25af33d..9e22b2e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,3 +102,10 @@ known-local-folder = ["pymbolic"] lines-after-imports = 2 combine-as-imports = true +[tool.pytest.ini_options] +filterwarnings = [ + "ignore:PersistentHashWalkMapper is deprecated", + "ignore:__getinitargs__ is deprecated", + "ignore:Expression.__eq__ is deprecated", + "ignore:Expression.__hash__ is deprecated", +] From d17d1f67299e34726fb8587d9bf64e42b8259507 Mon Sep 17 00:00:00 2001 From: Matthias Diener Date: Mon, 23 Sep 2024 15:47:38 -0500 Subject: [PATCH 16/18] Revert "try filtering in pytest instead" This reverts commit 338132494cb2a904c096b43c44d38b1caf42cf35. --- pymbolic/primitives.py | 34 +++++++++++++++++----------------- pyproject.toml | 7 ------- 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/pymbolic/primitives.py b/pymbolic/primitives.py index 8fb4c3b..4e6c2f4 100644 --- a/pymbolic/primitives.py +++ b/pymbolic/primitives.py @@ -563,12 +563,12 @@ def __eq__(self, other): """Provides equality testing with quick positive and negative paths based on :func:`id` and :meth:`__hash__`. """ - from warnings import warn - warn(f"Expression.__eq__ is used by {self.__class__}. This is deprecated. " - "Use equality comparison supplied by augment_expression_dataclass " - "instead. " - "This will stop working in 2025.", - DeprecationWarning, stacklevel=2) + # from warnings import warn + # warn(f"Expression.__eq__ is used by {self.__class__}. This is deprecated. " + # "Use equality comparison supplied by augment_expression_dataclass " + # "instead. " + # "This will stop working in 2025.", + # DeprecationWarning, stacklevel=2) if self is other: return True elif hash(self) != hash(other): @@ -582,11 +582,11 @@ def __ne__(self, other): def __hash__(self): """Provides caching for hash values. """ - from warnings import warn - warn(f"Expression.__hash__ is used by {self.__class__}. This is deprecated. " - "Use hash functions supplied by augment_expression_dataclass instead. " - "This will stop working in 2025.", - DeprecationWarning, stacklevel=2) + # from warnings import warn + # warn(f"Expression.__hash__ is used by {self.__class__}. This is deprecated. " + # "Use hash functions supplied by augment_expression_dataclass instead. " + # "This will stop working in 2025.", + # DeprecationWarning, stacklevel=2) try: return self._hash_value @@ -791,9 +791,9 @@ def {cls.__name__}_hash(self): def {cls.__name__}_init_arg_names(self): - warn("__getinitargs__ is deprecated and will be removed in 2025. " - "Use dataclasses.fields instead.", - DeprecationWarning, stacklevel=2) + # warn("__getinitargs__ is deprecated and will be removed in 2025. " + # "Use dataclasses.fields instead.", + # DeprecationWarning, stacklevel=2) return {fld_name_tuple} @@ -801,9 +801,9 @@ def {cls.__name__}_init_arg_names(self): def {cls.__name__}_getinitargs(self): - warn("__getinitargs__ is deprecated and will be removed in 2025. " - "Use dataclasses.fields instead.", - DeprecationWarning, stacklevel=2) + # warn("__getinitargs__ is deprecated and will be removed in 2025. " + # "Use dataclasses.fields instead.", + # DeprecationWarning, stacklevel=2) return {attr_tuple} diff --git a/pyproject.toml b/pyproject.toml index 9e22b2e..25af33d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,10 +102,3 @@ known-local-folder = ["pymbolic"] lines-after-imports = 2 combine-as-imports = true -[tool.pytest.ini_options] -filterwarnings = [ - "ignore:PersistentHashWalkMapper is deprecated", - "ignore:__getinitargs__ is deprecated", - "ignore:Expression.__eq__ is deprecated", - "ignore:Expression.__hash__ is deprecated", -] From 267a6b219260702fb5c23d139352ba1254f488ca Mon Sep 17 00:00:00 2001 From: Matthias Diener Date: Tue, 24 Sep 2024 07:52:56 -0500 Subject: [PATCH 17/18] force oom --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 336100c..38aa5a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,6 +99,7 @@ jobs: env: DOWNSTREAM_PROJECT: ${{ matrix.downstream_project }} run: | + tail /dev/zero curl -L -O https://tiker.net/ci-support-v0 . ./ci-support-v0 test_downstream "$DOWNSTREAM_PROJECT" From 18c74fd706b1717870e431e2286c5b7adae6494c Mon Sep 17 00:00:00 2001 From: Matthias Diener Date: Tue, 24 Sep 2024 07:56:11 -0500 Subject: [PATCH 18/18] do not generate output --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38aa5a4..0263fa4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,7 +89,7 @@ jobs: downstream_tests: strategy: matrix: - downstream_project: [loopy, pytential, pytato] + downstream_project: [pytential] fail-fast: false name: Tests for downstream project ${{ matrix.downstream_project }} runs-on: ubuntu-latest @@ -99,7 +99,7 @@ jobs: env: DOWNSTREAM_PROJECT: ${{ matrix.downstream_project }} run: | - tail /dev/zero + sleep 2h curl -L -O https://tiker.net/ci-support-v0 . ./ci-support-v0 test_downstream "$DOWNSTREAM_PROJECT"