Skip to content

Commit

Permalink
Merge branch 'v0.20.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
fredkingham committed Nov 27, 2020
2 parents 239a52d + f58da03 commit 03f20ef
Show file tree
Hide file tree
Showing 48 changed files with 292 additions and 198 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ python:
- "3.5"
- "3.6"
- "3.7"
- "3.8"

services:
- postgresql
Expand Down
2 changes: 0 additions & 2 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
recursive-include opal/static *
recursive-include opal/templates *
recursive-include opal/scaffolding *
recursive-include opal/core/collaborative/static *
recursive-include opal/core/collaborative/templates *
recursive-include opal/core/search/static *
recursive-include opal/core/search/templates *
recursive-include opal/core/pathway/static *
Expand Down
35 changes: 35 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,38 @@
### 0.20.0 (Major Release)

#### Python 3 version changes.

Opal now supports python 3.5 - python 3.8.
Please note that the 0.21.0 release will drop support for python 3.5.

### Scaffold application episode category

The scaffolded application created by `startproject` now creates a custom
episode category class.

### Removes Django Axes

Axes has been removed from the Opal core application. The package creates a database
log of all login attempts and was installed by default. It is now considered that this
should be an application level choice rather than a framework choice. Installing it on a
per application basis is simple, and requires only settings and requirements changes.

### Removes Letter

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.

#### Updates to the Dependency Graph

* Django: 2.0.13 -> 2.2.16
* Django-compressor: 2.2 -> 2.4
* Six==1.15.0
* Psycopg2: 2.8.3 -> 2.8.6
* Requests: 2.22.0 -> 2.25.0
* Python-dateutil: 2.8.0 -> 2.8.1
* Django-rest-framework: 3.10.2 -> 3.12.2
* Django-Axes -> Removed
* Letter -> Removed

### 0.18.4 (Minor Release)

#### Some models have translations
Expand Down
12 changes: 1 addition & 11 deletions doc/docs/guides/episodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ such as a start and end date, and the type of episode. This may be an inpatient
stay, an outpatient treatment, a telephone consultation - or any other arbitrarily
defined period of care.


## Episode Categories

An episode must have a related category. An Opal `EpisodeCategory` is a discoverable
Expand All @@ -19,7 +18,7 @@ the `display_name` attribute of the relevant category.
```python
episode = patient.episode_set.first()
print episode.category
# <opal.core.episode.InpatientEpisode object>
# <{{ your app name }}.InpatientEpisode object>

print episode.category.display_name
# "Inpatient"
Expand All @@ -34,15 +33,6 @@ The category of an episode determines which template will be used to display it
on the detail page for the patient. This template is determined by looking up
the `detail_template` attribute of the `EpisodeCategory`.

```python
episode.category
print episode.category
# <opal.core.episode.InpatientEpisode object>

print episode.category.detail_template
# detail/inpatient.html
```

The Episode Category template does not comprise the entire
[Patient detail view](patient_detail_views.md). This is made of multiple episodes
and by default will display some basic demographic details as well as other episodes.
Expand Down
7 changes: 0 additions & 7 deletions doc/docs/reference/episode_categories.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,3 @@ rest of the data that's been used to update the episode.
InpatientEpisode(episode).set_stage('Discharged', user, data_dict)
# -> True
```


## InpatientEpisode

This is the default EpisodeCategory imlpementation - applications started with Opal's
scaffolding scripts will use this as the `OpalApplication.default_episode_category`.
It sets the detail template to `detail/inpatient.html`
57 changes: 57 additions & 0 deletions doc/docs/reference/upgrading.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,63 @@
This document provides instructions for specific steps required to upgrading your Opal
application to a later version where there are extra steps required.

#### v0.18.3 -> v0.20.0

##### Dependency upgrades

How you do this depends on how you have configured your application. You will need to
update both the Opal version, and versions of dependencies upgraded dependencies if
you have specified them in for instance, a requirements.txt.

