Exemple #1
0
def load_app() -> App:
    sys.path.insert(0, os.getcwd())
    spec = importlib.util.spec_from_file_location("app", "app.py")
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    app = getattr(module, 'app', None)
    if app is None:
        msg = "The 'app.py' module did not contain an 'app' variable."
        raise exceptions.ConfigurationError(msg)
    if not isinstance(app, App):
        msg = "The 'app' variable in 'app.py' is not an App instance."
        raise exceptions.ConfigurationError(msg)
    return app
Exemple #2
0
def login(credentials: LoginSchema, jwt: JWT) -> str:
    """
    View d'authentification

    Args:
        credentials: credentials username/password
        jwt: JWT componement pour l'encodage du payload

    Toutes les erreurs "raise"

    Returns:
        token
    """

    user = User.get(username=credentials["username"])

    if not user or not user.check_password(credentials["password"]):
        raise exceptions.Forbidden("Incorrect username or password.")

    if not user.actif:
        raise exceptions.Forbidden("Utilisateur inactif")

    payload = {
        "id": user.id,
        "username": user.username,
        "iat": pendulum.now(),
        "exp": pendulum.now() + pendulum.Duration(seconds=1000),
    }
    token = jwt.encode(payload)
    if token is None:
        raise exceptions.ConfigurationError("échec de l'encodage jwt")

    return token
Exemple #3
0
    def __init__(self, routes: RouteConfig) -> None:
        rules = []  # type: typing.List[Rule]
        views = {}  # type: typing.Dict[str, typing.Callable]

        for path, method, view, name in flatten_routes(routes):
            if name in views:
                msg = ('Route wtih name "%s" exists more than once. Use an '
                       'explicit name="..." on the Route to avoid a conflict.'
                       ) % name
                raise exceptions.ConfigurationError(msg)

            template = uritemplate.URITemplate(path)
            werkzeug_path = str(path)

            parameters = inspect.signature(view).parameters

            for arg in template.variable_names:
                converter = self._get_converter(parameters, arg, view)
                template_format = '{%s}' % arg
                werkzeug_format = '<%s:%s>' % (converter, arg)
                werkzeug_path = werkzeug_path.replace(template_format,
                                                      werkzeug_format)

            rule = Rule(werkzeug_path, methods=[method], endpoint=name)
            rules.append(rule)
            views[name] = view

        self._routes = routes
        self._adapter = Map(rules).bind('')
        self._views = views

        # Use an MRU cache for router lookups.
        self._lookup_cache = collections.OrderedDict(
        )  # type: collections.OrderedDict
        self._lookup_cache_size = 10000
Exemple #4
0
    def __init__(self, value: Mapping = None) -> None:
        if value is None:
            value = self._os_environ

        try:
            super().__init__(value)
        except exceptions.SchemaError as exc:
            raise exceptions.ConfigurationError(exc.detail)
    def __init__(self, value: typing.Mapping = None) -> None:
        if value is None:
            value = self._os_environ

        try:
            super().__init__(value)
        except exceptions.TypeSystemError as exc:
            raise exceptions.ConfigurationError(exc.detail) from None
Exemple #6
0
 def get_url(self, path: str) -> str:
     try:
         return self._router.reverse_url('serve_static',
                                         values={'path': path})
     except exceptions.NoReverseMatch:
         msg = (
             'The "serve_static" handler must be included in the App routes '
             'in order to use WhiteNoiseStaticFiles')
         raise exceptions.ConfigurationError(msg) from None
Exemple #7
0
 def can_handle_parameter(self, parameter: inspect.Parameter):
     """重写这个方法是为了增加typing.Union类型的判定"""
     return_annotation = inspect.signature(self.resolve).return_annotation
     if return_annotation is inspect.Signature.empty:
         msg = ('Component "%s" must include a return annotation on the '
                '`resolve()` method, or override `can_handle_parameter`')
         raise exceptions.ConfigurationError(msg % self.__class__.__name__)
     return type(return_annotation) == typing._Union and \
            parameter.annotation in return_annotation.__args__ or \
            parameter.annotation is return_annotation
Exemple #8
0
def get_current_app(use_cache=True) -> App:
    global _current_app

    if _current_app is not None and use_cache:
        return _current_app

    sys.path.insert(0, os.getcwd())
    spec = importlib.util.spec_from_file_location("app", "app.py")
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    app = getattr(module, 'app', None)
    if app is None:
        msg = "The 'app.py' module did not contain an 'app' variable."
        raise exceptions.ConfigurationError(msg)
    if not isinstance(app, App):
        msg = "The 'app' variable in 'app.py' is not an App instance."
        raise exceptions.ConfigurationError(msg)

    if use_cache:
        _current_app = app

    return app
Exemple #9
0
    def _get_converter(self, parameters: typing.Mapping[str,
                                                        inspect.Parameter],
                       arg: str, view: typing.Callable) -> str:
        if arg not in parameters:
            msg = 'URL Argument "%s" missing from view "%s".' % (arg, view)
            raise exceptions.ConfigurationError(msg)

        annotation = parameters[arg].annotation

        if annotation is inspect.Parameter.empty:
            return 'string'
        elif issubclass(annotation, PathWildcard):
            return 'path'
        elif issubclass(annotation, str):
            return 'string'
        elif issubclass(annotation, int):
            return 'int'
        elif issubclass(annotation, float):
            return 'float'

        msg = 'Invalid type for path parameter "%s" in view "%s".' % (
            parameters[arg], view)
        raise exceptions.ConfigurationError(msg)
Exemple #10
0
 def can_handle_parameter(self, parameter: inspect.Parameter):
     # Return `True` if this component can handle the given parameter.
     #
     # The default behavior is for components to handle whatever class
     # is used as the return annotation by the `resolve` method.
     #
     # You can override this for more customized styles, for example if you
     # wanted name-based parameter resolution, or if you want to provide
     # a value for a range of different types.
     #
     # Eg. Include the `Request` instance for any parameter named `request`.
     return_annotation = inspect.signature(self.resolve).return_annotation
     if return_annotation is inspect.Signature.empty:
         msg = ('Component "%s" must include a return annotation on the '
                "`resolve()` method, or override `can_handle_parameter`")
         raise exceptions.ConfigurationError(msg % self.__class__.__name__)
     return parameter.annotation is return_annotation
