Skip to content

Commit

Permalink
update samplesheets api versioning (#1936)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkonie committed Sep 10, 2024
1 parent 2868dda commit eb0753b
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 38 deletions.
24 changes: 13 additions & 11 deletions docs_manual/source/api_samplesheets.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ Sample Sheets API
The REST API for sample sheet operations is described in this document.


Versioning
==========

Media Type
``application/vnd.bihealth.sodar.samplesheets+json``
Current Version
``1.0``
Accepted Versions
``1.0``
Header Example
``Accept: application/vnd.bihealth.sodar.samplesheets+json; version=x.y``


API Views
=========

Expand Down Expand Up @@ -58,14 +71,3 @@ iRODS Data Requests
.. autoclass:: IrodsDataRequestAcceptAPIView

.. autoclass:: IrodsDataRequestRejectAPIView


Versioning
==========

For accept header versioning, the following header is expected in the current
SODAR version:

.. code-block:: console
Accept: application/vnd.bihealth.sodar+json; version=0.15.0
7 changes: 7 additions & 0 deletions samplesheets/tests/test_views_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@
IrodsAccessTicketViewTestMixin,
)
from samplesheets.views import SheetImportMixin
from samplesheets.views_api import (
SAMPLESHEETS_API_MEDIA_TYPE,
SAMPLESHEETS_API_DEFAULT_VERSION,
)


app_settings = AppSettingAPI()
Expand Down Expand Up @@ -96,6 +100,9 @@
class SampleSheetAPIViewTestBase(SampleSheetIOMixin, APIViewTestBase):
"""Base view for samplesheets API views tests"""

media_type = SAMPLESHEETS_API_MEDIA_TYPE
api_version = SAMPLESHEETS_API_DEFAULT_VERSION


class IrodsAccessTicketAPITestBase(
IrodsAccessTicketMixin,
Expand Down
28 changes: 19 additions & 9 deletions samplesheets/tests/test_views_api_taskflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,6 @@
IRODS_REQUEST_STATUS_REJECTED,
IRODS_REQUEST_ACTION_DELETE,
)
from samplesheets.views import (
IRODS_REQUEST_EVENT_CREATE as CREATE_ALERT,
IRODS_REQUEST_EVENT_ACCEPT as ACCEPT_ALERT,
IRODS_REQUEST_EVENT_REJECT as REJECT_ALERT,
)
from samplesheets.views_api import (
IRODS_QUERY_ERROR_MSG,
)

from samplesheets.tests.test_io import SampleSheetIOMixin, SHEET_DIR
from samplesheets.tests.test_models import (
IrodsAccessTicketMixin,
Expand All @@ -60,6 +51,16 @@
TICKET_STR,
TICKET_LABEL,
)
from samplesheets.views import (
IRODS_REQUEST_EVENT_CREATE as CREATE_ALERT,
IRODS_REQUEST_EVENT_ACCEPT as ACCEPT_ALERT,
IRODS_REQUEST_EVENT_REJECT as REJECT_ALERT,
)
from samplesheets.views_api import (
IRODS_QUERY_ERROR_MSG,
SAMPLESHEETS_API_MEDIA_TYPE,
SAMPLESHEETS_API_DEFAULT_VERSION,
)

# SODAR constants
PROJECT_TYPE_PROJECT = SODAR_CONSTANTS['PROJECT_TYPE_PROJECT']
Expand All @@ -84,6 +85,9 @@ class SampleSheetAPITaskflowTestBase(
):
"""Base samplesheets API view test class with Taskflow enabled"""

media_type = SAMPLESHEETS_API_MEDIA_TYPE
api_version = SAMPLESHEETS_API_DEFAULT_VERSION

def setUp(self):
super().setUp()
# Make project with owner in Taskflow and Django
Expand All @@ -109,6 +113,9 @@ class IrodsAccessTicketAPIViewTestBase(
):
"""Base samplesheets API view test class for iRODS access ticket requests"""

media_type = SAMPLESHEETS_API_MEDIA_TYPE
api_version = SAMPLESHEETS_API_DEFAULT_VERSION

def assert_alert_count(self, alert_name, user, count, project=None):
"""
Assert expected app alert count. If project is not specified, default to
Expand Down Expand Up @@ -171,6 +178,9 @@ class TestIrodsDataRequestAPIViewBase(
):
"""Base samplesheets API view test class for iRODS delete requests"""

media_type = SAMPLESHEETS_API_MEDIA_TYPE
api_version = SAMPLESHEETS_API_DEFAULT_VERSION

# TODO: Retrieve this from a common base/helper class instead of redef
def assert_alert_count(self, alert_name, user, count, project=None):
"""
Expand Down
105 changes: 87 additions & 18 deletions samplesheets/views_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
UpdateAPIView,
)
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from rest_framework.versioning import AcceptHeaderVersioning
from rest_framework.views import APIView

