[pygobject] Renamed getter/setter instance attributes to fget/fset respectively.



commit 77ab27ab8a580d98f76730f075e083e1e870f55e
Author: simon <simon gerty>
Date:   Tue Mar 13 01:41:53 2012 -0700

    Renamed getter/setter instance attributes to fget/fset respectively.
    
    The python 'property' class allows for decoration of methods using
    .getter and .setter. These were added as methods to the GObject.property
    class to match that of the python property class and allow for decoratored
    setter methods.
    
    In addition, __call__ was added to allow an instantiated decorator with
    args to also decorate a method:
    
    class C(GObject.GObject):
        _value = 0
        @GObject.property(type=int, default=0)
        def propInt(self):
            return self._value
        @propInt.setter
        def propInt(self, value):
            self._value = value
    
    https://bugzilla.gnome.org/show_bug.cgi?id=586181
    
    Signed-off-by: Martin Pitt <martin pitt ubuntu com>

 gi/_gobject/__init__.py       |   10 +++---
 gi/_gobject/propertyhelper.py |   59 +++++++++++++++++++++++++++++-----------
 tests/test_properties.py      |   41 ++++++++++++++++++++++++++++
 3 files changed, 89 insertions(+), 21 deletions(-)
---
diff --git a/gi/_gobject/__init__.py b/gi/_gobject/__init__.py
index e94e7b8..7576142 100644
--- a/gi/_gobject/__init__.py
+++ b/gi/_gobject/__init__.py
@@ -84,11 +84,11 @@ class GObjectMeta(type):
         if ('do_get_property' in cls.__dict__ or
             'do_set_property' in cls.__dict__):
             for prop in props:
-                if (prop.getter != prop._default_getter or
-                    prop.setter != prop._default_setter):
+                if (prop.fget != prop._default_getter or
+                    prop.fset != prop._default_setter):
                     raise TypeError(
                         "GObject subclass %r defines do_get/set_property"
-                        " and it also uses a property which a custom setter"
+                        " and it also uses a property with a custom setter"
                         " or getter. This is not allowed" % (
                         cls.__name__,))
 
@@ -96,14 +96,14 @@ class GObjectMeta(type):
             name = pspec.name.replace('-', '_')
             prop = getattr(cls, name, None)
             if prop:
-                return prop.getter(self)
+                return prop.fget(self)
         cls.do_get_property = obj_get_property
 
         def obj_set_property(self, pspec, value):
             name = pspec.name.replace('-', '_')
             prop = getattr(cls, name, None)
             if prop:
-                prop.setter(self, value)
+                prop.fset(self, value)
         cls.do_set_property = obj_set_property
 
     def _type_register(cls, namespace):
diff --git a/gi/_gobject/propertyhelper.py b/gi/_gobject/propertyhelper.py
index 9208a0b..74c3d35 100644
--- a/gi/_gobject/propertyhelper.py
+++ b/gi/_gobject/propertyhelper.py
@@ -47,8 +47,8 @@ class property(object):
     Creates a new property which in conjunction with GObject subclass will
     create a property proxy:
 
-    >>> class MyObject(gobject.GObject):
-    >>> ... prop = gobject.property(type=str)
+    >>> class MyObject(GObject.GObject):
+    >>> ... prop = GObject.property(type=str)
 
     >>> obj = MyObject()
     >>> obj.prop = 'value'
@@ -58,17 +58,25 @@ class property(object):
 
     The API is similar to the builtin property:
 
-    class AnotherObject(gobject.GObject):
-        @gobject.property
+    class AnotherObject(GObject.GObject):
+        @GObject.property
         def prop(self):
+            '''Read only property.'''
             return ...
 
