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..d7787b83c0a977ba1ed8c7caf50d3856f4a0ef95 100644
--- a/pymbolic/interop/ast.py
+++ b/pymbolic/interop/ast.py
@@ -91,12 +91,15 @@ class ASTMapper(object):
 # {{{ mapper
 
 class ASTToPymbolic(ASTMapper):
+    @staticmethod
     def _add(x, y):  # noqa
         return p.Sum((x, y))
 
+    @staticmethod
     def _sub(x, y):  # noqa
         return p.Sum((x, p.Product(((-1), y))))
 
+    @staticmethod
     def _mult(x, y):  # noqa
         return p.Product((x, y))
 
@@ -127,8 +130,9 @@ class ASTToPymbolic(ASTMapper):
 
         return op_constructor(self.rec(expr.left), self.rec(expr.right))
 
+    @staticmethod
     def _neg(x):  # noqa
-        return p.Product((-1), x)
+        return p.Product((-1, x),)
 
     unary_op_map = {
             ast.Invert: _neg,
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_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..bcb04e2c1b4cad088f14ca1e9f43c93303cac2a0 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
@@ -70,9 +77,6 @@ class LexicalMonomialOrder:
         return "LexicalMonomialOrder()"
 
 
-
-
-
 class Polynomial(Expression):
     def __init__(self, base, data=None, unit=1, var_less=LexicalMonomialOrder()):
         self.Base = base
@@ -218,7 +222,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 +256,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 +287,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 +301,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 +324,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..d6198e30cbafb422f484f36190449ea8d48cae81 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))  # 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,)