Beispiel #1
0
    def resolve_function(self,
                         func,
                         output_name=None,
                         seen_state=None,
                         parent_parameter=None):
        if output_name is None:
            output_name = 'response'
        if seen_state is None:
            seen_state = set(self.initial)

        steps = []
        kwargs = {}
        consts = {}

        parameters = inspect.signature(func).parameters.values()
        for parameter in parameters:
            # The 'response' keyword always indicates the previous return value.
            if parameter.name == 'response':
                kwargs['response'] = 'response'
                continue

            # Check if the parameter class exists in 'initial'.
            if parameter.annotation in self.reverse_initial:
                initial_kwarg = self.reverse_initial[parameter.annotation]
                kwargs[parameter.name] = initial_kwarg
                continue

            # The 'Parameter' annotation can be used to get the parameter
            # itself. Used for example in 'Header' components that need the
            # parameter name in order to lookup a particular value.
            if parameter.annotation is inspect.Parameter:
                consts[parameter.name] = parent_parameter
                continue

            # Otherwise, find a component to resolve the parameter.
            for component in self.components:
                if component.can_handle_parameter(parameter):
                    identity = component.identity(parameter)
                    kwargs[parameter.name] = identity
                    if identity not in seen_state:
                        seen_state.add(identity)
                        steps += self.resolve_function(
                            func=component.resolve,
                            output_name=identity,
                            seen_state=seen_state,
                            parent_parameter=parameter)
                    break
            else:
                msg = 'No component able to handle parameter "%s" on function "%s".'
                raise ConfigurationError(msg % (parameter.name, func.__name__))

        is_async = asyncio.iscoroutinefunction(func)
        if is_async and not self.allow_async:
            msg = 'Function "%s" may not be async.'
            raise ConfigurationError(msg % (func.__name__, ))

        step = (func, is_async, kwargs, consts, output_name)
        steps.append(step)
        return steps
Beispiel #2
0
 def encode(payload, secret=None, algorithm=None, **kwargs):
     if secret is None:
         msg = 'The secret keyword argument must be defined.'
         raise ConfigurationError(msg) from None
     algorithm = 'HS256' if algorithm is None else algorithm
     try:
         token = jwt.encode(payload, secret, algorithm=algorithm,
                            **kwargs).decode(encoding='UTF-8')
     except Exception as exc:
         raise ConfigurationError(exc.__class__.__name__) from None
     return token
