diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 43b36f96947b4ce881b370e34f6a207ffb5e2521..ae39fb4fbc1e0e4afcc857737edb85091e84114a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -7,6 +7,7 @@ Python 2.7:
   - python2.7
   except:
   - tags
+
 Python 3.5:
   script:
   - py_version=3.5
@@ -16,6 +17,7 @@ Python 3.5:
   - python3.5
   except:
   - tags
+
 Python 2.6:
   script:
   - py_version=2.6
@@ -26,3 +28,12 @@ Python 2.6:
   - python2.6
   except:
   - tags
+
+Flake8:
+  script:
+  - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/prepare-and-run-flake8.sh
+  - ". ./prepare-and-run-flake8.sh pyopencl test"
+  tags:
+  - python3.5
+  except:
+  - tags
diff --git a/pytools/batchjob.py b/pytools/batchjob.py
index 4a190a427a2c06912a8e4d8e24fbef12b356e011..2afde16b595c1d7133457197bafabd7af570ce1f 100644
--- a/pytools/batchjob.py
+++ b/pytools/batchjob.py
@@ -1,5 +1,7 @@
 from __future__ import absolute_import
 import six
+
+
 def _cp(src, dest):
     from pytools import assert_not_a_file
     assert_not_a_file(dest)
@@ -15,16 +17,11 @@ def _cp(src, dest):
         inf.close()
 
 
-
-
-
 def get_timestamp():
     from datetime import datetime
     return datetime.now().strftime("%Y-%m-%d-%H%M%S")
 
 
-
-
 class BatchJob(object):
     def __init__(self, moniker, main_file, aux_files=[], timestamp=None):
         import os
@@ -49,7 +46,7 @@ class BatchJob(object):
 
         runscript = open("%s/run.sh" % self.path, "w")
         import sys
-        runscript.write("%s %s setup.cpy" 
+        runscript.write("%s %s setup.cpy"
                 % (sys.executable, main_file))
         runscript.close()
 
@@ -68,14 +65,10 @@ class BatchJob(object):
         setup.close()
 
 
-
-
-class INHERIT(object):
+class INHERIT(object):  # noqa
     pass
 
 
-
-
 class GridEngineJob(BatchJob):
     def submit(self, env={"LD_LIBRARY_PATH": INHERIT, "PYTHONPATH": INHERIT},
             memory_megs=None, extra_args=[]):
@@ -103,8 +96,6 @@ class GridEngineJob(BatchJob):
             raise RuntimeError("Process submission of %s failed" % self.moniker)
 
 
-
-
 class PBSJob(BatchJob):
     def submit(self, env={"LD_LIBRARY_PATH": INHERIT, "PYTHONPATH": INHERIT},
             memory_megs=None, extra_args=[]):
@@ -132,11 +123,9 @@ class PBSJob(BatchJob):
             raise RuntimeError("Process submission of %s failed" % self.moniker)
 
 
-
-
 def guess_job_class():
     from subprocess import Popen, PIPE, STDOUT
-    qstat_helplines = Popen(["qstat", "--help"], 
+    qstat_helplines = Popen(["qstat", "--help"],
             stdout=PIPE, stderr=STDOUT).communicate()[0].split("\n")
     if qstat_helplines[0].startswith("GE"):
         return GridEngineJob
@@ -144,8 +133,6 @@ def guess_job_class():
         return PBSJob
 
 
-
-
 class ConstructorPlaceholder:
     def __init__(self, classname, *args, **kwargs):
         self.classname = classname
@@ -162,8 +149,8 @@ class ConstructorPlaceholder:
         return "%s(%s)" % (self.classname,
                 ",".join(
                     [str(arg) for arg in self.args]
-                    + ["%s=%s" % (kw, repr(val)) for kw, val in six.iteritems(self.kwargs)]
+                    + ["%s=%s" % (kw, repr(val))
+                        for kw, val in six.iteritems(self.kwargs)]
                     )
                 )
     __repr__ = __str__
-
diff --git a/pytools/debug.py b/pytools/debug.py
index 6ddb171b3edcbb78ee196621bef758d801abb5f4..98b73de5141a465598021806b2b33a3274ff0e9c 100644
--- a/pytools/debug.py
+++ b/pytools/debug.py
@@ -163,6 +163,7 @@ def setup_readline():
 
     readline.parse_and_bind("tab: complete")
 
+
 try:
     import readline
     import rlcompleter
diff --git a/pytools/log.py b/pytools/log.py
index d7f1f958d7c7a3af06a04236dfa7399af803cdb3..13301fc4a8d2c394bb2854bb1ef67cadcc1e8355 100644
--- a/pytools/log.py
+++ b/pytools/log.py
@@ -538,7 +538,7 @@ class LogManager(object):
         self.constants[name] = value
 
         from pickle import dumps
-        value = buffer(dumps(value))
+        value = bytes(dumps(value))
 
         if existed:
             self.db_conn.execute("update constants set value = ? where name = ?",
@@ -662,7 +662,7 @@ class LogManager(object):
             from pickle import dumps
             self.db_conn.execute("""insert into quantities values (?,?,?,?)""", (
                 name, unit, description,
-                buffer(dumps(def_agg))))
+                bytes(dumps(def_agg))))
             self.db_conn.execute("""create table %s
               (step integer, rank integer, value real)""" % name)
 
diff --git a/pytools/mpi.py b/pytools/mpi.py
index 5d9c93137e638929496cb9b0555400f9764d9356..8f4b2bba06c0151f093a4bbb4d69f1a987ceffc4 100644
--- a/pytools/mpi.py
+++ b/pytools/mpi.py
@@ -1,4 +1,6 @@
 from __future__ import absolute_import
+
+
 def check_for_mpi_relaunch(argv):
     if argv[1] != "--mpi-relaunch":
         return
diff --git a/pytools/mpiwrap.py b/pytools/mpiwrap.py
index 0090e885a289d2db3e0d1698240701e4c536c91b..5c5ed24b484b780a6ade4ddff6d062d5451978cc 100644
--- a/pytools/mpiwrap.py
+++ b/pytools/mpiwrap.py
@@ -8,14 +8,15 @@ mpi4py.rc.initialize = False
 import pytools.prefork
 pytools.prefork.enable_prefork()
 
-from mpi4py.MPI import *
+from mpi4py.MPI import *  # noqa
 
-if Is_initialized():
+
+if Is_initialized():  # noqa
     raise RuntimeError("MPI already initialized before MPI wrapper import")
 
-def InitWithAutoFinalize(*args, **kwargs):
-    result = Init(*args, **kwargs)
+
+def InitWithAutoFinalize(*args, **kwargs):  # noqa
+    result = Init(*args, **kwargs)  # noqa
     import atexit
-    atexit.register(Finalize)
+    atexit.register(Finalize)  # noqa
     return result
-
diff --git a/pytools/obj_array.py b/pytools/obj_array.py
index 597d212e2e41d34683ad6b2b9008c8f12535bea1..e425e70a5c6e1f697865239f5187625f65ccd360 100644
--- a/pytools/obj_array.py
+++ b/pytools/obj_array.py
@@ -66,6 +66,7 @@ def obj_array_to_hashable(f):
     else:
         return f
 
+
 hashable_field = MovedFunctionDeprecationWrapper(obj_array_to_hashable)
 
 
@@ -78,6 +79,7 @@ def obj_array_equal(a, b):
     else:
         return a == b
 
+
 field_equal = MovedFunctionDeprecationWrapper(obj_array_equal)
 
 
@@ -129,6 +131,7 @@ def with_object_array_or_scalar(f, field, obj_array_only=False):
     else:
         return f(field)
 
+
 as_oarray_func = decorator(with_object_array_or_scalar)
 
 
@@ -158,6 +161,7 @@ def with_object_array_or_scalar_n_args(f, *args):
     else:
         return f(*args)
 
+
 as_oarray_func_n_args = decorator(with_object_array_or_scalar_n_args)
 
 
diff --git a/pytools/prefork.py b/pytools/prefork.py
index 6932bc977498ff6e6eb4dcddeb8928a845311076..68a46d865e89aedd4b8315a6979b777a0fd95e99 100644
--- a/pytools/prefork.py
+++ b/pytools/prefork.py
@@ -37,7 +37,7 @@ class DirectForker(object):
 
             return self.count
         except OSError as e:
-             raise ExecError("error invoking '%s': %s"
+            raise ExecError("error invoking '%s': %s"
                              % (" ".join(cmdline), e))
 
     def call_capture_output(self, cmdline, cwd=None, error_on_nonzero=True):
diff --git a/pytools/stopwatch.py b/pytools/stopwatch.py
index 231b4c6e461367bceb54deadd2c9d1a20bd31ae6..e34bb9f3644e503a4ab33f990bda2b9679a81c29 100644
--- a/pytools/stopwatch.py
+++ b/pytools/stopwatch.py
@@ -1,12 +1,8 @@
-from __future__ import division
-from __future__ import absolute_import
-from __future__ import print_function
+from __future__ import division, absolute_import, print_function
 import time
 import pytools
 
 
-
-
 class StopWatch:
     def __init__(self):
         self.Elapsed = 0.
@@ -42,16 +38,14 @@ class Job:
         JOB_TIMES[self.Name] += elapsed
         if self.is_visible():
             print(" " * (len(self.Name) + 2), elapsed, "seconds")
-  
+
     def is_visible(self):
         if PRINT_JOBS.get():
-            return not self.Name in HIDDEN_JOBS
+            return self.Name not in HIDDEN_JOBS
         else:
             return self.Name in VISIBLE_JOBS
 
 
-
-
 class EtaEstimator:
     def __init__(self, total_steps):
         self.stopwatch = StopWatch().start()
@@ -67,17 +61,11 @@ class EtaEstimator:
             return None
 
 
-
-
 def print_job_summary():
     for key in JOB_TIMES:
         print(key, " " * (50-len(key)), JOB_TIMES[key])
 
 
-
-
-
-
 HIDDEN_JOBS = []
 VISIBLE_JOBS = []
 JOB_TIMES = pytools.DictionaryWithDefault(lambda x: 0)
diff --git a/setup.cfg b/setup.cfg
index 9c207b0563d93bd665913d2f7abf624340e76d41..4f28d744a43e004359603baf770d76abca656fa4 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,5 +1,6 @@
 [flake8]
-ignore = E126,E127,E128,E123,E226,E241,E242,E265,E402,W503
+ignore = E126,E127,E128,E123,E226,E241,E242,E265,E402,W503,E731
 max-line-length=85
+exclude=pytools/arithmetic_container.py,pytools/decorator.py
 [wheel]
 universal = 1
diff --git a/test/test_math_stuff.py b/test/test_math_stuff.py
index 7450e5315f96de81ed448d4418d725db8749fdbc..52040088dd4afa90bfa6f1035b6fbb077aa59206 100644
--- a/test/test_math_stuff.py
+++ b/test/test_math_stuff.py
@@ -2,8 +2,6 @@ from __future__ import division
 from __future__ import absolute_import
 
 
-
-
 def test_variance():
     data = [4, 7, 13, 16]
 
@@ -12,7 +10,7 @@ def test_variance():
         return ((
             sum(di**2 for di in data)
             - sum(data)**2/n)
-            /(n-1))
+            / (n-1))
 
     from pytools import variance
     orig_variance = variance(data, entire_pop=False)
@@ -21,4 +19,3 @@ def test_variance():
 
     data = [1e9 + x for x in data]
     assert abs(variance(data, entire_pop=False) - orig_variance) < 1e-15
-