From f4840e324997817468a1f878cc1ae08d81440be7 Mon Sep 17 00:00:00 2001 From: ejd Date: Wed, 2 Jan 2019 21:26:12 -0500 Subject: [PATCH 1/3] py3: update CloseableQueue and tests to enable use under Python 3 In `CloseableQueue.py`, the imports are now wrapped in a try/except block. The new Python 3 imports are done in the `try` clause and the original Python 2 imports are left intact under the `except` clause. To update the tests, used a [recent version of test_queue.py][1] as a reference to find out how the mainline copy evolved since the creation of CloseableQueue. I integrated the changes that allowed the test cases to run without crashing. [1]: https://github.com/python/cpython/blob/v3.7.2/Lib/test/test_queue.py --- CloseableQueue.py | 8 ++++++-- test/__init__.py | 10 +++++----- test/test_queue.py | 31 ++++++++++++++++++------------- test/test_support.py | 9 +++++---- 4 files changed, 34 insertions(+), 24 deletions(-) diff --git a/CloseableQueue.py b/CloseableQueue.py index 38d1a32..6ef8a55 100644 --- a/CloseableQueue.py +++ b/CloseableQueue.py @@ -1,7 +1,11 @@ """Defines the CloseableQueue class and the Close exception class.""" -from Queue import Empty, Full, _time -import Queue as _Queue +try: + from queue import Empty, Full, time as _time + import queue as _Queue +except ImportError: + from Queue import Empty, Full, _time + import Queue as _Queue class Closed(Exception): """Exception raised by CloseableQueue.put/get on a closed queue.""" diff --git a/test/__init__.py b/test/__init__.py index c25edd2..be0c9e8 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -14,8 +14,8 @@ """ from CloseableQueue import CloseableQueue, Closed from CloseableQueue import CloseableLifoQueue, CloseablePriorityQueue -from test_queue import BlockingTestMixin, BaseQueueTest -from test_queue import FailingQueue, FailingQueueTest +from .test_queue import BlockingTestMixin, BaseQueueTest +from .test_queue import FailingQueue, FailingQueueTest import unittest # Because the method queue_test.BaseQueueTest.simple_queue_test @@ -64,12 +64,12 @@ def __init__(self, *args): def _put(self, item): if self.fail_next_put: self.fail_next_put = False - raise FailingQueueException, "You Lose" + raise FailingQueueException("You Lose") return CloseableQueue._put(self, item) def _get(self): if self.fail_next_get: self.fail_next_get = False - raise FailingQueueException, "You Lose" + raise FailingQueueException("You Lose") return CloseableQueue._get(self) class FailingCloseableQueueTest(FailingQueueTest): @@ -252,7 +252,7 @@ def test_join_after_close(self): self.cum = 0 for i in (0,1): threading.Thread(target=self.worker, args=(q,)).start() - for i in xrange(100): + for i in range(100): q.put(i) q.close() q.join() diff --git a/test/test_queue.py b/test/test_queue.py index e0eb8f4..1b11c43 100644 --- a/test/test_queue.py +++ b/test/test_queue.py @@ -1,6 +1,9 @@ # Some simple queue module tests, plus some failure conditions # to ensure the Queue locks remain stable. -import Queue +try: + import queue as Queue +except ImportError: + import Queue import sys import threading import time @@ -87,7 +90,7 @@ def setUp(self): def simple_queue_test(self, q): if not q.empty(): - raise RuntimeError, "Call this function with an empty queue" + raise RuntimeError("Call this function with an empty queue") # I guess we better check things actually queue correctly a little :) q.put(111) q.put(333) @@ -102,21 +105,23 @@ def simple_queue_test(self, q): q.put(i) self.assert_(not q.empty(), "Queue should not be empty") self.assert_(not q.full(), "Queue should not be full") - q.put("last") + last = 2 * QUEUE_SIZE + full = 3 * 2 * QUEUE_SIZE + q.put(last) self.assert_(q.full(), "Queue should be full") try: - q.put("full", block=0) + q.put(full, block=0) self.fail("Didn't appear to block with a full queue") except Queue.Full: pass try: - q.put("full", timeout=0.01) + q.put(full, timeout=0.01) self.fail("Didn't appear to time-out with a full queue") except Queue.Full: pass # Test a blocking put - self.do_blocking_test(q.put, ("full",), q.get, ()) - self.do_blocking_test(q.put, ("full", True, 10), q.get, ()) + self.do_blocking_test(q.put, (full,), q.get, ()) + self.do_blocking_test(q.put, (full, True, 10), q.get, ()) # Empty it for i in range(QUEUE_SIZE): q.get() @@ -139,7 +144,7 @@ def simple_queue_test(self, q): def worker(self, q): while True: x = q.get() - if x is None: + if x < 0: q.task_done() return with self.cumlock: @@ -150,13 +155,13 @@ def queue_join_test(self, q): self.cum = 0 for i in (0,1): threading.Thread(target=self.worker, args=(q,)).start() - for i in xrange(100): + for i in range(100): q.put(i) q.join() self.assertEquals(self.cum, sum(range(100)), "q.join() did not block until all tasks were done") for i in (0,1): - q.put(None) # instruct the threads to close + q.put(-1) # instruct the threads to close q.join() # verify that you can join twice def test_queue_task_done(self): @@ -213,19 +218,19 @@ def __init__(self, *args): def _put(self, item): if self.fail_next_put: self.fail_next_put = False - raise FailingQueueException, "You Lose" + raise FailingQueueException("You Lose") return Queue.Queue._put(self, item) def _get(self): if self.fail_next_get: self.fail_next_get = False - raise FailingQueueException, "You Lose" + raise FailingQueueException("You Lose") return Queue.Queue._get(self) class FailingQueueTest(unittest.TestCase, BlockingTestMixin): def failing_queue_test(self, q): if not q.empty(): - raise RuntimeError, "Call this function with an empty queue" + raise RuntimeError("Call this function with an empty queue") for i in range(QUEUE_SIZE-1): q.put(i) # Test a failing non-blocking put. diff --git a/test/test_support.py b/test/test_support.py index d4b891e..b4c3cb3 100644 --- a/test/test_support.py +++ b/test/test_support.py @@ -1,4 +1,5 @@ """Supporting definitions for the Python regression tests.""" +from __future__ import print_function if __name__ != 'test.test_support': raise ImportError('test_support must be imported from the test package') @@ -95,7 +96,7 @@ def unlink(filename): def rmtree(path): try: shutil.rmtree(path) - except OSError, e: + except (OSError) as e: # Unix returns ENOENT, Windows returns ESRCH. if e.errno not in (errno.ENOENT, errno.ESRCH): raise @@ -289,10 +290,10 @@ def fcmp(x, y): # fuzzy comparison function except UnicodeEncodeError: pass else: - print \ + print(\ 'WARNING: The filename %r CAN be encoded by the filesystem. ' \ 'Unicode filename tests may not be effective' \ - % TESTFN_UNICODE_UNENCODEABLE + % TESTFN_UNICODE_UNENCODEABLE) # Make sure we can write to TESTFN, try in /tmp if we can't fp = None @@ -763,7 +764,7 @@ def run_doctest(module, verbosity=None): finally: sys.stdout = save_stdout if verbose: - print 'doctest (%s) ... %d tests with zero failures' % (module.__name__, t) + print('doctest (%s) ... %d tests with zero failures' % (module.__name__, t)) return f, t #======================================================================= From 818f7bd8cbb538cb936e5284b47972c83e219578 Mon Sep 17 00:00:00 2001 From: ejd Date: Wed, 2 Jan 2019 22:23:47 -0500 Subject: [PATCH 2/3] py3: eliminate DeprecationWarnings In `CloseableQueue.py`, replace `raise StopIteration` with `return`, since [these are equivalent][1]. The deprecation is related to [PEP 479][2]. In the tests, `assertEquals` and `assert_` were replaced with `assertEqual` and `assertTrue`, respectively. The old names were [deprecated in Python 3.2][3]. [1]: https://docs.python.org/2/reference/simple_stmts.html#the-return-statement [2]: https://www.python.org/dev/peps/pep-0479/ [3]: https://docs.python.org/3/library/unittest.html?highlight=unittest#deprecated-aliases --- CloseableQueue.py | 4 ++-- test/__init__.py | 4 ++-- test/test_queue.py | 36 ++++++++++++++++++------------------ 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/CloseableQueue.py b/CloseableQueue.py index 6ef8a55..74569dd 100644 --- a/CloseableQueue.py +++ b/CloseableQueue.py @@ -184,12 +184,12 @@ def dequeue(q, getargs={}, on_empty='stop'): while True: yield q.get(**getargs) except Closed: - raise StopIteration + return except Empty: if on_empty == 'raise': raise elif on_empty == 'stop': - raise StopIteration + return else: yield on_empty diff --git a/test/__init__.py b/test/__init__.py index be0c9e8..a08bd52 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -256,8 +256,8 @@ def test_join_after_close(self): q.put(i) q.close() q.join() - self.assertEquals(self.cum, sum(range(100)), - "q.join() did not block until all tasks were done") + self.assertEqual(self.cum, sum(range(100)), + "q.join() did not block until all tasks were done") try: for i in (0,1): q.put(None) # instruct the threads to close diff --git a/test/test_queue.py b/test/test_queue.py index 1b11c43..85d0deb 100644 --- a/test/test_queue.py +++ b/test/test_queue.py @@ -99,16 +99,16 @@ def simple_queue_test(self, q): LifoQueue = [222, 333, 111], PriorityQueue = [111, 222, 333]) actual_order = [q.get(), q.get(), q.get()] - self.assertEquals(actual_order, target_order[q.__class__.__name__], - "Didn't seem to queue the correct data!") + self.assertEqual(actual_order, target_order[q.__class__.__name__], + "Didn't seem to queue the correct data!") for i in range(QUEUE_SIZE-1): q.put(i) - self.assert_(not q.empty(), "Queue should not be empty") - self.assert_(not q.full(), "Queue should not be full") + self.assertTrue(not q.empty(), "Queue should not be empty") + self.assertTrue(not q.full(), "Queue should not be full") last = 2 * QUEUE_SIZE full = 3 * 2 * QUEUE_SIZE q.put(last) - self.assert_(q.full(), "Queue should be full") + self.assertTrue(q.full(), "Queue should be full") try: q.put(full, block=0) self.fail("Didn't appear to block with a full queue") @@ -125,7 +125,7 @@ def simple_queue_test(self, q): # Empty it for i in range(QUEUE_SIZE): q.get() - self.assert_(q.empty(), "Queue should be empty") + self.assertTrue(q.empty(), "Queue should be empty") try: q.get(block=0) self.fail("Didn't appear to block with an empty queue") @@ -158,8 +158,8 @@ def queue_join_test(self, q): for i in range(100): q.put(i) q.join() - self.assertEquals(self.cum, sum(range(100)), - "q.join() did not block until all tasks were done") + self.assertEqual(self.cum, sum(range(100)), + "q.join() did not block until all tasks were done") for i in (0,1): q.put(-1) # instruct the threads to close q.join() # verify that you can join twice @@ -247,7 +247,7 @@ def failing_queue_test(self, q): except FailingQueueException: pass q.put("last") - self.assert_(q.full(), "Queue should be full") + self.assertTrue(q.full(), "Queue should be full") # Test a failing blocking put q.fail_next_put = True try: @@ -269,17 +269,17 @@ def failing_queue_test(self, q): # Check the Queue isn't damaged. # put failed, but get succeeded - re-add q.put("last") - self.assert_(q.full(), "Queue should be full") + self.assertTrue(q.full(), "Queue should be full") q.get() - self.assert_(not q.full(), "Queue should not be full") + self.assertTrue(not q.full(), "Queue should not be full") q.put("last") - self.assert_(q.full(), "Queue should be full") + self.assertTrue(q.full(), "Queue should be full") # Test a blocking put self.do_blocking_test(q.put, ("full",), q.get, ()) # Empty it for i in range(QUEUE_SIZE): q.get() - self.assert_(q.empty(), "Queue should be empty") + self.assertTrue(q.empty(), "Queue should be empty") q.put("first") q.fail_next_get = True try: @@ -287,16 +287,16 @@ def failing_queue_test(self, q): self.fail("The queue didn't fail when it should have") except FailingQueueException: pass - self.assert_(not q.empty(), "Queue should not be empty") + self.assertTrue(not q.empty(), "Queue should not be empty") q.fail_next_get = True try: q.get(timeout=0.1) self.fail("The queue didn't fail when it should have") except FailingQueueException: pass - self.assert_(not q.empty(), "Queue should not be empty") + self.assertTrue(not q.empty(), "Queue should not be empty") q.get() - self.assert_(q.empty(), "Queue should be empty") + self.assertTrue(q.empty(), "Queue should be empty") q.fail_next_get = True try: self.do_exceptional_blocking_test(q.get, (), q.put, ('empty',), @@ -305,9 +305,9 @@ def failing_queue_test(self, q): except FailingQueueException: pass # put succeeded, but get failed. - self.assert_(not q.empty(), "Queue should not be empty") + self.assertTrue(not q.empty(), "Queue should not be empty") q.get() - self.assert_(q.empty(), "Queue should be empty") + self.assertTrue(q.empty(), "Queue should be empty") def test_failing_queue(self): # Test to make sure a queue is functioning correctly. From d0fc82ad4cf6dea685e0598cc322fb9b179ae1f7 Mon Sep 17 00:00:00 2001 From: ejd Date: Wed, 10 Feb 2021 17:04:51 -0500 Subject: [PATCH 3/3] add Python 3 classifier --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index c87b361..d76d04c 100644 --- a/setup.py +++ b/setup.py @@ -36,6 +36,7 @@ def file_contents(filename): Operating System :: OS Independent Programming Language :: Python Programming Language :: Python :: 2 + Programming Language :: Python :: 3 Topic :: Software Development :: Libraries :: Python Modules Topic :: Utilities """),