diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ef10883e0143a36949be0c44752916367de83c1a..70b78b9cc3ae585cd4d5e7da61655193acf8d028 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -67,6 +67,17 @@ Python 3.5 Apple: reports: junit: test/pytest.xml +Pylint: + script: + - EXTRA_INSTALL="numpy sympy symengine scipy pexpect" + - py_version=3.6 + - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/prepare-and-run-pylint.sh + - ". ./prepare-and-run-pylint.sh pymbolic test/test_*.py" + tags: + - python3.6 + except: + - tags + Documentation: script: - EXTRA_INSTALL="numpy" diff --git a/pymbolic/algorithm.py b/pymbolic/algorithm.py index 18cb09e548bac0d3dd50e68be5087723f5444a9f..357fe9b917ebadda221adc7fe0a8c030e4449cec 100644 --- a/pymbolic/algorithm.py +++ b/pymbolic/algorithm.py @@ -227,7 +227,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]] + result[i] = sum(S.data[idx]*x[S.indices[idx]] # noqa pylint:disable=unsupported-assignment-operation for idx in range(S.indptr[i], S.indptr[i+1])) return result diff --git a/pymbolic/geometric_algebra/mapper.py b/pymbolic/geometric_algebra/mapper.py index 448d408d1fd8c1059a36ad454af91263e0a5fea7..5ee93265d9f42a96981740d66b2faae9409c003b 100644 --- a/pymbolic/geometric_algebra/mapper.py +++ b/pymbolic/geometric_algebra/mapper.py @@ -145,11 +145,15 @@ class Dimensionalizer(EvaluationMapper): Dimension of ambient space. Must be provided by subclass. """ + @property + def ambient_dim(self): + raise NotImplementedError + def map_multivector_variable(self, expr): from pymbolic.primitives import make_sym_vector return MultiVector( make_sym_vector(expr.name, self.ambient_dim, - var_class=type(expr))) + var_factory=type(expr))) def map_nabla(self, expr): from pytools.obj_array import make_obj_array @@ -232,6 +236,9 @@ class DerivativeBinder(IdentityMapper): self.derivative_source_and_nabla_component_collector() self.restrict_to_id = restrict_to_id + def take_derivative(self, ambient_axis, expr): + raise NotImplementedError + def map_product(self, expr): # {{{ gather NablaComponents and DerivativeSources diff --git a/pymbolic/imperative/transform.py b/pymbolic/imperative/transform.py index b324bab48f41289db7c1b471e685747ba9b72420..6f4c08de7c04aacdd144e4459809807cd78ddd4d 100644 --- a/pymbolic/imperative/transform.py +++ b/pymbolic/imperative/transform.py @@ -67,7 +67,7 @@ def fuse_instruction_streams_with_unique_ids(insns_a, insns_b): def disambiguate_identifiers(statements_a, statements_b, should_disambiguate_name=None): if should_disambiguate_name is None: - def should_disambiguate_name(name): + def should_disambiguate_name(name): # pylint:disable=function-redefined return True from pymbolic.imperative.analysis import get_all_used_identifiers diff --git a/pymbolic/interop/ast.py b/pymbolic/interop/ast.py index 6a826f151fb313198e5d71397a41110cf9bd8102..3b871ff00a2d79e6f791300784a2ab0459430279 100644 --- a/pymbolic/interop/ast.py +++ b/pymbolic/interop/ast.py @@ -90,15 +90,23 @@ class ASTMapper(object): # {{{ mapper -class ASTToPymbolic(ASTMapper): - def _add(x, y): # noqa - return p.Sum((x, y)) +def _add(x, y): + return p.Sum((x, y)) + + +def _sub(x, y): + return p.Sum((x, p.Product(((-1), y)))) + + +def _mult(x, y): + return p.Product((x, y)) - def _sub(x, y): # noqa - return p.Sum((x, p.Product(((-1), y)))) - def _mult(x, y): # noqa - return p.Product((x, y)) +def _neg(x): + return p.Product((-1, x),) + + +class ASTToPymbolic(ASTMapper): bin_op_map = { ast.Add: _add, @@ -127,9 +135,6 @@ class ASTToPymbolic(ASTMapper): return op_constructor(self.rec(expr.left), self.rec(expr.right)) - def _neg(x): # noqa - return p.Product((-1), x) - unary_op_map = { ast.Invert: _neg, ast.Not: p.LogicalNot, diff --git a/pymbolic/interop/common.py b/pymbolic/interop/common.py index d8b75f50e9c7915af98f90ff05419efd7afa9a91..23ea2ea28cf88209fa5fa813d31728f9778b0297 100644 --- a/pymbolic/interop/common.py +++ b/pymbolic/interop/common.py @@ -130,6 +130,13 @@ class SympyLikeToPymbolicMapper(SympyLikeMapperBase): class PymbolicToSympyLikeMapper(EvaluationMapper): + @property + def sym(self): + raise NotImplementedError + + def raise_conversion_error(self, message): + raise NotImplementedError + def map_variable(self, expr): return self.sym.Symbol(expr.name) diff --git a/pymbolic/interop/sympy.py b/pymbolic/interop/sympy.py index 1e31eade77fdd4a0faa0730319d312031f3cd57d..76ef76c56f9e2436a5261d45a893508cef5dbf4b 100644 --- a/pymbolic/interop/sympy.py +++ b/pymbolic/interop/sympy.py @@ -61,7 +61,7 @@ class SympyToPymbolicMapper(SympyLikeToPymbolicMapper): # only called for Py2 def map_long(self, expr): - return long(expr) # noqa + return long(expr) # noqa pylint:disable=undefined-variable def map_Indexed(self, expr): # noqa return prim.Subscript( diff --git a/pymbolic/mapper/__init__.py b/pymbolic/mapper/__init__.py index a280d51fff434729c6b7a56437307acf9c240b4f..3ed5240587a905c24af3a986232dd0ad06df19ad 100644 --- a/pymbolic/mapper/__init__.py +++ b/pymbolic/mapper/__init__.py @@ -135,6 +135,9 @@ class Mapper(object): rec = __call__ + def map_algebraic_leaf(self, expr, *args, **kwargs): + raise NotImplementedError + def map_variable(self, expr, *args, **kwargs): return self.map_algebraic_leaf(expr, *args, **kwargs) @@ -153,6 +156,21 @@ class Mapper(object): def map_rational(self, expr, *args, **kwargs): return self.map_quotient(expr, *args, **kwargs) + def map_quotient(self, expr, *args, **kwargs): + raise NotImplementedError + + def map_constant(self, expr, *args, **kwargs): + raise NotImplementedError + + def map_list(self, expr, *args, **kwargs): + raise NotImplementedError + + def map_tuple(self, expr, *args, **kwargs): + raise NotImplementedError + + def map_numpy_array(self, expr, *args, **kwargs): + raise NotImplementedError + def map_foreign(self, expr, *args, **kwargs): """Mapper method dispatch for non-:mod:`pymbolic` objects.""" @@ -195,6 +213,9 @@ class CombineMapper(RecursiveMapper): :class:`pymbolic.mapper.dependency.DependencyMapper` is another example. """ + def combine(self, values): + raise NotImplementedError + def map_call(self, expr, *args, **kwargs): return self.combine( (self.rec(expr.function, *args, **kwargs),) diff --git a/pymbolic/mapper/constant_converter.py b/pymbolic/mapper/constant_converter.py index cc7f94eb9c4626a1a369f4e3d00292ab0055dce8..5a8f645c8ce7bef5d8874f6bf1da921517cc3ad7 100644 --- a/pymbolic/mapper/constant_converter.py +++ b/pymbolic/mapper/constant_converter.py @@ -44,8 +44,8 @@ class ConstantToNumpyConversionMapper(pymbolic.mapper.IdentityMapper): complex_type = np.complex64 elif real_type is np.float64: complex_type = np.complex128 - elif real_type is np.float128: - complex_type = np.complex256 + elif real_type is np.float128: # pylint:disable=no-member + complex_type = np.complex256 # pylint:disable=no-member else: raise TypeError( "unable to determine corresponding complex type for '%s'" diff --git a/pymbolic/mapper/constant_folder.py b/pymbolic/mapper/constant_folder.py index b642fa63d115ff5c6eb097351cca7757231a0789..f40e4adf6b2e75bec21194416beb40d05d9249d1 100644 --- a/pymbolic/mapper/constant_folder.py +++ b/pymbolic/mapper/constant_folder.py @@ -47,7 +47,7 @@ class ConstantFoldingMapperBase(object): queue = list(expr.children) while queue: - child = self.rec(queue.pop(0)) + child = self.rec(queue.pop(0)) # pylint:disable=no-member if isinstance(child, klass): queue = list(child.children) + queue else: diff --git a/pymbolic/mapper/differentiator.py b/pymbolic/mapper/differentiator.py index 86ac2f9bbadb82955e0a581f2b97f136f434e071..b6ec695c77b72a8a61e662dbfa4c0cc5582e0326 100644 --- a/pymbolic/mapper/differentiator.py +++ b/pymbolic/mapper/differentiator.py @@ -174,7 +174,7 @@ class DifferentiationMapper(pymbolic.mapper.RecursiveMapper): return ( Polynomial(self.rec_undiff(expr.base, *args), - tuple(deriv_coeff), expr.unit) + + tuple(deriv_coeff), expr.unit) + Polynomial(self.rec_undiff(expr.base, *args), tuple(deriv_base), expr.unit)) diff --git a/pymbolic/mapper/unifier.py b/pymbolic/mapper/unifier.py index aa1f825088704f63c86ebbc3013fbd626d91c789..4ac8f2c4d099e4d804c926e5ec0cc218e0afc742 100644 --- a/pymbolic/mapper/unifier.py +++ b/pymbolic/mapper/unifier.py @@ -119,6 +119,9 @@ class UnifierBase(RecursiveMapper): self.rhs_mapping_candidates = rhs_mapping_candidates self.force_var_match = force_var_match + def treat_mismatch(self, expr, other, urecs): + raise NotImplementedError + def unification_record_from_equation(self, lhs, rhs): if isinstance(lhs, (tuple, list)) or isinstance(rhs, (tuple, list)): # Always force lists/tuples to agree elementwise, never diff --git a/pymbolic/parser.py b/pymbolic/parser.py index 00ef94a5e0c090c5f6355cf345abef27a9cfdbfb..8f199b3e31ef3876208eaf0c18fc382540ce9831 100644 --- a/pymbolic/parser.py +++ b/pymbolic/parser.py @@ -212,7 +212,7 @@ class Parser(object): left_exp = self.parse_expression(pstate, _PREC_UNARY) elif pstate.is_next(_minus): pstate.advance() - left_exp = -self.parse_expression(pstate, _PREC_UNARY) + left_exp = -self.parse_expression(pstate, _PREC_UNARY) # noqa pylint:disable=invalid-unary-operand-type elif pstate.is_next(_not): pstate.advance() from pymbolic.primitives import LogicalNot diff --git a/pymbolic/polynomial.py b/pymbolic/polynomial.py index ad878fd05265f982db3d3e3658a202796671ff55..a8e53b1f612e25b0836e0f3353eddb552c744168 100644 --- a/pymbolic/polynomial.py +++ b/pymbolic/polynomial.py @@ -56,6 +56,13 @@ def _sort_uniq(data): +def _get_dependencies(expr): + from pymbolic.mapper.dependency import DependencyMapper + return DependencyMapper()(expr) + + + + class LexicalMonomialOrder: def __call__(self, a, b): from pymbolic.primitives import Variable @@ -218,7 +225,7 @@ class Polynomial(Expression): return quot * self, rem * self if other.degree == -1: - raise DivisionByZeroError + raise ZeroDivisionError quot = Polynomial(self.Base, ()) rem = self @@ -252,11 +259,11 @@ class Polynomial(Expression): __truediv__ = __div__ - def __floordiv__(self): - return self.__divmod__(self, other)[0] + def __floordiv__(self, other): + return self.__divmod__(other)[0] - def __mod__(self): - return self.__divmod__(self, other)[1] + def __mod__(self, other): + return self.__divmod__(other)[1] def _data(self): return self.Data @@ -283,7 +290,7 @@ class Polynomial(Expression): mapper_method = intern("map_polynomial") def as_primitives(self): - deps = pymbolic.get_dependencies(self) + deps = _get_dependencies(self) context = dict((dep, dep) for dep in deps) return pymbolic.evaluate(self, context) @@ -297,21 +304,6 @@ class Polynomial(Expression): -def from_primitives(expr, var_order): - from pymbolic import get_dependencies, evaluate - - deps = get_dependencies(expr) - var_deps = [dep for dep in deps if dep in var_order] - context = dict((vd, Polynomial(vd, var_order=var_order)) - for vd in var_deps) - - # FIXME not fast, but works - # (and exercises multivariate polynomial code) - return evaluate(expr, context) - - - - def differentiate(poly): return Polynomial( poly.base, @@ -335,7 +327,8 @@ def integrate_definite(poly, a, b): a_bound = pymbolic.substitute(antideriv, {poly.base: a}) b_bound = pymbolic.substitute(antideriv, {poly.base: b}) - return pymbolic.sum((b_bound, -a_bound)) + from pymbolic.primitives import Sum + return Sum((b_bound, -a_bound)) diff --git a/pymbolic/primitives.py b/pymbolic/primitives.py index d18c1c6d5ce34a5e192530275052158ba5c21b48..018cbaae75ac93009fbb62901df9baf7b8ce653a 100644 --- a/pymbolic/primitives.py +++ b/pymbolic/primitives.py @@ -216,6 +216,14 @@ class Expression(object): .. automethod:: ge """ + # {{{ init arg names (override by subclass) + + @property + def init_arg_names(self): + raise NotImplementedError + + # }}} + # {{{ arithmetic def __add__(self, other): @@ -516,6 +524,9 @@ class Expression(object): self.hash_value = self.get_hash() return self.hash_value + def __getinitargs__(self): + raise NotImplementedError + def __getstate__(self): return self.__getinitargs__() @@ -1297,8 +1308,9 @@ class Vector(Expression): 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)) + return Vector(tuple(operator.div(x, other) for x in self)) # noqa pylint: disable=no-member def __truediv__(self, other): import operator @@ -1557,7 +1569,7 @@ global VALID_CONSTANT_CLASSES global VALID_OPERANDS VALID_CONSTANT_CLASSES = (int, float, complex) if six.PY2: - VALID_CONSTANT_CLASSES += (long,) # noqa + VALID_CONSTANT_CLASSES += (long,) # noqa pylint:disable=undefined-variable VALID_OPERANDS = (Expression,) diff --git a/test/test_pymbolic.py b/test/test_pymbolic.py index 09d2e7b5f667c66a5d81083f8ee59a9ba9f3346f..2cc3c82738d5a34c28b7f3ff61b1351cb7e0d581 100644 --- a/test/test_pymbolic.py +++ b/test/test_pymbolic.py @@ -97,7 +97,7 @@ def test_sympy_interaction(): x, y = sp.symbols("x y") f = sp.Function("f") - s1_expr = 1/f(x/sp.sqrt(x**2+y**2)).diff(x, 5) + s1_expr = 1/f(x/sp.sqrt(x**2+y**2)).diff(x, 5) # pylint:disable=not-callable from pymbolic.sympy_interface import ( SympyToPymbolicMapper,