Merge lp:~cjwatson/lazr.jobrunner/py3 into lp:lazr.jobrunner

Proposed by Colin Watson
Status: Merged
Merged at revision: 59
Proposed branch: lp:~cjwatson/lazr.jobrunner/py3
Merge into: lp:lazr.jobrunner
Prerequisite: lp:~cjwatson/lazr.jobrunner/celery-4.3
Diff against target: 340 lines (+70/-34)
11 files modified
NEWS.txt (+4/-0)
setup.py (+5/-3)
src/lazr/__init__.py (+23/-1)
src/lazr/jobrunner/bin/clear_queues.py (+5/-3)
src/lazr/jobrunner/jobrunner.py (+3/-3)
src/lazr/jobrunner/tests/config1.py (+1/-1)
src/lazr/jobrunner/tests/config_do_not_create_missing_queues.py (+1/-1)
src/lazr/jobrunner/tests/test_celerytask.py (+25/-19)
src/lazr/jobrunner/tests/time_limit_config_fast_lane.py (+1/-1)
src/lazr/jobrunner/tests/time_limit_config_slow_lane.py (+1/-1)
tox.ini (+1/-1)
To merge this branch: bzr merge lp:~cjwatson/lazr.jobrunner/py3
Reviewer Review Type Date Requested Status
Adam Collard (community) Approve
Launchpad code reviewers Pending
Review via email: mp+366179@code.launchpad.net

Commit message

Add Python 3 support (requires celery >= 4.3).