# Projectroles dependency
Expand Down Expand Up @@ -70,6 +72,10 @@
table_builder = SampleSheetTableBuilder()


# Local constants
SAMPLESHEETS_API_MEDIA_TYPE = 'application/vnd.bihealth.sodar.samplesheets+json'
SAMPLESHEETS_API_ALLOWED_VERSIONS = ['1.0']
SAMPLESHEETS_API_DEFAULT_VERSION = '1.0'
MD5_RE = re.compile(r'([a-fA-F\d]{32})')
APP_NAME = 'samplesheets'
IRODS_QUERY_ERROR_MSG = 'Exception querying iRODS objects'
Expand All @@ -78,11 +84,31 @@
IRODS_TICKET_NO_UPDATE_FIELDS_MSG = 'No fields to update'


# Base Classes and Mixins ------------------------------------------------------


class SamplesheetsAPIVersioningMixin:
"""
Samplesheets API view versioning mixin for overriding media type and
accepted versions.
"""

class FilesfoldersAPIRenderer(JSONRenderer):
media_type = SAMPLESHEETS_API_MEDIA_TYPE

class FilesfoldersAPIVersioning(AcceptHeaderVersioning):
allowed_versions = SAMPLESHEETS_API_ALLOWED_VERSIONS
default_version = SAMPLESHEETS_API_DEFAULT_VERSION

renderer_classes = [FilesfoldersAPIRenderer]
versioning_class = FilesfoldersAPIVersioning


# API Views --------------------------------------------------------------------


class InvestigationRetrieveAPIView(
SODARAPIGenericProjectMixin, RetrieveAPIView
SamplesheetsAPIVersioningMixin, SODARAPIGenericProjectMixin, RetrieveAPIView
):
"""
Retrieve metadata of an investigation with its studies and assays.
Expand Down Expand Up @@ -116,7 +142,10 @@ class InvestigationRetrieveAPIView(


class IrodsCollsCreateAPIView(
IrodsCollsCreateViewMixin, SODARAPIBaseProjectMixin, APIView
IrodsCollsCreateViewMixin,
SamplesheetsAPIVersioningMixin,
SODARAPIBaseProjectMixin,
APIView,
):
"""
Create iRODS collections for a project.
Expand Down Expand Up @@ -162,7 +191,10 @@ def post(self, request, *args, **kwargs):


class SheetISAExportAPIView(
SheetISAExportMixin, SODARAPIBaseProjectMixin, APIView
SheetISAExportMixin,
SamplesheetsAPIVersioningMixin,
SODARAPIBaseProjectMixin,
APIView,
):
"""
Export sample sheets as ISA-Tab TSV files, either packed in a zip archive or
Expand Down Expand Up @@ -197,7 +229,12 @@ def get(self, request, *args, **kwargs):
raise APIException('Unable to export ISA-Tab: {}'.format(ex))


class SheetImportAPIView(SheetImportMixin, SODARAPIBaseProjectMixin, APIView):
class SheetImportAPIView(
SheetImportMixin,
SamplesheetsAPIVersioningMixin,
SODARAPIBaseProjectMixin,
APIView,
):
"""
Upload sample sheet as separate ISA-Tab TSV files or a zip archive. Will
replace existing sheets if valid.
Expand Down Expand Up @@ -315,7 +352,7 @@ def post(self, request, *args, **kwargs):


class IrodsAccessTicketRetrieveAPIView(
SODARAPIGenericProjectMixin, RetrieveAPIView
SamplesheetsAPIVersioningMixin, SODARAPIGenericProjectMixin, RetrieveAPIView
):
"""
Retrieve an iRODS access ticket for a project.
Expand Down Expand Up @@ -345,7 +382,9 @@ class IrodsAccessTicketRetrieveAPIView(
queryset_project_field = 'study__investigation__project'


class IrodsAccessTicketListAPIView(SODARAPIBaseProjectMixin, ListAPIView):
class IrodsAccessTicketListAPIView(
SamplesheetsAPIVersioningMixin, SODARAPIBaseProjectMixin, ListAPIView
):
"""
List iRODS access tickets for a project.
Expand Down Expand Up @@ -376,7 +415,10 @@ def get_queryset(self):


class IrodsAccessTicketCreateAPIView(
IrodsAccessTicketModifyMixin, SODARAPIGenericProjectMixin, CreateAPIView
IrodsAccessTicketModifyMixin,
SamplesheetsAPIVersioningMixin,
SODARAPIGenericProjectMixin,
CreateAPIView,
):
"""
Create an iRODS access ticket for a project.
Expand Down Expand Up @@ -429,7 +471,10 @@ def perform_create(self, serializer):


class IrodsAccessTicketUpdateAPIView(
IrodsAccessTicketModifyMixin, SODARAPIGenericProjectMixin, UpdateAPIView
IrodsAccessTicketModifyMixin,
SamplesheetsAPIVersioningMixin,
SODARAPIGenericProjectMixin,
UpdateAPIView,
):
"""
Update an iRODS access ticket for a project.
Expand Down Expand Up @@ -463,7 +508,10 @@ def perform_update(self, serializer):


