diff --git a/CHANGES.rst b/CHANGES.rst index 5109e11..5c13ce5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,6 +7,8 @@ - Drop support for Python 2.7, 3.5, 3.6. +- Drop support for deprecated ``python setup.py test.``. + 3.1.0 (2023-03-17) ================== diff --git a/setup.py b/setup.py index c4a24e5..383bae9 100644 --- a/setup.py +++ b/setup.py @@ -43,11 +43,7 @@ def _read_file(filename): "Operating System :: Microsoft :: Windows", "Operating System :: Unix", "Programming Language :: Python", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", @@ -57,8 +53,8 @@ def _read_file(filename): "Programming Language :: Python :: Implementation :: PyPy", "Framework :: ZODB", ], - author="Zope Corporation", - author_email="zodb-dev@zope.org", + author="Zope Foundation and Contributors", + author_email="zodb-dev@zope.dev", url="https://github.com/zopefoundation/transaction", project_urls={ 'Issue Tracker': ('https://github.com/zopefoundation/' @@ -71,17 +67,13 @@ def _read_file(filename): package_dir={'': 'src'}, include_package_data=True, zip_safe=False, - test_suite="transaction.tests", - tests_require=tests_require, - python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*', + python_requires='>=3.7', install_requires=[ 'zope.interface', ], extras_require={ 'docs': ['Sphinx', 'repoze.sphinx.autointerface'], 'test': tests_require, - 'testing': ['nose', 'coverage'] + tests_require, + 'testing': ['coverage'] + tests_require, }, - entry_points="""\ - """ ) diff --git a/src/transaction/__init__.py b/src/transaction/__init__.py index a5dbe87..b1292b9 100644 --- a/src/transaction/__init__.py +++ b/src/transaction/__init__.py @@ -26,10 +26,10 @@ #: A thread-safe `~ITransactionManager` from transaction._manager import ThreadTransactionManager -# NB: "with transaction:" does not work under Python 3 because they worked +# NB: "with transaction:" does not work because they worked # really hard to break looking up special methods like __enter__ and __exit__ -# via getattr and getattribute; see http://bugs.python.org/issue12022. On -# Python 3, you must use ``with transaction.manager`` instead. +# via getattr and getattribute; see http://bugs.python.org/issue12022. +# You must use ``with transaction.manager`` instead. #: The default transaction manager (a `~.ThreadTransactionManager`). All other #: functions in this module refer to this object. diff --git a/src/transaction/_compat.py b/src/transaction/_compat.py index 016717d..757cb19 100644 --- a/src/transaction/_compat.py +++ b/src/transaction/_compat.py @@ -1,75 +1,10 @@ -import sys - - -PY3 = sys.version_info[0] == 3 -JYTHON = sys.platform.startswith('java') - -if PY3: # pragma: no cover - text_type = str -else: # pragma: no cover - # py2 - text_type = unicode # noqa: F821 undefined name 'unicode' - - def text_(s): - if not isinstance(s, text_type): # pragma: no cover + if not isinstance(s, str): # pragma: no cover s = s.decode('utf-8') return s -if PY3: # pragma: no cover - def native_(s, encoding='latin-1', errors='strict'): - if isinstance(s, text_type): - return s - return str(s, encoding, errors) -else: # pragma: no cover - def native_(s, encoding='latin-1', errors='strict'): - if isinstance(s, text_type): - return s.encode(encoding, errors) - return str(s) - -if PY3: # pragma: no cover - from io import StringIO -else: # pragma: no cover - from io import BytesIO - - # Prevent crashes in IPython when writing tracebacks if a commit fails - # ref: - # https://github.com/ipython/ipython/issues/9126#issuecomment-174966638 - - class StringIO(BytesIO): - def write(self, s): - s = native_(s, encoding='utf-8') - super(StringIO, self).write(s) - - -if PY3: # pragma: no cover - def reraise(tp, value, tb=None): - if value.__traceback__ is not tb: # pragma: no cover - raise value.with_traceback(tb) - raise value - -else: # pragma: no cover - def exec_(code, globs=None, locs=None): - """Execute code in a namespace.""" - if globs is None: - frame = sys._getframe(1) - globs = frame.f_globals - if locs is None: - locs = frame.f_locals - del frame - elif locs is None: - locs = globs - exec("""exec code in globs, locs""") - - exec_("""def reraise(tp, value, tb=None): - raise tp, value, tb -""") - -# isort: off - -try: # pragma: no cover - from threading import get_ident as get_thread_ident -except ImportError: # pragma: no cover - # PY2 - from thread import get_ident as get_thread_ident # noqa: F401 unused +def native_(s, encoding='latin-1', errors='strict'): + if isinstance(s, str): + return s + return str(s, encoding, errors) diff --git a/src/transaction/_manager.py b/src/transaction/_manager.py index b5c0295..d8c0aa8 100644 --- a/src/transaction/_manager.py +++ b/src/transaction/_manager.py @@ -22,7 +22,6 @@ from zope.interface import implementer -from transaction._compat import reraise from transaction._compat import text_ from transaction._transaction import Transaction from transaction.interfaces import AlreadyInTransaction @@ -60,7 +59,7 @@ def _new_transaction(txn, synchs): @implementer(ITransactionManager) -class TransactionManager(object): +class TransactionManager: """Single-thread implementation of `~transaction.interfaces.ITransactionManager`. """ @@ -183,20 +182,18 @@ def run(self, func=None, tries=3): if tries <= 0: raise ValueError("tries must be > 0") - # These are ordinarily native strings, but that's + # These are ordinarily strings, but that's # not required. A callable class could override them - # to anything, and a Python 2.7 file could have - # imported `from __future__ import unicode_literals` - # which gets unicode docstrings. + # to anything. name = func.__name__ doc = func.__doc__ - name = text_(name) if name else u'' - doc = text_(doc) if doc else u'' + name = text_(name) if name else '' + doc = text_(doc) if doc else '' - if name and name != u'_': + if name and name != '_': if doc: - doc = name + u'\n\n' + doc + doc = name + '\n\n' + doc else: doc = name @@ -290,7 +287,7 @@ def run(self, func=None, tries=3): return self.manager.run(func, tries) -class Attempt(object): +class Attempt: success = False @@ -302,7 +299,7 @@ def _retry_or_raise(self, t, v, tb): self.manager.abort() if retry: return retry # suppress the exception if necessary - reraise(t, v, tb) # otherwise reraise the exception + raise v.with_traceback(tb) # otherwise reraise the exception def __enter__(self): return self.manager.__enter__() diff --git a/src/transaction/_transaction.py b/src/transaction/_transaction.py index 9508c38..173f2be 100644 --- a/src/transaction/_transaction.py +++ b/src/transaction/_transaction.py @@ -13,17 +13,15 @@ ############################################################################ import logging import sys +import threading import traceback import warnings import weakref +from io import StringIO from zope.interface import implementer from transaction import interfaces -from transaction._compat import StringIO -from transaction._compat import get_thread_ident -from transaction._compat import reraise -from transaction._compat import text_type from transaction.interfaces import TransactionFailedError from transaction.weakset import WeakSet @@ -45,10 +43,10 @@ def _makeTracebackBuffer(): # pragma NO COVER def _makeLogger(): # pragma NO COVER if _LOGGER is not None: return _LOGGER - return logging.getLogger("txn.%d" % get_thread_ident()) + return logging.getLogger("txn.%d" % threading.get_ident()) -class Status(object): +class Status: # ACTIVE is the initial state. ACTIVE = "Active" @@ -62,7 +60,7 @@ class Status(object): COMMITFAILED = "Commit failed" -class _NoSynchronizers(object): +class _NoSynchronizers: @staticmethod def map(_f): @@ -70,7 +68,7 @@ def map(_f): @implementer(interfaces.ITransaction) -class Transaction(object): +class Transaction: """Default implementation of `~transaction.interfaces.ITransaction`.""" # Assign an index to each savepoint so we can invalidate later savepoints @@ -84,8 +82,8 @@ class Transaction(object): # Meta data. extended_info is also metadata, but is initialized to an # empty dict in __init__. - _user = u"" - _description = u"" + _user = "" + _description = "" def __init__(self, synchronizers=None, manager=None): self.status = Status.ACTIVE @@ -190,8 +188,9 @@ def join(self, resource): self.status is not Status.DOOMED): # TODO: Should it be possible to join a committing transaction? # I think some users want it. - raise ValueError("expected txn status %r or %r, but it's %r" % ( - Status.ACTIVE, Status.DOOMED, self.status)) + raise ValueError( + f"expected txn status {Status.ACTIVE!r} or {Status.DOOMED!r}," + f" but it's {self.status!r}") self._resources.append(resource) if self._savepoint2index: @@ -280,7 +279,7 @@ def commit(self): try: t, v, tb = self._saveAndGetCommitishError() self._callAfterCommitHooks(status=False) - reraise(t, v, tb) + raise v.with_traceback(tb) finally: del t, v, tb else: @@ -314,7 +313,7 @@ def _saveAndRaiseCommitishError(self): tb = None try: t, v, tb = self._saveAndGetCommitishError() - reraise(t, v, tb) + raise v.with_traceback(tb) finally: del t, v, tb @@ -454,7 +453,7 @@ def _commitResources(self): self._cleanup(L) finally: self._synchronizers.map(lambda s: s.afterCompletion(self)) - reraise(t, v, tb) + raise v.with_traceback(tb) finally: del t, v, tb @@ -568,7 +567,7 @@ def abort(self): self.log.debug("abort") if tb is not None: - reraise(t, v, tb) + raise v.with_traceback(tb) finally: self._free() del t, v, tb @@ -578,13 +577,13 @@ def note(self, text): if text is not None: text = text_or_warn(text).strip() if self.description: - self.description += u"\n" + text + self.description += "\n" + text else: self.description = text - def setUser(self, user_name, path=u"/"): + def setUser(self, user_name, path="/"): """See `~transaction.interfaces.ITransaction`.""" - self.user = u"%s %s" % (text_or_warn(path), text_or_warn(user_name)) + self.user = "{} {}".format(text_or_warn(path), text_or_warn(user_name)) def setExtendedInfo(self, name, value): """See `~transaction.interfaces.ITransaction`.""" @@ -604,7 +603,7 @@ def rm_key(rm): @implementer(interfaces.ISavepoint) -class Savepoint(object): +class Savepoint: """Implementation of `~transaction.interfaces.ISavepoint`, a transaction savepoint. @@ -648,7 +647,7 @@ def rollback(self): transaction._saveAndRaiseCommitishError() # reraises! -class AbortSavepoint(object): +class AbortSavepoint: def __init__(self, datamanager, transaction): self.datamanager = datamanager @@ -659,7 +658,7 @@ def rollback(self): self.transaction._unjoin(self.datamanager) -class NoRollbackSavepoint(object): +class NoRollbackSavepoint: def __init__(self, datamanager): self.datamanager = datamanager @@ -669,11 +668,11 @@ def rollback(self): def text_or_warn(s): - if isinstance(s, text_type): + if isinstance(s, str): return s warnings.warn("Expected text", DeprecationWarning, stacklevel=3) if isinstance(s, bytes): return s.decode('utf-8', 'replace') else: - return text_type(s) + return str(s) diff --git a/src/transaction/tests/common.py b/src/transaction/tests/common.py index 2a753f0..8f566a2 100644 --- a/src/transaction/tests/common.py +++ b/src/transaction/tests/common.py @@ -13,7 +13,7 @@ ############################################################################## -class DummyFile(object): +class DummyFile: def __init__(self): self._lines = [] @@ -24,7 +24,7 @@ def writelines(self, lines): self._lines.extend(lines) -class DummyLogger(object): +class DummyLogger: def __init__(self): self._clear() @@ -47,7 +47,7 @@ def critical(self, msg, *args, **kw): self.log('critical', msg, *args, **kw) -class Monkey(object): +class Monkey: # context-manager for replacing module names in the scope of a test. def __init__(self, module, **kw): self.module = module diff --git a/src/transaction/tests/examples.py b/src/transaction/tests/examples.py index 344c3e0..c25b28d 100644 --- a/src/transaction/tests/examples.py +++ b/src/transaction/tests/examples.py @@ -16,7 +16,7 @@ """ -class DataManager(object): +class DataManager: """ Sample data manager. Used by the 'datamanager' chapter in the Sphinx docs. @@ -100,7 +100,7 @@ def commit(self, transaction): self.transaction = None -class SavePoint(object): +class SavePoint: def __init__(self, rm): self.rm = rm diff --git a/src/transaction/tests/savepointsample.py b/src/transaction/tests/savepointsample.py index f6a4565..dd67283 100644 --- a/src/transaction/tests/savepointsample.py +++ b/src/transaction/tests/savepointsample.py @@ -25,7 +25,7 @@ @implementer(transaction.interfaces.IDataManager) -class SampleDataManager(object): +class SampleDataManager: """Sample implementation of data manager that doesn't support savepoints This data manager stores named simple values, like strings and numbers. diff --git a/src/transaction/tests/test__manager.py b/src/transaction/tests/test__manager.py index 9c25518..073c75d 100644 --- a/src/transaction/tests/test__manager.py +++ b/src/transaction/tests/test__manager.py @@ -12,8 +12,8 @@ # ############################################################################## import unittest +from unittest import mock -import mock import zope.interface.verify from .. import interfaces @@ -61,7 +61,7 @@ def test_begin_wo_existing_txn_w_synchs(self): self.assertTrue(tm._txn in synch._txns) def test_begin_w_existing_txn(self): - class Existing(object): + class Existing: _aborted = False def abort(self): @@ -79,7 +79,7 @@ def test_get_wo_existing_txn(self): self.assertTrue(isinstance(txn, Transaction)) def test_get_w_existing_txn(self): - class Existing(object): + class Existing: _aborted = False def abort(self): @@ -96,7 +96,7 @@ def test_free_w_other_txn(self): self.assertRaises(ValueError, tm.free, txn) def test_free_w_existing_txn(self): - class Existing(object): + class Existing: _aborted = False def abort(self): @@ -146,7 +146,7 @@ def test_isDoomed_wo_existing_txn(self): self.assertTrue(tm.isDoomed()) def test_isDoomed_w_existing_txn(self): - class Existing(object): + class Existing: _doomed = False def isDoomed(self): @@ -166,7 +166,7 @@ def test_doom(self): self.assertTrue(tm.isDoomed()) def test_commit_w_existing_txn(self): - class Existing(object): + class Existing: _committed = False def commit(self): @@ -177,7 +177,7 @@ def commit(self): self.assertTrue(txn._committed) def test_abort_w_existing_txn(self): - class Existing(object): + class Existing: _aborted = False def abort(self): @@ -188,7 +188,7 @@ def abort(self): self.assertTrue(txn._aborted) def test_as_context_manager_wo_error(self): - class _Test(object): + class _Test: _committed = False _aborted = False @@ -204,7 +204,7 @@ def abort(self): self.assertFalse(txn._aborted) def test_as_context_manager_w_error(self): - class _Test(object): + class _Test: _committed = False _aborted = False @@ -224,7 +224,7 @@ def abort(self): self.assertTrue(txn._aborted) def test_savepoint_default(self): - class _Test(object): + class _Test: _sp = None def savepoint(self, optimistic): @@ -235,7 +235,7 @@ def savepoint(self, optimistic): self.assertFalse(txn._sp) def test_savepoint_explicit(self): - class _Test(object): + class _Test: _sp = None def savepoint(self, optimistic): @@ -458,7 +458,7 @@ def _(): def test_run_callable_with_bytes_doc(self): import transaction - class Callable(object): + class Callable: def __init__(self): self.__doc__ = b'some bytes' @@ -488,7 +488,7 @@ def test__retryable_w_normal_exception_no_resources(self): self.assertFalse(tm._retryable(Exception, object())) def test__retryable_w_normal_exception_w_resource_voting_yes(self): - class _Resource(object): + class _Resource: def should_retry(self, err): return True tm = self._makeOne() @@ -496,7 +496,7 @@ def should_retry(self, err): self.assertTrue(tm._retryable(Exception, object())) def test__retryable_w_multiple(self): - class _Resource(object): + class _Resource: _should = True def should_retry(self, err): @@ -671,7 +671,7 @@ def test_notify_transaction_late_comers(self): # If a datamanager registers for synchonization after a # transaction has started, we should call newTransaction so it # can do necessry setup. - import mock + from unittest import mock from .. import TransactionManager manager = TransactionManager() @@ -899,7 +899,7 @@ def test_explicit_mode(self): tm.commit() -class DummyManager(object): +class DummyManager: entered = False committed = False aborted = False @@ -946,7 +946,7 @@ class TestTxnException(Exception): pass -class BasicJar(object): +class BasicJar: def __init__(self, errors=(), tracing=0): if not isinstance(errors, tuple): @@ -963,9 +963,8 @@ def __init__(self, errors=(), tracing=0): self.ccommit_sub = 0 def __repr__(self): - return "<%s %X %s>" % (self.__class__.__name__, - positive_id(self), - self.errors) + return "<{} {:X} {}>".format( + self.__class__.__name__, positive_id(self), self.errors) def sortKey(self): # All these jars use the same sort key, and Python's list.sort() @@ -974,7 +973,7 @@ def sortKey(self): def check(self, method): if self.tracing: # pragma: no cover - print('%s calling method %s' % (str(self.tracing), method)) + print('{} calling method {}'.format(str(self.tracing), method)) if method in self.errors: raise TestTxnException("error %s" % method) @@ -1006,7 +1005,7 @@ def tpc_finish(self, *args): self.ctpc_finish += 1 -class DummySynch(object): +class DummySynch: def __init__(self): self._txns = set() diff --git a/src/transaction/tests/test__transaction.py b/src/transaction/tests/test__transaction.py index 6a2e2b4..4f1258c 100644 --- a/src/transaction/tests/test__transaction.py +++ b/src/transaction/tests/test__transaction.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- ############################################################################## # # Copyright (c) 2001, 2002, 2005 Zope Foundation and Contributors. @@ -74,8 +73,8 @@ def test_ctor_defaults(self): self.assertTrue(isinstance(txn._synchronizers, WeakSet)) self.assertEqual(len(txn._synchronizers), 0) self.assertTrue(txn._manager is None) - self.assertEqual(txn.user, u"") - self.assertEqual(txn.description, u"") + self.assertEqual(txn.user, "") + self.assertEqual(txn.description, "") self.assertTrue(txn._savepoint2index is None) self.assertEqual(txn._savepoint_index, 0) self.assertEqual(txn._resources, []) @@ -129,7 +128,7 @@ def test_doom_already_doomed(self): def test__prior_operation_failed(self): from transaction.interfaces import TransactionFailedError - class _Traceback(object): + class _Traceback: def getvalue(self): return 'TRACEBACK' txn = self._makeOne() @@ -144,7 +143,7 @@ def test_join_COMMITFAILED(self): from transaction._transaction import Status from transaction.interfaces import TransactionFailedError - class _Traceback(object): + class _Traceback: def getvalue(self): return 'TRACEBACK' txn = self._makeOne() @@ -187,7 +186,7 @@ def test_savepoint_COMMITFAILED(self): from transaction._transaction import Status from transaction.interfaces import TransactionFailedError - class _Traceback(object): + class _Traceback: def getvalue(self): return 'TRACEBACK' txn = self._makeOne() @@ -214,8 +213,9 @@ def test_savepoint_empty(self): self.assertEqual(txn._savepoint2index[sp], 1) def test_savepoint_non_optimistc_resource_wo_support(self): + from io import StringIO + from transaction import _transaction - from transaction._compat import StringIO from transaction._transaction import Status from transaction.tests.common import DummyLogger from transaction.tests.common import Monkey @@ -240,7 +240,7 @@ def test__remove_and_invalidate_after_miss(self): txn = self._makeOne() txn._savepoint2index = WeakKeyDictionary() - class _SP(object): + class _SP: def __init__(self, txn): self.transaction = txn holdme = [] @@ -257,7 +257,7 @@ def test__remove_and_invalidate_after_hit(self): txn = self._makeOne() txn._savepoint2index = WeakKeyDictionary() - class _SP(object): + class _SP: def __init__(self, txn, index): self.transaction = txn self._index = index @@ -281,7 +281,7 @@ def test__invalidate_all_savepoints(self): txn = self._makeOne() txn._savepoint2index = WeakKeyDictionary() - class _SP(object): + class _SP: def __init__(self, txn, index): self.transaction = txn self._index = index @@ -308,7 +308,7 @@ def test_commit_COMMITFAILED(self): from transaction._transaction import Status from transaction.interfaces import TransactionFailedError - class _Traceback(object): + class _Traceback: def getvalue(self): return 'TRACEBACK' txn = self._makeOne() @@ -322,7 +322,7 @@ def test_commit_wo_savepoints_wo_hooks_wo_synchronizers(self): from transaction.tests.common import DummyLogger from transaction.tests.common import Monkey - class _Mgr(object): + class _Mgr: def __init__(self, txn): self._txn = txn @@ -347,7 +347,7 @@ def test_commit_w_savepoints(self): from transaction.tests.common import DummyLogger from transaction.tests.common import Monkey - class _SP(object): + class _SP: def __init__(self, txn, index): self.transaction = txn self._index = index @@ -395,7 +395,7 @@ def test_commit_w_synchronizers(self): from transaction.tests.common import Monkey from transaction.weakset import WeakSet - class _Synch(object): + class _Synch: _before = _after = False def beforeCompletion(self, txn): @@ -444,7 +444,7 @@ def test_commit_error_w_afterCompleteHooks(self): from transaction.tests.common import DummyLogger from transaction.tests.common import Monkey - class BrokenResource(object): + class BrokenResource: def sortKey(self): return 'zzz' @@ -484,7 +484,7 @@ def test_commit_error_w_synchronizers(self): from transaction.tests.common import Monkey from transaction.weakset import WeakSet - class _Synch(object): + class _Synch: _before = _after = False def beforeCompletion(self, txn): @@ -497,7 +497,7 @@ def afterCompletion(self, txn): for synch in synchs: ws.add(synch) - class BrokenResource(object): + class BrokenResource: def sortKey(self): return 'zzz' @@ -515,7 +515,7 @@ def tpc_begin(self, txn): self.assertTrue(synch._after is txn) # called in _cleanup def test_commit_clears_resources(self): - class DM(object): + class DM: tpc_begin = commit = tpc_finish = tpc_vote = lambda s, txn: True dm = DM() @@ -682,7 +682,7 @@ def test__commitResources_error_in_afterCompletion(self): from transaction.tests.common import DummyLogger from transaction.tests.common import Monkey - class _Synchronizers(object): + class _Synchronizers: def __init__(self, res): self._res = res @@ -797,7 +797,7 @@ def test_abort_wo_savepoints_wo_hooks_wo_synchronizers(self): from transaction.tests.common import DummyLogger from transaction.tests.common import Monkey - class _Mgr(object): + class _Mgr: def __init__(self, txn): self._txn = txn @@ -822,7 +822,7 @@ def test_abort_w_savepoints(self): from transaction.tests.common import DummyLogger from transaction.tests.common import Monkey - class _SP(object): + class _SP: def __init__(self, txn, index): self.transaction = txn self._index = index @@ -872,7 +872,7 @@ def test_abort_w_synchronizers(self): from transaction.tests.common import Monkey test = self - class _Synch(object): + class _Synch: _before = _after = None def beforeCompletion(self, txn): @@ -893,7 +893,7 @@ def afterCompletion(self, txn): raise SystemExit # Ensure iteration order - class Synchs(object): + class Synchs: synchs = [_Synch(), _Synch(), _Synch(), _BadSynch()] def map(self, func): @@ -902,7 +902,7 @@ def map(self, func): logger = DummyLogger() - class Manager(object): + class Manager: txn = None def free(self, txn): @@ -959,7 +959,7 @@ def test_abort_error_w_afterCommitHooks(self): from transaction.tests.common import DummyLogger from transaction.tests.common import Monkey - class BrokenResource(object): + class BrokenResource: def sortKey(self): raise AssertionError("Not called") @@ -999,7 +999,7 @@ def test_abort_error_w_synchronizers(self): from transaction.tests.common import Monkey from transaction.weakset import WeakSet - class _Synch(object): + class _Synch: _before = _after = False def beforeCompletion(self, txn): @@ -1012,7 +1012,7 @@ def afterCompletion(self, txn): for synch in synchs: ws.add(synch) - class BrokenResource(object): + class BrokenResource: def sortKey(self): raise AssertionError("Should not be called") @@ -1035,7 +1035,7 @@ def test_abort_synchronizer_error_w_resources(self): from transaction.tests.common import DummyLogger from transaction.tests.common import Monkey - class _Synch(object): + class _Synch: _before = _after = False def beforeCompletion(self, txn): @@ -1050,7 +1050,7 @@ def beforeCompletion(self, txn): raise SystemExit # Ensure iteration order - class Synchs(object): + class Synchs: synchs = [_Synch(), _Synch(), _Synch(), _BadSynch()] def map(self, func): @@ -1074,7 +1074,7 @@ def map(self, func): self.assertTrue(resource._a) def test_abort_clears_resources(self): - class DM(object): + class DM: def abort(self, txn): return True @@ -1271,10 +1271,10 @@ def aah(): def test_note(self): txn = self._makeOne() try: - txn.note(u'This is a note.') - self.assertEqual(txn.description, u'This is a note.') - txn.note(u'Another.') - self.assertEqual(txn.description, u'This is a note.\nAnother.') + txn.note('This is a note.') + self.assertEqual(txn.description, 'This is a note.') + txn.note('Another.') + self.assertEqual(txn.description, 'This is a note.\nAnother.') finally: txn.abort() @@ -1284,16 +1284,16 @@ def test_note_bytes(self): warnings.simplefilter("always") txn.note(b'haha') self.assertNonTextDeprecationWarning(w) - self.assertEqual(txn.description, u'haha') + self.assertEqual(txn.description, 'haha') def test_note_None(self): txn = self._makeOne() - self.assertEqual(u'', txn.description) + self.assertEqual('', txn.description) with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") txn.note(None) self.assertFalse(w) - self.assertEqual(txn.description, u'') + self.assertEqual(txn.description, '') def test_note_42(self): txn = self._makeOne() @@ -1301,7 +1301,7 @@ def test_note_42(self): warnings.simplefilter("always") txn.note(42) self.assertNonTextDeprecationWarning(w) - self.assertEqual(txn.description, u'42') + self.assertEqual(txn.description, '42') def assertNonTextDeprecationWarning(self, w): [w] = w @@ -1317,7 +1317,7 @@ def test_description_bytes(self): warnings.simplefilter("always") txn.description = b'haha' self.assertNonTextDeprecationWarning(w) - self.assertEqual(txn.description, u'haha') + self.assertEqual(txn.description, 'haha') def test_description_42(self): txn = self._makeOne() @@ -1325,33 +1325,33 @@ def test_description_42(self): warnings.simplefilter("always") txn.description = 42 self.assertNonTextDeprecationWarning(w) - self.assertEqual(txn.description, u'42') + self.assertEqual(txn.description, '42') def test_description_None(self): txn = self._makeOne() - self.assertEqual(u'', txn.description) + self.assertEqual('', txn.description) with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") txn.description = None self.assertFalse(w) - self.assertEqual(txn.description, u'') + self.assertEqual(txn.description, '') def test_setUser_default_path(self): txn = self._makeOne() - txn.setUser(u'phreddy') - self.assertEqual(txn.user, u'/ phreddy') + txn.setUser('phreddy') + self.assertEqual(txn.user, '/ phreddy') def test_setUser_explicit_path(self): txn = self._makeOne() - txn.setUser(u'phreddy', u'/bedrock') - self.assertEqual(txn.user, u'/bedrock phreddy') + txn.setUser('phreddy', '/bedrock') + self.assertEqual(txn.user, '/bedrock phreddy') def test_user_w_none(self): txn = self._makeOne() - txn.user = u'phreddy' + txn.user = 'phreddy' with self.assertRaises(ValueError): txn.user = None # raises - self.assertEqual(txn.user, u'phreddy') + self.assertEqual(txn.user, 'phreddy') def _test_user_non_text(self, user, path, expect, both=False): txn = self._makeOne() @@ -1374,21 +1374,21 @@ def _test_user_non_text(self, user, path, expect, both=False): self.assertEqual(expect, txn.user) def test_user_non_text(self, user=b'phreddy', path=b'/bedrock', - expect=u"/bedrock phreddy", both=True): + expect="/bedrock phreddy", both=True): self._test_user_non_text(b'phreddy', b'/bedrock', - u"/bedrock phreddy", True) - self._test_user_non_text(b'phreddy', None, u'/ phreddy') - self._test_user_non_text(b'phreddy', False, u'phreddy') - self._test_user_non_text(b'phreddy', u'/bedrock', u'/bedrock phreddy') - self._test_user_non_text(u'phreddy', b'/bedrock', u'/bedrock phreddy') - self._test_user_non_text(u'phreddy', 2, u'2 phreddy') - self._test_user_non_text(1, u'/bedrock', u'/bedrock 1') - self._test_user_non_text(1, 2, u'2 1', True) + "/bedrock phreddy", True) + self._test_user_non_text(b'phreddy', None, '/ phreddy') + self._test_user_non_text(b'phreddy', False, 'phreddy') + self._test_user_non_text(b'phreddy', '/bedrock', '/bedrock phreddy') + self._test_user_non_text('phreddy', b'/bedrock', '/bedrock phreddy') + self._test_user_non_text('phreddy', 2, '2 phreddy') + self._test_user_non_text(1, '/bedrock', '/bedrock 1') + self._test_user_non_text(1, 2, '2 1', True) def test_setExtendedInfo_single(self): txn = self._makeOne() txn.setExtendedInfo('frob', 'qux') - self.assertEqual(txn.extension, {u'frob': 'qux'}) + self.assertEqual(txn.extension, {'frob': 'qux'}) self.assertTrue(txn._extension is txn._extension) # legacy def test_setExtendedInfo_multiple(self): @@ -1396,7 +1396,7 @@ def test_setExtendedInfo_multiple(self): txn.setExtendedInfo('frob', 'qux') txn.setExtendedInfo('baz', 'spam') txn.setExtendedInfo('frob', 'quxxxx') - self.assertEqual(txn._extension, {u'frob': 'quxxxx', u'baz': 'spam'}) + self.assertEqual(txn._extension, {'frob': 'quxxxx', 'baz': 'spam'}) self.assertTrue(txn._extension is txn._extension) # legacy def test__extension_settable(self): @@ -1405,7 +1405,7 @@ def test__extension_settable(self): txn = self._makeOne() txn._extension = dict(baz='spam') txn.setExtendedInfo('frob', 'qux') - self.assertEqual(txn.extension, {u'frob': 'qux', 'baz': 'spam'}) + self.assertEqual(txn.extension, {'frob': 'qux', 'baz': 'spam'}) def test_data(self): txn = self._makeOne() @@ -1456,7 +1456,7 @@ def test_isRetryableError_w_normal_exception_no_resources(self): def test_isRetryableError_w_normal_exception_w_resource_voting_yes(self): from transaction._manager import TransactionManager - class _Resource(object): + class _Resource: def should_retry(self, err): return True txn = self._makeOne(manager=TransactionManager()) @@ -1467,7 +1467,7 @@ def should_retry(self, err): def test_isRetryableError_w_multiple(self): from transaction._manager import TransactionManager - class _Resource(object): + class _Resource: _should = True def should_retry(self, err): @@ -1519,7 +1519,7 @@ def test_ctor_w_savepoint_oblivious_resource_optimistic(self): self.assertTrue(sp._savepoints[0].datamanager is resource) def test_ctor_w_savepoint_aware_resources(self): - class _Aware(object): + class _Aware: def savepoint(self): return self txn = object() @@ -1544,7 +1544,7 @@ def test_rollback_w_txn_None(self): from transaction.interfaces import InvalidSavepointRollbackError txn = None - class _Aware(object): + class _Aware: def savepoint(self): return self resource = _Aware() @@ -1552,26 +1552,26 @@ def savepoint(self): self.assertRaises(InvalidSavepointRollbackError, sp.rollback) def test_rollback_w_sp_error(self): - class _TXN(object): + class _TXN: _sarce = False _raia = None def _saveAndRaiseCommitishError(self): import sys - from transaction._compat import reraise self._sarce = True - reraise(*sys.exc_info()) + _, v, tb = sys.exc_info() + raise v.with_traceback(tb) def _remove_and_invalidate_after(self, sp): self._raia = sp - class _Broken(object): + class _Broken: def rollback(self): raise ValueError() _broken = _Broken() - class _GonnaRaise(object): + class _GonnaRaise: def savepoint(self): return _broken txn = _TXN() @@ -1599,13 +1599,13 @@ def test_ctor(self): self.assertTrue(asp.transaction is txn) def test_rollback(self): - class _DM(object): + class _DM: _aborted = None def abort(self, txn): self._aborted = txn - class _TXN(object): + class _TXN: _unjoined = None def _unjoin(self, datamanager): @@ -1650,7 +1650,7 @@ def test_bug239086(self): dm = SPS.SampleSavepointDataManager() self.assertEqual(list(dm.keys()), []) - class Sync(object): + class Sync: def __init__(self, label): self.label = label self.log = [] @@ -1662,7 +1662,7 @@ def afterCompletion(self, txn): raise AssertionError("Not called") def newTransaction(self, txn): - self.log.append('%s %s' % (self.label, 'new')) + self.log.append('{} {}'.format(self.label, 'new')) def run_in_thread(f): txn = threading.Thread(target=f) @@ -1701,14 +1701,14 @@ def test_gh5(self): buffer = _transaction._makeTracebackBuffer() - s = u'ąčę' + s = 'ąčę' buffer.write(s) buffer.seek(0) self.assertEqual(buffer.read(), native_(s, 'utf-8')) -class Resource(object): +class Resource: _b = _c = _v = _f = _a = _x = _after = False def __init__(self, key, error=None): diff --git a/src/transaction/tests/test_weakset.py b/src/transaction/tests/test_weakset.py index 21de2bb..ad32dea 100644 --- a/src/transaction/tests/test_weakset.py +++ b/src/transaction/tests/test_weakset.py @@ -11,10 +11,9 @@ # FOR A PARTICULAR PURPOSE # ############################################################################## +import sys import unittest -from transaction._compat import JYTHON - class WeakSetTests(unittest.TestCase): def test_contains(self): @@ -38,7 +37,7 @@ def test_len(self): self.assertEqual(len(w), 2) del d1 gc.collect() - if JYTHON: + if sys.platform.startswith('java'): # The Jython GC is non deterministic pass # pragma: no cover else: @@ -84,7 +83,7 @@ def test_as_weakref_list(self): L = [x() for x in refs] # L is a list, but it does not have a guaranteed order. self.assertTrue(list, type(L)) - self.assertEqual(set(L), set([dummy, dummy2])) + self.assertEqual(set(L), {dummy, dummy2}) def test_map(self): from transaction.weakset import WeakSet @@ -137,4 +136,4 @@ class Dummy: def test_suite(): - return unittest.makeSuite(WeakSetTests) + return unittest.defaultTestLoader.loadTestsFromTestCase(WeakSetTests) diff --git a/src/transaction/weakset.py b/src/transaction/weakset.py index 38d62ea..a8aab0f 100644 --- a/src/transaction/weakset.py +++ b/src/transaction/weakset.py @@ -19,7 +19,7 @@ # sets.Set interface for our needs. -class WeakSet(object): +class WeakSet: """A set of objects that doesn't keep its elements alive. The objects in the set must be weakly referencable.