Skip to content

Commit

Permalink
Merge pull request #370 from azneto/master
Browse files Browse the repository at this point in the history
Creates history table to log every managment command execution
  • Loading branch information
azneto authored Jan 21, 2025
2 parents 60e81ae + 1f4edf0 commit 0692b78
Show file tree
Hide file tree
Showing 38 changed files with 741 additions and 102 deletions.
39 changes: 38 additions & 1 deletion machado/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from machado.models import Cvterm, Feature, Featureloc
from machado.models import FeatureRelationship
from machado.models import Pub
from machado.models import Organism, Pub


class JBrowseGlobalSerializer(serializers.Serializer):
Expand Down Expand Up @@ -203,6 +203,39 @@ class OrganismIDSerializer(serializers.Serializer):
organism_id = serializers.IntegerField()


class OrganismListSerializer(serializers.ModelSerializer):
"""Organism serializer."""

genus = serializers.CharField(required=True, help_text="The genus of the organism.")
species = serializers.CharField(
required=True, help_text="The species of the organism."
)
abbreviation = serializers.CharField(
required=False, help_text="Abbreviation of the organism name."
)
common_name = serializers.CharField(
required=False, help_text="Common name of the organism."
)
infraspecific_name = serializers.CharField(
required=False, help_text="Infraspecific name of the organism."
)
comment = serializers.CharField(
required=False, help_text="Additional comments about the organism."
)

class Meta:
model = Organism
fields = [
"organism_id",
"genus",
"species",
"abbreviation",
"common_name",
"infraspecific_name",
"comment",
]


class FeatureIDSerializer(serializers.Serializer):
"""Feature ID serializer."""

Expand Down Expand Up @@ -461,3 +494,7 @@ class FeatureLocationSerializer(serializers.Serializer):
strand = serializers.IntegerField()
ref = serializers.CharField()
jbrowse_url = serializers.CharField()


class LoadCallSerializer(serializers.Serializer):
"""Load call serializer."""
49 changes: 31 additions & 18 deletions machado/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,79 +12,92 @@
from drf_yasg.views import get_schema_view
from drf_yasg import openapi

from machado.api import views
from machado.api.views import read as readViews
from machado.api.views import load as loadViews


router = routers.SimpleRouter(trailing_slash=False)

# readViews

router.register(
"jbrowse/stats/global", views.JBrowseGlobalViewSet, basename="jbrowse_global"
"jbrowse/stats/global", readViews.JBrowseGlobalViewSet, basename="jbrowse_global"
)
router.register(
r"jbrowse/features/(?P<refseq>.+)",
views.JBrowseFeatureViewSet,
readViews.JBrowseFeatureViewSet,
basename="jbrowse_features",
)
router.register(r"jbrowse/names", views.JBrowseNamesViewSet, basename="jbrowse_names")
router.register(
r"jbrowse/refSeqs.json", views.JBrowseRefSeqsViewSet, basename="jbrowse_refseqs"
r"jbrowse/names", readViews.JBrowseNamesViewSet, basename="jbrowse_names"
)
router.register(
r"jbrowse/refSeqs.json", readViews.JBrowseRefSeqsViewSet, basename="jbrowse_refseqs"
)
router.register(r"autocomplete", views.autocompleteViewSet, basename="autocomplete")
router.register(r"autocomplete", readViews.autocompleteViewSet, basename="autocomplete")

router.register(r"organism/id", views.OrganismIDViewSet, basename="organism_id")
router.register(r"feature/id", views.FeatureIDViewSet, basename="feature_id")
router.register(r"organism/id", readViews.OrganismIDViewSet, basename="organism_id")
router.register(
r"organism/list", readViews.OrganismListViewSet, basename="organism_list"
)
router.register(r"feature/id", readViews.FeatureIDViewSet, basename="feature_id")
router.register(
r"feature/ontology/(?P<feature_id>\d+)",
views.FeatureOntologyViewSet,
readViews.FeatureOntologyViewSet,
basename="feature_ontology",
)

