Skip to content

Commit

Permalink
Model help string typo; more field validation
Browse files Browse the repository at this point in the history
  • Loading branch information
k1o0 committed Mar 5, 2024
1 parent 03c959c commit b8820b3
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 7 deletions.
2 changes: 1 addition & 1 deletion alyx/actions/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ class Session(BaseAction):
help_text=' / '.join([str(q[0]) + ': ' + q[1] for q in QC_CHOICES]))

extended_qc = models.JSONField(null=True, blank=True,
help_text="Structured data about session QC,"
help_text="Structured data about session QC, "
"formatted in a user-defined way")

auto_datetime = models.DateTimeField(auto_now=True, blank=True, null=True,
Expand Down
2 changes: 1 addition & 1 deletion alyx/data/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class DatasetAdmin(BaseExperimentalDataAdmin):
'session_ro', 'collection', 'auto_datetime', 'revision_', 'default_dataset',
'_protected', '_public', 'tags', 'qc']
readonly_fields = ['name_', 'session_ro', '_online', 'auto_datetime', 'revision_',
'_protected', '_public', 'tags']
'_protected', '_public', 'tags', 'qc']
list_display = ['name_', '_online', 'version', 'collection', 'dataset_type_', 'file_size',
'session_ro', 'created_by', 'created_datetime', 'qc']
inlines = [FileRecordInline]
Expand Down
5 changes: 5 additions & 0 deletions alyx/data/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from rest_framework import serializers
from django.db.models import Count, Q, BooleanField

from one.alf.spec import QC

from .models import (DataRepositoryType, DataRepository, DataFormat, DatasetType,
Dataset, Download, FileRecord, Revision, Tag)
from .transfers import _get_session, _change_default_dataset
Expand Down Expand Up @@ -180,6 +182,9 @@ def create(self, validated_data):
name = validated_data.get('name', None)
default = validated_data.get('default_dataset', None)
session = validated_data.get('session', None)
# validate QC value
if 'qc' in validated_data:
validated_data['qc'] = QC.validate(validated_data['qc'])

if session:
if default is not False:
Expand Down
3 changes: 3 additions & 0 deletions alyx/data/tests_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ def test_dataset(self):
self.assertEqual(r.data['collection'], None)
# Check that it has been set as the default dataset
self.assertEqual(r.data['default_dataset'], True)
# Check QC value is NOT_SET by default
self.assertEqual(r.data['qc'], 'NOT_SET')
# Make sure a session has been created.
session = r.data['session']
r = self.client.get(session)
Expand All @@ -162,6 +164,7 @@ def test_dataset(self):
'date': '2018-01-01',
'number': 2,
'collection': 'test_path',
'qc': 'PASS'
}

r = self.post(reverse('dataset-list'), data)
Expand Down
10 changes: 9 additions & 1 deletion alyx/data/transfers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import numpy as np
from one.alf.files import add_uuid_string, folder_parts
from one.registration import get_dataset_type
from one.util import ensure_list
from one.alf.spec import QC

from alyx import settings
from data.models import FileRecord, Dataset, DatasetType, DataFormat, DataRepository
Expand Down Expand Up @@ -244,7 +246,7 @@ def _check_dataset_protected(session, collection, filename):
def _create_dataset_file_records(
rel_dir_path=None, filename=None, session=None, user=None,
repositories=None, exists_in=None, collection=None, hash=None,
file_size=None, version=None, revision=None, default=None):
file_size=None, version=None, revision=None, default=None, qc=None):

assert session is not None
revision_name = f'#{revision.name}#' if revision else ''
Expand All @@ -265,6 +267,12 @@ def _create_dataset_file_records(
dataset_type=dataset_type, data_format=data_format, revision=revision
)
dataset.default_dataset = default is True
try:
dataset.qc = int(QC.validate(qc or 'NOT_SET'))
except ValueError:
data = {'status_code': 400,
'detail': f'Invalid QC value "{qc}" for dataset "{relative_path}"'}
return None, Response(data=data, status=403)
dataset.save()

# If the dataset already existed see if it is protected (i.e can't be overwritten)
Expand Down
15 changes: 12 additions & 3 deletions alyx/data/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ def _make_dataset_response(dataset):
'collection': dataset.collection,
'revision': getattr(dataset.revision, 'name', None),
'default': dataset.default_dataset,
'qc': dataset.qc
}
out['file_records'] = file_records
return out
Expand Down Expand Up @@ -355,6 +356,7 @@ def create(self, request):
'hashes': ['f9c26e42-8f22-4f07-8fdd-bb51a63bedaa',
'f9c26e42-8f22-4f07-8fdd-bb51a63bedad'] # optional
'filesizes': [145684, 354213], # optional
'qc': ['NOT_SET', 'PASS'], # optional
'server_only': True, # optional, defaults to False. Will only create file
# records in the server repositories and skips local repositories
'versions': ['1.4.4', '1.4.4'], # optional, usually refers to the software version
Expand All @@ -375,7 +377,7 @@ def create(self, request):
```
If the dataset already exists, it will use the file hash to deduce if the file has been
patched or not (ie. the filerecords will be created as not existing)
patched or not (i.e. the filerecords will be created as not existing)
"""
user = request.data.get('created_by', None)
if user:
Expand Down Expand Up @@ -422,6 +424,13 @@ def create(self, request):
if isinstance(filesizes, str):
filesizes = filesizes.split(',')

# qc if provided
qcs = request.data.get('qc', [None] * len(filenames)) or 'NOT_SET'
if isinstance(qcs, str):
qcs = qcs.split(',')
if len(qcs) == 1:
qcs = qcs * len(filenames)

# flag to discard file records creation on local repositories, defaults to False
server_only = request.data.get('server_only', False)
if isinstance(server_only, str):
Expand Down Expand Up @@ -482,7 +491,7 @@ def create(self, request):
return Response(data=data, status=403)

response = []
for filename, hash, fsize, version in zip(filenames, hashes, filesizes, versions):
for filename, hash, fsize, version, qc in zip(filenames, hashes, filesizes, versions, qcs):
if not filename:
continue
info, resp = _get_name_collection_revision(filename, rel_dir_path)
Expand All @@ -499,7 +508,7 @@ def create(self, request):
collection=info['collection'], rel_dir_path=info['rel_dir_path'],
filename=info['filename'], session=session, user=user, repositories=repositories,
exists_in=exists_in, hash=hash, file_size=fsize, version=version,
revision=revision, default=default)
revision=revision, default=default, qc=qc)
if resp:
return resp
out = _make_dataset_response(dataset)
Expand Down
2 changes: 1 addition & 1 deletion alyx/misc/management/commands/one_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from experiments.models import ProbeInsertion

logger = logging.getLogger(__name__)
ONE_API_VERSION = '2.7.0' # Minimum compatible ONE api version
ONE_API_VERSION = '2.7' # Minimum compatible ONE api version


def measure_time(func):
Expand Down

0 comments on commit b8820b3

Please sign in to comment.