Ejemplo n.º 1
0
    def test_get_kwarg_names(self):
        def func1():
            pass

        self.assertEqual(utils.get_kwarg_names(func1), [])

        def func2(key1):
            pass

        self.assertEqual(utils.get_kwarg_names(func2), ["key1"])

        def func3(key1, key2=2):
            pass

        self.assertEqual(utils.get_kwarg_names(func3), ["key1", "key2"])

        def func4(key1, *argv, key2=2):
            pass

        self.assertEqual(utils.get_kwarg_names(func4), ["key2"])

        def func5(*argv, key1, key2=2):
            pass

        self.assertEqual(utils.get_kwarg_names(func5), ["key1", "key2"])

        def func6(key1, key2, key3, *argv):
            pass

        self.assertEqual(utils.get_kwarg_names(func6), [])

        def func7(key1, key2=1, key3=3, **kwargs):
            pass

        self.assertEqual(utils.get_kwarg_names(func7),
                         ["key1", "key2", "key3"])
Ejemplo n.º 2
0
    def sample(self, sampling_rule, **kwargs):
        '''Samples the sampling rule

        Returns a sampled instance of the `sampling_rule` field.
        The logic behind the sampling depends on the type of
        `sampling_rule`. These are checked in the following order of
        priority:

        1. Any object with a callable `sample()` method has this
            method called and returned.
        2. If the rule is a ``dict``, sample each value and combine the 
            result into a new ``dict`` using the original keys.
        3. If the rule is a ``list``, sample each element of the list and
            combine the result into a ne ``list``.
        4. If the rule is an ``iterable``, return the next output.
        5. If the rule is callable, call it with its accepted arguments.
            Example arguments can be the value of some other property.
        6. If none of the above apply, return the rule itself.
        
        Parameters
        ----------
        sampling_rule : any
            The rule to sample values from.
        **kwargs
            Arguments that will be passed on to functions that accepts them.

        Returns
        -------
        any
            A sampled instance of the `sampling_rule`.

        '''

        if hasmethod(sampling_rule, "sample"):
            # If the ruleset itself implements a sample method,
            # call it instead.
            return sampling_rule.sample(**kwargs)

        elif isinstance(sampling_rule, dict):
            # If the ruleset is a dict, return a new dict with each
            # element being sampled from the original dict.
            out = {}
            for key, val in self.sampling_rule.items():
                out[key] = self.sample(val, **kwargs)
            return out

        elif isinstance(sampling_rule, list):
            return [self.sample(item, **kwargs) for item in sampling_rule]

        elif isinstance(sampling_rule, (tuple, np.ndarray)):
            # tuple and ndarrays are elementary
            return sampling_rule

        elif isiterable(sampling_rule):
            # If it's iterable, return the next value
            try:
                return next(sampling_rule)
            except StopIteration:
                return self.current_value

        elif callable(sampling_rule):
            # If it's a function, extract the arguments it accepts.
            function_input = {}

            # Get the kwarg arguments the function accepts
            for key in get_kwarg_names(sampling_rule):
                # If that name is among passed kwarg arguments
                if key in kwargs:
                    if isinstance(kwargs[key], Property):
                        # If it is a property, update it and pass the current value
                        kwargs[key].update(**kwargs)

                        if isinstance(kwargs[key], SequentialProperty):
                            kwargs[key] = kwargs[key].current_value[
                                kwargs["sequence_step"]]
                        else:
                            kwargs[key] = kwargs[key].current_value

                    function_input[key] = kwargs[key]

            return sampling_rule(**function_input)

        else:
            # Else, assume it's elementary.
            return sampling_rule