Exemple #11
0
    def __init__(self,
                 routes: RoutesConfig,
                 initial_types: List[type] = None) -> None:
        required_type = wsgi.WSGIResponse

        initial_types = initial_types or []
        initial_types += [wsgi.WSGIEnviron, URLPathArgs, Exception]

        rules = []
        views = {}

        for (path, method, view) in walk(routes):
            view_signature = inspect.signature(view)
            uritemplate = URITemplate(path)

            # Ensure view arguments include all URL arguments
            for arg in uritemplate.variable_names:
                assert arg in view_signature.parameters, (
                    'URL argument "%s" in path "%s" must be included as a '
                    'keyword argument in the view function "%s"' %
                    (arg, path, view.__name__))

            # Create a werkzeug path string
            werkzeug_path = path[:]
            for arg in uritemplate.variable_names:
                param = view_signature.parameters[arg]
                if param.annotation is inspect.Signature.empty:
                    converter = 'string'
                elif issubclass(param.annotation, (schema.String, str)):
                    if getattr(param.annotation, 'format', None) == 'path':
                        converter = 'path'
                    else:
                        converter = 'string'
                elif issubclass(param.annotation, (schema.Number, float)):
                    converter = 'float'
                elif issubclass(param.annotation, (schema.Integer, int)):
                    converter = 'int'
                else:
                    msg = 'Invalid type for path parameter, %s.' % param.annotation
                    raise exceptions.ConfigurationError(msg)

                werkzeug_path = werkzeug_path.replace(
                    '{%s}' % arg, '<%s:%s>' % (converter, arg))

            # Create a werkzeug routing rule
            name = view.__name__
            rule = Rule(werkzeug_path, methods=[method], endpoint=name)
            rules.append(rule)

            # Determine any inferred type annotations for the view
            extra_annotations = {}  # type: Dict[str, type]
            for param in view_signature.parameters.values():

                if param.annotation is inspect.Signature.empty:
                    annotated_type = str
                else:
                    annotated_type = param.annotation

                if param.name in uritemplate.variable_names:

                    class TypedURLPathArg(URLPathArg):
                        schema = annotated_type

                    extra_annotations[param.name] = TypedURLPathArg
                elif (annotated_type in primitive_types) or issubclass(
                        annotated_type, schema_types):
                    if method in ('POST', 'PUT', 'PATCH'):
                        if issubclass(annotated_type, schema.Object):

                            class TypedDataParam(http.RequestData):
                                schema = annotated_type

                            extra_annotations[param.name] = TypedDataParam
                        else:

                            class TypedFieldParam(http.RequestField):
                                schema = annotated_type

                            extra_annotations[param.name] = TypedFieldParam
                    else:

                        class TypedQueryParam(http.QueryParam):
                            schema = annotated_type

                        extra_annotations[param.name] = TypedQueryParam

            return_annotation = view_signature.return_annotation
            if return_annotation is inspect.Signature.empty:
                extra_annotations['return'] = http.ResponseData
            elif issubclass(
                    return_annotation,
                (schema_types, primitive_types, typing_types)):  # type: ignore
                extra_annotations['return'] = http.ResponseData

            # Determine the pipeline for the view.
            pipeline = pipelines.build_pipeline(view, initial_types,
                                                required_type,
                                                extra_annotations)
            views[name] = Endpoint(view, pipeline)

        self.exception_pipeline = pipelines.build_pipeline(
            exception_handler, initial_types, required_type, {})
        self.routes = routes
        self.adapter = Map(rules).bind('example.com')
        self.views = views
    def generate_fields(self, url, method, handler):
        if not self.documented:
            return []

        fields = []

        for name, param in signature(handler).parameters.items():
            if issubclass(param.annotation, _PathParam):
                if issubclass(param.annotation, int):
                    validator_cls = validators.Integer
                elif issubclass(param.annotation, float):
                    validator_cls = validators.Number
                elif issubclass(param.annotation, str):
                    validator_cls = validators.String
                else:
                    raise exceptions.ConfigurationError(
                        f"Cannot handle {name} of {handler}")

                location = 'path'
                schema = validator_cls()
                field = Field(name=name, location=location, schema=schema)
                fields.append(field)

            elif issubclass(param.annotation, _QueryParam):
                if param.default is param.empty:
                    kwargs = {}
                elif param.default is None:
                    # TODO handle Optional
                    kwargs = {'default': None, 'allow_null': True}
                else:
                    kwargs = {'default': param.default}

                if issubclass(param.annotation, int):
                    validator_cls = validators.Integer
                elif issubclass(param.annotation, float):
                    validator_cls = validators.Number
                elif issubclass(param.annotation, str):
                    validator_cls = validators.String
                elif getattr(param.annotation, '__bool__', None):
                    validator_cls = validators.Boolean
                else:
                    raise exceptions.ConfigurationError(
                        f"Cannot handle {name} of {handler}")

                location = 'query'
                schema = validator_cls(**kwargs)
                field = Field(name=name, location=location, schema=schema)
                fields.append(field)

            elif issubclass(param.annotation, _BodyData):
                location = 'body'
                schema = validators.Object()
                field = Field(name=name, location=location, schema=schema)
                fields.append(field)

            elif issubclass(param.annotation, ParamData):
                raise exceptions.ConfigurationError(
                    f"{param.annotation} do not support documentation.")

            else:
                # fallback to original generate_fields() method
                path_names = [
                    item.strip('{}').lstrip('+')
                    for item in re.findall('{[^}]*}', url)
                ]
                if name in path_names:
                    schema = {
                        param.empty: None,
                        int: validators.Integer(),
                        float: validators.Number(),
                        str: validators.String()
                    }[param.annotation]
                    field = Field(name=name, location='path', schema=schema)
                    fields.append(field)

                elif param.annotation in (param.empty, int, float, bool, str,
                                          http.QueryParam):
                    if param.default is param.empty:
                        kwargs = {}
                    elif param.default is None:
                        kwargs = {'default': None, 'allow_null': True}
                    else:
                        kwargs = {'default': param.default}
                    schema = {
                        param.empty: None,
                        int: validators.Integer(**kwargs),
                        float: validators.Number(**kwargs),
                        bool: validators.Boolean(**kwargs),
                        str: validators.String(**kwargs),
                        http.QueryParam: validators.String(**kwargs),
                    }[param.annotation]
                    field = Field(name=name, location='query', schema=schema)
                    fields.append(field)

                elif issubclass(param.annotation, types.Type):
                    if method in ('GET', 'DELETE'):
                        items = param.annotation.validator.properties.items()
                        for name, validator in items:
                            field = Field(name=name,
                                          location='query',
                                          schema=validator)
                            fields.append(field)
                    else:
                        field = Field(name=name,
                                      location='body',
                                      schema=param.annotation.validator)
                        fields.append(field)

        return fields