To post a comment you must log in.
Revision history for this message
Adam Collard (adam-collard) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'NEWS.txt'
--- NEWS.txt 2019-03-08 18:24:33 +0000
+++ NEWS.txt 2019-05-02 14:16:27 +0000
@@ -1,6 +1,10 @@
1News1News
2====2====
33
4UNRELEASED
5----------
6* Add Python 3 support (requires celery >= 4.3).
7
40.1480.14
5----9----
6* Add tox testing support.10* Add tox testing support.
711
=== modified file 'setup.py'
--- setup.py 2019-03-08 18:24:33 +0000
+++ setup.py 2019-05-02 14:16:27 +0000
@@ -28,11 +28,13 @@
28 # List your project dependencies here.28 # List your project dependencies here.
29 # For more details, see:29 # For more details, see:
30 # http://packages.python.org/distribute/setuptools.html#declaring-dependencies30 # http://packages.python.org/distribute/setuptools.html#declaring-dependencies
31 'celery>=3.0,<5.0',31 'celery>=3.0,<5.0; python_version < "3"',
32 'celery>=4.3,<5.0; python_version >= "3"',
32]33]
3334
34tests_require = [35tests_require = [
35 'oops>=0.0.11',36 'oops>=0.0.11',
37 'six',
36 'unittest2',38 'unittest2',
37 'zope.testing',39 'zope.testing',
38 ]40 ]
@@ -51,8 +53,8 @@
51 url='https://launchpad.net/lazr.jobrunner',53 url='https://launchpad.net/lazr.jobrunner',
52 license='GPL v3',54 license='GPL v3',
53 packages=find_packages('src'),55 packages=find_packages('src'),
54 package_dir = {'': 'src'},56 package_dir={'': 'src'},
55 namespace_packages = ['lazr'],57 namespace_packages=['lazr'],
56 include_package_data=True,58 include_package_data=True,
57 zip_safe=False,59 zip_safe=False,
58 install_requires=install_requires,60 install_requires=install_requires,
5961
=== modified file 'src/lazr/__init__.py'
--- src/lazr/__init__.py 2012-02-23 10:32:17 +0000
+++ src/lazr/__init__.py 2019-05-02 14:16:27 +0000
@@ -1,1 +1,23 @@
1__import__('pkg_resources').declare_namespace(__name__)1# Copyright 2019 Canonical Ltd. All rights reserved.
2#
3# This file is part of lazr.jobrunner.
4#
5# lazr.jobrunner is free software: you can redistribute it and/or modify it
6# under the terms of the GNU Lesser General Public License as published by
7# the Free Software Foundation, version 3 of the License.
8#
9# lazr.jobrunner is distributed in the hope that it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12# License for more details.
13#
14# You should have received a copy of the GNU Lesser General Public License
15# along with lazr.jobrunner. If not, see <http://www.gnu.org/licenses/>.
16
17# this is a namespace package
18try:
19 import pkg_resources
20 pkg_resources.declare_namespace(__name__)
21except ImportError:
22 import pkgutil
23 __path__ = pkgutil.extend_path(__path__, __name__)
224
=== modified file 'src/lazr/jobrunner/bin/clear_queues.py'
--- src/lazr/jobrunner/bin/clear_queues.py 2019-03-05 17:06:13 +0000
+++ src/lazr/jobrunner/bin/clear_queues.py 2019-05-02 14:16:27 +0000
@@ -17,6 +17,8 @@
1717
18"""Inspect Celery result queues."""18"""Inspect Celery result queues."""
1919
20from __future__ import absolute_import, print_function
21
20__metaclass__ = type22__metaclass__ = type
2123
22from argparse import ArgumentParser24from argparse import ArgumentParser
@@ -28,9 +30,9 @@
2830
2931
30def show_queue_data(body, message):32def show_queue_data(body, message):
31 print '%s: %s' % (33 print('%s: %s' % (
32 message.delivery_info['routing_key'],34 message.delivery_info['routing_key'],
33 json.dumps(body, sort_keys=True))35 json.dumps(body, sort_keys=True)))
3436
3537
36def clear_queues(args):38def clear_queues(args):
@@ -56,7 +58,7 @@
56 RunJob.app, [queue], callbacks=[show_queue_data],58 RunJob.app, [queue], callbacks=[show_queue_data],
57 retain=True, passive_queues=True)59 retain=True, passive_queues=True)
58 except amqp.exceptions.NotFound as exc:60 except amqp.exceptions.NotFound as exc:
59 print >>sys.stderr, exc.reply_text61 print(exc.reply_text, file=sys.stderr)
6062
6163
62def main():64def main():
6365
=== modified file 'src/lazr/jobrunner/jobrunner.py'
--- src/lazr/jobrunner/jobrunner.py 2012-10-24 17:57:42 +0000
+++ src/lazr/jobrunner/jobrunner.py 2019-05-02 14:16:27 +0000
@@ -160,7 +160,7 @@
160 try:160 try:
161 try:161 try:
162 job.run()162 job.run()
163 except self.retryErrorTypes(job), e:163 except self.retryErrorTypes(job) as e:
164 if job.attempt_count > job.max_retries:164 if job.attempt_count > job.max_retries:
165 raise165 raise
166 self.logger.warning(166 self.logger.warning(
@@ -192,7 +192,7 @@
192 try:192 try:
193 try:193 try:
194 self.runJob(job, fallback)194 self.runJob(job, fallback)
195 except self.userErrorTypes(job), e:195 except self.userErrorTypes(job) as e:
196 self.logger.info(196 self.logger.info(
197 '%s failed with user error %r.'197 '%s failed with user error %r.'
198 % (self.job_str(job), e))198 % (self.job_str(job), e))
@@ -200,7 +200,7 @@
200 except Exception:200 except Exception:
201 info = sys.exc_info()201 info = sys.exc_info()
202 return self._doOops(job, info)202 return self._doOops(job, info)
203 except Exception, e:203 except Exception as e:
204 # This only happens if _doOops() fails.204 # This only happens if _doOops() fails.
205 self.logger.exception("Failure in _doOops: %s" % e)205 self.logger.exception("Failure in _doOops: %s" % e)
206 info = sys.exc_info()206 info = sys.exc_info()
207207
=== modified file 'src/lazr/jobrunner/tests/config1.py'
--- src/lazr/jobrunner/tests/config1.py 2012-07-09 10:58:00 +0000
+++ src/lazr/jobrunner/tests/config1.py 2019-05-02 14:16:27 +0000
@@ -1,4 +1,4 @@
1from simple_config import *1from lazr.jobrunner.tests.simple_config import *
2import os2import os
3import oops3import oops
4CELERY_ANNOTATIONS = {4CELERY_ANNOTATIONS = {
55
=== modified file 'src/lazr/jobrunner/tests/config_do_not_create_missing_queues.py'
--- src/lazr/jobrunner/tests/config_do_not_create_missing_queues.py 2012-07-09 10:58:00 +0000
+++ src/lazr/jobrunner/tests/config_do_not_create_missing_queues.py 2019-05-02 14:16:27 +0000
@@ -1,2 +1,2 @@
1from simple_config import *1from lazr.jobrunner.tests.simple_config import *
2CELERY_CREATE_MISSING_QUEUES = False2CELERY_CREATE_MISSING_QUEUES = False
33
=== modified file 'src/lazr/jobrunner/tests/test_celerytask.py'
--- src/lazr/jobrunner/tests/test_celerytask.py 2019-03-06 12:17:21 +0000
+++ src/lazr/jobrunner/tests/test_celerytask.py 2019-05-02 14:16:27 +0000
@@ -31,7 +31,12 @@
31import tempfile31import tempfile
32from time import sleep32from time import sleep
33from unittest import TestCase33from unittest import TestCase
34import urllib234
35from six.moves.urllib.error import URLError
36from six.moves.urllib.request import (
37 build_opener,
38 HTTPBasicAuthHandler,
39 )
3540
36os.environ.setdefault('CELERY_CONFIG_MODULE', 'lazr.jobrunner.celeryconfig')41os.environ.setdefault('CELERY_CONFIG_MODULE', 'lazr.jobrunner.celeryconfig')
3742
@@ -143,7 +148,7 @@
143 def ensure_dir(path):148 def ensure_dir(path):
144 try:149 try:
145 os.mkdir(path)150 os.mkdir(path)
146 except OSError, e:151 except OSError as e:
147 if e.errno != errno.EEXIST:152 if e.errno != errno.EEXIST:
148 raise153 raise
149 ensure_dir(self.job_root)154 ensure_dir(self.job_root)
@@ -176,7 +181,7 @@
176 try:181 try:
177 with self._job_output_file(job.job_id, 'r') as job_output_file:182 with self._job_output_file(job.job_id, 'r') as job_output_file:
178 return job_output_file.read()183 return job_output_file.read()
179 except IOError, e:184 except IOError as e:
180 if e.errno == errno.ENOENT:185 if e.errno == errno.ENOENT:
181 return None186 return None
182 raise187 raise
@@ -269,7 +274,7 @@
269 # There is exactly one OOPS report.274 # There is exactly one OOPS report.
270 self.assertEqual(1, len(oops_repository.oopses))275 self.assertEqual(1, len(oops_repository.oopses))
271 # This OOPS describes a MemoryError.276 # This OOPS describes a MemoryError.
272 oops_report = oops_repository.oopses.values()[0]277 oops_report = list(oops_repository.oopses.values())[0]
273 self.assertEqual('MemoryError', oops_report['type'])278 self.assertEqual('MemoryError', oops_report['type'])
274279
275 def test_acquires_lease(self):280 def test_acquires_lease(self):
@@ -288,11 +293,11 @@
288class TestCeleryD(TestCase):293class TestCeleryD(TestCase):
289294
290 def getQueueInfo(self):295 def getQueueInfo(self):
291 auth_handler = urllib2.HTTPBasicAuthHandler()296 auth_handler = HTTPBasicAuthHandler()
292 auth_handler.add_password(297 auth_handler.add_password(
293 realm='Management: Web UI', user='guest', passwd='guest',298 realm='Management: Web UI', user='guest', passwd='guest',
294 uri='http://localhost:55672/api/queues')299 uri='http://localhost:55672/api/queues')
295 opener = urllib2.build_opener(auth_handler)300 opener = build_opener(auth_handler)
296 info = opener.open('http://localhost:55672/api/queues').read()301 info = opener.open('http://localhost:55672/api/queues').read()
297 info = json.loads(info)302 info = json.loads(info)
298 # info is a list of dictionaries with details about the queues.303 # info is a list of dictionaries with details about the queues.
@@ -305,7 +310,7 @@
305 super(TestCeleryD, self).setUp()310 super(TestCeleryD, self).setUp()
306 try:311 try:
307 self.queue_status_during_setup = self.getQueueInfo()312 self.queue_status_during_setup = self.getQueueInfo()
308 except urllib2.URLError:313 except URLError:
309 # The rabbitmq-management package is currently broken314 # The rabbitmq-management package is currently broken
310 # on Precise, so the RabbitMQ management interface may315 # on Precise, so the RabbitMQ management interface may
311 # not be available.316 # not be available.
@@ -314,7 +319,7 @@
314 def tearDown(self):319 def tearDown(self):
315 try:320 try:
316 current_queue_status = self.getQueueInfo()321 current_queue_status = self.getQueueInfo()
317 except urllib2.URLError:322 except URLError:
318 # See setUp()323 # See setUp()
319 return324 return
320 bad_queues = []325 bad_queues = []
@@ -390,9 +395,10 @@
390 err = proc.stderr.read()395 err = proc.stderr.read()
391 self.assertEqual(JobStatus.FAILED, job.status)396 self.assertEqual(JobStatus.FAILED, job.status)
392 self.assertIs(None, job.job_source.get_output(job))397 self.assertIs(None, job.job_source.get_output(job))
393 self.assertIn(398 expected_message = (
394 "OOPS while executing job 10: [] Exception(u'Catch me if you"399 "OOPS while executing job 10: [] Exception(%r,)" %
395 " can!',)", err)400 u'Catch me if you can!').encode('UTF-8')
401 self.assertIn(expected_message, err)
396402
397 def test_timeout_long(self):403 def test_timeout_long(self):
398 """Raises exception when a job exceeds the configured time limit."""404 """Raises exception when a job exceeds the configured time limit."""
@@ -404,7 +410,7 @@
404 self.assertEqual(JobStatus.FAILED, job.status)410 self.assertEqual(JobStatus.FAILED, job.status)
405 err = proc.stderr.read()411 err = proc.stderr.read()
406 self.assertIn(412 self.assertIn(
407 'OOPS while executing job 10: [] SoftTimeLimitExceeded', err)413 b'OOPS while executing job 10: [] SoftTimeLimitExceeded', err)
408414
409 def test_timeout_in_fast_lane_passes_in_slow_lane(self):415 def test_timeout_in_fast_lane_passes_in_slow_lane(self):
410 # If a fast and a slow lane are configured, jobs which time out416 # If a fast and a slow lane are configured, jobs which time out
@@ -526,12 +532,12 @@
526 return (532 return (
527 '%s: {"children": [], "result": null, "status": "SUCCESS", '533 '%s: {"children": [], "result": null, "status": "SUCCESS", '
528 '"task_id": "%s", "traceback": null}\n'534 '"task_id": "%s", "traceback": null}\n'
529 % (self.queueName(task_id), task_id))535 % (self.queueName(task_id), task_id)).encode('UTF-8')
530536
531 def noQueueMessage(self, task_id):537 def noQueueMessage(self, task_id):
532 return (538 return (
533 "NOT_FOUND - no queue '%s' in vhost '/'\n"539 "NOT_FOUND - no queue '%s' in vhost '/'\n"
534 % self.queueName(task_id))540 % self.queueName(task_id)).encode('UTF-8')
535541
536 def test_clear_queues__result_not_consumed(self):542 def test_clear_queues__result_not_consumed(self):
537 """When a Celery task is started so that a result is returned543 """When a Celery task is started so that a result is returned
@@ -546,12 +552,12 @@
546 clear_queue_config = 'lazr.jobrunner.tests.simple_config'552 clear_queue_config = 'lazr.jobrunner.tests.simple_config'
547 stdout, stderr = self.runClearQueues(clear_queue_config, [task_id])553 stdout, stderr = self.runClearQueues(clear_queue_config, [task_id])
548 self.assertEqual(self.successMessage(task_id), stdout)554 self.assertEqual(self.successMessage(task_id), stdout)
549 self.assertEqual('', stderr)555 self.assertEqual(b'', stderr)
550556
551 # Reading a queue is destructive. An attempt to read again from557 # Reading a queue is destructive. An attempt to read again from
552 # a queue results in an error.558 # a queue results in an error.
553 stdout, stderr = self.runClearQueues(clear_queue_config, [task_id])559 stdout, stderr = self.runClearQueues(clear_queue_config, [task_id])
554 self.assertEqual('', stdout)560 self.assertEqual(b'', stdout)
555 self.assertEqual(self.noQueueMessage(task_id), stderr)561 self.assertEqual(self.noQueueMessage(task_id), stderr)
556562
557 def test_clear_queues__two_queues(self):563 def test_clear_queues__two_queues(self):
@@ -567,7 +573,7 @@
567 expected_stdout = (573 expected_stdout = (
568 self.successMessage(task_id_1) + self.successMessage(task_id_2))574 self.successMessage(task_id_1) + self.successMessage(task_id_2))
569 self.assertEqual(expected_stdout, stdout)575 self.assertEqual(expected_stdout, stdout)
570 self.assertEqual('', stderr)576 self.assertEqual(b'', stderr)
571577
572 def test_clear_queues__task_without_result(self):578 def test_clear_queues__task_without_result(self):
573 """A Celery task which was started so that no result is returned579 """A Celery task which was started so that no result is returned
@@ -577,7 +583,7 @@
577 task_id = self.invokeJob(celery_config_jobrunner, RunFileJobNoResult)583 task_id = self.invokeJob(celery_config_jobrunner, RunFileJobNoResult)
578 clear_queue_config = 'lazr.jobrunner.tests.simple_config'584 clear_queue_config = 'lazr.jobrunner.tests.simple_config'
579 stdout, stderr = self.runClearQueues(clear_queue_config, [task_id])585 stdout, stderr = self.runClearQueues(clear_queue_config, [task_id])
580 self.assertEqual('', stdout)586 self.assertEqual(b'', stdout)
581 self.assertEqual(self.noQueueMessage(task_id), stderr)587 self.assertEqual(self.noQueueMessage(task_id), stderr)
582588
583 def test_clear_queues__config_create_missing_queues_false(self):589 def test_clear_queues__config_create_missing_queues_false(self):
@@ -596,5 +602,5 @@
596 # not have the desired effect602 # not have the desired effect
597 task_id = 'this-queue-does-not-exist'603 task_id = 'this-queue-does-not-exist'
598 stdout, stderr = self.runClearQueues(celery_config, [task_id])604 stdout, stderr = self.runClearQueues(celery_config, [task_id])
599 self.assertEqual('', stdout)605 self.assertEqual(b'', stdout)
600 self.assertEqual(self.noQueueMessage(task_id), stderr)606 self.assertEqual(self.noQueueMessage(task_id), stderr)
601607
=== modified file 'src/lazr/jobrunner/tests/time_limit_config_fast_lane.py'
--- src/lazr/jobrunner/tests/time_limit_config_fast_lane.py 2012-04-10 12:44:00 +0000
+++ src/lazr/jobrunner/tests/time_limit_config_fast_lane.py 2019-05-02 14:16:27 +0000
@@ -1,3 +1,3 @@
1from config_two_queues import *1from lazr.jobrunner.tests.config_two_queues import *
2CELERYD_TASK_SOFT_TIME_LIMIT = 12CELERYD_TASK_SOFT_TIME_LIMIT = 1
3FALLBACK_QUEUE = 'standard_slow'3FALLBACK_QUEUE = 'standard_slow'
44
=== modified file 'src/lazr/jobrunner/tests/time_limit_config_slow_lane.py'
--- src/lazr/jobrunner/tests/time_limit_config_slow_lane.py 2012-04-10 12:44:00 +0000
+++ src/lazr/jobrunner/tests/time_limit_config_slow_lane.py 2019-05-02 14:16:27 +0000
@@ -1,2 +1,2 @@
1from config_two_queues import *1from lazr.jobrunner.tests.config_two_queues import *
2CELERYD_TASK_SOFT_TIME_LIMIT = 52CELERYD_TASK_SOFT_TIME_LIMIT = 5
33
=== modified file 'tox.ini'
--- tox.ini 2019-05-02 14:16:27 +0000
+++ tox.ini 2019-05-02 14:16:27 +0000
@@ -1,6 +1,6 @@
1[tox]1[tox]
2envlist =2envlist =
3 py27-celery{31,40,41,42,43}3 py27-celery{31,40,41,42,43}, py35-celery43
44
5[testenv]5[testenv]
6commands =6commands =

Subscribers

People subscribed via source and target branches

to all changes: