def solve(self, value, args=None, kwargs=None):
<EOL>if self.function:<EOL><INDENT>try:<EOL><INDENT>return self.function(value, *(args or []), **(kwargs or {}))<EOL><DEDENT>except Exception as ex:<EOL><INDENT>raise CallableError(self, value, args, kwargs, ex)<EOL><DEDENT><DEDENT>try:<EOL><INDENT>result = getattr(value, self.name)<EOL><DEDENT>except AttributeError:<EOL><INDENT>try:<EOL><INDENT>result = value[self.name]<EOL><DEDENT>except (TypeError, KeyError):<EOL><INDENT>raise AttributeNotFound(self)<EOL><DEDENT><DEDENT>if args is not None or kwargs is not None:<EOL><INDENT>result = result(*(args or []), **(kwargs or {}))<EOL><DEDENT>elif not isclass(result) and callable(result):<EOL><INDENT>try:<EOL><INDENT>result = result()<EOL><DEDENT>except Exception as ex:<EOL><INDENT>if isfunction(result) or ismethod(result):<EOL><INDENT>raise CallableError(self, value, args, kwargs, ex)<EOL><DEDENT><DEDENT><DEDENT>return result<EOL>
Try to get the current attribute/function result for the given value.

        If ``args`` or ``kwargs`` are passed, the attribute got from ``value`` must be callable.
        They will be passed anyway (using ``[]`` and ``{}`` as default values) if the attribute
        is a function.

        And if it's not a function but a real attribute, if no args are passed but the attribute
        got from ``value`` is "callable", we'll try to call it without argument.
        If any exception occurs during the call, two things may happen:
        - the "thing" called is a function or method, then we raise the exception
        - it's something else, like an instance of a class having a ``__call__`` method,
          in this case we want to return the instance (if the user want the thing to be
          called it could still use parentheses)

        Arguments
        ---------
        value : ?
            The value from which we want the attribute.
        args : list, default ``None``
            If defined, list of non-named arguments that will be passed to the attribute if it's
            callable.
        kwargs : dict, default ``None``
            If defined, list of named arguments that will be passed to the attribute if it's
            callable.

        Returns
        -------
        Value of the current attribute/function result for the ``value`` instance.

        Raises
        ------
        dataql.solvers.exceptions.CallableError
            If an exception was raised when the attribute/function was called.

        Example
        -------

        >>> from datetime import date
        >>> d = date(2015, 6, 1)
        >>> Attribute('day').solve(d)
        1
        >>> Attribute('strftime').solve(d, ['%F'])
        '2015-06-01'
        >>> Attribute('day').solve('a string') # doctest: +ELLIPSIS
        Traceback (most recent call last):
        dataql...AttributeNotFound: `<Attribute 'day'>` is not an allowed attribute
        >>> Attribute('day').solve(d, ['foo'])
        Traceback (most recent call last):
        TypeError: 'int' object is not callable
        >>> Attribute('str', function=str).solve(d)
        '2015-06-01'

        # Test the dict-like approach
        >>> class MyDict(dict):
        ...     foo = 1
        >>> d = MyDict(bar=2)
        >>> Attribute('foo').solve(d)
        1
        >>> Attribute('bar').solve(d)
        2

        Example with callable
        ----------------------

        >>> class Klass1:
        ...     def __call__(self):
        ...         return 'foo'
        >>> class Klass2:
        ...     def __call__(self, arg):
        ...         return 'foo'
        >>> class Klass3:
        ...     def __call__(self):
        ...         raise TypeError('error')
        >>> class Klass4:
        ...     def __call__(self, **kwargs):
        ...         return 'foo'
        >>> class Klass5:
        ...     def __call__(self, **kwargs):
        ...         return kwargs['foo']
        >>> class Klass6:
        ...     def __call__(self, *args):
        ...         return 'foo'
        >>> class Klass7:
        ...     def __call__(self, *args):
        ...         return args[0]
        >>> class Klass:
        ...     def call1(self):
        ...         return 'foo'
        ...     def call2(self, arg):
        ...         return 'foo'
        ...     def call3(self):
        ...         raise TypeError('error')
        ...     def call4(self, **kwargs):
        ...         return 'foo'
        ...     def call5(self, **kwargs):
        ...         return kwargs['foo']
        ...     def call6(self, *args):
        ...         return 'foo'
        ...     def call7(self, *args):
        ...         return args[0]
        ...     k1, k2, k3, k4 = Klass1(), Klass2(), Klass3(), Klass4()
        ...     k5, k6, k7 = Klass5(), Klass6(), Klass7()

        >>> v = Klass()

        # Can be called without arguments: we call it
        >>> Attribute('call1').solve(v)
        'foo'

        # TypeError while calling without argument, but it's a method: raise
        >>> Attribute('call2').solve(v) # doctest: +ELLIPSIS
        Traceback (most recent call last):
        dataql.solvers.exceptions.CallableError:...calling `call2` (without arguments)

        # TypeError but no argument needed, but it's a method: raise
        >>> Attribute('call3').solve(v) # doctest: +ELLIPSIS
        Traceback (most recent call last):
        dataql.solvers.exceptions.CallableError:...calling `call3` (without arguments)

        # Can be called without used kwargs: we call it
        >>> Attribute('call4').solve(v)
        'foo'

        # KeyError while calling without argument, in a get of kwargs, but it's a method: raise
        >>> Attribute('call5').solve(v) # doctest: +ELLIPSIS
        Traceback (most recent call last):
        dataql.solvers.exceptions.CallableError:...calling `call5` (without arguments)

        # Can be called without used args: we call it
        >>> Attribute('call6').solve(v)
        'foo'

        # IndexError while calling without argument, in a get of args, but it's a method: raise
        >>> Attribute('call7').solve(v) # doctest: +ELLIPSIS
        Traceback (most recent call last):
        dataql.solvers.exceptions.CallableError:...calling `call7` (without arguments)



        # Can be called without arguments: we call it
        >>> Attribute('k1').solve(v)
        'foo'

        # TypeError while calling without argument, but it's NOT a method: return not called
        >>> isinstance(Attribute('k2').solve(v), Klass2)
        True

        # TypeError but no argument needed, but it's NOT a method: return not called
        >>> isinstance(Attribute('k3').solve(v), Klass3)
        True

        # Can be called without used kwargs: we call it
        >>> Attribute('k4').solve(v)
        'foo'

        # KeyError while calling without argument, in a get of kwargs, but it's NOT a method:
        # return not called
        >>> isinstance(Attribute('k5').solve(v), Klass5)
        True

        # Can be called without used args: we call it
        >>> Attribute('k6').solve(v)
        'foo'

        # IndexError while calling without argument, in a get of args, but it's NOT a method:
        # return not called
        >>> isinstance(Attribute('k7').solve(v), Klass7)
        True