-    Which will create a read-only property called prop.
+        @GObject.property(type=int)
+        def propInt(self):
+            '''Read-write integer property.'''
+            return ...
+
+        @propInt.setter
+        def propInt(self, value):
+            ...
     """
 
     class __metaclass__(type):
         def __repr__(self):
-            return "<class 'gobject.property'>"
+            return "<class 'GObject.property'>"
 
     def __init__(self, getter=None, setter=None, type=None, default=None,
                  nick='', blurb='', flags=_gobject.PARAM_READWRITE,
@@ -96,16 +104,6 @@ class property(object):
         @keyword maximum:  maximum allowed value (int, float, long only)
         """
 
-        if getter and not setter:
-            setter = self._readonly_setter
-        elif setter and not getter:
-            getter = self._writeonly_getter
-        elif not setter and not getter:
-            getter = self._default_getter
-            setter = self._default_setter
-        self.getter = getter
-        self.setter = setter
-
         if type is None:
             type = object
         self.type = self._type_from_python(type)
@@ -124,6 +122,17 @@ class property(object):
             raise TypeError("invalid flag value: %r" % (flags,))
         self.flags = flags
 
+        # Call after setting blurb for potential __doc__ usage.
+        if getter and not setter:
+            setter = self._readonly_setter
+        elif setter and not getter:
+            getter = self._writeonly_getter
+        elif not setter and not getter:
+            getter = self._default_getter
+            setter = self._default_setter
+        self.getter(getter)
+        self.setter(setter)
+
         if minimum is not None:
             if minimum < self._get_minimum():
                 raise TypeError(
@@ -174,6 +183,24 @@ class property(object):
             self._exc = None
             raise exc
 
+    def __call__(self, fget):
+        """Allows application of the getter along with init arguments."""
+        return self.getter(fget)
+
+    def getter(self, fget):
+        """Set the getter function to fget. For use as a decorator."""
+        if self.__doc__ is None:
+            self.__doc__ = fget.__doc__
+        if not self.blurb and fget.__doc__:
+            self.blurb = fget.__doc__
+        self.fget = fget
+        return self
+
+    def setter(self, fset):
+        """Set the setter function to fset. For use as a decorator."""
+        self.fset = fset
+        return self
+
     def _type_from_python(self, type_):
         if type_ == _long:
             return TYPE_LONG
diff --git a/tests/test_properties.py b/tests/test_properties.py
index 75aacff..6ab6d93 100644
--- a/tests/test_properties.py
+++ b/tests/test_properties.py
@@ -310,6 +310,38 @@ class TestProperty(unittest.TestCase):
         self.assertEquals(o._value, 'bar')
         self.assertRaises(TypeError, getattr, o, 'prop')
 
+    def testDecoratorDefault(self):
+        class C(GObject.GObject):
+            _value = 'value'
+            @GObject.property
+            def value(self):
+                return self._value
+            @value.setter
+            def value(self, value):
+                self._value = value
+
+        o = C()
+        self.assertEqual(o.value, 'value')
+        o.value = 'blah'
+        self.assertEqual(o.value, 'blah')
+        self.assertEqual(o.props.value, 'blah')
+
+    def testDecoratorWithCall(self):
+        class C(GObject.GObject):
+            _value = 1
+            @GObject.property(type=int, default=1, minimum=1, maximum=10)
+            def typedValue(self):
+                return self._value
+            @typedValue.setter
+            def typedValue(self, value):
+                self._value = value
+
+        o = C()
+        self.assertEqual(o.typedValue, 1)
+        o.typedValue = 5
+        self.assertEqual(o.typedValue, 5)
+        self.assertEqual(o.props.typedValue, 5)
+
     def testErrors(self):
         self.assertRaises(TypeError, GObject.property, type='str')
         self.assertRaises(TypeError, GObject.property, nick=False)
@@ -510,6 +542,15 @@ class TestProperty(unittest.TestCase):
         del t
         self.assertEquals(sys.getrefcount(o), rc)
 
+    def testDocStringAsBlurb(self):
+        class C(GObject.GObject):
+            @GObject.property
+            def blurbed(self):
+                """blurbed doc string"""
+                return 0
+
+        self.assertEqual(C.blurbed.blurb, 'blurbed doc string')
+
 
 if __name__ == '__main__':
     unittest.main()



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]