Esempio n. 1
0
    def __call__(self, func):
        """This is the real decorator.
        Returns:
        A wrapped function. The wrapper does input and output validation.
        """
        header_schema = None
        if self.header_params is not None:
            header_params = list(self.header_params)
            if self.request_schema:
                header_params.append(CONTENT_TYPE)
            header_schema = to_schema(header_params)

        path_schema = to_schema(self.path_params, required='all')
        query_schema = to_schema(self.query_params)

        self.func = func

        wrapped = self.wrap_with_validation(
            self.request_schema,
            self.response_schema,
            header_schema,
            path_schema,
            query_schema,
        )

        _verify_parameters(self.path, path_schema)

        self.operation_id = func.__module__ + "." + func.__name__

        def _mandatory_parameter_names(*_params):
            schema: Type[Schema]
            req = []
            for schema in _params:
                if not schema:
                    continue
                for name, field in schema().declared_fields.items():
                    if field.required:
                        req.append(field.attribute or name)
            return tuple(sorted(req))

        params = _mandatory_parameter_names(header_schema, path_schema,
                                            query_schema)

        # Call to see if a Rule can be constructed. Will throw an AttributeError if not possible.
        _ = self.default_path

        ENDPOINT_REGISTRY.add_endpoint(self, params)

        if not self.output_empty and self.response_schema is None:
            raise ValueError(
                f"{self.operation_id}: 'response_schema' required when output will be sent."
            )

        if self.output_empty and self.response_schema:
            raise ValueError(
                f"{self.operation_id}: If `output_empty` is True, "
                "'response_schema' may not be used.")

        self.wrapped = wrapped
        return self.wrapped
Esempio n. 2
0
def link_endpoint(
    module_name: str,
    rel: LinkRelation,
    parameters: Dict[str, str],
) -> LinkType:
    """Link to a specific endpoint by name.

    Args:
        module_name:
            The Python dotted path name, where the endpoint to be linked to, is defined.

        rel:
            The endpoint's rel-name.

        parameters:
            A dict, mapping parameter names to their desired values. e.g. if the link should have
            "/foo/{baz}" rendered to "/foo/bar", this mapping should be {'baz': 'bar'}.

    """
    endpoint = ENDPOINT_REGISTRY.lookup(module_name, rel, parameters)
    return link_rel(
        href=endpoint["endpoint"].make_url(parameters),
        rel=endpoint["rel"],
        method=endpoint["method"],
    )
Esempio n. 3
0
    def __call__(self, func: WrappedFunc) -> WrappedEndpoint:
        """This is the real decorator.
        Returns:
        A wrapped function. The wrapper does input and output validation.
        """
        self.operation_id = func.__module__ + "." + func.__name__
        if self.method in ("get", "delete") and self.request_schema:
            raise ValueError(
                f"According to the OpenAPI 3 spec, consumers SHALL ignore request bodies on "
                f"{self.method.upper()!r}. Please use another request method for the endpont: "
                f"{self.operation_id} "
                "See: https://swagger.io/specification/#operation-object")

        header_schema = None
        if self.header_params is not None:
            header_params = list(self.header_params)
            if self.request_schema:
                header_params.append(CONTENT_TYPE)
            header_schema = to_schema(header_params)

        path_schema = to_schema(self.path_params)
        query_schema = to_schema(self.query_params)
        response_schema = to_schema(self.response_schema)
        request_schema = to_schema(self.request_schema)

        self.func = func

        wrapped = self.wrapped = self.wrap_with_validation(
            request_schema,
            response_schema,
            header_schema,
            path_schema,
            query_schema,
        )

        _verify_parameters(self.path, path_schema)

        def _mandatory_parameter_names(*_params):
            schema: Type[Schema]
            req = []
            for schema in _params:
                if not schema:
                    continue
                for name, field in schema().declared_fields.items():
                    if field.required:
                        req.append(field.attribute or name)
            return tuple(sorted(req))

        params = _mandatory_parameter_names(header_schema, path_schema,
                                            query_schema)

        # Call to see if a Rule can be constructed. Will throw an AttributeError if not possible.
        _ = self.default_path

        ENDPOINT_REGISTRY.add_endpoint(self, params)

        if (self.content_type == "application/json" and not self.output_empty
                and self.response_schema is None):
            raise ValueError(
                f"{self.operation_id}: 'response_schema' required when output will be sent."
            )

        if self.output_empty and self.response_schema:
            raise ValueError(
                f"{self.operation_id}: If `output_empty` is True, "
                "'response_schema' may not be used.")

        return WrappedEndpoint(self, wrapped)