Skip to content

Commit

Permalink
Adding support for propertty setter and deleter
Browse files Browse the repository at this point in the history
  • Loading branch information
Debith committed May 19, 2015
1 parent ebe82e5 commit 666a444
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
Changelog
=========

0.14.0 (2015-05-19)
-------------------
- New feature: Setter and Deleter for properties are now supported

0.13.0 (2015-04-25)
-------------------
- New feature: Decorator type_safe to check function arguments
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,32 @@ class ExampleTrait(object):
def trait_property(self):
return self.public, self._hidden, self.__private

@trait_property.setter
def trait_property(self, new_value):
self.public, self._hidden, self.__private = new_value

@trait_property.deleter
def trait_property(self):
self.public, self._hidden, self.__private = (42, 43, 44)


# Then add the property as a part of our new class simply by referring it.
ExampleClass.add_traits(ExampleTrait.trait_property)


# Here are the proofs that composed property works as part of new class.
# Also we show that there is no inheritance done for ExampleClass instance.
example_instance = ExampleClass()
assert ExampleClass.__bases__ == (object, ), "Inheritance has occurred!"
assert ExampleClass().trait_property == (42, 43, 44),\
assert example_instance.trait_property == (42, 43, 44),\
"Cherry-picked property not working in new class!"

# We also demonstrate that we can alter the values through the property
example_instance.trait_property = (142, 143, 144)
assert example_instance.trait_property == (142, 143, 144),\
"Cherry-picked property's setter not working in new class!"

# Finally, we can delete property's content
del example_instance.trait_property
assert example_instance.trait_property == (42, 43, 44),\
"Cherry-picked property's deleter not working in new class!"
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ class ExampleTrait(object):
def trait_property(self):
return self.public, self._hidden, self.__private

@trait_property.setter
def trait_property(self, new_value):
self.public, self._hidden, self.__private = new_value

@trait_property.deleter
def trait_property(self):
self.public, self._hidden, self.__private = (42, 43, 44)


# Create instance out of the trait class. Now we need to notice that we need
# to refer to instance's class to get the property and transfer it to new
Expand All @@ -34,6 +42,17 @@ def trait_property(self):

# Here are the proofs that composed property works as part of new class.
# Also we show that there is no inheritance done for ExampleClass instance.
example_instance = ExampleClass()
assert ExampleClass.__bases__ == (object, ), "Inheritance has occurred!"
assert ExampleClass().trait_property == (42, 43, 44),\
assert example_instance.trait_property == (42, 43, 44),\
"Cherry-picked property not working in new class!"

# We also demonstrate that we can alter the values through the property
example_instance.trait_property = (142, 143, 144)
assert example_instance.trait_property == (142, 143, 144),\
"Cherry-picked property's setter not working in new class!"

# Finally, we can delete property's content
del example_instance.trait_property
assert example_instance.trait_property == (42, 43, 44),\
"Cherry-picked property's deleter not working in new class!"
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/python -tt
# -*- coding: utf-8 -*-
from pytraits import extendable


# Let's start by creating a simple class with some values. It contains
# only instance variables. Composed property will have access to all
# these variables.
@extendable
class ExampleClass(object):
def __init__(self):
self.public = 42
self._hidden = 43
self.__private = 44


# Then we create a class which contains different types of methods that will be
# transferred as a part of the class above. Note that ExampleTrait requires target
# object to contain instance variables, thus it won't work as a stand-alone object.
class ExampleTrait(object):
@property
def trait_property(self):
return self.public, self._hidden, self.__private

@trait_property.setter
def trait_property(self, new_value):
self.public, self._hidden, self.__private = new_value

@trait_property.deleter
def trait_property(self):
self.public, self._hidden, self.__private = (42, 43, 44)


# Then add the property as a part of our new class simply by referring it.
example_instance = ExampleClass()
example_instance.add_traits(ExampleTrait.trait_property)


# Here are the proofs that composed property works as part of new class.
assert example_instance.trait_property == (42, 43, 44),\
"Cherry-picked property not working in new class!"

# We also demonstrate that we can alter the values through the property
example_instance.trait_property = (142, 143, 144)
assert example_instance.trait_property == (142, 143, 144),\
"Cherry-picked property's setter not working in new class!"

# Finally, we can delete property's content
del example_instance.trait_property
assert example_instance.trait_property == (42, 43, 44),\
"Cherry-picked property's deleter not working in new class!"
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/usr/bin/python -tt
# -*- coding: utf-8 -*-
from pytraits import extendable


# Let's start by creating a simple class with some values. It contains
# only instance variables. Composed property will have access to all
# these variables.
@extendable
class ExampleClass(object):
def __init__(self):
self.public = 42
self._hidden = 43
self.__private = 44


# Then we create a class which contains different types of methods that will be
# transferred as a part of the class above. Note that ExampleTrait requires target
# object to contain instance variables, thus it won't work as a stand-alone object.
class ExampleTrait(object):
@property
def trait_property(self):
return self.public, self._hidden, self.__private

@trait_property.setter
def trait_property(self, new_value):
self.public, self._hidden, self.__private = new_value

@trait_property.deleter
def trait_property(self):
self.public, self._hidden, self.__private = (42, 43, 44)


# Create instance out of the trait class. Now we need to notice that we need
# to refer to instance's class to get the property and transfer it to new
# location. Using directly my_trait_instance.trait_property would naturally
# invoke retrieval of the values (which in this case would not even exist and
# and would raise an error).
example_instance = ExampleClass()
my_trait_instance = ExampleTrait()
example_instance.add_traits(my_trait_instance.__class__.trait_property)


# Here are the proofs that composed property works as part of new class.
# Also we show that there is no inheritance done for ExampleClass instance.
assert example_instance.trait_property == (42, 43, 44),\
"Cherry-picked property not working in new class!"

# We also demonstrate that we can alter the values through the property
example_instance.trait_property = (142, 143, 144)
assert example_instance.trait_property == (142, 143, 144),\
"Cherry-picked property's setter not working in new class!"

# Finally, we can delete property's content
del example_instance.trait_property
assert example_instance.trait_property == (42, 43, 44),\
"Cherry-picked property's deleter not working in new class!"
21 changes: 15 additions & 6 deletions src/pytraits/sources/prop.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,28 @@
limitations under the License.
'''

from pytraits.sources.routine import RoutineSource
from pytraits.sources.routine import recompile


class PropertySource:
def __init__(self, prop, resolutions):
self._property = prop
self._resolutions = resolutions

def __recompile_property_func(self, func_name, clazz, new_name):
func = getattr(self._property, func_name, None)
if func:
return recompile(func, clazz, new_name)

def for_class(self, clazz):
name = self._resolutions.get(self._property.fget.__name__, self._property.fget.__name__)
getter = RoutineSource(self._property.fget, name)
getter.for_class(clazz)
setattr(clazz, name, property(getattr(clazz, name)))
name = self._resolutions.get(self._property.fget.__name__,
self._property.fget.__name__)

getter = self.__recompile_property_func('fget', clazz, name)
setter = self.__recompile_property_func('fset', clazz, name)
deleter = self.__recompile_property_func('fdel', clazz, name)

setattr(clazz, name, property(getter, setter, deleter))

def for_instance(self, instance):
setattr(instance.__class__, self._name, self._property)
self.for_class(instance.__class__)

0 comments on commit 666a444

Please sign in to comment.