Esempio n. 1
0
def test_s_arg_wrapper():
    """Tests the arg.s wrapper utility

    Simulates the same test scenario as test_validators_with_defaults()
    """

    def fails(arg1):
        """A validator that always passes"""
        if arg1 == 'UPPER':
            raise ValueError

    def my_func(arg1):
        return arg1

    my_func_runner = arg.s(
        arg.defaults(arg1=arg.val('arg1').upper()), arg.validators(fails)
    )

    with pytest.raises(ValueError):
        my_func_runner(my_func)(arg1='upper')

    assert my_func_runner(my_func)(arg1='lower') == 'LOWER'

    assert isinstance(arg.s()(my_func), arg.Args)
    assert arg.s()(my_func)('hello') == 'hello'
    def run(self):
        request_args = self.request.data
        form = self.form_class(request_args)
        form.full_clean()
        self.args = {
            **self.get_default_args(),
            **request_args,
            **form.cleaned_data,
        }

        def _validate_form():
            if not form.is_valid():
                raise exceptions.ValidationError(form.errors)

        wrapper = arg.s(self.get_wrapper(), arg.validators(_validate_form))
        self.result = wrapper(self.action.func)(**self.args)

        object_to_serialize = self.result

        # Object actions may be parametrized and return a list by default.
        # Return only one object if this is the case
        if (isinstance(object_to_serialize, list)
                and len(object_to_serialize) == 1):
            object_to_serialize = object_to_serialize[0]

        if self.refetch_for_serialization:
            object_to_serialize = self.get_object()

        serializer = self.viewset.get_serializer(
            object_to_serialize, context={'request': self.request})
        return Response(serializer.data)
Esempio n. 3
0
    def wrapper(cls):
        arg_decs = []
        if cls.select_for_update is not None:  # pragma: no branch
            arg_decs = [arg.contexts(transaction.atomic)]

        arg_decs += [
            arg.defaults(
                **{
                    cls.objects_arg:
                    arg.first(
                        'objects',
                        daf.contrib.single_list('object'),
                        cls.objects_arg,
                    )
                }),
            arg.defaults(
                **{
                    cls.objects_arg:
                    djarg.qset(
                        cls.objects_arg,
                        qset=cls.queryset,
                        select_for_update=cls.select_for_update,
                    )
                }),
            super().wrapper,
        ]

        return arg.s(*arg_decs)
Esempio n. 4
0
 def run_func(self):
     """
     Run the primary function. This should be called from the "done()"
     method that is overridden by users.
     """
     self.func_args = {
         **self.get_default_args(),
         **self.get_cleaned_data(*self.get_form_list()),
     }
     self.func_results = arg.s()(self.func)(**self.func_args)
     return self.func_results
Esempio n. 5
0
class GrantStaffObjectsView(djarg.views.SuccessMessageMixin,
                            djarg.views.ObjectsFormView):
    model = User
    func = arg.s(
        arg.contexts(error_collector=raise_trapped_errors),
        arg.parametrize(user=arg.val('objects')),
        arg.contexts(trap_errors),
    )(grant_staff_access)
    template_name = 'tests/grant_staff_access.html'
    form_class = GrantAccessObjectForm
    success_url = '.'
    success_message = '{granter} successfully granted staff access to users.'

    def get_default_args(self):
        return {**super().get_default_args(), **{'granter': self.request.user}}
 def wrapper(cls):
     return arg.s(
         arg.contexts(trapped_errors=daf.contrib.raise_trapped_errors),
         arg.defaults(
             objects=arg.first(
                 'objects',
                 daf.contrib.single_list('object'),
                 daf.contrib.single_list(cls.object_arg),
             )
         ),
         arg.defaults(objects=djarg.qset('objects', qset=cls.queryset)),
         arg.parametrize(**{cls.object_arg: arg.val('objects')}),
         arg.contexts(daf.contrib.trap_errors),
         super().wrapper,
     )
