Skip to content

Commit

Permalink
Merge pull request #145 from FAIRDataPipeline/adding_field_to_qc
Browse files Browse the repository at this point in the history
Add additional object to QualityControlled representing the quality control document
  • Loading branch information
alahiff authored Sep 22, 2021
2 parents d4e1330 + 72c87b3 commit 4e76552
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 21 deletions.
5 changes: 4 additions & 1 deletion data_management/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -667,16 +667,19 @@ class QualityControlled(BaseModel):
### Writable Fields:
`object`: API URL of the associated `Object`
`document`: API URL of the `Object` representing the quality control document
### Read-only Fields:
`url`: Reference to the instance of the `QualityControlled`, final integer is the `QualityControlled` id
`last_updated`: Datetime that this record was last updated
`updated_by`: Reference to the user that updated this record
"""
ADMIN_LIST_FIELDS = ('object',)
ADMIN_LIST_FIELDS = ('object', 'document')

object = models.OneToOneField(Object, on_delete=models.PROTECT, related_name='quality_control')
document = models.ForeignKey(Object, on_delete=models.PROTECT, related_name='quality_control_document')


class Keyword(BaseModel):
Expand Down
22 changes: 19 additions & 3 deletions data_management/tests/initdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ def init_db(test=True):
root='https://raw.githubusercontent.com/ScottishCovidResponse/temporary_data/master/',
)

scl_repo = StorageRoot.objects.create(
updated_by=user,
root='https://raw.githubusercontent.com/ScottishCovidResponse/modelling-software-checklist',
)

sl_repo_prob = StorageLocation.objects.create(
updated_by=user,
path='master/SCRC/human/infection/SARS-CoV-2/symptom-probability/0.1.0.toml',
Expand Down Expand Up @@ -104,6 +109,13 @@ def init_db(test=True):
storage_root=sr_boydorr,
)

scl_repo_checklist = StorageLocation.objects.create(
updated_by=user,
path='main/software-checklist.md',
hash='f250b8dff4783cb59ee537d375a9420e3fbe66c2',
storage_root=scl_repo,
)

StorageLocation.objects.create(
updated_by=user,
path='PREFIX qb: <http://purl.org/linked-data/cube#>PREFIX data: <http://statistics.gov.scot/data/>PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>PREFIX mp: <http://statistics.gov.scot/def/measure-properties/>PREFIX dim: <http://purl.org/linked-data/sdmx/2009/dimension#>PREFIX sdim: <http://statistics.gov.scot/def/dimension/>PREFIX stat: <http://statistics.data.gov.uk/def/statistical-entity#>SELECT ?featurecode ?featurename ?date ?measure ?variable ?countWHERE { ?indicator qb:dataSet data:coronavirus-covid-19-management-information; dim:refArea ?featurecode; dim:refPeriod ?period; sdim:variable ?varname; qb:measureType ?type.{?indicator mp:count ?count.} UNION {?indicator mp:ratio ?count.} ?featurecode <http://publishmydata.com/def/ontology/foi/displayName> ?featurename. ?period rdfs:label ?date. ?varname rdfs:label ?variable. ?type rdfs:label ?measure.}',
Expand Down Expand Up @@ -423,9 +435,13 @@ def init_db(test=True):
cr.inputs.set([oc_prob, oc_infect, oc_latent])
cr.outputs.set([oc_prob, oc_infect, oc_latent])

QualityControlled.objects.create(updated_by=user, object=o_code)
QualityControlled.objects.create(updated_by=user, object=o_boy_cases_h5)
QualityControlled.objects.create(updated_by=user, object=o_boy_mort_h5)
o_scl_1 = Object.objects.create(updated_by=user, storage_location=scl_repo_checklist)
o_scl_2 = Object.objects.create(updated_by=user, storage_location=scl_repo_checklist)
o_scl_3 = Object.objects.create(updated_by=user, storage_location=scl_repo_checklist)

QualityControlled.objects.create(updated_by=user, object=o_code, document=o_scl_1)
QualityControlled.objects.create(updated_by=user, object=o_boy_cases_h5, document=o_scl_2)
QualityControlled.objects.create(updated_by=user, object=o_boy_mort_h5, document=o_scl_3)

Licence.objects.create(updated_by=user, object=o_code, licence_info='''
Copyright 2020 SCRC
Expand Down
53 changes: 41 additions & 12 deletions data_management/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ def setUp(self):
self.user = get_user_model().objects.create(username='Test User')
init_db()

def test_full_name(self):
self.assertEqual(self.user.full_name(), 'User Not Found')

def test_user_orgs(self):
self.assertEqual(self.user.orgs(), [])

# def _get_token(self):
# request = self.factory.get(reverse('get_token'))
# request.user = self.user
Expand Down Expand Up @@ -98,7 +104,7 @@ def test_get_list(self):
self.assertEqual(response.status_code, 200)
self.assertEqual(response['Content-Type'], 'application/json')
results = response.json()['results']
self.assertEqual(len(results), 7)
self.assertEqual(len(results), 8)

def test_get_detail(self):
client = APIClient()
Expand Down Expand Up @@ -137,7 +143,7 @@ def test_get_list(self):
self.assertEqual(response.status_code, 200)
self.assertEqual(response['Content-Type'], 'application/json')
results = response.json()['results']
self.assertEqual(len(results), 18)
self.assertEqual(len(results), 19)

def test_get_detail(self):
client = APIClient()
Expand Down Expand Up @@ -173,6 +179,28 @@ def test_filter_by_hash(self):
self.assertEqual(len(results), 1)
self.assertEqual(results[0]['path'], 'human/infection/SARS-CoV-2/scotland/cases_and_management/v0.1.0.h5')

class StorageAPITests(TestCase):

def setUp(self):
self.user = get_user_model().objects.create(username='Test User')
init_db()

def test_get_data(self):
client = APIClient()
client.force_authenticate(user=self.user)
url = reverse("get_data_product", kwargs={"data_product_name": "human/infection/SARS-CoV-2/symptom-probability", "namespace": "FAIR", "version": "0.1.0"})
response = client.get(url)

self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, 'https://raw.githubusercontent.com/ScottishCovidResponse/DataRepository/master/SCRC/human/infection/SARS-CoV-2/symptom-probability/0.1.0.toml')

def test_get_external_object(self):
client = APIClient()
client.force_authenticate(user=self.user)
url = reverse("get_external_object", kwargs={"alternate_identifier": "scottish deaths-involving-coronavirus-covid-19", "title": "scottish deaths-involving-coronavirus-covid-19", "version": "0.1.0"})
response = client.get(url)

self.assertEqual(response.status_code, 302)

class ObjectAPITests(TestCase):

Expand All @@ -189,29 +217,29 @@ def test_get_list(self):
self.assertEqual(response.status_code, 200)
self.assertEqual(response['Content-Type'], 'application/json')
results = response.json()['results']
self.assertEqual(len(results), 16)
self.assertEqual(len(results), 19)

def test_get_detail(self):
client = APIClient()
client.force_authenticate(user=self.user)
url = reverse('object-detail', kwargs={'pk': 3})
response = client.get(url, format='json')
response = client.get(url, format='json', HTTP_HOST='localhost')

self.assertEqual(response.status_code, 200)
self.assertEqual(response['Content-Type'], 'application/json')
self.assertEqual(response.json()['storage_location'], 'http://testserver/api/storage_location/2/')
self.assertEqual(response.json()['storage_location'], 'http://localhost/api/storage_location/2/')

def test_filter_by_storage_location(self):
client = APIClient()
client.force_authenticate(user=self.user)
url = reverse('object-list')
response = client.get(url, data={'storage_location': '3'}, format='json')
response = client.get(url, data={'storage_location': '3'}, format='json', HTTP_HOST='localhost')

self.assertEqual(response.status_code, 200)
self.assertEqual(response['Content-Type'], 'application/json')
results = response.json()['results']
self.assertEqual(len(results), 1)
self.assertEqual(results[0]['storage_location'], 'http://testserver/api/storage_location/3/')
self.assertEqual(results[0]['storage_location'], 'http://localhost/api/storage_location/3/')


class ObjectComponentAPITests(TestCase):
Expand All @@ -229,7 +257,7 @@ def test_get_list(self):
self.assertEqual(response.status_code, 200)
self.assertEqual(response['Content-Type'], 'application/json')
results = response.json()['results']
self.assertEqual(len(results), 48)
self.assertEqual(len(results), 51)

def test_get_detail_whole_object(self):
client = APIClient()
Expand Down Expand Up @@ -427,11 +455,12 @@ def test_get_detail(self):
client = APIClient()
client.force_authenticate(user=self.user)
url = reverse('qualitycontrolled-detail', kwargs={'pk': 1})
response = client.get(url, format='json')
response = client.get(url, format='json', HTTP_HOST='localhost')

self.assertEqual(response.status_code, 200)
self.assertEqual(response['Content-Type'], 'application/json')
self.assertEqual(response.json()['object'], 'http://testserver/api/object/15/')
self.assertEqual(response.json()['object'], 'http://localhost/api/object/15/')
self.assertEqual(response.json()['document'], 'http://localhost/api/object/17/')


class KeywordAPITests(TestCase):
Expand Down Expand Up @@ -1063,7 +1092,7 @@ def test_get_provn(self):
client.force_authenticate(user=self.user)
url = reverse("prov_report", kwargs={"pk": 1})
response = client.get(
url, format="provn", HTTP_ACCEPT="text/provenance-notation"
url, format="provn", HTTP_ACCEPT="text/provenance-notation", HTTP_HOST='localhost'
)
self.assertEqual(response.status_code, 200)
self.assertEqual(
Expand All @@ -1074,7 +1103,7 @@ def test_get_provn(self):
result_end = result_bits[1].split("xsd:dateTime, ", 1)[1]
result = result_bits[0] + result_end
expected_result = """document
default <http://testserver/>
default <http://localhost/>
entity(api/data_product/1, [prov:type="file", storage="https://data.scrc.uk/api/text_file/input/1", description="input 1 object", namespace="prov", name="this/is/cr/test/input/1", version="0.2.0"])
agent(api/author/1, [prov:type="prov:Person", name="Ivana Valenti"])
Expand Down
4 changes: 2 additions & 2 deletions data_management/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
path('tables/dataproducts', cache_page(cache_duration)(tables.data_product_table_data)),
path('tables/externalobjects', cache_page(cache_duration)(tables.external_objects_table_data)),
path('tables/codereporeleases', cache_page(cache_duration)(tables.code_repo_release_table_data)),
path('data_product/<str:namespace>:<path:data_product_name>@<str:version>', views.data_product),
path('external_object/<path:alternate_identifier>:<path:title>@<str:version>', views.external_object),
path('data_product/<str:namespace>:<path:data_product_name>@<str:version>', views.data_product, name='get_data_product'),
path('external_object/<path:alternate_identifier>:<path:title>@<str:version>', views.external_object, name='get_external_object'),
path('data/<str:name>', views.get_data),
path('api/data/<str:checksum>', api_views.ObjectStorageView.as_view()),
path('api/data', api_views.ObjectStorageView.as_view())
Expand Down
6 changes: 3 additions & 3 deletions data_management/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,10 +251,10 @@ def external_object(request, alternate_identifier, title, version):
return HttpResponseNotFound()

# Use storage location if it exists and user has not requested the original_store
if external_object.object.storage_location and 'original' not in request.GET:
if external_object.data_product.object.storage_location and 'original' not in request.GET:
if 'root' in request.GET:
return HttpResponse(external_object.object.storage_location.storage_root.root)
return redirect(external_object.object.storage_location.full_uri())
return HttpResponse(external_object.data_product.object.storage_location.storage_root.root)
return redirect(external_object.data_product.object.storage_location.full_uri())

# Use original_store if it exists
if external_object.original_store:
Expand Down

0 comments on commit 4e76552

Please sign in to comment.