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
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
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
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
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
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
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
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)
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
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