Esempio n. 7
0
    def check_class_definition(cls):
        """
        Verifies all properties have been filled out properly for the action
        class. Called by the metaclass only on concrete actions
        """
        super().check_class_definition()

        if not cls.objects_arg:
            cls.definition_error('Must provide "objects_arg" attribute.')

        func_parameters = inspect.signature(arg.s()(cls.func).func).parameters
        if cls.objects_arg not in func_parameters:
            cls.definition_error(
                f'objects_arg "{cls.objects_arg}" not an argument to callable.'
                f' Possible parameters={func_parameters}')
 def wrapper(cls):
     return arg.s(
         arg.defaults(
             **{
                 cls.objects_arg: arg.first(
                     'objects',
                     daf.contrib.single_list('object'),
                     cls.objects_arg,
                 )
             }
         ),
         arg.defaults(
             **{
                 cls.objects_arg: djarg.qset(
                     cls.objects_arg, qset=cls.queryset
                 )
             }
         ),
         super().wrapper,
     )
Esempio n. 9
0
    def wrapper(cls):
        arg_decs = []
        if cls.select_for_update is not None:  # pragma: no branch
            arg_decs = [arg.contexts(transaction.atomic)]

        arg_decs += [
            arg.contexts(trapped_errors=daf.contrib.raise_trapped_errors),
            arg.defaults(objects=arg.first(
                'objects',
                daf.contrib.single_list('object'),
                daf.contrib.single_list(cls.object_arg),
            )),
            arg.defaults(objects=djarg.qset(
                'objects',
                qset=cls.queryset,
                select_for_update=cls.select_for_update,
            )),
            arg.parametrize(**{cls.object_arg: arg.val('objects')}),
            arg.contexts(daf.contrib.trap_errors),
            super().wrapper,
        ]

        return arg.s(*arg_decs)
 def name(cls):
     """The identifying name of the action"""
     return arg.s()(cls.func).func.__name__
Esempio n. 11
0
class Interface(metaclass=InterfaceMeta):
    """
    Provides base properties for any action interface.
    """

    ###
    # Core properties of the interface.
    ###

    # The primary action
    action = None

    # Instrumentation of how the action is run
    wrapper = arg.s()

    @classmethod
    def get_wrapper(cls):
        # A utility so that instance methods can safely access
        # the class wrapper variable. self.wrapper() will use
        # "self" as an argument when calling
        return cls.wrapper

    @utils.classproperty
    def func(cls):
        return cls.get_wrapper()(cls.action.func)

    # The namespace to which the interface belongs. Allows for querying
    # interfaces for a particular type of application such as the admin
    namespace = ''

    # The type of interface
    type = 'interface'

    @utils.classproperty
    def uri(cls):
        """The URI used when registering the interface to an action"""
        return f'{cls.namespace}.{cls.type}' if cls.namespace else cls.type

    @classmethod
    def as_interface(cls, **kwargs):
        cls.check_interface_definition()
        interface = cls.build_interface(**kwargs)
        cls.check_built_interface(interface)
        return interface

    @classmethod
    def build_interface(cls, **kwargs):
        raise NotImplementedError

    ###
    # Mirrored static action properties.
    #
    # Static action properties are automatically mirrored as
    # static properties on interfaces.
    ###

    @utils.classproperty
    def app_label(cls):
        return cls.action.app_label

    @utils.classproperty
    def model(cls):
        return cls.action.model

    @utils.classproperty
    def url_name(cls):
        return f'{cls.action.url_name}_{cls.type}'

    @utils.classproperty
    def url_path(cls):
        return cls.action.url_path

    @utils.classproperty
    def permission_uri(cls):
        return cls.action.permission_uri

    @utils.classproperty
    def display_name(cls):
        return cls.action.display_name

    @utils.classproperty
    def queryset(cls):
        return cls.action.queryset

    ###
    # Mirrored dynamic action properties.
    #
    # The get_ methods for dynamic action properties are automatically
    # mirrored on interfaces.
    ###

    def get_success_message(self, args, results):
        return self.action.get_success_message(args, results)

    ###
    # Runtime properties that change behavior.
    ###

    # True if the action permission should be required
    permission_required = False

    ###
    # Interface class checkers.
    #
    # When interfaces are created, class definitions are checked to ensure
    # they are are set up correctly.
    ###

    @classmethod
    def definition_error(cls, msg):
        raise AttributeError(f'{cls.__name__} - {msg}')

    @classmethod
    def check_interface_definition(cls):
        pass

    @classmethod
    def check_built_interface(cls, interface):
        pass
Esempio n. 12
0
 def run_func(self, form):
     self.func_args = {**self.get_default_args(), **form.cleaned_data}
     self.func_results = arg.s()(self.func)(**self.func_args)
     return self.func_results