class IrodsAccessTicketDestroyAPIView(
IrodsAccessTicketModifyMixin, SODARAPIGenericProjectMixin, DestroyAPIView
IrodsAccessTicketModifyMixin,
SamplesheetsAPIVersioningMixin,
SODARAPIGenericProjectMixin,
DestroyAPIView,
):
"""
Delete an iRODS access ticket.
Expand Down Expand Up @@ -497,7 +545,7 @@ def perform_destroy(self, instance):


class IrodsDataRequestRetrieveAPIView(
SODARAPIGenericProjectMixin, RetrieveAPIView
SamplesheetsAPIVersioningMixin, SODARAPIGenericProjectMixin, RetrieveAPIView
):
"""
Retrieve a iRODS data request.
Expand Down Expand Up @@ -526,7 +574,9 @@ class IrodsDataRequestRetrieveAPIView(
serializer_class = IrodsDataRequestSerializer


class IrodsDataRequestListAPIView(SODARAPIBaseProjectMixin, ListAPIView):
class IrodsDataRequestListAPIView(
SamplesheetsAPIVersioningMixin, SODARAPIBaseProjectMixin, ListAPIView
):
"""
List the iRODS data requests for a project.
Expand Down Expand Up @@ -561,7 +611,10 @@ def get_queryset(self):


class IrodsDataRequestCreateAPIView(
IrodsDataRequestModifyMixin, SODARAPIGenericProjectMixin, CreateAPIView
IrodsDataRequestModifyMixin,
SamplesheetsAPIVersioningMixin,
SODARAPIGenericProjectMixin,
CreateAPIView,
):
"""
Create an iRODS delete request for a project.
Expand Down Expand Up @@ -592,7 +645,10 @@ def perform_create(self, serializer):


class IrodsDataRequestUpdateAPIView(
IrodsDataRequestModifyMixin, SODARAPIGenericProjectMixin, UpdateAPIView
IrodsDataRequestModifyMixin,
SamplesheetsAPIVersioningMixin,
SODARAPIGenericProjectMixin,
UpdateAPIView,
):
"""
Update an iRODS data request for a project.
Expand Down Expand Up @@ -622,7 +678,10 @@ def perform_update(self, serializer):


class IrodsDataRequestDestroyAPIView(
IrodsDataRequestModifyMixin, SODARAPIGenericProjectMixin, DestroyAPIView
IrodsDataRequestModifyMixin,
SamplesheetsAPIVersioningMixin,
SODARAPIGenericProjectMixin,
DestroyAPIView,
):
"""
Delete an iRODS data request object.
Expand Down Expand Up @@ -651,7 +710,10 @@ def perform_destroy(self, instance):


class IrodsDataRequestAcceptAPIView(
IrodsDataRequestModifyMixin, SODARAPIBaseProjectMixin, APIView
IrodsDataRequestModifyMixin,
SamplesheetsAPIVersioningMixin,
SODARAPIBaseProjectMixin,
APIView,
):
"""
Accept an iRODS data request for a project.
Expand Down Expand Up @@ -696,7 +758,10 @@ def post(self, request, *args, **kwargs):


class IrodsDataRequestRejectAPIView(
IrodsDataRequestModifyMixin, SODARAPIBaseProjectMixin, APIView
IrodsDataRequestModifyMixin,
SamplesheetsAPIVersioningMixin,
SODARAPIBaseProjectMixin,
APIView,
):
"""
Reject an iRODS data request for a project.
Expand Down Expand Up @@ -738,7 +803,9 @@ def post(self, request, *args, **kwargs):
)


class SampleDataFileExistsAPIView(SODARAPIBaseMixin, APIView):
class SampleDataFileExistsAPIView(
SamplesheetsAPIVersioningMixin, SODARAPIBaseMixin, APIView
):
"""
Return status of data object existing in SODAR iRODS by MD5 checksum.
Includes all projects in search regardless of user permissions.
Expand Down Expand Up @@ -812,7 +879,9 @@ def get(self, request, *args, **kwargs):
return Response(ret, status=status.HTTP_200_OK)


class ProjectIrodsFileListAPIView(SODARAPIBaseProjectMixin, APIView):
class ProjectIrodsFileListAPIView(
SamplesheetsAPIVersioningMixin, SODARAPIBaseProjectMixin, APIView
):
"""
Return a list of files in the project sample data repository.
Expand Down

0 comments on commit eb0753b

Please sign in to comment.