Ejemplo n.º 3
0
    def sample(self, sampling_rule, **kwargs):
        """Samples the sampling rule

        Returns a sampled instance of the `sampling_rule` field.
        The logic behind the sampling depends on the type of
        `sampling_rule`. These are checked in the following order of
        priority:

        1. Any object with a callable `sample()` method has this
            method called and returned.
        2. If the rule is a ``dict``, sample each value and combine the
            result into a new ``dict`` using the original keys.
        3. If the rule is a ``list``, sample each element of the list and
            combine the result into a ne ``list``.
        4. If the rule is an ``iterable``, return the next output.
        5. If the rule is callable, call it with its accepted arguments.
            Example arguments can be the value of some other property.
        6. If none of the above apply, return the rule itself.

        Parameters
        ----------
        sampling_rule : any
            The rule to sample values from.
        **kwargs
            Arguments that will be passed on to functions that accepts them.

        Returns
        -------
        any
            A sampled instance of the `sampling_rule`.

        """

        if isinstance(sampling_rule, deeptrack.Feature):
            # I am worried passing kwargs may lead to name clash
            sampling_rule._update(**kwargs)
            return sampling_rule

        if isinstance(sampling_rule, Property):
            sampling_rule.parent.update_item(sampling_rule)
            return sampling_rule.current_value

        elif isinstance(sampling_rule, dict):
            # If the ruleset is a dict, return a new dict with each
            # element being sampled from the original dict.
            out = {}
            for key, val in sampling_rule.items():
                out[key] = self.sample(val, **kwargs)
            return out

        elif isinstance(sampling_rule, list):
            return [self.sample(item, **kwargs) for item in sampling_rule]

        elif isinstance(sampling_rule, (tuple, np.ndarray)):
            # tuple and ndarrays are elementary
            return sampling_rule

        elif isiterable(sampling_rule):
            # If it's iterable, return the next value
            try:
                return next(sampling_rule)
            except StopIteration:
                return self.current_value

        elif callable(sampling_rule):
            # If it's a function, extract the arguments it accepts.
            function_input = {}

            # Get the kwarg arguments the function accepts
            knames = get_kwarg_names(sampling_rule)
            for i in range(len(knames)):
                key = knames[i]
                # If that name is among passed kwarg arguments
                if key in kwargs:
                    if isinstance(kwargs[key], Property):
                        # If it is a property, update it and pass the current value
                        if not kwargs[key] is self:
                            if kwargs[key].parent:
                                kwargs[key].parent.update_item(kwargs[key])
                            else:
                                kwargs[key].update(**kwargs)

                        if (isinstance(kwargs[key], SequentialProperty)
                                and "sequence_step" in kwargs):
                            function_input[key] = kwargs[key].current_value[
                                kwargs["sequence_step"]]
                        else:
                            function_input[key] = kwargs[key].current_value

                    else:
                        function_input[key] = kwargs[key]

                elif not kwarg_has_default(sampling_rule, key):
                    function_input[key] = None

            new_value = sampling_rule(**function_input)
            while isinstance(new_value, Property):
                new_value = self.sample(new_value, **kwargs)
            return new_value
        else:
            # Else, assume it's elementary.
            return sampling_rule
Ejemplo n.º 4
0
    def sample(self, sampling_rule, **kwargs):
        r'''Samples the sampling rule

        Returns a sampled instance of the `sampling_rule` field.
        The logic behind the sampling depends on the type of
        `sampling_rule`. These are checked in the following order of
        priority:

        1. Any object with a callable `sample()` method has this
            method called and returned.
        2. If the rule is a ``dict``, the ``dict`` is copied and any value
            with has a callable sample method is replaced with the
            output of that call.
        3. If the rule is a ``list`` or a 1-dimensional ``ndarray``, return
        4. If the rule is an ``iterable``, return the next output.
        5. If the rule is callable, return the output of a call with
            no input parameters.
            a single element drawn from that ``list``/``ndarray``.
        6. If none of the above apply, return the rule itself.

        Returns
        -------
        any
            A sampled instance of the `sampling_rule`.

        '''

        if hasmethod(sampling_rule, "sample"):
            # If the ruleset itself implements a sample method,
            # call it instead.
            return sampling_rule.sample(**kwargs)

        elif isinstance(sampling_rule, dict):
            # If the ruleset is a dict, return a new dict with each
            # element being sampled from the original dict.
            out = {}
            for key, val in self.sampling_rule.items():
                    out[key] = self.sample(val, **kwargs)
            return out

        elif isinstance(sampling_rule, list):
            return [self.sample(item, **kwargs) for item in sampling_rule]

        elif isinstance(sampling_rule, (tuple, np.ndarray)):
            # tuple and ndarrays are elementary
            return sampling_rule

        elif isiterable(sampling_rule):
            # If it's iterable, return the next value
            try:
                return next(sampling_rule)
            except StopIteration:
                return self.current_value
  
        elif callable(sampling_rule):
            # If it's a function
            function_input = {}
            for key in get_kwarg_names(sampling_rule):
                if key in kwargs:
                    if isinstance(kwargs[key], Property):
                        kwargs[key].update(**kwargs)
                        
                        if isinstance(kwargs[key], SequentialProperty):
                            kwargs[key] = kwargs[key].current_value[kwargs["sequence_step"]]
                        else:
                            kwargs[key] = kwargs[key].current_value

                    
                         
                    function_input[key] = kwargs[key]

            return sampling_rule(**function_input)
            
        else:
            # Else, assume it's elementary.
            return sampling_rule