Beispiel #3
0
def get_current_app() -> App:
    app_path = get_app_path()
    if not os.path.exists(app_path):
        raise ConfigurationError("No app.py module exists.")

    spec = importlib.util.spec_from_file_location("app", app_path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    app = getattr(module, 'app', None)
    if app is None:
        raise ConfigurationError("The app.py module did not contain an 'app' variable.")

    return app
Beispiel #4
0
    def __new__(cls, name, bases, attrs):
        properties = []
        for key, value in list(attrs.items()):
            if key in ['keys', 'items', 'values', 'get', 'validator']:
                msg = ('Cannot use reserved name "%s" on Type "%s", as it '
                       'clashes with the class interface.')
                raise ConfigurationError(msg % (key, name))

            elif hasattr(value, 'validate'):
                attrs.pop(key)
                properties.append((key, value))

        # If this class is subclassing another Type, add that Type's properties.
        # Note that we loop over the bases in reverse. This is necessary in order
        # to maintain the correct order of properties.
        for base in reversed(bases):
            if hasattr(base, 'validator'):
                properties = [(key, base.validator.properties[key])
                              for key in base.validator.properties
                              if key not in attrs] + properties

        properties = sorted(properties,
                            key=lambda item: item[1]._creation_counter)
        required = [
            key for key, value in properties if not value.has_default()
        ]

        attrs['validator'] = validators.Object(def_name=name,
                                               properties=properties,
                                               required=required,
                                               additional_properties=None)
        attrs['_creation_counter'] = validators.Validator._creation_counter
        validators.Validator._creation_counter += 1
        return super(TypeMetaclass, cls).__new__(cls, name, bases, attrs)
Beispiel #5
0
 def __init__(self,
              settings: Settings,
              token=None,
              issuer=None,
              audience=None,
              leeway=None):
     jwt_settings = settings.get('JWT', {})
     self.secret = jwt_settings.get('SECRET', None)
     if self.secret is None:
         msg = 'The SECRET setting under JWT settings must be defined.'
         raise ConfigurationError(msg) from None
     self.algorithms = jwt_settings.get('ALGORITHMS', ['HS256'])
     self.token = token
     self.issuer = issuer if issuer is not None else jwt_settings.get(
         'ISSUER', None)
     self.audience = audience if audience is not None else jwt_settings.get(
         'AUDIENCE', None)
     self.leeway = leeway if leeway is not None else jwt_settings.get(
         'LEEWAY', None)
     try:
         kwargs = {}
         if self.issuer:
             kwargs.update({'issuer': self.issuer})
         if self.audience:
             kwargs.update({'audience': self.audience})
         if self.leeway:
             kwargs.update({'leeway': self.leeway})
         self.payload = jwt.decode(self.token,
                                   self.secret,
                                   algorithms=self.algorithms,
                                   **kwargs)
     except Exception:
         self.payload = None
         raise AuthenticationFailed()
Beispiel #6
0
 def build(cls, arg_name: ArgName, templates: Templates):
     paths = arg_name.split(cls.path_delimiter)
     path = os.path.join(cls.prefix, *paths)
     for suffix in cls.suffixes:
         try:
             return templates.get_template(path + suffix)
         except jinja2.TemplateNotFound:
             pass
     raise ConfigurationError('No template found for "%s".' % arg_name)
Beispiel #7
0
def get_settings(settings: Settings):
    user_settings = dict(DEFAULTS)
    user_settings.update(settings.get(SETTINGS_KEY, {}))

    for module in IMPORT_STRINGS:
        if module not in user_settings and module not in DEFAULTS:
            raise ConfigurationError(f'{module} settings is required.')

        if user_settings['ORM'] == 'sqlalcamy':
            user_settings[module] = import_from_string(user_settings[module])

    return user_settings
Beispiel #8
0
def test(file_or_dir):
    if not file_or_dir:
        file_or_dir = []
        if os.path.exists('tests'):
            file_or_dir.append('tests')
        if os.path.exists('tests.py'):
            file_or_dir.append('tests.py')
        if not file_or_dir:
            raise ConfigurationError(
                "No 'tests/' directory or 'tests.py' module.")

    exitcode = pytest.main(list(file_or_dir))
    if exitcode:
        sys.exit(exitcode)
Beispiel #9
0
def get_current_app():
    app_path = os.path.join(os.getcwd(), 'app.py')
    if not os.path.exists(app_path):
        raise NoCurrentApp("No app.py module exists.")

    spec = importlib.util.spec_from_file_location("app", app_path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    if not hasattr(module, 'app'):
        raise ConfigurationError(
            "The app.py module did not contain an 'app' variable.")

    app = module.app
    return app
Beispiel #10
0
def test() -> None:  # pragma: nocover
    """
    Run the test suite.
    """
    file_or_dir = []
    if os.path.exists('tests'):
        file_or_dir.append('tests')
    if os.path.exists('tests.py'):
        file_or_dir.append('tests.py')
    if not file_or_dir:
        raise ConfigurationError("No 'tests/' directory or 'tests.py' module.")

    exitcode = pytest.main(list(file_or_dir))
    if exitcode:
        sys.exit(exitcode)
Beispiel #11
0
def test(file_or_dir):
    from apistar.main import get_current_app
    app = get_current_app()

    if not file_or_dir:
        file_or_dir = []
        if os.path.exists('tests'):
            file_or_dir.append('tests')
        if os.path.exists('tests.py'):
            file_or_dir.append('tests.py')
        if not file_or_dir:
            raise ConfigurationError(
                "No 'tests/' directory or 'tests.py' module.")

    exitcode = pytest.main(list(file_or_dir))
    if exitcode:
        sys.exit(exitcode)
Beispiel #12
0
    def __new__(cls, name, bases, attrs):
        properties = []
        for key, value in list(attrs.items()):
            if key in ['keys', 'items', 'values', 'get', 'validator']:
                msg = ('Cannot use reserved name "%s" on Type "%s", as it '
                       'clashes with the class interface.')
                raise ConfigurationError(msg % (key, name))

            elif isinstance(value, validators.Validator):
                attrs.pop(key)
                properties.append((key, value))

        properties = sorted(properties,
                            key=lambda item: item[1]._creation_counter)
        required = [
            key for key, value in properties if not value.has_default()
        ]

        attrs['validator'] = validators.Object(def_name=name,
                                               properties=properties,
                                               required=required,
                                               additional_properties=None)
        return super(TypeMetaclass, cls).__new__(cls, name, bases, attrs)
Beispiel #13
0
 def _raise_setup_error(self):
     msg = ('JWT_SECRET must be defined as an environment variable or passed as part of'
            ' settings on instantiation.'
            ' See https://github.com/audiolion/apistar-jwt#Setup')
     raise ConfigurationError(msg)
    def resolve_function(
        self,
        func,
        output_name=None,
        seen_state=None,
        parent_parameter=None,
        set_return=False,
    ):
        if seen_state is None:
            seen_state = set(self.initial)

        steps = []
        kwargs = {}
        consts = {}

        signature = inspect.signature(func)

        if output_name is None:
            if signature.return_annotation in self.reverse_initial:
                output_name = self.reverse_initial[signature.return_annotation]
            else:
                output_name = "return_value"

        for parameter in signature.parameters.values():
            if parameter.annotation is ReturnValue:
                kwargs[parameter.name] = "return_value"
                continue

            # Check if the parameter class exists in 'initial'.
            if parameter.annotation in self.reverse_initial:
                initial_kwarg = self.reverse_initial[parameter.annotation]
                kwargs[parameter.name] = initial_kwarg
                continue

            # The 'Parameter' annotation can be used to get the parameter
            # itself. Used for example in 'Header' components that need the
            # parameter name in order to lookup a particular value.
            if parameter.annotation is inspect.Parameter:
                consts[parameter.name] = parent_parameter
                continue

            # Otherwise, find a component to resolve the parameter.
            for component in self.components:
                if component.can_handle_parameter(parameter):
                    identity = component.identity(parameter)
                    kwargs[parameter.name] = identity
                    if identity not in seen_state:
                        seen_state.add(identity)
                        steps += self.resolve_function(
                            func=component.resolve,
                            output_name=identity,
                            seen_state=seen_state,
                            parent_parameter=parameter,
                        )
                    break
            else:
                msg = f"No component able to handle parameter {parameter.name}: {parameter} on function {func.__name__}."
                raise ConfigurationError(msg)

        is_async = asyncio.iscoroutinefunction(func)
        if is_async and not self.allow_async:
            msg = 'Function "%s" may not be async.'
            raise ConfigurationError(msg % (func.__name__, ))

        step = (func, is_async, kwargs, consts, output_name, set_return)
        steps.append(step)
        return steps