@@ -345,7 +345,7 @@ class Meta:
345345 allowed_methods = ['get' , 'post' , 'put' ]
346346 authorization = Authorization ()
347347 authentication = ApiKeyAuthentication ()
348- throttle = CacheThrottle (throttle_at = 50 , timeframe = 60 )
348+ throttle = CacheThrottle (throttle_at = 500 , timeframe = 60 )
349349
350350 def _db (self ):
351351 try :
@@ -370,6 +370,8 @@ def get_object_list(self, request):
370370
371371 query = {}
372372
373+ if "query" in request .GET :
374+ query = request .GET ['query' ]
373375 if "number" in request .GET :
374376 query ['number' ] = int (request .GET ['number' ])
375377 if "detector" in request .GET :
@@ -379,6 +381,7 @@ def get_object_list(self, request):
379381 if "_id" in request .GET :
380382 query ['_id' ] = request .GET ['_id' ]
381383
384+
382385 cursor = self ._db ()[settings .RUNS_DB_COLLECTION ].find (query ).sort ("_id" , - 1 )
383386
384387 ret = []
@@ -530,3 +533,210 @@ def obj_delete(self, bundle, **kwargs):
530533
531534 def rollback (self , bundles ):
532535 pass
536+
537+
538+
539+ # Run
540+ class QualityResource (Resource ):
541+ number = fields .IntegerField (attribute = "number" )
542+ _id = fields .CharField (attribute = "_id" )
543+ detector = fields .CharField (attribute = "detector" )
544+ name = fields .CharField (attribute = "name" )
545+ doc = fields .DictField (attribute = "doc" )
546+ class Meta :
547+ resource_name = 'quality'
548+ object_class = rundoc
549+ allowed_methods = ['get' , 'post' , 'put' ]
550+ authorization = Authorization ()
551+ authentication = ApiKeyAuthentication ()
552+ throttle = CacheThrottle (throttle_at = 500 , timeframe = 60 )
553+
554+ def _db (self ):
555+ try :
556+ return (pymongo .MongoClient (settings .RUNS_DB_ADDR )
557+ [settings .RUNS_DB_NAME ])
558+ except :
559+ return None
560+
561+ def detail_uri_kwargs (self , bundle_or_obj ):
562+ kwargs = {}
563+ if isinstance (bundle_or_obj , Bundle ):
564+ kwargs ['pk' ] = bundle_or_obj .obj ._id
565+ else :
566+ kwargs ['pk' ] = bundle_or_obj ._id
567+ return kwargs
568+
569+ def get_object_list (self , request ):
570+ # This will return a stripped down version of the run doc
571+ # It includes _id, name, number (if applicable), and detector
572+ self .throttle_check (request )
573+ self .log_throttled_access (request )
574+
575+ query = {}
576+
577+ if "query" in request .GET :
578+ query = request .GET ['query' ]
579+ if "number" in request .GET :
580+ query ['number' ] = int (request .GET ['number' ])
581+ if "detector" in request .GET :
582+ query ['detector' ] = request .GET ['detector' ]
583+ if "name" in request .GET :
584+ query ['name' ] = request .GET ['name' ]
585+ if "_id" in request .GET :
586+ query ['_id' ] = request .GET ['_id' ]
587+
588+
589+ cursor = self ._db ()[settings .RUNS_DB_COLLECTION ].find (query ).sort ("_id" , - 1 )
590+
591+ ret = []
592+ for doc in cursor :
593+ if 'number' in doc :
594+ thedoc = {"number" : doc ['number' ] }
595+ else :
596+ thedoc = {"number" : - 1 }
597+ thedoc ['name' ] = doc ['name' ]
598+ thedoc ['_id' ] = doc ['_id' ]
599+ thedoc ['detector' ] = doc ['detector' ]
600+ thedoc ['doc' ] = doc
601+ ret .append (rundoc (initial = thedoc ))
602+
603+ return ret
604+
605+
606+ def obj_get_list (self , bundle , ** kwargs ):
607+ return self .get_object_list (bundle .request )
608+
609+
610+ def obj_get (self , bundle , ** kwargs ):
611+ self .throttle_check (bundle .request )
612+ self .log_throttled_access (bundle .request )
613+ req = {}
614+ if 'pk' in kwargs :
615+ req ['_id' ] = kwargs ['pk' ]
616+ return self ._create_obj (req )
617+ return rundoc (initial = {"error" : "For now we only support searching for a run by number" })
618+
619+ def _create_obj (self , req ):
620+
621+ doc = self ._db ()[settings .RUNS_DB_COLLECTION ].find_one (
622+ {"_id" :
623+ ObjectId (req ['_id' ])})
624+ if doc is None :
625+ return
626+
627+ ret = {}
628+ if 'number' in doc :
629+ ret ['number' ] = doc ['number' ]
630+ else :
631+ ret ['number' ] = - 1
632+ ret ['detector' ] = doc ['detector' ]
633+ ret ['_id' ] = doc ['_id' ]
634+ ret ['name' ] = doc ['name' ]
635+ ret ['doc' ] = doc
636+ ret_obj = rundoc (initial = ret )
637+
638+ return ret_obj
639+
640+ def obj_create (self , bundle , ** kwargs ):
641+ return self .obj_update (bundle , kwargs )
642+
643+
644+
645+ def obj_update (self , bundle , ** kwargs ):
646+ self .throttle_check (bundle .request )
647+ self .log_throttled_access (bundle .request )
648+ searchDict = {}
649+ ret = {}
650+
651+ reader = codecs .getreader ("utf-8" )
652+ request = (json .load (reader (bundle .request )))
653+ logger .error (request )
654+ if 'pk' in kwargs :
655+ searchDict ['_id' ] = ObjectId (kwargs ['pk' ])
656+ elif 'number' in request :
657+ searchDict ['number' ] = int (request ['number' ])
658+ elif 'name' in request and 'detector' in request :
659+ searchDict ['name' ] = request ['name' ]
660+ searchDict ['detector' ] = request ['detector' ]
661+
662+ # We REQUIRE the following format
663+ # {
664+ # "qname": a unique name for this check
665+ # "version": the version info for this check
666+ # "checks": [] a list of string/bool pairs i.e. {"deadtime": true}
667+ # "extracted": a dictionary of any format of size < 100kB
668+ # }
669+
670+
671+ updateDict = {}
672+ if ( 'qname' not in request or 'checks' not in request
673+ or 'version' not in request ):
674+ doc = self ._default (
675+ "ERROR" ,
676+ "Bad request. Require status, host, location, and type"
677+ )
678+ bundle .obj = rundoc (initial = doc )
679+ bundle = self .full_hydrate (bundle )
680+ return bundle .obj
681+
682+ updateDict ['qname' ] = request ['qname' ]
683+ updateDict ['checks' ] = request ['checks' ]
684+ updateDict ['version' ] = request ['version' ]
685+
686+ if 'extracted' in request :
687+ if sys .getsizeof (request ['extracted' ]) > 50000 :
688+ doc = self ._default (
689+ "ERROR" ,
690+ "Bad request. Quality dictionary must be less than 50kB."
691+ )
692+ bundle .obj = rundoc (initial = doc )
693+ bundle = self .full_hydrate (bundle )
694+ return bundle .obj
695+ else :
696+ updateDict ['extracted' ] = request ['extracted' ]
697+
698+ # Enforce string/bool types for checks array
699+ for key , value in updateDict ['checks' ]:
700+ extre = "test"
701+ if type (key ) != type (extre ) or type (value ) != type (True ):
702+
703+ elif request ['status' ] == 'processed' :
704+ if 'pax_version' not in request :
705+ return {"number" : doc ['number' ],
706+ "ERROR" : "pax_version must be provided for processed data" }
707+ updateDict ['pax_version' ] = request ['pax_version' ]
708+
709+ # Status needed for new entry
710+ updateDict ['status' ] = request ['status' ]
711+ updateDict ['creation_time' ] = datetime .datetime .utcnow (),
712+
713+ # Now add a new entry
714+ res = self ._db ()[settings .RUNS_DB_COLLECTION ].update_one (
715+ searchDict ,
716+ {"$push" : {"data" : updateDict }})
717+ doc = self ._default (
718+ "Success" ,
719+ "Document updated" ,
720+ res
721+ )
722+ bundle .obj = rundoc (initial = doc )
723+ bundle = self .full_hydrate (bundle )
724+
725+ return rundoc (initial = doc )
726+
727+ def _default (self , message , longer , return_value ):
728+ doc = {
729+ "number" : - 1 ,
730+ "_id" : - 1 ,
731+ "detector" : "ret" ,
732+ "name" : message ,
733+ "doc" : {
734+ "message" : longer ,
735+ "success" : message ,
736+ "ret" : return_value
737+ }
738+ }
739+ return doc
740+
741+ def obj_delete_list (self , bundle , ** kwargs ):
742+ pass
0 commit comments