Skip to content

Commit 8b09065

Browse files
author
fredkingham
committed
Merge branch 'v0.21.0'
2 parents 03f20ef + 9cfa084 commit 8b09065

20 files changed

+133
-78
lines changed

.travis.yml

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
language: python
22
dist: xenial
33
python:
4-
- "3.5"
54
- "3.6"
65
- "3.7"
76
- "3.8"

changelog.md

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
1+
### 0.21.0 (Major Release)
2+
3+
#### Celery upgrade and Django Celery library change.
4+
`django-celery` only officially supports Python 3.5 which Opal no longer supports. It is also no longer the recommended solution for results by Celery. So we have removed this dependency and added the `django-celery-results` module that has a similar functionality.
5+
6+
#### Drops support for Python 3.5
7+
Opal now supports Python 3.6 - Python 3.8.
8+
9+
110
### 0.20.0 (Major Release)
211

312
#### Python 3 version changes.
413

5-
Opal now supports python 3.5 - python 3.8.
6-
Please note that the 0.21.0 release will drop support for python 3.5.
14+
Opal now supports Python 3.5 - Python 3.8.
15+
Please note that the 0.21.0 release will drop support for Python 3.5.
716

817
### Scaffold application episode category
918

@@ -19,7 +28,7 @@ per application basis is simple, and requires only settings and requirements cha
1928

2029
### Removes Letter
2130

22-
The dependency on the letter python package has been removed from the Opal core application. If you wish to send emails, django ships with email wrappers to make this easy.
31+
The dependency on the letter python package has been removed from the Opal core application. If you wish to send emails, Django ships with email wrappers to make this easy.
2332

2433
#### Updates to the Dependency Graph
2534

doc/docs/reference/upgrading.md

+45
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,51 @@
33
This document provides instructions for specific steps required to upgrading your Opal
44
application to a later version where there are extra steps required.
55

6+
#### v0.20.0 -> v0.21.0
7+
8+
Opal no longer supports Python 3.5.
9+
You will need to use 3.6, 3.7 or 3.8 and therefore must make sure they are installed in your environment.
10+
11+
#### Celery changes
12+
13+
Opal does not require you to run Celery but we do pre-configure Opal applications for use with
14+
Celery.
15+
16+
If you don't have `celery` or `django-celery` in your requirements.txt this section can be ignored.
17+
18+
`django-celery` has been removed as a dependency. Please remove it from your requirements.
19+
20+
__Note__ This means that old results from `django-celery` will no longer be visible from the admin.
21+
22+
`django-celery-results==2.0.0` replaces `django-celery`, please add it to your requirements.
23+
This will show Celery task results in the admin and requires `python manage.py migrate` to be run.
24+
25+
Celery has been upgraded to 5.0.2.
26+
27+
So if you're using a requirements.txt for example it should now include.
28+
# requirements.txt
29+
opal==0.21.0
30+
celery==5.0.2
31+
django-celery-results==2.0.0
32+
33+
34+
The Django Celery management command has changed from
35+
`python manage.py celery worker -l info` to `celery -A opal.core worker -l INFO`
36+
37+
Add the below to your settings.py.
38+
```
39+
CELERY_RESULT_BACKEND = 'django-db'
40+
CELERY_CACHE_BACKEND = 'django-cache'
41+
```
42+
43+
Remove `djcelery` from your `INSTALLED APPS` in settings and add `django_celery_results`
44+
```
45+
INSTALLED_APPS = (
46+
...,
47+
'django_celery_results',
48+
)
49+
```
50+
651
#### v0.18.3 -> v0.20.0
752

853
##### Dependency upgrades

doc/mkdocs.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ dev_addr: 0.0.0.0:8965
121121
include_next_prev: false
122122

123123
extra:
124-
version: v0.20.0
124+
version: v0.21.0
125125

126126
markdown_extensions:
127127
- fenced_code

opal/_version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
"""
22
Declare our current version string
33
"""
4-
__version__ = '0.20.0'
4+
__version__ = '0.21.0'

opal/core/celery.py

+13-16
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,24 @@
1-
from __future__ import absolute_import
2-
1+
import os
32
import sys
4-
3+
from opal.core import commandline
54
from celery import Celery
65

7-
# set the default Django settings module for the 'celery' program.
8-
# os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'proj.settings')
96

10-
from django.conf import settings # noqa
7+
def set_up():
8+
if 'runtests.py' not in sys.argv:
9+
if 'DJANGO_SETTINGS_MODULE' not in os.environ:
10+
app_name = commandline.find_application_name()
11+
settings_location = f"{app_name}.settings"
12+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', settings_location)
13+
app = Celery('opal')
14+
app.config_from_object('django.conf:settings', namespace='CELERY')
15+
app.autodiscover_tasks()
16+
return app
1117

12-
app = Celery('proj')
1318

