Beispiel #1
0
    def __init__(self,
                 forward_function=None,
                 back_function=None,
                 *arguments,
                 **keywords):
        if (not (forward_function is None or is_callable(forward_function))
                or not (back_function is None or is_callable(back_function))):
            raise TypeError('both functions must be callable or None')

        super(FunctionalMediator, self).__init__()

        self.__forward_function = forward_function or _identity
        self.__back_function = back_function or _identity
        self.__arguments = arguments
        self.__keywords = keywords
Beispiel #2
0
    def wrap (cls, callable_object, arguments = (), keywords = None):
        """
        Return a callable with semantics of the binding class this method is called for.
        I{If necessary} (e.g. if C{arguments} tuple is not empty), this method creates a
        binding instance first.  In any case, you can assume that returned object will
        I{behave} identically to an instance of this class with C{callable_object} and
        C{arguments} passed to C{L{__init__}} method.  However, the returned object I{is
        not required} to be an instance.

        This is the preferred method of creating bindings.  It is generally more memory-
        and call-time-efficient since in some cases no new objects are created at all.

        @param  callable_object: the callable object that will be invoked by this binding
                                 from C{L{__call__}} method.
        @type   callable_object: callable

        @param  arguments:       optional list of argument for C{callable_object} that
                                 will be prepended to call arguments.
        @type   arguments:       iterable

        @rtype:            callable

        @raises TypeError: if C{callable_object} is not callable or C{arguments} is not
                           iterable.
        """

        if arguments or keywords:
            return cls (callable_object, arguments, keywords)
        else:
            if not is_callable (callable_object):
                raise TypeError ("'callable_object' must be callable")

            return callable_object
Beispiel #3
0
    def wrap(cls, callable_object, arguments=(), keywords=None):
        """
        Return a callable with semantics of the binding class this method is called for.
        I{If necessary} (e.g. if C{arguments} tuple is not empty), this method creates a
        binding instance first.  In any case, you can assume that returned object will
        I{behave} identically to an instance of this class with C{callable_object} and
        C{arguments} passed to C{L{__init__}} method.  However, the returned object I{is
        not required} to be an instance.

        This is the preferred method of creating bindings.  It is generally more memory-
        and call-time-efficient since in some cases no new objects are created at all.

        @param  callable_object: the callable object that will be invoked by this binding
                                 from C{L{__call__}} method.
        @type   callable_object: callable

        @param  arguments:       optional list of argument for C{callable_object} that
                                 will be prepended to call arguments.
        @type   arguments:       iterable

        @rtype:            callable

        @raises TypeError: if C{callable_object} is not callable or C{arguments} is not
                           iterable.
        """

        if arguments or keywords:
            return cls(callable_object, arguments, keywords)
        else:
            if not is_callable(callable_object):
                raise TypeError("'callable_object' must be callable")

            return callable_object
Beispiel #4
0
    def __init__(self, transformer, variable):
        if not is_callable (transformer):
            raise TypeError ('transformer must be callable')

        super (_VariableTransformation, self).__init__(transformer (variable.get ()))

        self.__transformer = transformer
        self.__variable    = weakref.ref (variable, self.__on_usage_change)

        variable.changed.connect (self.__update)
Beispiel #5
0
    def __init__(self, predicate, variable):
        if not is_callable (predicate):
            raise TypeError ('predicate must be callable')

        super (_PredicateOverVariable, self).__init__(predicate (variable.get ()))

        self.__predicate = predicate
        self.__variable  = weakref.ref (variable, self.__on_usage_change)

        variable.changed.connect (self.__update)
Beispiel #6
0
    def __init__(self, predicate, variable):
        if not is_callable(predicate):
            raise TypeError('predicate must be callable')

        super(_PredicateOverVariable, self).__init__(predicate(variable.get()))

        self.__predicate = predicate
        self.__variable = weakref.ref(variable, self.__on_usage_change)

        variable.changed.connect(self.__update)
Beispiel #7
0
    def test_is_callable (self):
        self.assert_(is_callable (is_callable))
        self.assert_(is_callable (UtilsTestCase))
        self.assert_(is_callable (UtilsTestCase.test_is_callable))

        self.assert_(not is_callable (None))
        self.assert_(not is_callable (5))
        self.assert_(not is_callable ('foo'))
        self.assert_(not is_callable ([]))
