Beispiel #1
0
        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
Beispiel #2
0
        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