def decorator_interceptor(*args, **kwargs): """ The interceptor function for the transaction decorator. """ # retrieves the self reference self = args[0] # retrieves the request reference and uses it to retrieve # the associated parameters instance to be used in the # operations to be done in the decorator request = args[1] parameters = request.parameters try: # calls the callback function, # retrieving the return value return_value = colony.call_safe(function, *args, **kwargs) except BaseException as exception: # logs a warning message because if an exception reached # this area it must be considered not handled gracefully # and must be considered an anomaly self.warning( "There was an exception in controller (%s): " %\ exception.__class__.__name__ + colony.legacy.UNICODE(exception) ) # retrieves the serializer and the exception # values from the parameters serializer = parameters.get("serializer", None) exception_handler = parameters.get("exception_handler", None) # in case the serializer and the exception # handler are not set must raise the exception # to the top levels, nothing to be done here if not serializer and not exception_handler: raise # verifies if the current exception contains a status # code attribute and in case it does uses it instead # of the default (fallback) error status code has_status_code = hasattr(exception, "status_code") status_code = exception.status_code if\ has_status_code else ERROR_STATUS_CODE # sets the error status code in the current request indicating # that a problem has occurred (default behavior) self.set_status_code(request, status_code) # retrieves the exception map for the exception, this map should # include extra information on the request together with the "base" # information about the exception to be handled exception_map = self.get_exception_map(exception, request) # retrieves the exception value from the exception map and then # unpacks it into its components of message or traceback exception = exception_map.get("exception") message = exception.get("message") traceback = exception.get("traceback") # in case the serializer is set (uses it as it # is has priority) if serializer: # dumps the exception map to the serialized form ant then # sets the serialized map as the request contents with # the appropriate mime type exception_map_serialized = serializer.dumps(exception_map) mime_type = serializer.get_mime_type() self.set_contents( request, exception_map_serialized, content_type = mime_type ) # sets the return value as invalid (error) return_value = False # in case the exception handler is set, must call the proper action # method so that the visual exception handler is called elif exception_handler: # retrieves the proper name for the exception handler action method # taking into account the "complex" naming scheme and the simplified # one os that it maintain compatibility with both schemes, then calls # the action method (handler) with the exception map as argument has_simple = hasattr(exception_handler, "exception") method_name = "exception" if has_simple else "handle_exception" method = getattr(exception_handler, method_name) return_value = colony.call_safe( method, request, parameters = exception_map, message = message, traceback = traceback ) else: # checks if the current message is already flushed (data sent to # the output) and in case it's not and there should be a default # success message sent the default success message is create, then # serialized and written to the output stream in the request is_flushed = request.is_flushed() serializer = parameters.get("serializer", None) should_default = not is_flushed and default_success and serializer if should_default: success_serialized = serializer.dumps(dict(result = "success")) mime_type = serializer.get_mime_type() self.set_contents( request, success_serialized, content_type = mime_type ) # returns the return value, resulting from the decorated method # this should be an already serialized value return return_value
def decorator_interceptor(*args, **kwargs): """ The interceptor function for the transaction decorator. """ # retrieves the self reference self = args[0] # retrieves the request reference and uses it to retrieve # the associated parameters instance to be used in the # operations to be done in the decorator request = args[1] parameters = request.parameters # retrieves the value for the serializer attribute, if this # value is defined it must contain a callable object that is # able to serialize any dictionary oriented value seralizer = parameters.get("serializer", None) # in case the call validation flag is not defined the value # of the should call (validation) flag must be inferred from # the existence or not of the serializer, because serialized # methods are not considered to be validated if call_validation_failed == None: should_call = False if seralizer else True # otherwise simply use the call validation failed value as the # value for the should call boolean flag (transition of value) else: should_call = call_validation_failed # in case the controller instance does not have the validate method # an exception should be raised indicating the problem if not hasattr(self, "validate"): raise exceptions.ControllerValidationError("validation method not found", self) # tests if the controller instance contains the validate method and # then tries to retrieve the current state of validation for the request # workflow, if the current request is already validated or if the current # controller does not contain a validate method the validation should # not be ran contains_validate = hasattr(self, "validate") validated = parameters.get("validated", False) run_validate = contains_validate and not validated # calls the validate method with the request # the parameters and the validation parameters and retrieves # the list with the validation failure reasons, in case no validate # method is present ignores the call reasons_list = run_validate and\ self.validate(request, parameters, validation_parameters) or [] # updates the validated flag for the current request workflow so that # no second validation occurs, this is the default (top to down) expected # behavior as only the front-end method gets validated parameters["validated"] = True # tries to retrieves the validation failed method from the current controller # instance, this is going to be used in case the validation method is enabled validation_failed_method = hasattr(self, "validation_failed") and\ self.validation_failed or None # in case the reasons list is not empty, there was a validation that failed # and so either the validation failed method must be called or an exception # should be immediately raised indicating the problem if reasons_list: # in case a validation failed method is defined and # the validation method should be called (by flag) if validation_failed_method and should_call: # calls the validation failed method with the request the parameters the # validation parameters and the reasons list and sets the return value return_value = validation_failed_method( request, parameters, validation_parameters, reasons_list ) # otherwise there is no validation method defined and the exception # must be raised (default fallback strategy) else: # raises the controller validation failed exception to indicate that # there was a problem validating the controller's action method raise exceptions.ControllerValidationReasonFailed( "validation failed for a series of reasons: " + str(reasons_list), self, reasons_list ) # otherwise the reason list is empty (no errors have occurred) and so the # "normal" function call workflow must be used else: return_value = colony.call_safe(function, *args, **kwargs) # returns the return value, retrieved from either the # validation method or form the decorated function return return_value