14-
# Using a string here means the worker will not have to
15-
# pickle the object when using Windows.
16-
app.config_from_object('django.conf:settings')
17-
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
19+
app = set_up()
1820

1921

2022
@app.task(bind=True)
2123
def debug_task(self):
2224
sys.stdout.write('Request: {0!r}\n'.format(self.request))
23-
24-
25-
app.conf.update(
26-
CELERY_RESULT_BACKEND='djcelery.backends.database:DatabaseBackend',
27-
)

opal/core/commandline.py

-11
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
import os
99
import subprocess
1010
import sys
11-
import logging
12-
1311
from django.core import management
1412
import ffs
1513

@@ -243,14 +241,5 @@ def parse_args(args):
243241
sys.exit(0)
244242

245243

246-
def warn_for_python_35():
247-
vi = sys.version_info
248-
if vi.major == 3 and vi.minor == 5:
249-
logging.warn(
250-
"Python 3.5 will be deprecated in Opal 0.21.0",
251-
)
252-
253-
254244
def main():
255-
warn_for_python_35()
256245
parse_args(sys.argv[1:])

opal/core/search/extract.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,9 @@ def zip_archive(episodes, description, user):
323323
return target
324324

325325

326-
def async_extract(user, criteria):
326+
def async_extract(user_id, criteria):
327327
"""
328328
Given the user and the criteria, let's run an async extract.
329329
"""
330330
from opal.core.search import tasks
331-
return tasks.extract.delay(user, criteria).id
331+
return tasks.extract.delay(user_id, criteria).id

opal/core/search/tasks.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from __future__ import absolute_import
2-
2+
from django.contrib.auth.models import User
33
from celery import shared_task
44

55

66
@shared_task
7-
def extract(user, criteria):
7+
def extract(user_id, criteria):
88
from opal.core.search import queries, extract
9+
user = User.objects.get(id=user_id)
910
query = queries.create_query(user, criteria)
1011
episodes = query.get_episodes()
1112
fname = extract.zip_archive(episodes, query.description(), user)

opal/core/search/tests/test_tasks.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@ def test_extract(self, zip_archive):
2121
u'queryType': u'Equals'
2222
}
2323
]
24-
fname = tasks.extract(self.user, criteria)
24+
fname = tasks.extract(self.user.id, criteria)
2525
self.assertEqual('Help', fname)

opal/core/search/views.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ def post(self, *args, **kwargs):
150150
if getattr(settings, 'EXTRACT_ASYNC', None):
151151
criteria = _get_request_data(self.request)['criteria']
152152
extract_id = async_extract(
153-
self.request.user,
153+
self.request.user.id,
154154
json.loads(criteria)
155155
)
156156
return json_response({'extract_id': extract_id})

opal/core/signals/tasks.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from celery import shared_task
55

66
from opal.models import Patient, Episode
7+
from opal.core.subrecords import get_subrecord_from_api_name
78

89

910
@shared_task
@@ -23,8 +24,9 @@ def episode_post_save(created, instance_id):
2324

2425

2526
@shared_task
26-
def subrecord_post_save(sender, created, instance_id):
27+
def subrecord_post_save(sender_api_name, created, instance_id):
2728
from opal.core.signals.worker import subrecord_post_save
29+
sender = get_subrecord_from_api_name(sender_api_name)
2830
instance = sender.objects.get(id=instance_id)
2931
subrecord_post_save.send(sender, created=created, instance=instance)
3032
return

opal/core/signals/worker.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@
1414

1515
def post_save_worker_forwarder(sender, created=None, instance=None, **kwargs):
1616
from django.conf import settings
17-
if 'djcelery' in settings.INSTALLED_APPS:
17+
if 'django_celery_results' in settings.INSTALLED_APPS:
1818
from opal.core.signals import tasks
1919
if sender == models.Patient:
2020
tasks.patient_post_save.delay(created, instance.id)
2121
if sender == models.Episode:
2222
tasks.episode_post_save.delay(created, instance.id)
2323
if issubclass(sender, models.Subrecord):
24-
tasks.subrecord_post_save.delay(sender, created, instance.id)
24+
tasks.subrecord_post_save.delay(
25+
sender.get_api_name(), created, instance.id
26+
)
2527
return
2628

2729

opal/scaffolding/scaffold/requirements.txt.jinja2

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ requests==2.25.0
1212
djangorestframework==3.12.2
1313
django-compressor==2.4
1414
python-dateutil==2.8.1
15-
django-celery==3.2.2
16-
celery==3.1.25
15+
django-celery-results==2.0.0
16+
celery==5.0.2
1717
opal=={{version}}

opal/tests/test_celery.py

+37-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,47 @@
11
"""
22
Unittests for opal.core.celery
33
"""
4-
from unittest.mock import patch, MagicMock
5-
4+
from unittest.mock import patch
65
from opal.core.test import OpalTestCase
76

87
from opal.core import celery
98