router.register(
r"feature/ortholog/(?P<feature_id>\d+)",
views.FeatureOrthologViewSet,
readViews.FeatureOrthologViewSet,
basename="feature_ortholog",
)
router.register(
r"feature/proteinmatches/(?P<feature_id>\d+)",
views.FeatureProteinMatchesViewSet,
readViews.FeatureProteinMatchesViewSet,
basename="feature_proteinmatches",
)
router.register(
r"feature/expression/(?P<feature_id>\d+)",
views.FeatureExpressionViewSet,
readViews.FeatureExpressionViewSet,
basename="feature_expression",
)
router.register(
r"feature/coexpression/(?P<feature_id>\d+)",
views.FeatureCoexpressionViewSet,
readViews.FeatureCoexpressionViewSet,
basename="feature_coexpression",
)
router.register(
r"feature/info/(?P<feature_id>\d+)",
views.FeatureInfoViewSet,
readViews.FeatureInfoViewSet,
basename="feature_info",
)
router.register(
r"feature/location/(?P<feature_id>\d+)",
views.FeatureLocationViewSet,
readViews.FeatureLocationViewSet,
basename="feature_location",
)
router.register(
r"feature/publication/(?P<feature_id>\d+)",
views.FeaturePublicationViewSet,
readViews.FeaturePublicationViewSet,
basename="feature_publication",
)
router.register(
r"feature/sequence/(?P<feature_id>\d+)",
views.FeatureSequenceViewSet,
readViews.FeatureSequenceViewSet,
basename="feature_sequence",
)
router.register(
r"feature/similarity/(?P<feature_id>\d+)",
views.FeatureSimilarityViewSet,
readViews.FeatureSimilarityViewSet,
basename="feature_similarity",
)


# loadViews

router.register(r"load/organism", loadViews.OrganismViewSet, basename="load_organism")

baseurl = None
if hasattr(settings, "MACHADO_URL"):
baseurl = "{}/api/".format(settings.MACHADO_URL)
Expand Down
5 changes: 5 additions & 0 deletions machado/api/views/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright 2018 by Embrapa. All rights reserved.
#
# This code is part of the machado distribution and governed by its
# license. Please see the LICENSE.txt and README.md files that should
# have been included as part of this package for licensing information.
99 changes: 99 additions & 0 deletions machado/api/views/load.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Copyright 2018 by Embrapa. All rights reserved.
#
# This code is part of the machado distribution and governed by its
# license. Please see the LICENSE.txt and README.md files that should
# have been included as part of this package for licensing information.

"""Load views."""

from django.conf import settings
from django.core.management import call_command

from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema

from machado.api.serializers import LoadCallSerializer

from rest_framework import viewsets
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from threading import Thread


class OrganismViewSet(viewsets.GenericViewSet):
"""ViewSet for loading organism."""

serializer_class = LoadCallSerializer
permission_classes = [IsAuthenticated]
operation_summary = "Load organism"
operation_description = operation_summary + "<br /><br />"
if hasattr(settings, "MACHADO_EXAMPLE_ORGANISM_COMMON_NAME"):
operation_description += "<b>Example:</b><br />common_name={}".format(
settings.MACHADO_EXAMPLE_ORGANISM_COMMON_NAME
)

request_body = openapi.Schema(
type=openapi.TYPE_OBJECT,
properties={
"genus": openapi.Schema(type=openapi.TYPE_STRING, description="Genus"),
"species": openapi.Schema(type=openapi.TYPE_STRING, description="Species"),
"infraspecific_name": openapi.Schema(
type=openapi.TYPE_STRING, description="Infraspecific name"
),
"abbreviation": openapi.Schema(
type=openapi.TYPE_STRING, description="Abbreviation"
),
"common_name": openapi.Schema(
type=openapi.TYPE_STRING, description="Common name"
),
"comment": openapi.Schema(type=openapi.TYPE_STRING, description="Comment"),
},
)

@swagger_auto_schema(
request_body=request_body,
operation_summary=operation_summary,
operation_description=operation_description,
)
def create(self, request):
"""Handle the POST request for loading organism."""
genus = request.data.get("genus")
species = request.data.get("species")
abbreviation = request.data.get("abbreviation")
common_name = request.data.get("common_name")
infraspecific_name = request.data.get("infraspecific_name")
comment = request.data.get("comment")

if not genus or not species:
return Response(
{"error": "Genus and species are required."},
status=status.HTTP_400_BAD_REQUEST,
)

thread = Thread(
target=call_command,
args=("insert_organism",),
kwargs=(
{
"genus": genus,
"species": species,
"abbreviation": abbreviation,
"common_name": common_name,
"infraspecific_name": infraspecific_name,
"comment": comment,
}
),
daemon=True,
)

