Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-zope.testrunner for 
openSUSE:Factory checked in at 2026-01-06 17:45:41
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-zope.testrunner (Old)
 and      /work/SRC/openSUSE:Factory/.python-zope.testrunner.new.1928 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-zope.testrunner"

Tue Jan  6 17:45:41 2026 rev:30 rq:1325513 version:8.1

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-zope.testrunner/python-zope.testrunner.changes
    2025-08-26 14:57:48.072410227 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-zope.testrunner.new.1928/python-zope.testrunner.changes
  2026-01-06 17:47:10.532022413 +0100
@@ -1,0 +2,21 @@
+Tue Jan  6 02:46:39 UTC 2026 - Steve Kowalik <[email protected]>
+
+- Update to 8.1:
+  * Remove run-time dependency on setuptools.
+  * Replace pkg_resources namespace with PEP 420 native namespace.
+  * Add --auto-path option. This automatically adds the path of all packages
+    from the --package option to the test paths. (#198)
+  * Improve @unittest.expectedFailure support, especially regarding
+    post-mortem debugger. (#196)
+  * Re-add a single import of pkg_resources to avoid other import issues in
+    mixed pip/buildout environments. (#194)
+  * Replace pkg_resources with importlib.metadata.
+  * Remove setup.py ftest command. (#178)
+  * Remove zope.testrunner.eggsupport. It is no longer usable as of
+    setuptools 72.0.0. (#185)
+  * Drop support for Python 3.8.
+  * Add option --only-level=level to run tests only at the specified
+    level. (#188)
+- Clean up BuildRequires.
+
+-------------------------------------------------------------------

Old:
----
  zope_testrunner-6.6.1.tar.gz

New:
----
  zope_testrunner-8.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-zope.testrunner.spec ++++++
--- /var/tmp/diff_new_pack.I46FMs/_old  2026-01-06 17:47:11.164048413 +0100
+++ /var/tmp/diff_new_pack.I46FMs/_new  2026-01-06 17:47:11.164048413 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-zope.testrunner
 #
-# Copyright (c) 2025 SUSE LLC and contributors
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -31,20 +31,18 @@
 %endif
 %{?sle15_python_module_pythons}
 Name:           python-zope.testrunner%{psuffix}
-Version:        6.6.1
+Version:        8.1
 Release:        0
 Summary:        Zope testrunner script
 License:        ZPL-2.1
 URL:            https://github.com/zopefoundation/zope.testrunner
 Source:         
https://files.pythonhosted.org/packages/source/z/zope_testrunner/zope_testrunner-%{version}.tar.gz
+BuildRequires:  %{python_module base >= 3.9}
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  %{python_module wheel}
-BuildRequires:  %{python_module zope.exceptions}
-BuildRequires:  %{python_module zope.interface}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
-Requires:       python-setuptools
 Requires:       python-zope.exceptions
 Requires:       python-zope.interface
 BuildArch:      noarch
@@ -101,8 +99,8 @@
 %license LICENSE.md
 %doc README.rst
 %python_alternative %{_bindir}/zope-testrunner
+%dir %{python_sitelib}/zope
 %{python_sitelib}/zope/testrunner
-%{python_sitelib}/zope.testrunner-%{version}-py*-nspkg.pth
 %{python_sitelib}/zope[_.]testrunner-%{version}.dist-info
 %endif
 

++++++ zope_testrunner-6.6.1.tar.gz -> zope_testrunner-8.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/.pre-commit-config.yaml 
new/zope_testrunner-8.1/.pre-commit-config.yaml
--- old/zope_testrunner-6.6.1/.pre-commit-config.yaml   2024-12-13 
18:01:02.000000000 +0100
+++ new/zope_testrunner-8.1/.pre-commit-config.yaml     2025-10-02 
08:39:26.000000000 +0200
@@ -3,26 +3,26 @@
 minimum_pre_commit_version: '3.6'
 repos:
   - repo: https://github.com/pycqa/isort
-    rev: "5.13.2"
+    rev: "6.0.1"
     hooks:
     - id: isort
   - repo: https://github.com/hhatto/autopep8
-    rev: "v2.3.1"
+    rev: "v2.3.2"
     hooks:
     - id: autopep8
       args: [--in-place, --aggressive, --aggressive]
   - repo: https://github.com/asottile/pyupgrade
-    rev: v3.17.0
+    rev: v3.19.1
     hooks:
     - id: pyupgrade
-      args: [--py38-plus]
+      args: [--py39-plus]
   - repo: https://github.com/isidentical/teyit
     rev: 0.4.3
     hooks:
     - id: teyit
       exclude: tests/testrunner-ex/sample2/badsyntax\.py
   - repo: https://github.com/PyCQA/flake8
-    rev: "7.1.1"
+    rev: "7.2.0"
     hooks:
     - id: flake8
       additional_dependencies:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/CHANGES.rst 
new/zope_testrunner-8.1/CHANGES.rst
--- old/zope_testrunner-6.6.1/CHANGES.rst       2024-12-13 18:01:02.000000000 
+0100
+++ new/zope_testrunner-8.1/CHANGES.rst 2025-10-02 08:39:26.000000000 +0200
@@ -2,6 +2,70 @@
  zope.testrunner Changelog
 ===========================
 
+8.1 (2025-10-02)
+================
+
+- Remove run-time dependency on ``setuptools``.
+
+
+8.0 (2025-09-12)
+================
+
+- Replace ``pkg_resources`` namespace with PEP 420 native namespace.
+
+
+7.4 (2025-05-28)
+================
+
+- Add ``--auto-path`` option.
+  This automatically adds the path of all packages from the ``--package`` 
option to the test paths.
+  (`#198 <https://github.com/zopefoundation/zope.testrunner/pull/198>`_)
+
+
+7.3 (2025-05-15)
+================
+
+- Improve ``@unittest.expectedFailure`` support, especially regarding
+  post-mortem debugger. (`#196 
<https://github.com/zopefoundation/zope.testrunner/pull/196>`_)
+
+
+7.2 (2025-03-06)
+================
+
+- Re-add a single import of ``pkg_resources`` to avoid other import issues in
+  mixed pip/buildout environments.
+  (`#194 <https://github.com/zopefoundation/zope.testrunner/issues/194>`_)
+
+
+7.1 (2025-03-05)
+================
+
+- Replace ``pkg_resources`` with ``importlib.metadata``.
+
+
+7.0 (2025-02-12)
+================
+
+Backwards-incompatible changes
+------------------------------
+
+- Remove ``setup.py ftest`` command.
+  (`#178 <https://github.com/zopefoundation/zope.testrunner/issues/178>`_)
+
+- Remove ``zope.testrunner.eggsupport``.  It is no longer usable as of
+  ``setuptools`` 72.0.0.
+  (`#185 <https://github.com/zopefoundation/zope.testrunner/issues/185>`_)
+
+
+6.7 (2025-02-07)
+================
+
+- Drop support for Python 3.8.
+
+- Add option ``--only-level=level`` to run tests only at the specified level.
+  (`#188 <https://github.com/zopefoundation/zope.testrunner/issues/188>`_)
+
+
 6.6.1 (2024-12-13)
 ==================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/CONTRIBUTING.md 
new/zope_testrunner-8.1/CONTRIBUTING.md
--- old/zope_testrunner-6.6.1/CONTRIBUTING.md   2024-12-13 18:01:02.000000000 
+0100
+++ new/zope_testrunner-8.1/CONTRIBUTING.md     2025-10-02 08:39:26.000000000 
+0200
@@ -1,7 +1,7 @@
 <!--
 Generated from:
 https://github.com/zopefoundation/meta/tree/master/config/pure-python
---> 
+-->
 # Contributing to zopefoundation projects
 
 The projects under the zopefoundation GitHub organization are open source and
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/PKG-INFO 
new/zope_testrunner-8.1/PKG-INFO
--- old/zope_testrunner-6.6.1/PKG-INFO  2024-12-13 18:01:04.317217000 +0100
+++ new/zope_testrunner-8.1/PKG-INFO    2025-10-02 08:39:27.567095000 +0200
@@ -1,11 +1,11 @@
-Metadata-Version: 2.1
+Metadata-Version: 2.2
 Name: zope.testrunner
-Version: 6.6.1
+Version: 8.1
 Summary: Zope testrunner script.
 Home-page: https://github.com/zopefoundation/zope.testrunner
 Author: Zope Foundation and Contributors
 Author-email: [email protected]
-License: ZPL 2.1
+License: ZPL-2.1
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Environment :: Console
 Classifier: Framework :: Zope :: 3
@@ -14,7 +14,6 @@
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
@@ -24,9 +23,8 @@
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
 Classifier: Topic :: Software Development :: Testing
-Requires-Python: >=3.8
+Requires-Python: >=3.9
 License-File: LICENSE.md
-Requires-Dist: setuptools
 Requires-Dist: zope.exceptions
 Requires-Dist: zope.interface
 Provides-Extra: test
@@ -37,6 +35,16 @@
 Provides-Extra: docs
 Requires-Dist: Sphinx; extra == "docs"
 Requires-Dist: sphinxcontrib-programoutput; extra == "docs"
+Dynamic: author
+Dynamic: author-email
+Dynamic: classifier
+Dynamic: description
+Dynamic: home-page
+Dynamic: license
+Dynamic: provides-extra
+Dynamic: requires-dist
+Dynamic: requires-python
+Dynamic: summary
 
 =================
  zope.testrunner
@@ -219,6 +227,70 @@
  zope.testrunner Changelog
 ===========================
 
+8.1 (2025-10-02)
+================
+
+- Remove run-time dependency on ``setuptools``.
+
+
+8.0 (2025-09-12)
+================
+
+- Replace ``pkg_resources`` namespace with PEP 420 native namespace.
+
+
+7.4 (2025-05-28)
+================
+
+- Add ``--auto-path`` option.
+  This automatically adds the path of all packages from the ``--package`` 
option to the test paths.
+  (`#198 <https://github.com/zopefoundation/zope.testrunner/pull/198>`_)
+
+
+7.3 (2025-05-15)
+================
+
+- Improve ``@unittest.expectedFailure`` support, especially regarding
+  post-mortem debugger. (`#196 
<https://github.com/zopefoundation/zope.testrunner/pull/196>`_)
+
+
+7.2 (2025-03-06)
+================
+
+- Re-add a single import of ``pkg_resources`` to avoid other import issues in
+  mixed pip/buildout environments.
+  (`#194 <https://github.com/zopefoundation/zope.testrunner/issues/194>`_)
+
+
+7.1 (2025-03-05)
+================
+
+- Replace ``pkg_resources`` with ``importlib.metadata``.
+
+
+7.0 (2025-02-12)
+================
+
+Backwards-incompatible changes
+------------------------------
+
+- Remove ``setup.py ftest`` command.
+  (`#178 <https://github.com/zopefoundation/zope.testrunner/issues/178>`_)
+
+- Remove ``zope.testrunner.eggsupport``.  It is no longer usable as of
+  ``setuptools`` 72.0.0.
+  (`#185 <https://github.com/zopefoundation/zope.testrunner/issues/185>`_)
+
+
+6.7 (2025-02-07)
+================
+
+- Drop support for Python 3.8.
+
+- Add option ``--only-level=level`` to run tests only at the specified level.
+  (`#188 <https://github.com/zopefoundation/zope.testrunner/issues/188>`_)
+
+
 6.6.1 (2024-12-13)
 ==================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/docs/api.rst 
new/zope_testrunner-8.1/docs/api.rst
--- old/zope_testrunner-6.6.1/docs/api.rst      2024-12-13 18:01:02.000000000 
+0100
+++ new/zope_testrunner-8.1/docs/api.rst        2025-10-02 08:39:26.000000000 
+0200
@@ -5,5 +5,3 @@
 .. automodule:: zope.testrunner
 
 .. autoclass:: zope.testrunner.runner.Runner
-
-.. automodule:: zope.testrunner.eggsupport
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/docs/conf.py 
new/zope_testrunner-8.1/docs/conf.py
--- old/zope_testrunner-6.6.1/docs/conf.py      2024-12-13 18:01:02.000000000 
+0100
+++ new/zope_testrunner-8.1/docs/conf.py        2025-10-02 08:39:26.000000000 
+0200
@@ -14,12 +14,11 @@
 
 import os
 import sys
-
-import pkg_resources
+from importlib.metadata import distribution
 
 
 sys.path.append(os.path.abspath('../src'))
-rqmt = pkg_resources.require('zope.testrunner')[0]
+rqmt = distribution('zope.testrunner')
 
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/docs/index.rst 
new/zope_testrunner-8.1/docs/index.rst
--- old/zope_testrunner-6.6.1/docs/index.rst    2024-12-13 18:01:02.000000000 
+0100
+++ new/zope_testrunner-8.1/docs/index.rst      2025-10-02 08:39:26.000000000 
+0200
@@ -80,7 +80,6 @@
 
    testrunner-simple
    testrunner-arguments
-   testrunner-eggsupport
    api
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/docs/testrunner-eggsupport.rst 
new/zope_testrunner-8.1/docs/testrunner-eggsupport.rst
--- old/zope_testrunner-6.6.1/docs/testrunner-eggsupport.rst    2024-12-13 
18:01:02.000000000 +0100
+++ new/zope_testrunner-8.1/docs/testrunner-eggsupport.rst      1970-01-01 
01:00:00.000000000 +0100
@@ -1 +0,0 @@
-.. include:: ../src/zope/testrunner/tests/testrunner-eggsupport.rst
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/pyproject.toml 
new/zope_testrunner-8.1/pyproject.toml
--- old/zope_testrunner-6.6.1/pyproject.toml    2024-12-13 18:01:02.000000000 
+0100
+++ new/zope_testrunner-8.1/pyproject.toml      2025-10-02 08:39:26.000000000 
+0200
@@ -3,7 +3,10 @@
 # https://github.com/zopefoundation/meta/tree/master/config/pure-python
 
 [build-system]
-requires = ["setuptools<74"]
+requires = [
+    "setuptools == 75.8.2",
+    "wheel",
+]
 build-backend = "setuptools.build_meta"
 
 [tool.coverage.run]
@@ -11,11 +14,20 @@
 source = ["zope.testrunner"]
 
 [tool.coverage.report]
-fail_under = 82.5
+fail_under = 84.4
 precision = 2
 ignore_errors = true
 show_missing = true
-exclude_lines = ["pragma: no cover", "pragma: nocover", "except ImportError:", 
"raise NotImplementedError", "if __name__ == '__main__':", "self.fail", "raise 
AssertionError", "raise unittest.Skip"]
+exclude_lines = [
+    "pragma: no cover",
+    "pragma: nocover",
+    "except ImportError:",
+    "raise NotImplementedError",
+    "if __name__ == '__main__':",
+    "self.fail",
+    "raise AssertionError",
+    "raise unittest.Skip",
+]
 
 [tool.coverage.html]
 directory = "parts/htmlcov"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/setup.py 
new/zope_testrunner-8.1/setup.py
--- old/zope_testrunner-6.6.1/setup.py  2024-12-13 18:01:02.000000000 +0100
+++ new/zope_testrunner-8.1/setup.py    2025-10-02 08:39:26.000000000 +0200
@@ -21,10 +21,9 @@
 from setuptools import setup
 
 
-version = '6.6.1'
+version = '8.1'
 
 INSTALL_REQUIRES = [
-    'setuptools',
     'zope.exceptions',
     'zope.interface',
 ]
@@ -63,16 +62,11 @@
     name='zope.testrunner',
     version=version,
     url='https://github.com/zopefoundation/zope.testrunner',
-    license='ZPL 2.1',
+    license='ZPL-2.1',
     description='Zope testrunner script.',
     long_description=long_description,
     author='Zope Foundation and Contributors',
     author_email='[email protected]',
-    packages=[
-        "zope",
-        "zope.testrunner",
-    ],
-    package_dir={'': 'src'},
     classifiers=[
         "Development Status :: 5 - Production/Stable",
         "Environment :: Console",
@@ -82,7 +76,6 @@
         "Operating System :: OS Independent",
         "Programming Language :: Python",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",
@@ -93,15 +86,12 @@
         "Topic :: Software Development :: Libraries :: Python Modules",
         "Topic :: Software Development :: Testing",
     ],
-    namespace_packages=['zope'],
-    python_requires='>=3.8',
+    python_requires='>=3.9',
     install_requires=INSTALL_REQUIRES,
     extras_require=EXTRAS_REQUIRE,
     entry_points={
         'console_scripts':
             ['zope-testrunner = zope.testrunner:run'],
-        'distutils.commands': [
-            'ftest = zope.testrunner.eggsupport:ftest'],
     },
     include_package_data=True,
     zip_safe=False,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/src/zope/__init__.py 
new/zope_testrunner-8.1/src/zope/__init__.py
--- old/zope_testrunner-6.6.1/src/zope/__init__.py      2024-12-13 
18:01:02.000000000 +0100
+++ new/zope_testrunner-8.1/src/zope/__init__.py        1970-01-01 
01:00:00.000000000 +0100
@@ -1 +0,0 @@
-__import__('pkg_resources').declare_namespace(__name__)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/src/zope/testrunner/debug.py 
new/zope_testrunner-8.1/src/zope/testrunner/debug.py
--- old/zope_testrunner-6.6.1/src/zope/testrunner/debug.py      2024-12-13 
18:01:02.000000000 +0100
+++ new/zope_testrunner-8.1/src/zope/testrunner/debug.py        2025-10-02 
08:39:26.000000000 +0200
@@ -34,7 +34,6 @@
 
 def _use_ipdb():
     """Check whether ipdb is usable."""
-    global _ipdb_ok
     if ipdb is None:
         return False
     if getattr(_ipdb_state, 'ok', None) is None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/zope_testrunner-6.6.1/src/zope/testrunner/eggsupport.py 
new/zope_testrunner-8.1/src/zope/testrunner/eggsupport.py
--- old/zope_testrunner-6.6.1/src/zope/testrunner/eggsupport.py 2024-12-13 
18:01:02.000000000 +0100
+++ new/zope_testrunner-8.1/src/zope/testrunner/eggsupport.py   1970-01-01 
01:00:00.000000000 +0100
@@ -1,141 +0,0 @@
-""" Add unit and functional testing support to setuptools-driven eggs.
-"""
-
-try:
-    from setuptools.command.test import ScanningLoader
-    from setuptools.command.test import test as BaseCommand
-except ImportError:
-    # a modern ``setuptools`` no longer supporting the ``test`` command
-    ScanningLoader = object
-    from setuptools import Command as BaseCommand
-
-
-def skipLayers(suite, _result=None):
-    """ Walk the suite returned by setuptools' testloader.
-
-    o Skip any tests which have a 'layer' defined.
-    """
-    from unittest import TestSuite
-    if _result is None:
-        _result = TestSuite()
-    # Sometimes test suites do not have tests, like DocFileSuite.
-    if not suite._tests:
-        _result.addTest(suite)
-        return _result
-    for test in suite._tests:
-        layer = getattr(test, 'layer', None)
-        if layer is not None:
-            continue
-        if isinstance(test, TestSuite):
-            skipLayers(test, _result)
-        else:
-            _result.addTest(test)
-    return _result
-
-
-class SkipLayers(ScanningLoader):
-    """
-    Load only unit tests (those which have no layer associated with
-    them).
-
-    * Running the tests using 'setup.py test' cannot, by default,
-      drive the full testrunner, with its support for layers (in
-      functional tests).  This loader allows the command to work, by
-      running only those tests which don't need the layer support.
-
-    * To run layer-dependent tests, use 'setup.py ftest' (see below
-      for adding the command to your setup.py).
-
-    * To use this loader your package add the following your 'setup()'
-      call::
-
-        setup(
-            ...
-            setup_requires=[
-                'eggtestinfo' # captures testing metadata in EGG-INFO
-            ],
-            tests_require=['zope.testrunner', ],
-            ...
-            test_loader='zope.testrunner.eggsupport:SkipLayers',
-            ...
-        )
-    """
-
-    def loadTestsFromModule(self, module):
-        return skipLayers(
-            ScanningLoader.loadTestsFromModule(self, module))
-
-    def loadTestsFromNames(self, testNames, module):
-        return skipLayers(
-            ScanningLoader.loadTestsFromNames(self, testNames, module))
-
-
-def print_usage():
-    print('python setup.py ftest')
-    print()
-    print(ftest.__doc__)
-
-
-class ftest(BaseCommand):
-    """
-    Run unit and functional tests after an in-place build.
-
-    * Note that this command runs *all* tests (unit *and* functional).
-
-    * This command does not provide any of the configuration options which
-      the usual testrunner provided by 'zope.testrunner' offers:  it is
-      intended to allow easy verification that a package has been installed
-      correctly via setuptools, but is not likely to be useful for
-      developers working on the package.
-
-    * Developers working on the package will likely prefer to work with
-      the stock testrunner, e.g., by using buildout with a recipe which
-      configures the testrunner as a standalone script.
-
-    * To use this in your package add the following to the 'entry_points'
-      section::
-
-          setup(
-              ...
-              setup_requires=[
-                  'zope.testrunner',
-                  'eggtestinfo' # captures testing metadata in EGG-INFO
-              ],
-              ...
-          )
-    """
-    description = "Run all functional and unit tests after in-place build"
-    user_options = []
-    help_options = [('usage', '?', 'Show usage', print_usage)]
-
-    def initialize_options(self):
-        pass  # suppress normal handling
-
-    def finalize_options(self):
-        pass  # suppress normal handling
-
-    def run(self):
-        if ScanningLoader is object:
-            # modern ``setuptools`` no longer supporting ``test``
-            from sys import exit
-            exit("You are using a modern `setuptools` version "
-                 "which no longer supports the ``test`` command. "
-                 "`zope.testrunner`'s `ftest` command depends on this "
-                 "and therefore cannot be used.")
-        from zope.testrunner import run
-        args = ['IGNORE_ME']
-
-        dist = self.distribution
-        for src_loc in (dist.package_dir.values() or ['.']):
-            args += ['--test-path', src_loc]
-
-        if dist.install_requires:
-            dist.fetch_build_eggs(dist.install_requires)
-
-        if dist.tests_require:
-            dist.fetch_build_eggs(dist.tests_require)
-
-        def _run():
-            run(args=args)
-
-        self.with_project_on_sys_path(_run)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/src/zope/testrunner/filter.py 
new/zope_testrunner-8.1/src/zope/testrunner/filter.py
--- old/zope_testrunner-6.6.1/src/zope/testrunner/filter.py     2024-12-13 
18:01:02.000000000 +0100
+++ new/zope_testrunner-8.1/src/zope/testrunner/filter.py       2025-10-02 
08:39:26.000000000 +0200
@@ -70,8 +70,14 @@
             if self.runner.options.all:
                 msg = "Running tests at all levels"
             else:
-                msg = (
-                    "Running tests at level %d" % self.runner.options.at_level)
+                if self.runner.options.only_level is None:
+                    msg = (
+                        "Running tests at level %d" %
+                        self.runner.options.at_level)
+                else:
+                    msg = (
+                        "Running tests only at level %d" %
+                        self.runner.options.only_level)
             self.runner.options.output.info(msg)
 
     def report(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/src/zope/testrunner/find.py 
new/zope_testrunner-8.1/src/zope/testrunner/find.py
--- old/zope_testrunner-6.6.1/src/zope/testrunner/find.py       2024-12-13 
18:01:02.000000000 +0100
+++ new/zope_testrunner-8.1/src/zope/testrunner/find.py 2025-10-02 
08:39:26.000000000 +0200
@@ -347,8 +347,8 @@
 
 def test_dirs(options, seen):
     if options.package:
-        for p in options.package:
-            p = import_name(p)
+        for package_name in options.package:
+            p = import_name(package_name)
             for p in p.__path__:
                 p = os.path.abspath(p)
                 if p in seen:
@@ -358,6 +358,13 @@
                         seen[p] = 1
                         yield p, package
                         break
+                else:
+                    if options.auto_path:
+                        seen[p] = 1
+                        result = p + os.path.sep, package_name
+                        options.prefix.append(result)
+                        yield result
+
     else:
         yield from options.test_path
 
@@ -471,9 +478,14 @@
                 duplicated_test_ids.add(suite_id)
             else:
                 seen_test_ids.add(suite_id)
-        if options.at_level <= 0 or level <= options.at_level:
-            if accept is None or accept(str(suite)):
-                yield (suite, layer)
+        if options.only_level is None:
+            if options.at_level <= 0 or level <= options.at_level:
+                if accept is None or accept(str(suite)):
+                    yield (suite, layer)
+        else:
+            if level == options.only_level:
+                if accept is None or accept(str(suite)):
+                    yield (suite, layer)
 
 
 _layer_name_cache = {}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/src/zope/testrunner/options.py 
new/zope_testrunner-8.1/src/zope/testrunner/options.py
--- old/zope_testrunner-6.6.1/src/zope/testrunner/options.py    2024-12-13 
18:01:02.000000000 +0100
+++ new/zope_testrunner-8.1/src/zope/testrunner/options.py      2025-10-02 
08:39:26.000000000 +0200
@@ -18,8 +18,7 @@
 import os
 import re
 import sys
-
-import pkg_resources
+from importlib.metadata import distribution
 
 from zope.testrunner.formatter import ColorfulOutputFormatter
 from zope.testrunner.formatter import OutputFormatter
@@ -141,6 +140,15 @@
     help="Run tests at all levels.")
 
 searching.add_argument(
+    '--only-level', type=int, dest='only_level',
+    default=None,
+    help="""\
+Run only the tests at the given level. Tests on other levels are not run.
+Default is None, which means the level is not restricted by this option.
+If this option is used it overrides `--at-level` and `--all` options.
+""")
+
+searching.add_argument(
     '--list-tests', action="store_true", dest='list_tests',
     default=False,
     help="List all tests that matched your filters.  Do not run any tests.")
@@ -448,6 +456,12 @@
 will be run.
 """)
 
+searching.add_argument(
+    '--auto-path', action="store_true", dest='auto_path',
+    help="""\
+Automatically add path of --package to the test paths.
+""")
+
 setup.add_argument(
     '--tests-pattern', action="store", dest='tests_pattern',
     default=_regex_search('^tests$'),
@@ -602,7 +616,7 @@
     options.original_testrunner_args = args
 
     if options.showversion:
-        dist = pkg_resources.require('zope.testrunner')[0]
+        dist = distribution('zope.testrunner')
         print('zope.testrunner version %s' % dist.version)
         sys.exit(0)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/src/zope/testrunner/runner.py 
new/zope_testrunner-8.1/src/zope/testrunner/runner.py
--- old/zope_testrunner-6.6.1/src/zope/testrunner/runner.py     2024-12-13 
18:01:02.000000000 +0100
+++ new/zope_testrunner-8.1/src/zope/testrunner/runner.py       2025-10-02 
08:39:26.000000000 +0200
@@ -379,6 +379,13 @@
             for test in tests:
                 if result.shouldStop:
                     break
+                expecting_failure = (
+                    getattr(test, "__unittest_expecting_failure__", False)
+                    or getattr(
+                        getattr(test, test._testMethodName),
+                        "__unittest_expecting_failure__",
+                        False)
+                )
                 result.startTest(test)
                 state = test.__dict__.copy()
                 try:
@@ -389,12 +396,19 @@
                     except unittest.SkipTest as e:
                         result.addSkip(test, str(e))
                     except BaseException:
-                        result.addError(
-                            test,
-                            sys.exc_info()[:2] + (sys.exc_info()[2].tb_next, ),
+                        exc_info = (
+                            sys.exc_info()[:2]
+                            + (sys.exc_info()[2].tb_next, )
                         )
+                        if expecting_failure:
+                            result.addExpectedFailure(test, exc_info)
+                        else:
+                            result.addError(test, exc_info)
                     else:
-                        result.addSuccess(test)
+                        if expecting_failure:
+                            result.addUnexpectedSuccess(test)
+                        else:
+                            result.addSuccess(test)
                 finally:
                     result.stopTest(test)
                 test.__dict__.clear()
@@ -414,7 +428,7 @@
         output.stop_tests()
         failures.extend(result.failures)
         n_failures = len(result.failures)
-        failures.extend(result.unexpectedSuccesses)
+        failures.extend([(s, None) for s in result.unexpectedSuccesses])
         n_failures += len(result.unexpectedSuccesses)
         skipped.extend(result.skipped)
         errors.extend(result.errors)
@@ -1052,9 +1066,8 @@
                                                       " when running a layer"
                                                       " as a subprocess!")
             else:
-                # XXX: what exc_info? there's no exc_info!
-                # flake8 is correct, but keep it quiet for now ...
-                zope.testrunner.debug.post_mortem(exc_info)  # noqa: F821
+                self.options.output.error_with_banner("Can't post-mortem debug"
+                                                      " an unexpected success")
         elif self.options.stop_on_error:
             self.stop()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/zope_testrunner-6.6.1/src/zope/testrunner/tests/test_doctest.py 
new/zope_testrunner-8.1/src/zope/testrunner/tests/test_doctest.py
--- old/zope_testrunner-6.6.1/src/zope/testrunner/tests/test_doctest.py 
2024-12-13 18:01:02.000000000 +0100
+++ new/zope_testrunner-8.1/src/zope/testrunner/tests/test_doctest.py   
2025-10-02 08:39:26.000000000 +0200
@@ -248,19 +248,6 @@
         doctest.DocTestSuite('zope.testrunner.find'),
     ]
 
-    try:
-        from setuptools.command.test import ScanningLoader  # noqa: F401
-    except ImportError:
-        # modern ``setuptools`` without ``test`` support
-        pass
-    else:
-        suites.append(
-            doctest.DocFileSuite(
-                'testrunner-eggsupport.rst',
-                setUp=setUp, tearDown=tearDown,
-                optionflags=optionflags,
-                checker=checker))
-
     # PyPy uses a different garbage collector
     if hasattr(gc, 'get_threshold'):
         suites.append(
@@ -389,7 +376,7 @@
                     checker=checker))
 
     suites.append(doctest.DocFileSuite(
-        'testrunner-unexpected-success.rst',
+        'testrunner-expected-failures.rst',
         setUp=setUp, tearDown=tearDown,
         optionflags=optionflags,
         checker=checker))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/zope_testrunner-6.6.1/src/zope/testrunner/tests/test_find.py 
new/zope_testrunner-8.1/src/zope/testrunner/tests/test_find.py
--- old/zope_testrunner-6.6.1/src/zope/testrunner/tests/test_find.py    
2024-12-13 18:01:02.000000000 +0100
+++ new/zope_testrunner-8.1/src/zope/testrunner/tests/test_find.py      
2025-10-02 08:39:26.000000000 +0200
@@ -25,6 +25,7 @@
 
     keepbytecode = True
     at_level = 99
+    only_level = None
     test = []
     module = []
     require_unique_ids = True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/zope_testrunner-6.6.1/src/zope/testrunner/tests/testrunner-debugging.rst 
new/zope_testrunner-8.1/src/zope/testrunner/tests/testrunner-debugging.rst
--- 
old/zope_testrunner-6.6.1/src/zope/testrunner/tests/testrunner-debugging.rst    
    2024-12-13 18:01:02.000000000 +0100
+++ new/zope_testrunner-8.1/src/zope/testrunner/tests/testrunner-debugging.rst  
2025-10-02 08:39:26.000000000 +0200
@@ -127,3 +127,44 @@
     Tearing down left over layers:
       Tear down zope.testrunner.layer.UnitTests in N.NNN seconds.
     False
+
+Tests marked as expected failures with the ``@unittest.expectedFailure`` 
decorator do
+not trigger the post-mortem debugger when they fail as expected:
+
+    >>> expected_failure_tests_defaults = [
+    ...     '--path', os.path.join(this_directory, 
'testrunner-ex-expectedFailure'),
+    ...     '--tests-pattern', '^sample_expected_failure_tests$',
+    ...     ]
+    >>> sys.stdin = Input('q')
+    >>> sys.argv = 'test -t test_expected_failure -D'.split()
+    >>> try: testrunner.run_internal(expected_failure_tests_defaults)
+    ... finally: sys.stdin = real_stdin
+    ... # doctest: +NORMALIZE_WHITESPACE +REPORT_NDIFF +ELLIPSIS
+    Running zope.testrunner.layer.UnitTests tests:
+      Set up zope.testrunner.layer.UnitTests in N.NNN seconds.
+      Ran 1 tests with 0 failures, 0 errors and 0 skipped in N.NNN seconds.
+    Tearing down left over layers:
+      Tear down zope.testrunner.layer.UnitTests in N.NNN seconds.
+    False
+
+When ``@unittest.expectedFailure`` test unexpectedly pass, it's not possible 
to use
+the post-mortem debugger, because no exception was raised. In that case a 
warning is
+printed:
+
+    >>> sys.stdin = Input('q')
+    >>> sys.argv = 'test -t test_unexpected_success -D'.split()
+    >>> try: testrunner.run_internal(expected_failure_tests_defaults)
+    ... finally: sys.stdin = real_stdin
+    ... # doctest: +NORMALIZE_WHITESPACE +REPORT_NDIFF +ELLIPSIS
+    Running zope.testrunner.layer.UnitTests tests:
+      Set up zope.testrunner.layer.UnitTests in N.NNN seconds.
+      Error in test test_unexpected_success 
(sample_expected_failure_tests.TestExpectedFailures...)
+      Traceback (most recent call last):
+      zope.testrunner.runner.UnexpectedSuccess
+      **********************************************************************
+      Can't post-mortem debug an unexpected success
+      **********************************************************************
+      Ran 1 tests with 1 failures, 0 errors and 0 skipped in N.NNN seconds.
+    Tearing down left over layers:
+      Tear down zope.testrunner.layer.UnitTests in N.NNN seconds.
+    True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/zope_testrunner-6.6.1/src/zope/testrunner/tests/testrunner-eggsupport.rst 
new/zope_testrunner-8.1/src/zope/testrunner/tests/testrunner-eggsupport.rst
--- 
old/zope_testrunner-6.6.1/src/zope/testrunner/tests/testrunner-eggsupport.rst   
    2024-12-13 18:01:02.000000000 +0100
+++ new/zope_testrunner-8.1/src/zope/testrunner/tests/testrunner-eggsupport.rst 
1970-01-01 01:00:00.000000000 +0100
@@ -1,143 +0,0 @@
-====================
- Setuptools Support
-====================
-
-
-The ``ftest`` Setup Command
-===========================
-
-The `.ftest` class is a proper `distutils` command and
-`zope.testrunner` exposes it as such via an entry point.
-
-  >>> import pkg_resources
-  >>> ws = pkg_resources.WorkingSet()
-  >>> eps = dict([(ep.name, ep)
-  ...             for ep in ws.iter_entry_points('distutils.commands')])
-  >>> 'ftest' in eps
-  True
-  >>> eps['ftest']
-  EntryPoint.parse('ftest = zope.testrunner.eggsupport:ftest')
-
-Let's now run this command:
-
-  >>> import zope.testrunner
-  >>> org_run = zope.testrunner.run
-
-  >>> def run(args):
-  ...     print(' '.join(args))
-  >>> zope.testrunner.run = run
-
-  >>> import os, tempfile, shutil
-  >>> tmpdir = tempfile.mkdtemp()
-  >>> srcdir = os.path.join(tmpdir, 'src')
-  >>> os.mkdir(srcdir)
-
-  >>> import setuptools.dist
-  >>> dist = setuptools.dist.Distribution(
-  ...     {'package_dir': {'': srcdir},
-  ...      'script_name': __file__})
-
-  >>> from zope.testrunner.eggsupport import ftest
-  >>> ftest(dist).run()
-  IGNORE_ME --test-path .../src
-
-Cleanup:
-
-  >>> zope.testrunner.run = org_run
-  >>> shutil.rmtree(tmpdir)
-
-
-Skipping Tests with Layers
-==========================
-
-The `.SkipLayers` scanning test loader can replace the standard test loader,
-so that any tests that require layers are skipped. This is necessary, since
-the standard setuptools testing facility does not handle layers. It can be
-used as follows::
-
-      setup(
-          ...
-          setup_requires=[
-              'eggtestinfo' # captures testing metadata in EGG-INFO
-          ],
-          tests_require=[
-              'zope.testrunner',
-          ],
-          ...
-          test_loader='zope.testrunner.eggsupport:SkipLayers',
-          ...
-      )
-
-Let's now create some test suites to make sure that all tests with layers are
-properly skipped.
-
-  >>> import doctest
-  >>> import unittest
-
-  >>> all = unittest.TestSuite()
-  >>> class T1(unittest.TestCase):
-  ...     def test_t1(self):
-  ...         pass
-  >>> class T2(unittest.TestCase):
-  ...     layer = 'layer'
-  ...     def test_t2(self):
-  ...         pass
-  >>> T3 = doctest.DocTestSuite('zope.testrunner.find')
-  >>> T4 = doctest.DocTestSuite('zope.testrunner.options')
-  >>> T4.layer = 'layer'
-  >>> T5 = doctest.DocFileSuite('testrunner.rst', 
package='zope.testrunner.tests')
-  >>> T6 = doctest.DocFileSuite('testrunner-gc.rst', 
package='zope.testrunner.tests')
-  >>> T6.layer = 'layer'
-
-  >>> all = unittest.TestSuite((
-  ...     unittest.defaultTestLoader.loadTestsFromTestCase(T1),
-  ...     unittest.defaultTestLoader.loadTestsFromTestCase(T2),
-  ...     T3, T4, T5, T6,
-  ...     ))
-
-Let's return those tests from the scan:
-
-  >>> from setuptools.command.test import ScanningLoader
-  >>> orig_loadTestsFromModule = ScanningLoader.loadTestsFromModule
-  >>> ScanningLoader.loadTestsFromModule = lambda *args: all
-
-Now we can retrieve the modules from the layer skipping loader:
-
-  >>> from zope.testrunner.eggsupport import SkipLayers
-  >>> filtered = SkipLayers().loadTestsFromModule('zope.testrunner')
-
-  >>> len(filtered._tests)
-  3
-  >>> from pprint import pprint
-  >>> pprint(filtered._tests)
-  [<...T1 testMethod=test_t1>,
-   StartUpFailure (zope.testrunner.find),
-   .../zope/testrunner/tests/testrunner.rst]
-
-Cleanup:
-
-  >>> ScanningLoader.loadTestsFromModule = orig_loadTestsFromModule
-
-When the distribution specified a ``test_suite``, another method is used to
-load the tests.
-
-  >>> orig_loadTestsFromNames = ScanningLoader.loadTestsFromNames
-  >>> ScanningLoader.loadTestsFromNames = lambda *args: all
-
-Now we can retrieve the modules from the layer skipping loader:
-
-  >>> from zope.testrunner.eggsupport import SkipLayers
-  >>> filtered = SkipLayers().loadTestsFromNames(
-  ...     'zope.testrunner.tests.test_suite', 'zope.testrunner')
-
-  >>> len(filtered._tests)
-  3
-  >>> from pprint import pprint
-  >>> pprint(filtered._tests)
-  [<...T1 testMethod=test_t1>,
-   StartUpFailure (zope.testrunner.find),
-   .../zope/testrunner/tests/testrunner.rst]
-
-Cleanup:
-
-  >>> ScanningLoader.loadTestsFromNames = orig_loadTestsFromNames
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/zope_testrunner-6.6.1/src/zope/testrunner/tests/testrunner-ex-719369/sampletestsf.py
 
new/zope_testrunner-8.1/src/zope/testrunner/tests/testrunner-ex-719369/sampletestsf.py
--- 
old/zope_testrunner-6.6.1/src/zope/testrunner/tests/testrunner-ex-719369/sampletestsf.py
    2024-12-13 18:01:02.000000000 +0100
+++ 
new/zope_testrunner-8.1/src/zope/testrunner/tests/testrunner-ex-719369/sampletestsf.py
      1970-01-01 01:00:00.000000000 +0100
@@ -1,22 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2011 Zope Foundation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-
-import unittest
-
-
-class TestUnexpectedSuccess(unittest.TestCase):
-
-    @unittest.expectedFailure
-    def test_ef(self):
-        pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/zope_testrunner-6.6.1/src/zope/testrunner/tests/testrunner-ex-expectedFailure/sample_expected_failure_tests.py
 
new/zope_testrunner-8.1/src/zope/testrunner/tests/testrunner-ex-expectedFailure/sample_expected_failure_tests.py
--- 
old/zope_testrunner-6.6.1/src/zope/testrunner/tests/testrunner-ex-expectedFailure/sample_expected_failure_tests.py
  1970-01-01 01:00:00.000000000 +0100
+++ 
new/zope_testrunner-8.1/src/zope/testrunner/tests/testrunner-ex-expectedFailure/sample_expected_failure_tests.py
    2025-10-02 08:39:26.000000000 +0200
@@ -0,0 +1,26 @@
+##############################################################################
+#
+# Copyright (c) 2011 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+import unittest
+
+
+class TestExpectedFailures(unittest.TestCase):
+
+    @unittest.expectedFailure
+    def test_expected_failure(self):
+        self.fail('test fail, as expected')
+
+    @unittest.expectedFailure
+    def test_unexpected_success(self):
+        self.assertTrue('unexpected success')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/zope_testrunner-6.6.1/src/zope/testrunner/tests/testrunner-expected-failures.rst
 
new/zope_testrunner-8.1/src/zope/testrunner/tests/testrunner-expected-failures.rst
--- 
old/zope_testrunner-6.6.1/src/zope/testrunner/tests/testrunner-expected-failures.rst
        1970-01-01 01:00:00.000000000 +0100
+++ 
new/zope_testrunner-8.1/src/zope/testrunner/tests/testrunner-expected-failures.rst
  2025-10-02 08:39:26.000000000 +0200
@@ -0,0 +1,65 @@
+testrunner handling of expected failures
+========================================
+
+    >>> import os, sys
+    >>> directory_with_tests = os.path.join(this_directory, 
'testrunner-ex-expectedFailure')
+
+    >>> from zope import testrunner
+
+    >>> defaults = [
+    ...     '--path', directory_with_tests,
+    ...     '--tests-pattern', '^sample_expected_failure_tests$',
+    ...     ]
+
+Expected failures are not reported as failures:
+
+    >>> sys.argv = 'test -t test_expected_failure'.split()
+    >>> testrunner.run_internal(defaults)
+    ... # doctest: +ELLIPSIS
+    Running zope.testrunner.layer.UnitTests tests:
+      Set up zope.testrunner.layer.UnitTests in N.NNN seconds.
+    <BLANKLINE>
+      Ran 1 tests with 0 failures, 0 errors and 0 skipped in N.NNN seconds.
+    Tearing down left over layers:
+      Tear down zope.testrunner.layer.UnitTests in N.NNN seconds.
+    False
+
+
+Unexpected successes are reported as failures:
+
+    >>> sys.argv = 'test -t test_unexpected_success'.split()
+    >>> testrunner.run_internal(defaults)
+    ... # doctest: +ELLIPSIS
+    Running zope.testrunner.layer.UnitTests tests:
+      Set up zope.testrunner.layer.UnitTests in N.NNN seconds.
+    <BLANKLINE>
+    <BLANKLINE>
+    Error in test test_unexpected_success 
(sample_expected_failure_tests.TestExpectedFailures...)
+    Traceback (most recent call last):
+      zope.testrunner.runner.UnexpectedSuccess
+    <BLANKLINE>
+      Ran 1 tests with 1 failures, 0 errors and 0 skipped in N.NNN seconds.
+    Tearing down left over layers:
+      Tear down zope.testrunner.layer.UnitTests in N.NNN seconds.
+    True
+
+In verbose mode, tests with unexpected failures are listed as failures in the 
summary:
+
+    >>> sys.argv = 'test -t test_unexpected_success -vv'.split()
+    >>> testrunner.run_internal(defaults)
+    ... # doctest: +ELLIPSIS
+    Running tests at level 1
+    Running zope.testrunner.layer.UnitTests tests:
+      Set up zope.testrunner.layer.UnitTests in N.NNN seconds.
+      Running:
+      test_unexpected_success 
(sample_expected_failure_tests.TestExpectedFailures...)
+    Error in test test_unexpected_success 
(sample_expected_failure_tests.TestExpectedFailures...)
+    Traceback (most recent call last):
+    zope.testrunner.runner.UnexpectedSuccess
+      Ran 1 tests with 1 failures, 0 errors and 0 skipped in N.NNN seconds.
+    Tearing down left over layers:
+      Tear down zope.testrunner.layer.UnitTests in N.NNN seconds.
+    Tests with failures:
+      test_unexpected_success 
(sample_expected_failure_tests.TestExpectedFailures...)
+    <BLANKLINE>
+    True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/zope_testrunner-6.6.1/src/zope/testrunner/tests/testrunner-test-selection.rst
 new/zope_testrunner-8.1/src/zope/testrunner/tests/testrunner-test-selection.rst
--- 
old/zope_testrunner-6.6.1/src/zope/testrunner/tests/testrunner-test-selection.rst
   2024-12-13 18:01:02.000000000 +0100
+++ 
new/zope_testrunner-8.1/src/zope/testrunner/tests/testrunner-test-selection.rst 
    2025-10-02 08:39:26.000000000 +0200
@@ -524,6 +524,22 @@
       Tear down zope.testrunner.layer.UnitTests in N.NNN seconds.
     False
 
+We get run 38 tests.  We can specify to run only the level 2 tests using
+``--only-level=2``. So we run less tests:
+
+    >>> sys.argv = 'test -u  -vv --only-level=2 -t test_y1 -t test_y0'.split()
+    >>> testrunner.run_internal(defaults)
+    Running tests only at level 2
+    Running zope.testrunner.layer.UnitTests tests:
+      Set up zope.testrunner.layer.UnitTests in N.NNN seconds.
+      Running:
+     test_y0 (sampletestsf.TestA2...)
+     test_y1 (sample1.sample11.sampletests.TestB2...)
+      Ran 2 tests with 0 failures, 0 errors and 0 skipped in N.NNN seconds.
+    Tearing down left over layers:
+      Tear down zope.testrunner.layer.UnitTests in N.NNN seconds.
+    False
+
 
 We can use the --all option to run tests at all levels:
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/zope_testrunner-6.6.1/src/zope/testrunner/tests/testrunner-unexpected-success.rst
 
new/zope_testrunner-8.1/src/zope/testrunner/tests/testrunner-unexpected-success.rst
--- 
old/zope_testrunner-6.6.1/src/zope/testrunner/tests/testrunner-unexpected-success.rst
       2024-12-13 18:01:02.000000000 +0100
+++ 
new/zope_testrunner-8.1/src/zope/testrunner/tests/testrunner-unexpected-success.rst
 1970-01-01 01:00:00.000000000 +0100
@@ -1,42 +0,0 @@
-testrunner handling of unexpected success
-=========================================
-
-Although testrunner is currently not able to handle unexpected successes
-correctly at least it does not report them as successes.
-
-
-This document has some edge-case examples to test various aspects of
-the test runner.
-
-Separating Python path and test directories
--------------------------------------------
-
-The --path option defines a directory to be searched for tests *and* a
-directory to be added to Python's search path.  The --test-path option
-can be used when you want to set a test search path without also
-affecting the Python path:
-
-    >>> import os, sys
-    >>> directory_with_tests = os.path.join(this_directory, 
'testrunner-ex-719369')
-
-    >>> from zope import testrunner
-
-    >>> defaults = [
-    ...     '--path', directory_with_tests,
-    ...     '--tests-pattern', '^sampletestsf?$',
-    ...     ]
-    >>> sys.argv = ['test']
-    >>> testrunner.run_internal(defaults)
-    ... # doctest: +ELLIPSIS
-    Running zope.testrunner.layer.UnitTests tests:
-      Set up zope.testrunner.layer.UnitTests in N.NNN seconds.
-    <BLANKLINE>
-    <BLANKLINE>
-    Error in test test_ef (sampletestsf.TestUnexpectedSuccess...)
-    Traceback (most recent call last):
-    ...UnexpectedSuccess
-    <BLANKLINE>
-      Ran 1 tests with 1 failures, 0 errors and 0 skipped in N.NNN seconds.
-    Tearing down left over layers:
-      Tear down zope.testrunner.layer.UnitTests in N.NNN seconds.
-    True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/zope_testrunner-6.6.1/src/zope.testrunner.egg-info/PKG-INFO 
new/zope_testrunner-8.1/src/zope.testrunner.egg-info/PKG-INFO
--- old/zope_testrunner-6.6.1/src/zope.testrunner.egg-info/PKG-INFO     
2024-12-13 18:01:04.000000000 +0100
+++ new/zope_testrunner-8.1/src/zope.testrunner.egg-info/PKG-INFO       
2025-10-02 08:39:27.000000000 +0200
@@ -1,11 +1,11 @@
-Metadata-Version: 2.1
+Metadata-Version: 2.2
 Name: zope.testrunner
-Version: 6.6.1
+Version: 8.1
 Summary: Zope testrunner script.
 Home-page: https://github.com/zopefoundation/zope.testrunner
 Author: Zope Foundation and Contributors
 Author-email: [email protected]
-License: ZPL 2.1
+License: ZPL-2.1
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Environment :: Console
 Classifier: Framework :: Zope :: 3
@@ -14,7 +14,6 @@
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
@@ -24,9 +23,8 @@
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
 Classifier: Topic :: Software Development :: Testing
-Requires-Python: >=3.8
+Requires-Python: >=3.9
 License-File: LICENSE.md
-Requires-Dist: setuptools
 Requires-Dist: zope.exceptions
 Requires-Dist: zope.interface
 Provides-Extra: test
@@ -37,6 +35,16 @@
 Provides-Extra: docs
 Requires-Dist: Sphinx; extra == "docs"
 Requires-Dist: sphinxcontrib-programoutput; extra == "docs"
+Dynamic: author
+Dynamic: author-email
+Dynamic: classifier
+Dynamic: description
+Dynamic: home-page
+Dynamic: license
+Dynamic: provides-extra
+Dynamic: requires-dist
+Dynamic: requires-python
+Dynamic: summary
 
 =================
  zope.testrunner
@@ -219,6 +227,70 @@
  zope.testrunner Changelog
 ===========================
 
+8.1 (2025-10-02)
+================
+
+- Remove run-time dependency on ``setuptools``.
+
+
+8.0 (2025-09-12)
+================
+
+- Replace ``pkg_resources`` namespace with PEP 420 native namespace.
+
+
+7.4 (2025-05-28)
+================
+
+- Add ``--auto-path`` option.
+  This automatically adds the path of all packages from the ``--package`` 
option to the test paths.
+  (`#198 <https://github.com/zopefoundation/zope.testrunner/pull/198>`_)
+
+
+7.3 (2025-05-15)
+================
+
+- Improve ``@unittest.expectedFailure`` support, especially regarding
+  post-mortem debugger. (`#196 
<https://github.com/zopefoundation/zope.testrunner/pull/196>`_)
+
+
+7.2 (2025-03-06)
+================
+
+- Re-add a single import of ``pkg_resources`` to avoid other import issues in
+  mixed pip/buildout environments.
+  (`#194 <https://github.com/zopefoundation/zope.testrunner/issues/194>`_)
+
+
+7.1 (2025-03-05)
+================
+
+- Replace ``pkg_resources`` with ``importlib.metadata``.
+
+
+7.0 (2025-02-12)
+================
+
+Backwards-incompatible changes
+------------------------------
+
+- Remove ``setup.py ftest`` command.
+  (`#178 <https://github.com/zopefoundation/zope.testrunner/issues/178>`_)
+
+- Remove ``zope.testrunner.eggsupport``.  It is no longer usable as of
+  ``setuptools`` 72.0.0.
+  (`#185 <https://github.com/zopefoundation/zope.testrunner/issues/185>`_)
+
+
+6.7 (2025-02-07)
+================
+
+- Drop support for Python 3.8.
+
+- Add option ``--only-level=level`` to run tests only at the specified level.
+  (`#188 <https://github.com/zopefoundation/zope.testrunner/issues/188>`_)
+
+
 6.6.1 (2024-12-13)
 ==================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/zope_testrunner-6.6.1/src/zope.testrunner.egg-info/SOURCES.txt 
new/zope_testrunner-8.1/src/zope.testrunner.egg-info/SOURCES.txt
--- old/zope_testrunner-6.6.1/src/zope.testrunner.egg-info/SOURCES.txt  
2024-12-13 18:01:04.000000000 +0100
+++ new/zope_testrunner-8.1/src/zope.testrunner.egg-info/SOURCES.txt    
2025-10-02 08:39:27.000000000 +0200
@@ -25,7 +25,6 @@
 docs/testrunner-debugging.rst
 docs/testrunner-discovery.rst
 docs/testrunner-edge-cases.rst
-docs/testrunner-eggsupport.rst
 docs/testrunner-errors.rst
 docs/testrunner-gc.rst
 docs/testrunner-knit.rst
@@ -44,12 +43,10 @@
 docs/testrunner-verbose.rst
 docs/testrunner-wo-source.rst
 docs/testrunner.rst
-src/zope/__init__.py
 src/zope.testrunner.egg-info/PKG-INFO
 src/zope.testrunner.egg-info/SOURCES.txt
 src/zope.testrunner.egg-info/dependency_links.txt
 src/zope.testrunner.egg-info/entry_points.txt
-src/zope.testrunner.egg-info/namespace_packages.txt
 src/zope.testrunner.egg-info/not-zip-safe
 src/zope.testrunner.egg-info/requires.txt
 src/zope.testrunner.egg-info/top_level.txt
@@ -59,7 +56,6 @@
 src/zope/testrunner/coverage.py
 src/zope/testrunner/debug.py
 src/zope/testrunner/digraph.py
-src/zope/testrunner/eggsupport.py
 src/zope/testrunner/exceptions.py
 src/zope/testrunner/feature.py
 src/zope/testrunner/filter.py
@@ -101,8 +97,8 @@
 src/zope/testrunner/tests/testrunner-debugging.rst
 src/zope/testrunner/tests/testrunner-discovery.rst
 src/zope/testrunner/tests/testrunner-edge-cases.rst
-src/zope/testrunner/tests/testrunner-eggsupport.rst
 src/zope/testrunner/tests/testrunner-errors.rst
+src/zope/testrunner/tests/testrunner-expected-failures.rst
 src/zope/testrunner/tests/testrunner-gc-after-test.rst
 src/zope/testrunner/tests/testrunner-gc.rst
 src/zope/testrunner/tests/testrunner-knit.rst
@@ -134,7 +130,6 @@
 src/zope/testrunner/tests/testrunner-subunit.rst
 src/zope/testrunner/tests/testrunner-tb-format.rst
 src/zope/testrunner/tests/testrunner-test-selection.rst
-src/zope/testrunner/tests/testrunner-unexpected-success.rst
 src/zope/testrunner/tests/testrunner-verbose.rst
 src/zope/testrunner/tests/testrunner-wo-source.rst
 src/zope/testrunner/tests/testrunner.rst
@@ -165,7 +160,7 @@
 src/zope/testrunner/tests/testrunner-ex-37/stop_on_error.py
 src/zope/testrunner/tests/testrunner-ex-37/stop_on_failure.py
 src/zope/testrunner/tests/testrunner-ex-6/cwdtests.py
-src/zope/testrunner/tests/testrunner-ex-719369/sampletestsf.py
+src/zope/testrunner/tests/testrunner-ex-expectedFailure/sample_expected_failure_tests.py
 src/zope/testrunner/tests/testrunner-ex-pp-lib/sample4/__init__.py
 src/zope/testrunner/tests/testrunner-ex-pp-lib/sample4/products/__init__.py
 src/zope/testrunner/tests/testrunner-ex-pp-products/__init__.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/zope_testrunner-6.6.1/src/zope.testrunner.egg-info/entry_points.txt 
new/zope_testrunner-8.1/src/zope.testrunner.egg-info/entry_points.txt
--- old/zope_testrunner-6.6.1/src/zope.testrunner.egg-info/entry_points.txt     
2024-12-13 18:01:04.000000000 +0100
+++ new/zope_testrunner-8.1/src/zope.testrunner.egg-info/entry_points.txt       
2025-10-02 08:39:27.000000000 +0200
@@ -1,5 +1,2 @@
 [console_scripts]
 zope-testrunner = zope.testrunner:run
-
-[distutils.commands]
-ftest = zope.testrunner.eggsupport:ftest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/zope_testrunner-6.6.1/src/zope.testrunner.egg-info/namespace_packages.txt 
new/zope_testrunner-8.1/src/zope.testrunner.egg-info/namespace_packages.txt
--- 
old/zope_testrunner-6.6.1/src/zope.testrunner.egg-info/namespace_packages.txt   
    2024-12-13 18:01:04.000000000 +0100
+++ new/zope_testrunner-8.1/src/zope.testrunner.egg-info/namespace_packages.txt 
1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-zope
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/zope_testrunner-6.6.1/src/zope.testrunner.egg-info/requires.txt 
new/zope_testrunner-8.1/src/zope.testrunner.egg-info/requires.txt
--- old/zope_testrunner-6.6.1/src/zope.testrunner.egg-info/requires.txt 
2024-12-13 18:01:04.000000000 +0100
+++ new/zope_testrunner-8.1/src/zope.testrunner.egg-info/requires.txt   
2025-10-02 08:39:27.000000000 +0200
@@ -1,4 +1,3 @@
-setuptools
 zope.exceptions
 zope.interface
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zope_testrunner-6.6.1/tox.ini 
new/zope_testrunner-8.1/tox.ini
--- old/zope_testrunner-6.6.1/tox.ini   2024-12-13 18:01:02.000000000 +0100
+++ new/zope_testrunner-8.1/tox.ini     2025-10-02 08:39:26.000000000 +0200
@@ -5,7 +5,6 @@
 envlist =
     release-check
     lint
-    py38
     py39
     py310
     py311
@@ -14,14 +13,14 @@
     pypy3
     docs
     coverage
-    py{38,39,310,311,312,313,py3}-subunit
+    py{39,310,311,312,313,py3}-subunit
 
 [testenv]
 usedevelop = true
 package = wheel
 wheel_build_env = .pkg
 deps =
-    setuptools  <74
+    setuptools == 75.8.2
 commands =
     zope-testrunner --test-path=src {posargs:-vc}
 extras =
@@ -39,7 +38,8 @@
 basepython = python3
 skip_install = true
 deps =
-    setuptools <74
+    setuptools == 75.8.2
+    wheel
     twine
     build
     check-manifest

Reply via email to