Beispiel #8
0
    def __init__(self, transformer, variable):
        if not is_callable(transformer):
            raise TypeError('transformer must be callable')

        super(_VariableTransformation,
              self).__init__(transformer(variable.get()))

        self.__transformer = transformer
        self.__variable = weakref.ref(variable, self.__on_usage_change)

        variable.changed.connect(self.__update)
Beispiel #9
0
    def __init__(self, true_value=True, false_value=False, fallback=None):
        if fallback is None:
            fallback = bool
        else:
            if not is_callable(fallback):
                raise TypeError("'fallback' must be a callable")

        super(BooleanMediator, self).__init__()

        self.__true_value = true_value
        self.__false_value = false_value
        self.__fallback = fallback
Beispiel #10
0
    def __init__(self,
                 callable_object,
                 arguments=(),
                 callback=None,
                 keywords=None):
        """
        Initialize a new weak binding which will call C{callable_object}, I{prepending}
        fixed C{arguments} (if any) to those specified at call time.  Here,
        C{callable_object} is usually a function or a method, but can in principle be
        anything callable, including an already existing binding.

        If C{callable_object} is a bound method, its object is referenced weakly.  It is
        also legal to create weak bindings for other callables, but they will behave
        identically to plain bindings in that case.

        See also C{L{wrap}} class method for a different way of creating weak bindings.

        @param  callable_object: the callable object that will be invoked by this binding
                                 from C{L{__call__}} method.
        @type   callable_object: callable

        @param  arguments:       optional list of argument for C{callable_object} that
                                 will be prepended to call arguments.
        @type   arguments:       iterable

        @param  callback:        optional callable that will be called if binding’s object
                                 is garbage-collected.
        @type   callback:        callable or C{None}

        @raises TypeError:                if C{callable_object} is not callable or
                                          C{arguments} is not iterable.
        @raises CannotWeakReferenceError: if C{callable_object} is a bound method, but
                                          its object is not weakly referencable.
        """

        super(WeakBinding, self).__init__(callable_object, arguments, keywords)

        if self._object is not None:
            if callback is not None and not is_callable(callback):
                raise TypeError("'callback' must be callable")

            try:
                self.__callback = callback
                self._object = weakref.ref(self._object,
                                           self.__object_garbage_collected)
            except:
                raise CannotWeakReferenceError(self._object)
        else:
            self._object = _NONE_REFERENCE

        self.__hash = None
Beispiel #11
0
    def __init__(self, callable_object, arguments = (), keywords = None):
        """
        Initialize a new binding which will call C{callable_object}, I{prepending} fixed
        C{arguments} (if any) to those specified at call time.  Here, C{callable_object}
        is usually a function or a method, but can in principle be anything callable,
        including an already existing binding.

        See also C{L{wrap}} class method for a different way of creating bindings.

        @param  callable_object: the callable object that will be invoked by this binding
                                 from C{L{__call__}} method.
        @type   callable_object: callable

        @param  arguments:       optional list of argument for C{callable_object} that
                                 will be prepended to call arguments.
        @type   arguments:       iterable

        @raises TypeError:       if C{callable_object} is not callable or C{arguments} is
                                 not iterable.
        """

        if not is_callable (callable_object):
            raise TypeError ("'callable_object' must be callable")

        # This raises `TypeError' if `arguments' or `keywords' type is inappropriate.
        arguments = tuple (arguments)
        if keywords is None:
            keywords = frozendict.EMPTY
        # Note: not isinstance, subclasses might become modifiable again.
        elif type (keywords) is not frozendict:
            keywords = frozendict (keywords)

        super (Binding, self).__init__()

        if isinstance (callable_object, BindingCompatibleTypes):
            if _PY3K:
                self._object   = callable_object.__self__
                self._function = callable_object.__func__
                self._class    = type (self._object)
            else:
                self._object   = callable_object.im_self
                self._function = callable_object.im_func
                self._class    = callable_object.im_class
        else:
            self._object   = None
            self._function = callable_object
            self._class    = None

        self._arguments = arguments
        self._keywords  = keywords
