Skip to content

Commit

Permalink
Merge pull request #160 from openearth/develop
Browse files Browse the repository at this point in the history
Merging develop into master for releasing version 1.0.0
  • Loading branch information
tschmits authored Jan 23, 2017
2 parents bb4dcd8 + 947eba4 commit 14cca67
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 50 deletions.
18 changes: 9 additions & 9 deletions delft3dworker/fixtures/default_template.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,14 @@
{
"name": "Base level change",
"validators": {
"max": 3.0,
"min": -3.0
"max": 80,
"min": -80
},
"factor": true,
"units": "m",
"units": "%",
"type": "numeric",
"id": "baselevel",
"description": "Positive values define 'a base level rise', negative values define 'a base level fall'. The magnitude of this value should be based on simulation stop time: the larger the stop time value, the larger the magnitude of this value can be."
"description": "Positive values define 'a base level rise', negative values define 'a base level fall'."
}
],
"name": "Forcing"
Expand Down Expand Up @@ -285,15 +285,15 @@
"name": "Base level change",
"default": 0,
"validators": {
"max": 3.0,
"max": 80.0,
"required": true,
"min": -3.0
"min": -80.0
},
"factor": true,
"units": "m",
"units": "%",
"type": "numeric",
"id": "baselevel",
"description": "Positive values define 'a base level rise', negative values define 'a base level fall'. The magnitude of this value should be based on simulation stop time: the larger the stop time value, the larger the magnitude of this value can be."
"description": "This is a percentage of the level change produced by the basin slope.<br><br>Click on the button below to see a table with the absolute values."
}
],
"name": "Forcing"
Expand Down Expand Up @@ -346,4 +346,4 @@
"model": "delft3dworker.template",
"pk": 53
}
]
]
16 changes: 10 additions & 6 deletions delft3dworker/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1667,14 +1667,18 @@ class Template(models.Model):
meta = JSONField(blank=True)
sections = JSONField(blank=True)

def save(self, *args, **kwargs):
returnval = super(Template, self).save(*args, **kwargs)
# The following method is disabled as it adds to much garbage
# to the MAIN search template
# TODO: implement proper search template which uses REST list_views

# def save(self, *args, **kwargs):
# returnval = super(Template, self).save(*args, **kwargs)

# update the MAIN search form after any template save
searchform, created = SearchForm.objects.get_or_create(name="MAIN")
searchform.update()
# # update the MAIN search form after any template save
# searchform, created = SearchForm.objects.get_or_create(name="MAIN")
# searchform.update()

return returnval
# return returnval

def __unicode__(self):
return self.name
Expand Down
72 changes: 37 additions & 35 deletions delft3dworker/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1474,38 +1474,40 @@ def setUp(self):
]
""")

def test_search_form_builds_on_template_save(self):
"""
Test if saving multiple templates creates and updates the search form.
"""

template = Template.objects.create(
name='Template 1',
meta='{}',
sections=self.sections_a,
)

# first template created non-existing search form
searchforms = SearchForm.objects.filter(name='MAIN')
self.assertEqual(len(searchforms), 1)

template2 = Template.objects.create(
name='Template 2',
meta='{}',
sections=self.sections_b,
)

# second template did not create an additional search form
searchforms = SearchForm.objects.filter(name='MAIN')
self.assertEqual(len(searchforms), 1)

# all fields are as expected
searchform = searchforms[0]
self.assertEqual(
searchform.templates,
self.templates_res
)
self.assertEqual(
searchform.sections,
self.sections_res
)
# TODO: implement proper means to generate search form json

# def test_search_form_builds_on_template_save(self):
# """
# Test if saving multiple templates creates and updates the search form.
# """

# template = Template.objects.create(
# name='Template 1',
# meta='{}',
# sections=self.sections_a,
# )

# # first template created non-existing search form
# searchforms = SearchForm.objects.filter(name='MAIN')
# self.assertEqual(len(searchforms), 1)

# template2 = Template.objects.create(
# name='Template 2',
# meta='{}',
# sections=self.sections_b,
# )

# # second template did not create an additional search form
# searchforms = SearchForm.objects.filter(name='MAIN')
# self.assertEqual(len(searchforms), 1)

# # all fields are as expected
# searchform = searchforms[0]
# self.assertEqual(
# searchform.templates,
# self.templates_res
# )
# self.assertEqual(
# searchform.sections,
# self.sections_res
# )
148 changes: 148 additions & 0 deletions delft3dworker/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from mock import MagicMock
from mock import patch

from delft3dworker.models import Container
from delft3dworker.models import Scenario
from delft3dworker.models import Scene
from delft3dworker.models import Template
Expand Down Expand Up @@ -524,6 +525,10 @@ def setUp(self):
}
}
self.scene_1.save()
container_1 = Container.objects.create(
version={'d3d': 1},
scene=self.scene_1
)

self.scene_2 = Scene.objects.create(
name='Testscene 2',
Expand All @@ -544,6 +549,10 @@ def setUp(self):
}
}
self.scene_2.save()
container_2 = Container.objects.create(
version={'d3d': 2, 'other': 'a'},
scene=self.scene_2
)

# Object general
assign_perm('view_scenario', self.user_bar, self.scenario)
Expand Down Expand Up @@ -713,13 +722,152 @@ def test_search_hack(self):
query = {'parameter': "hack,mud,grease,more"}
self.assertEqual(len(self._request(query)), 2)

def test_search_versions(self):
"""
Test search options
"""

query = {'versions': "argh"}
self.assertEqual(len(self._request(query)), 2)

query = {'versions': "{}"}
self.assertEqual(len(self._request(query)), 2)