(This will be the case if you use the requirements.txt originally provided by
`opal startproject`)

# requirements.txt
opal==0.20.0
django==2.2.16
djangorestframework==3.12.2
django-compressor==2.4
six==1.15.0
psycopg2==2.8.6
requests==2.25.0
python-dateutil==2.8.1


##### API API Changes (REST Framework)

Note that the Django REST Framework update includes a breaking change to their public
API which may affect your application. The `base_name` attribute of a ViewSet has been
renamed to `basename` ([release notes](https://www.django-rest-framework.org/community/release-notes/#390)).

Any APIs implemented in your application will likely need to rename this attribute as
part of this upgrade.

##### Episode Categories


`Inpatient` is no longer provided in `opal.core.episodes`. If you are using the
Inpatient episode category you can add it in your `{{ appname }}/episode_categories.py`
```
from opal.core.episodes import EpisodeCategory
class InpatientEpisode(EpisodeCategory):
display_name = 'Inpatient'
detail_template = 'detail/inpatient.html'
stages = [
'Inpatient',
'Followup',
'Discharged'
]
```

##### Django Axes

Opal has removed the built in dependency on Django Axes. If your application wishes to
continue using it, then the relevant settings should already be in your settings file.
If you were relying on the entry in the opal `setup.py` to install it at deployment time,
you will need to ensure this via some other mechanism - for instance ensuring it is in your
application `requirements.txt`.

#### v0.17.1 -> v0.18.2

Expand Down
2 changes: 1 addition & 1 deletion doc/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ dev_addr: 0.0.0.0:8965
include_next_prev: false

extra:
version: v0.18.4
version: v0.20.0

markdown_extensions:
- fenced_code
2 changes: 1 addition & 1 deletion opal/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""
Declare our current version string
"""
__version__ = '0.18.4'
__version__ = '0.20.0'
28 changes: 14 additions & 14 deletions opal/core/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@


class OPALRouter(routers.DefaultRouter):
def get_default_base_name(self, viewset):
name = getattr(viewset, 'base_name', None)
def get_default_basename(self, viewset):
name = getattr(viewset, 'basename', None)
if name is None:
return routers.DefaultRouter.get_default_base_name(self, viewset)
return routers.DefaultRouter.get_default_basename(self, viewset)
return name


Expand Down Expand Up @@ -81,7 +81,7 @@ class RecordViewSet(LoginRequiredViewset):
Return the serialization of all active record types ready to
initialize on the client side.
"""
base_name = 'record'
basename = 'record'

def list(self, request):
return json_response(schemas.list_records())
Expand All @@ -91,7 +91,7 @@ class ReferenceDataViewSet(LoginRequiredViewset):
"""
API for referencedata
"""
base_name = 'referencedata'
basename = 'referencedata'

def list(self, request):
data = {}
Expand Down Expand Up @@ -141,7 +141,7 @@ class MetadataViewSet(LoginRequiredViewset):
"""
Our metadata API
"""
base_name = 'metadata'
basename = 'metadata'

def list(self, request):
data = {}
Expand Down Expand Up @@ -237,7 +237,7 @@ class UserProfileViewSet(LoginRequiredViewset):
"""
Returns the user profile details for the currently logged in user
"""
base_name = 'userprofile'
basename = 'userprofile'

def list(self, request):
profile = request.user.profile
Expand All @@ -248,7 +248,7 @@ class UserViewSet(LoginRequiredViewset):
"""
Provides applications with information about all system users
"""
base_name = 'user'
basename = 'user'

def list(self, request):
"""
Expand All @@ -269,7 +269,7 @@ class TaggingViewSet(LoginRequiredViewset):
"""
Returns taggings associated with episodes
"""
base_name = 'tagging'
basename = 'tagging'

@episode_from_pk
def retrieve(self, request, episode):
Expand All @@ -293,7 +293,7 @@ class EpisodeViewSet(LoginRequiredViewset):
"""
Episodes of care
"""
base_name = 'episode'
basename = 'episode'

def list(self, request):
return json_response(
Expand Down Expand Up @@ -357,7 +357,7 @@ def retrieve(self, request, episode):


class PatientViewSet(LoginRequiredViewset):
base_name = 'patient'
basename = 'patient'

@patient_from_pk
def retrieve(self, request, patient):
Expand All @@ -366,7 +366,7 @@ def retrieve(self, request, patient):


class PatientRecordAccessViewSet(LoginRequiredViewset):
base_name = 'patientrecordaccess'
basename = 'patientrecordaccess'

def retrieve(self, request, pk=None):
return json_response([
Expand All @@ -376,7 +376,7 @@ def retrieve(self, request, pk=None):


class PatientListViewSet(LoginRequiredViewset):
base_name = 'patientlist'
basename = 'patientlist'
permission_classes = (IsAuthenticated,)

def retrieve(self, request, pk=None):
Expand All @@ -401,7 +401,7 @@ def register_subrecords():
sub_name = subrecord.get_api_name()

class SubViewSet(SubrecordViewSet):
base_name = sub_name
basename = sub_name
model = subrecord

router.register(sub_name, SubViewSet)
Expand Down
6 changes: 2 additions & 4 deletions opal/core/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class OpalApplication(object):
index=0
)
]
default_episode_category = 'Inpatient'
default_episode_category = None

@classmethod
def get_core_javascripts(klass, namespace):
Expand All @@ -113,10 +113,8 @@ def get_menu_items(klass, user=None):
"""
Default implementation of get_menu_items()
"""
# we import here as settings must be set before this is imported
from django.contrib.auth.views import logout as logout_view
logout = menus.MenuItem(
href=reverse(logout_view), icon="fa-sign-out", index=1000
href=reverse("logout"), icon="fa-sign-out", index=1000
)
admin = menus.MenuItem(
href="/admin/", icon="fa-cogs", display=_("Admin"),
Expand Down
10 changes: 10 additions & 0 deletions opal/core/commandline.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import os
import subprocess
import sys
import logging

from django.core import management
import ffs
Expand Down Expand Up @@ -242,5 +243,14 @@ def parse_args(args):
sys.exit(0)


def warn_for_python_35():
vi = sys.version_info
if vi.major == 3 and vi.minor == 5:
logging.warn(
"Python 3.5 will be deprecated in Opal 0.21.0",
)


def main():
warn_for_python_35()
parse_args(sys.argv[1:])
10 changes: 0 additions & 10 deletions opal/core/episodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,3 @@ def set_stage(self, stage, user, data):
)
raise ValueError(msg)
self.episode.stage = stage


class InpatientEpisode(EpisodeCategory):
display_name = 'Inpatient'
detail_template = 'detail/inpatient.html'
stages = [
'Inpatient',
'Followup',
'Discharged'
]
2 changes: 1 addition & 1 deletion opal/core/pathway/tests/pathway_test/pathways.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
class SomeComplicatedStep(steps.Step):
display_name = "Some complicated step"
step_controller = "SomeController"
template = "Sometemplate.html"
template = "complicated_step_template.html"


class PagePathwayExample(pathways.PagePathway):
Expand Down
Empty file.
10 changes: 5 additions & 5 deletions opal/core/patient_lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,17 +298,17 @@ def get_member_lists(klass):
Returns an iterable of PatientLists
Defaults to the `.member_lists` property
"""
for l in klass.member_lists:
yield l
for member_list in klass.member_lists:
yield member_list

@classmethod
def get_member_lists_for_user(klass, user):
"""
Returns an iterable of the visible member lists for a given USER
"""
for l in klass.get_member_lists():
if l.visible_to(user):
yield l
for member_list in klass.get_member_lists():
if member_list.visible_to(user):
yield member_list

@classmethod
def visible_to(klass, user):
Expand Down
Loading

0 comments on commit 03f20ef

Please sign in to comment.