Beispiel #12
0
    def __init__(self, callable_object, arguments=(), keywords=None):
        """
        Initialize a new binding which will call C{callable_object}, I{prepending} fixed
        C{arguments} (if any) to those specified at call time.  Here, C{callable_object}
        is usually a function or a method, but can in principle be anything callable,
        including an already existing binding.

        See also C{L{wrap}} class method for a different way of creating bindings.

        @param  callable_object: the callable object that will be invoked by this binding
                                 from C{L{__call__}} method.
        @type   callable_object: callable

        @param  arguments:       optional list of argument for C{callable_object} that
                                 will be prepended to call arguments.
        @type   arguments:       iterable

        @raises TypeError:       if C{callable_object} is not callable or C{arguments} is
                                 not iterable.
        """

        if not is_callable(callable_object):
            raise TypeError("'callable_object' must be callable")

        # This raises `TypeError' if `arguments' or `keywords' type is inappropriate.
        arguments = tuple(arguments)
        if keywords is None:
            keywords = frozendict.EMPTY
        # Note: not isinstance, subclasses might become modifiable again.
        elif type(keywords) is not frozendict:
            keywords = frozendict(keywords)

        super(Binding, self).__init__()

        if isinstance(callable_object, BindingCompatibleTypes):
            if _PY3K:
                self._object = callable_object.__self__
                self._function = callable_object.__func__
                self._class = type(self._object)
            else:
                self._object = callable_object.im_self
                self._function = callable_object.im_func
                self._class = callable_object.im_class
        else:
            self._object = None
            self._function = callable_object
            self._class = None

        self._arguments = arguments
        self._keywords = keywords
Beispiel #13
0
    def __init__(self, callable_object, arguments = (), callback = None, keywords = None):
        """
        Initialize a new weak binding which will call C{callable_object}, I{prepending}
        fixed C{arguments} (if any) to those specified at call time.  Here,
        C{callable_object} is usually a function or a method, but can in principle be
        anything callable, including an already existing binding.

        If C{callable_object} is a bound method, its object is referenced weakly.  It is
        also legal to create weak bindings for other callables, but they will behave
        identically to plain bindings in that case.

        See also C{L{wrap}} class method for a different way of creating weak bindings.

        @param  callable_object: the callable object that will be invoked by this binding
                                 from C{L{__call__}} method.
        @type   callable_object: callable

        @param  arguments:       optional list of argument for C{callable_object} that
                                 will be prepended to call arguments.
        @type   arguments:       iterable

        @param  callback:        optional callable that will be called if binding’s object
                                 is garbage-collected.
        @type   callback:        callable or C{None}

        @raises TypeError:                if C{callable_object} is not callable or
                                          C{arguments} is not iterable.
        @raises CannotWeakReferenceError: if C{callable_object} is a bound method, but
                                          its object is not weakly referencable.
        """

        super (WeakBinding, self).__init__(callable_object, arguments, keywords)

        if self._object is not None:
            if callback is not None and not is_callable (callback):
                raise TypeError ("'callback' must be callable")

            try:
                self.__callback = callback
                self._object    = weakref.ref (self._object, self.__object_garbage_collected)
            except:
                raise CannotWeakReferenceError (self._object)
        else:
            self._object = _NONE_REFERENCE

        self.__hash = None
Beispiel #14
0
    def __init__(self, predicate, initial_object):
        """
        Initialize a new predicate conditon, setting its initial state to
        C{predicate (initial_object)}.  C{predicate} is stored to be invoked also on any
        subsequent calls to C{L{update}} method.  Return value of C{predicate} is always
        coerced using C{bool} function, so it needn’t return a boolean value.

        @param predicate:      a callable accepting one argument used to compute
                               condition’s state.

        @param initial_object: the value to be passed to C{predicate} to find initial
                               state.
        @type  initial_object: C{object}

        @raises exception:     whatever C{predicate} raises, if anything.
        """

        if not is_callable(predicate):
            raise TypeError('predicate must be callable')

        super(PredicateCondition, self).__init__(predicate(initial_object))
        self.__predicate = predicate
Beispiel #15
0
    def back(self, function):
        """
        Return a callable accepting one argument that applies back transformation to it
        and passes result to C{function}.  It holds that if C{m1} and C{m2} are two equal
        mediators and C{f1} and C{f2} are two equal callables (e.g. functions), then:

            >>> m1.back (f1) == m2.back (f2)

        In addition to that, for any C{value} to which back transformation can be applied,

            >>> m1.back (f1) (value) == m2.back (f2) (value) == m1.back_value (value)


        @rtype:            callable

        @raises TypeError: if C{function} is not callable.
        """

        if is_callable(function):
            return _Back(self, function)
        else:
            raise TypeError("'function' must be callable")