query = {'versions': '{"d3d":[1]}'}
self.assertEqual(len(self._request(query)), 1)

query = {'versions': '{"d3d":[2]}'}
self.assertEqual(len(self._request(query)), 1)

query = {'versions': '{"d3d":[1,2]}'}
self.assertEqual(len(self._request(query)), 2)

query = {'versions': '{"d3d":[1,2], "other": "a"}'}
self.assertEqual(len(self._request(query)), 2)

query = {'versions': '{"d3d":[1], "other": "a"}'}
self.assertEqual(len(self._request(query)), 2)

query = {'versions': '{"d3d":[2], "other": "a"}'}
self.assertEqual(len(self._request(query)), 1)

query = {'versions': '{"d3d":None}'}
self.assertEqual(len(self._request(query)), 2)

def _request(self, query):
url = reverse('scene-list')
self.client.login(username='bar', password='secret')
response = self.client.get(url, query, format='json')
return response.data


class SceneVersionTestCase(APITestCase):
"""
SceneVersionTestCase
Tests the Scenario Django REST API
"""

def setUp(self):
user_bar = User.objects.create_user(
username='bar',
password='secret'
)
scenario = Scenario.objects.create(
name='Testscenario',
owner=user_bar,
)

scene_1 = Scene.objects.create(
name='Testscene 1',
owner=user_bar
)
scene_1.scenario.add(scenario)

scene_2 = Scene.objects.create(
name='Testscene 1',
owner=user_bar
)
scene_2.scenario.add(scenario)
container_2_1 = Container.objects.create(
version={ 'd3dversion': '1' },
scene=scene_2
)

scene_3 = Scene.objects.create(
name='Testscene 1',
owner=user_bar
)
scene_3.scenario.add(scenario)
container_3_1 = Container.objects.create(
version={ 'd3dversion': '2' },
scene=scene_3
)

scene_4 = Scene.objects.create(
name='Testscene 1',
owner=user_bar
)
scene_4.scenario.add(scenario)
container_4_1 = Container.objects.create(
version={ 'd3dversion': '1' },
scene=scene_4
)
container_4_2 = Container.objects.create(
version={ 'svnversion': 'a' },
scene=scene_4
)

scene_5 = Scene.objects.create(
name='Testscene 1',
owner=user_bar
)
scene_5.scenario.add(scenario)
container_5_1 = Container.objects.create(
version={ 'd3dversion': '1' },
scene=scene_5
)
container_5_2 = Container.objects.create(
version={ 'svnversion': 'b' },
scene=scene_5
)
container_5_3 = Container.objects.create(
version={ 'anything': 'I' },
scene=scene_5
)

# Object general
assign_perm('view_scenario', user_bar, scenario)
assign_perm('view_scene', user_bar, scene_1)
assign_perm('view_scene', user_bar, scene_2)
assign_perm('view_scene', user_bar, scene_3)
assign_perm('view_scene', user_bar, scene_4)
assign_perm('view_scene', user_bar, scene_5)

# Model general
user_bar.user_permissions.add(
Permission.objects.get(codename='view_scenario'))
user_bar.user_permissions.add(
Permission.objects.get(codename='view_scene'))

# Refetch to empty permissions cache
user_bar = User.objects.get(pk=user_bar.pk)

def test_get_versions(self):
# detail view
url = reverse('scene-versions')

# foo can see
self.client.login(username='bar', password='secret')
response = self.client.get(url, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
response.render()
self.assertEqual(response.data, {
'svnversion': set(['a', 'b']),
'd3dversion': set(['1', '2']),
'anything': set(['I'])
})


class ScenarioTestCase(APITestCase):
"""
ScenarioTestCase
Expand Down
28 changes: 28 additions & 0 deletions delft3dworker/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
import datetime
import django_filters
import io
import json
import logging
import zipfile

from django.contrib.auth.models import Group
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse_lazy
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.utils.dateparse import parse_date
Expand All @@ -33,6 +35,7 @@
from rest_framework.decorators import list_route
from rest_framework.response import Response

from delft3dworker.models import Container
from delft3dworker.models import Scenario
from delft3dworker.models import Scene
from delft3dworker.models import Template
Expand Down Expand Up @@ -225,6 +228,8 @@ def get_queryset(self):
shared = self.request.query_params.getlist('shared', [])
users = self.request.query_params.getlist('users', [])

versions = self.request.query_params.get('versions', "\{\}")

created_after = self.request.query_params.get('created_after', '')
created_before = self.request.query_params.get('created_before', '')
started_after = self.request.query_params.get('started_after', '')
Expand Down Expand Up @@ -342,6 +347,17 @@ def get_queryset(self):
userids = [int(user) for user in users if user.isdigit()]
queryset = queryset.filter(owner__in=userids)

if versions != "\{\}":
try:
version_dict = json.loads(versions)
except ValueError:
version_dict = {}
f = Q()
for key, values in version_dict.iteritems():
for value in values:
f = f | Q(container__version__contains={key: value})
queryset = queryset.filter(f)

if created_after != '':
created_after_date = parse_date(created_after)
if created_after_date:
Expand Down Expand Up @@ -531,6 +547,18 @@ def export_all(self, request):
resp['Content-Disposition'] = 'attachment; filename=Delft3DGTFiles.zip'
return resp

@list_route(methods=["get"])
def versions(self, request):
queryset = Container.objects.all()

resp = {}
for container in queryset:
for key, val in container.version.iteritems():
resp.setdefault(key, set([])).add(val)

return Response(resp)


class SearchFormViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows search forms to be viewed.
Expand Down

0 comments on commit 14cca67

Please sign in to comment.