9+
1010
class DebugTaskTestCase(OpalTestCase):
11-
def test_debug_task(self):
11+
def test_with_runtests(self):
1212
with patch.object(celery.sys, 'stdout') as mock_stdout:
1313
celery.debug_task()
14-
mock_stdout.write.assert_called_with('Request: <Context: {}>\n')
14+
mock_stdout.write.assert_called_with("Request: <Context: {'args': (), 'kwargs': {}}>\n")
15+
16+
@patch("opal.core.celery.sys")
17+
@patch("opal.core.celery.Celery")
18+
@patch("opal.core.celery.os")
19+
def test_with_settings_module(self, os, Celery, sys):
20+
sys.argv = []
21+
os.environ = {'DJANGO_SETTINGS_MODULE': 'already_set'}
22+
celery.set_up()
23+
Celery.assert_called_once_with('opal')
24+
app = Celery.return_value
25+
app.config_from_object.assert_called_once_with(
26+
'django.conf:settings', namespace='CELERY'
27+
)
28+
app.autodiscover_tasks.assert_called_once_with()
29+
30+
@patch("opal.core.celery.sys")
31+
@patch("opal.core.celery.Celery")
32+
@patch("opal.core.celery.os")
33+
@patch("opal.core.celery.commandline")
34+
def test_without_settings_module(self, commandline, os, Celery, sys):
35+
sys.argv = []
36+
os.environ = {}
37+
commandline.find_application_name.return_value = "my_fake_app"
38+
celery.set_up()
39+
Celery.assert_called_once_with('opal')
40+
app = Celery.return_value
41+
app.config_from_object.assert_called_once_with(
42+
'django.conf:settings', namespace='CELERY'
43+
)
44+
app.autodiscover_tasks.assert_called_once_with()
45+
self.assertEqual(
46+
os.environ, {"DJANGO_SETTINGS_MODULE": "my_fake_app.settings"}
47+
)

opal/tests/test_command_detect_duplicates.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010

1111
from opal.management.commands import detect_duplicates as detector
1212

13-
class CommandTestCase(OpalTestCase):
1413

14+
class CommandTestCase(OpalTestCase):
1515
def test_handle(self):
16-
patient = models.Patient.objects.create()
16+
models.Patient.objects.create()
1717
c = detector.Command()
1818
with patch.object(c.stdout, 'write') as writer:
1919
c.handle()
@@ -35,11 +35,9 @@ def test_handle_duplicate_names(self):
3535
c = detector.Command()
3636
with patch.object(c.stdout, 'write') as writer:
3737
c.handle()
38-
3938
writer.assert_any_call('Jenny Smith {0}'.format(p1.id))
4039
writer.assert_any_call('Jenny Smith {0}'.format(p2.id))
4140

42-
4341
def test_handle_duplicate_with_three(self):
4442
"""
4543
Print the duplicate triple once, but not the third instance.

opal/tests/test_core_commandline.py

-18
Original file line numberDiff line numberDiff line change
@@ -225,21 +225,3 @@ def test_main(self):
225225
with patch.object(commandline, 'parse_args') as pa:
226226
commandline.main()
227227
pa.assert_called_with(sys.argv[1:])
228-
229-
230-
@patch("opal.core.commandline.sys")
231-
@patch("opal.core.commandline.logging")
232-
class WarnForPython35TestCase(OpalTestCase):
233-
def test_with_python_35(self, logging, sys):
234-
sys.version_info.major = 3
235-
sys.version_info.minor = 5
236-
commandline.warn_for_python_35()
237-
logging.warn.assert_called_with(
238-
"Python 3.5 will be deprecated in Opal 0.21.0"
239-
)
240-
241-
def test_not_with_python_35(self, logging, sys):
242-
sys.version_info.major = 3
243-
sys.version_info.minor = 6
244-
commandline.warn_for_python_35()
245-
self.assertFalse(logging.called)

runtests.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,13 @@
5151
'django.contrib.admin',
5252
'reversion',
5353
'compressor',
54-
'djcelery',
54+
'django_celery_results',
5555
'opal',
5656
'opal.tests',
5757
'opal.core.search',
5858
'opal.core.pathway.tests.pathway_test',
5959
'opal.core.pathway',
60+
'opal.core.signals'
6061
),
6162
TEMPLATES = [
6263
{
@@ -80,7 +81,7 @@
8081
},
8182
},
8283
],
83-
CELERY_ALWAYS_EAGER=True,
84+
CELERY_TASK_ALWAYS_EAGER=True,
8485
LOGGING = {
8586
'version': 1,
8687
'disable_existing_loggers': False,
@@ -131,7 +132,6 @@
131132
import django
132133
django.setup()
133134
from opal.core import celery
134-
celery.app.config_from_object('django.conf:settings')
135135

136136
try:
137137
sys.argv.remove('--failfast')

0 commit comments

Comments
 (0)