Beispiel #16
0
    def __init__(self, predicate, initial_object):
        """
        Initialize a new predicate conditon, setting its initial state to
        C{predicate (initial_object)}.  C{predicate} is stored to be invoked also on any
        subsequent calls to C{L{update}} method.  Return value of C{predicate} is always
        coerced using C{bool} function, so it needn’t return a boolean value.

        @param predicate:      a callable accepting one argument used to compute
                               condition’s state.

        @param initial_object: the value to be passed to C{predicate} to find initial
                               state.
        @type  initial_object: C{object}

        @raises exception:     whatever C{predicate} raises, if anything.
        """

        if not is_callable (predicate):
            raise TypeError ('predicate must be callable')

        super (PredicateCondition, self).__init__(predicate (initial_object))
        self.__predicate = predicate
Beispiel #17
0
    def _generate_derived_type_dictionary(cls, options):
        """
        Generate an iterable of pairs in the form (Python identifier, value) for a new
        type created by C{L{derive_type}}.  Exact pairs should be influenced by
        C{options}, which are C{options} as passed to C{derive_type} plus C{cls} (for
        convenience) and C{new_class_name}.

        This method is not meant to be callable from outside, use C{L{derive_type}} for
        that instead.

        Overriden implementations of this method are recommended but not required to be
        generator functions.  They should generally start like this:

            >>> def _generate_derived_type_dictionary (cls, options):
            ...     for attribute in super (..., cls)._generate_derived_type_dictionary (options):
            ...         yield attribute
            ...
            ...     ...

        That is only an approximation and you can, for instance, change or override
        attributes returned by super-method.

        C{options} dictionary is constructed in such a way you should be able to evaluate
        all function-defining statements in it.  For instance, you can write own
        C{_generate_derived_type_dictionary} like this:

            >>> def _generate_derived_type_dictionary (cls, options):
            ...     ...
            ...
            ...     functions = {}
            ...
            ...     if 'foo_value' in options:
            ...         exec 'def foo (self): return foo_value' \
            ...              in { 'foo_value': options['foo_value'] }, functions
            ...
            ...     ...
            ...
            ...     for function in functions.iteritems ():
            ...         yield function

        Returned value for C{__slots__} is treated specially.  While normally values
        associated with the same name override previous values, values for C{__slots__}
        are combined into a tuple instead.

        Note that it is not recommended to use C{options} for execution globals or locals
        dictionary directly.  This way your code may become vulnerable to other option
        addition, e.g. for some derivative of the class.  For instance, you may use
        C{property} built-in, then setting it in C{options} will hide the built-in from
        your code.  Consider using C{L{_filter_options}} utility method.

        @param options:    dictionary of options passed to C{L{derive_type}} method, plus
                           C{cls} and C{new_class_name}.
        @type  options:    C{dict}

        @rtype:            iterable
        @returns:          Pairs of (Python identifier, value) for the new type.

        @raises exception: if there is any error in C{options}.
        """

        functions = {}
        filtered_options = AbstractValueObject._filter_options(
            options, 'cls', 'getter', 'setter')

        if 'object' in options:
            object = options['object']
            if not is_valid_identifier(object):
                raise ValueError("'%s' is not a valid Python identifier" %
                                 object)

            yield '__slots__', mangle_identifier(options['new_class_name'],
                                                 object)

            execute(('def __init__(self, %s):\n'
                     '    cls.__init__(self)\n'
                     '    %s = %s') %
                    (object, AbstractValueObject._get_object(options), object),
                    filtered_options, functions)

            if 'property' in options:
                property = options['property']
                if property == object:
                    raise ValueError(
                        "'property' option cannot be the same as 'object'")

                if not is_valid_identifier(property):
                    raise ValueError("'%s' is not a valid Python identifier" %
                                     property)

                execute(
                    '%s = property (lambda self: %s)' %
                    (mangle_identifier(options['new_class_name'], property),
                     AbstractValueObject._get_object(options)), functions)

        else:
            if 'property' in options:
                raise ValueError(
                    "'property' without 'object' option doesn't make sense")

        if 'dict' in options and options['dict']:
            # Gracefully ignore if this type already has a dict.
            if not _type_has_dictionary(cls):
                yield '__slots__', '__dict__'

        if 'getter' in options:
            if not is_callable(options['getter']):
                raise TypeError("'getter' must be a callable")

            execute(
                'def get (self): return getter (%s)' %
                AbstractValueObject._get_object(options), filtered_options,
                functions)

        if 'setter' in options:
            if not is_callable(options['setter']):
                raise TypeError("'setter' must be a callable")

            execute(
                'def set (self, value): return setter (%s, value)' %
                AbstractValueObject._get_object(options), filtered_options,
                functions)

        for function in functions.items():
            yield function
