--- a/tox.ini	2020-09-18 04:19:44.000000000 -0600
+++ b/tox.ini	2021-09-08 13:50:00.480290094 -0600
@@ -1,36 +1,81 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/pure-python
 [tox]
+minversion = 3.18
 envlist =
-# Jython 2.7b1 support pending fix for Jython incompat. w/ pip's vendored-in
-# requests -> html5 libraries.  See
-# https://github.com/html5lib/html5lib-python/pull/150
-#   py27,py33,py34,pypy,pypy3,jython,coverage,docs
-    py27,py35,py36,py37,py38,py39,pypy,pypy3,coverage,docs
+    lint
+    py27
+    py35
+    py36
+    py37
+    py38
+    py39
+    pypy
+    pypy3
+    docs
+    coverage
 
 [testenv]
-commands =
-    coverage run -m zope.testrunner --test-path=src []
+usedevelop = true
 deps =
-    .[test]
-    coverage
-setenv =
-   COVERAGE_FILE=.coverage.{envname}
+    Sphinx
+commands =
+    zope-testrunner --test-path=src {posargs:-vc}
+    !py27-!pypy: sphinx-build -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest
+extras =
+    test
 
-[testenv:coverage]
-setenv =
-  COVERAGE_FILE=.coverage
+[testenv:lint]
+basepython = python3
 skip_install = true
+deps =
+    flake8
+    check-manifest
+    check-python-versions
 commands =
-    coverage erase
-    coverage combine
-    coverage report
-    coverage html
-    coverage xml
+    flake8 src setup.py
+    check-manifest
+    check-python-versions
 
 [testenv:docs]
-basepython =
-    python2.7
+basepython = python3
+skip_install = false
+deps = Sphinx
+commands_pre =
 commands =
     sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html
     sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest
+
+[testenv:coverage]
+basepython = python3
+allowlist_externals =
+    mkdir
 deps =
+    coverage
+    coverage-python-version
     Sphinx
+commands =
+    mkdir -p {toxinidir}/parts/htmlcov
+    coverage run -m zope.testrunner --test-path=src {posargs:-vc}
+    coverage run -a -m sphinx -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest
+    coverage html
+    coverage report -m --fail-under=100
+
+[coverage:run]
+branch = True
+plugins = coverage_python_version
+source = zope.event
+
+[coverage:report]
+precision = 2
+exclude_lines =
+    pragma: no cover
+    pragma: nocover
+    except ImportError:
+    raise NotImplementedError
+    if __name__ == '__main__':
+    self.fail
+    raise AssertionError
+
+[coverage:html]
+directory = parts/htmlcov