thread.start()

return Response(
{
"status": "Submited successfully",
"call_command": "insert_organism",
},
status=status.HTTP_200_OK,
)
13 changes: 12 additions & 1 deletion machado/api/views.py → machado/api/views/read.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# license. Please see the LICENSE.txt and README.md files that should
# have been included as part of this package for licensing information.

"""Views."""
"""Read views."""

from django.conf import settings
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
Expand Down Expand Up @@ -37,6 +37,7 @@
from machado.api.serializers import FeatureSequenceSerializer
from machado.api.serializers import FeatureSimilaritySerializer
from machado.api.serializers import OrganismIDSerializer
from machado.api.serializers import OrganismListSerializer
from machado.loaders.common import retrieve_organism, retrieve_feature_id
from machado.models import Analysis, Analysisfeature, Cvterm, Organism, Pub
from machado.models import Feature, Featureloc, Featureprop, FeatureRelationship
Expand Down Expand Up @@ -473,6 +474,16 @@ def dispatch(self, *args, **kwargs):
return super(OrganismIDViewSet, self).dispatch(*args, **kwargs)


class OrganismListViewSet(viewsets.ViewSet):
"""Retrieve all the organisms."""

def list(self, request):
"""List."""
queryset = Organism.objects.exclude(genus="multispecies")
serializer = OrganismListSerializer(queryset, many=True)
return Response(serializer.data)


class FeatureIDViewSet(viewsets.GenericViewSet):
"""Retrieve the feature ID by accession."""

Expand Down
7 changes: 7 additions & 0 deletions machado/management/commands/insert_organism.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from machado.loaders.common import insert_organism
from machado.loaders.exceptions import ImportingError
from machado.models import History


class Command(BaseCommand):
Expand Down Expand Up @@ -44,6 +45,9 @@ def handle(
**options
) -> None:
"""Execute the main function."""
history_obj = History()
history_obj.start(command="insert_organism", params=locals())

try:
insert_organism(
genus=genus,
Expand All @@ -54,8 +58,11 @@ def handle(
comment=comment,
)
except ImportingError as e:
history_obj.failure(description=str(e))
raise CommandError(e)

history_obj.success(description="{} {} registered".format(genus, species))

if verbosity > 0:
self.stdout.write(
self.style.SUCCESS("{} {} registered".format(genus, species))
Expand Down
17 changes: 10 additions & 7 deletions machado/management/commands/load_coexpression_clusters.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from machado.loaders.common import retrieve_organism
from machado.loaders.exceptions import ImportingError
from machado.loaders.feature import FeatureLoader
from machado.models import Cv, Cvterm, Dbxref, Db
from machado.models import Cv, Cvterm, Dbxref, Db, History


class Command(BaseCommand):
Expand Down Expand Up @@ -65,22 +65,22 @@ def handle(
**options
):
"""Execute the main function."""
history_obj = History()
history_obj.start(command="load_coexpression_clusters", params=locals())
filename = os.path.basename(file)
if verbosity > 0:
self.stdout.write("Processing file: {}".format(filename))

try:
organism = retrieve_organism(organism)
except IntegrityError as e:
raise ImportingError(e)
try:
FileValidator().validate(file)
except ImportingError as e:
raise CommandError(e)
try:
clusters = open(file, "r")
# retrieve only the file name
except IntegrityError as e:
history_obj.failure(description=str(e))
raise ImportingError(e)
except ImportingError as e:
history_obj.failure(description=str(e))
raise CommandError(e)

tasks = list()
Expand Down Expand Up @@ -111,12 +111,14 @@ def handle(
try:
FieldsValidator().validate(nfields, fields)
except ImportingError as e:
history_obj.failure(description=str(e))
raise CommandError(e)

if re.search(r"^(\w+)\:", fields[0]):
group_field = re.match(r"^(\w+)\:", fields[0])
name = group_field.group(1)
else:
history_obj.failure(description="Cluster identification has problems.")
raise CommandError("Cluster identification has problems.")
# remove cluster name before loading
fields.pop(0)
Expand All @@ -136,5 +138,6 @@ def handle(
if task.result():
raise (task.result())
pool.shutdown()
history_obj.success(description="Done")
if verbosity > 0:
self.stdout.write(self.style.SUCCESS("Done with {}".format(filename)))
Loading

0 comments on commit 0692b78

Please sign in to comment.