Beispiel #18
0
    def _generate_derived_type_dictionary (cls, options):
        """
        Generate an iterable of pairs in the form (Python identifier, value) for a new
        type created by C{L{derive_type}}.  Exact pairs should be influenced by
        C{options}, which are C{options} as passed to C{derive_type} plus C{cls} (for
        convenience) and C{new_class_name}.

        This method is not meant to be callable from outside, use C{L{derive_type}} for
        that instead.

        Overriden implementations of this method are recommended but not required to be
        generator functions.  They should generally start like this:

            >>> def _generate_derived_type_dictionary (cls, options):
            ...     for attribute in super (..., cls)._generate_derived_type_dictionary (options):
            ...         yield attribute
            ...
            ...     ...

        That is only an approximation and you can, for instance, change or override
        attributes returned by super-method.

        C{options} dictionary is constructed in such a way you should be able to evaluate
        all function-defining statements in it.  For instance, you can write own
        C{_generate_derived_type_dictionary} like this:

            >>> def _generate_derived_type_dictionary (cls, options):
            ...     ...
            ...
            ...     functions = {}
            ...
            ...     if 'foo_value' in options:
            ...         exec 'def foo (self): return foo_value' \
            ...              in { 'foo_value': options['foo_value'] }, functions
            ...
            ...     ...
            ...
            ...     for function in functions.iteritems ():
            ...         yield function

        Returned value for C{__slots__} is treated specially.  While normally values
        associated with the same name override previous values, values for C{__slots__}
        are combined into a tuple instead.

        Note that it is not recommended to use C{options} for execution globals or locals
        dictionary directly.  This way your code may become vulnerable to other option
        addition, e.g. for some derivative of the class.  For instance, you may use
        C{property} built-in, then setting it in C{options} will hide the built-in from
        your code.  Consider using C{L{_filter_options}} utility method.

        @param options:    dictionary of options passed to C{L{derive_type}} method, plus
                           C{cls} and C{new_class_name}.
        @type  options:    C{dict}

        @rtype:            iterable
        @returns:          Pairs of (Python identifier, value) for the new type.

        @raises exception: if there is any error in C{options}.
        """

        functions        = {}
        filtered_options = AbstractValueObject._filter_options (options, 'cls', 'getter', 'setter')


        if 'object' in options:
            object = options['object']
            if not is_valid_identifier (object):
                raise ValueError ("'%s' is not a valid Python identifier" % object)

            yield '__slots__', mangle_identifier (options['new_class_name'], object)

            execute (('def __init__(self, %s):\n'
                      '    cls.__init__(self)\n'
                      '    %s = %s')
                     % (object, AbstractValueObject._get_object (options), object),
                     filtered_options, functions)

            if 'property' in options:
                property = options['property']
                if property == object:
                    raise ValueError ("'property' option cannot be the same as 'object'")

                if not is_valid_identifier (property):
                    raise ValueError ("'%s' is not a valid Python identifier" % property)

                execute ('%s = property (lambda self: %s)'
                         % (mangle_identifier (options['new_class_name'], property),
                            AbstractValueObject._get_object (options)),
                         functions)

        else:
            if 'property' in options:
                raise ValueError ("'property' without 'object' option doesn't make sense")

        if 'dict' in options and options['dict']:
            # Gracefully ignore if this type already has a dict.
            if not _type_has_dictionary (cls):
                yield '__slots__', '__dict__'

        if 'getter' in options:
            if not is_callable (options['getter']):
                raise TypeError ("'getter' must be a callable")

            execute ('def get (self): return getter (%s)'
                     % AbstractValueObject._get_object (options),
                     filtered_options, functions)

        if 'setter' in options:
            if not is_callable (options['setter']):
                raise TypeError ("'setter' must be a callable")

            execute ('def set (self, value): return setter (%s, value)'
                     % AbstractValueObject._get_object (options),
                     filtered_options, functions)

        for function in functions.items ():
            yield function
Beispiel #19
0
    def test_dummy_reference (self):
        self.assert_(is_callable (DummyReference (None)))
        self.assert_(DummyReference (None) () is None)

        self.assert_(is_callable (DummyReference (self)))
        self.assert_(DummyReference (self) () is self)