diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6f5364d..f529e74 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -12,9 +12,9 @@ jobs: test: strategy: matrix: - python-version: ["pypy-3.10", "3.10", "3.11", "3.12", "3.13"] + python-version: ["pypy-3.11", "3.10", "3.11", "3.12", "3.13", "3.14"] extras: - - "[test,docs]" + - "[test,docs,zodb,test-zodb]" runs-on: ubuntu-latest steps: @@ -37,10 +37,14 @@ jobs: coverage combine || true coverage report -i || true - name: Lint - if: matrix.python-version == '3.12' + if: matrix.python-version == '3.14' run: | python -m pip install -U pylint pylint src + - name: Test No ZODB + run: | + python -m pip uninstall -y ZODB zope.site persistent + python -m zope.testrunner --test-path=src --auto-color --auto-progress - name: Submit to Coveralls # This is a container action, which only runs on Linux. uses: AndreMiras/coveralls-python-action@develop diff --git a/CHANGES.rst b/CHANGES.rst index bcdbc17..381e153 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,10 +2,11 @@ Changes ========= -4.3.1 (unreleased) +4.4.0 (unreleased) ================== -- Nothing changed yet. +- Move ZODB and related dependencies to the optional 'zodb' extra. +- Add support for Python 3.14. 4.3.0 (2025-04-22) diff --git a/setup.py b/setup.py index 0042769..75bcaa8 100755 --- a/setup.py +++ b/setup.py @@ -13,7 +13,6 @@ TESTS_REQUIRE = [ 'Acquisition', - 'zope.site', 'zope.testrunner', 'testgres >= 1.11', 'psycopg2-binary; python_implementation != "PyPy"', @@ -47,6 +46,7 @@ def _read(fname): 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', 'Programming Language :: Python :: 3.13', + 'Programming Language :: Python :: 3.14', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Software Development :: Testing', @@ -56,7 +56,6 @@ def _read(fname): packages=find_namespace_packages(where='src'), package_dir={'': 'src'}, install_requires=[ - 'ZODB >= 5.6.0', # Error messages changed in 5.1, reprs changed <= 5.4 'zope.interface >= 5.4.0', 'pyhamcrest', @@ -72,7 +71,13 @@ def _read(fname): entry_points=entry_points, include_package_data=True, extras_require={ + 'zodb': [ + 'ZODB >= 5.6.0', + ], 'test': TESTS_REQUIRE, + 'test-zodb': [ + 'zope.site', + ], 'docs': [ 'Sphinx', 'furo', diff --git a/src/nti/testing/tests/test_base.py b/src/nti/testing/tests/test_base.py index fb25d01..29d9b6b 100644 --- a/src/nti/testing/tests/test_base.py +++ b/src/nti/testing/tests/test_base.py @@ -89,7 +89,10 @@ def test_thing(self): def test_configuring_base(self): - import zope.traversing.tests.test_traverser + try: + import zope.traversing.tests.test_traverser + except ModuleNotFoundError: + self.skipTest('zope.traversing not installed') class MyTest(base.ConfiguringTestBase): set_up_packages = ('zope.component', ('configure.zcml', 'zope.component'), @@ -104,7 +107,10 @@ def test_thing(self): mt.tearDown() # pylint:disable=no-value-for-parameter def test_shared_configuring_base(self): - import zope.traversing.tests.test_traverser + try: + import zope.traversing.tests.test_traverser + except ModuleNotFoundError: + self.skipTest('zope.traversing not installed') class MyTest(base.SharedConfiguringTestBase): layer = None # replaced by metaclass set_up_packages = ('zope.component', diff --git a/src/nti/testing/tests/test_main.py b/src/nti/testing/tests/test_main.py index d1327ad..3c53073 100644 --- a/src/nti/testing/tests/test_main.py +++ b/src/nti/testing/tests/test_main.py @@ -32,16 +32,22 @@ def test_suite(): here = os.path.dirname(__file__) suite = unittest.defaultTestLoader.loadTestsFromName(__name__) - suite.addTest(doctest.DocFileSuite( - 'test_component_cleanup_broken.txt')) + try: + import zope.site as has_zope_site + except ModuleNotFoundError: + has_zope_site = None + else: + suite.addTest(doctest.DocFileSuite( + 'test_component_cleanup_broken.txt')) readmedir = here while not os.path.exists(os.path.join(readmedir, 'setup.py')): readmedir = os.path.dirname(readmedir) readme = os.path.join(readmedir, 'README.rst') - suite.addTest(doctest.DocFileSuite( - readme, - module_relative=False, - optionflags=doctest.ELLIPSIS, - )) + if has_zope_site: + suite.addTest(doctest.DocFileSuite( + readme, + module_relative=False, + optionflags=doctest.ELLIPSIS, + )) return suite diff --git a/src/nti/testing/tests/test_zodb.py b/src/nti/testing/tests/test_zodb.py index 2a77698..abda355 100644 --- a/src/nti/testing/tests/test_zodb.py +++ b/src/nti/testing/tests/test_zodb.py @@ -14,7 +14,13 @@ import transaction from transaction.interfaces import NoTransaction from zope import interface -from nti.testing import zodb +try: + from nti.testing import zodb + base_mock_db_trans = zodb.mock_db_trans +except ModuleNotFoundError as ex: + assert ex.name == 'ZODB' + zodb = None + base_mock_db_trans = object # pylint:disable=protected-access,pointless-string-statement @@ -41,7 +47,7 @@ def cacheMinimize(self): self.minimized = True -class MockDBTrans(zodb.mock_db_trans): +class MockDBTrans(base_mock_db_trans): def __init__(self, db=None): if db is None: @@ -52,6 +58,8 @@ def __init__(self, db=None): class TestMockDBTrans(unittest.TestCase): def setUp(self): + if zodb is None: + self.skipTest("ZODB not installed") self._was_explicit = transaction.manager.explicit transaction.manager.explicit = False @@ -226,7 +234,7 @@ def __bool__(self): class MyMock(MockDBTrans): seen_tx = None aborted = False - def on_connection_opened(self, conn): + def on_connection_opened(self, _conn): # pylint:disable=no-member self.seen_tx = self._mock_db_trans__current_transaction abort = self.seen_tx.abort @@ -255,7 +263,13 @@ def _abort(): class TestZODBLayer(unittest.TestCase): - layer = zodb.ZODBLayer + if zodb is not None: + layer = zodb.ZODBLayer + + def setUp(self): + super().setUp() + if zodb is None: + self.skipTest("ZODB not installed") def test_registration(self): from ZODB.interfaces import IDatabase @@ -288,10 +302,14 @@ def __init__(self, *args): pass class TestResetDbCaches(unittest.TestCase): - layer = zodb.ZODBLayer + + if zodb is not None: + layer = zodb.ZODBLayer def setUp(self): super().setUp() + if zodb is None: + self.skipTest("ZODB not installed") gc.disable() def tearDown(self): diff --git a/tox.ini b/tox.ini index 67f3847..fb7253a 100644 --- a/tox.ini +++ b/tox.ini @@ -4,6 +4,8 @@ envlist = py38,py39,py310,py311,py312,pypy3,coverage,docs [testenv] extras = test + zodb + test-zodb commands = zope-testrunner --test-path=src --auto-color --auto-progress [] # substitute with tox positional args setenv = @@ -20,6 +22,10 @@ commands = deps = coverage +[testenv:py314] +extras = + test + [testenv:docs] commands = sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html