Welcome to traity’s documentation!¶
Contents:
Traity’s API¶
This is traity an alternative to enthought’s traits package
Contents:
Events¶
Event Objects¶
-
class
traity.events.
Event
(snitch, target, dispatcher=None, **kwargs)¶ An event should never need to be created directly. Use events(obj).etrigger to start a chain of events.
Parameters: - event_type – type of event
- target –
-
dispatch
(listener)¶ call a listener object
-
target
¶ The target this event will trigger action for.
Snitch Objects¶
-
class
traity.events.
Snitch
(instance)¶ Snitch object handles events. and propegates them to the object’s upstream nodes.
-
etrigger
(target, **metadata)¶ trigger an event.
Parameters: target – only listeners listening to this target will fire
-
listen
(target, listener, weak=None)¶ Add a listener to listen to events with target ‘target’.
-
queue
(*args, **kwds)¶ queue listened to events for this object.
-
quiet
(*args, **kwds)¶ Context manager to stop events being propegated.
-
trigger
(event)¶ Parameters: event – Event object to trigger
-
unique
(*args, **kwds)¶ remove duplicate events.
-
unlisten
(target, listener=None)¶ Remove a listener.
-
Functions¶
-
traity.events.
connect
(upstream, downstream, target, init=True)¶ Connect two objects together so that events will bubble upstream.
-
traity.events.
disconnect
(upstream, downstream, target, init=True)¶ Discnnect two objects.
-
traity.events.
events
(instance, init=False)¶ Get the events class associated with this object. If init is true. call init_events if events are uninitialized, otherwize, raise an exception.
-
traity.events.
init_events
(*instances)¶ Initialize the events for an object
-
traity.events.
init_events
(*instances) Initialize the events for an object
Global liteners¶
-
traity.events.
add_global_listener
(listener, target=None)¶ Add a listener to events on all objects.
-
traity.events.
remove_global_listener
(listener, target=None)¶ remove a add_global_listener
-
traity.events.
global_listener
(*args, **kwds)¶ Parameters: - listener – callable object, signature must be listener(event)
- target – target tuple
Context manager for global listeners
def print_event(event): print event with global_listener(print_event): ...
ok
Global dispatchers¶
-
traity.events.
add_global_dispatcher
(dispatcher)¶ Add a dispatcher to the stack.
Parameters: dispatcher – callable object. signature must be dispatcher(event, listener)
-
traity.events.
pop_global_dispatcher
()¶ remove the last global disopatcher from the stack
-
traity.events.
remove_global_dispatcher
(dispatcher)¶ remove the last dispatcher from the stack
Parameters: dispatcher – specific dispatcher to remove
-
traity.events.
global_dispatcher
(*args, **kwds)¶ Parameters: dispatcher – callable object. signature must be dispatcher(event, listener) Add a global dispatcher in a context:
with global_dispatcher(myfunc): #Trigger events
ok
-
traity.events.
quiet
(*args, **kwds)¶ Do not dispatch any events
-
traity.events.
queue
(*args, **kwds)¶ Put all events into a queue. example:
with queue() as todo: ... print "I have cought %i events" % len(todo)
this
-
traity.events.
unique
(*args, **kwds)¶ Only process unique events eg:
num_calls = 0 with global_listener(inc_num_calls): with unique(): triggers_event() triggers_event() assert num_calls == 1
and how
Static Properties¶
Static properties allow users to define attributes to a class ad class creation.
Unlike python’s native property descriptor. a vproperty’s getter setter and deleter are already defined.
class Foo(object):
x = vproperty()
Normal python descriptor symantics are already defined:
class Foo(object):
@vproperty
def x(self):
'Getter for x'
@x.setter
def x(self):
'Setter for x'
Validation¶
Type and instance arguments may be given to perform arbitrary valitation before the setter is called.
class Foo(object):
x = vproperty(type=int)
class Bar(object):
x = vproperty(isntance=int)
- The type argument is only required to be a function that acccepts a single input and returns a value::
- class Foo(object):
- x = vproperty(type=lambda item: item.lower())
or
class Foo(object):
x = vproperty()
@x.type
def check_x_type(self, value):
pass
The instance argument performs a strict isinstance check.
class Foo(object):
x = vproperty(type=int)
class Bar(object):
x = vproperty(isntance=int)
foo = Foo()
foo.x = '1' # x is set to one
bar = Bar()
bar.x = '1' # error x is not an int.
Delegation¶
Delegation may be one of two forms, strict: and can only be done when the instance argument is used or loose, where no error checking is done:
class Foo(object):
x = vproperty(type=int)
class Bar(object):
foo = vproperty(isntance=Foo)
# Strong Delegation of bar.x to bar.foo.x
x = foo.x
# Weak delegation of bar.y to bar.foo.x
y = delegate('foo', 'x')
# Also can do
y = delegate(foo, Foo.x)
vproperty objects¶
-
class
traity.statics.
vproperty
(fget=None, fset=None, fdel=None, type=None, ftype=None, instance=None, fdefault=None)¶ Parameters: - fget – method to get attribute
- fset – method to set attribute
- fdel – method to delete attribute
- ftype – method to convert type of attribute on assignment
- instance – if given, all assignments to this property must pass an isinstance check.
- fdefault – method to get attribute if undefined
- type – shorthand for ftype, type may be a basic python type not a method. int, float etc.
Define a static attribute to a class. Behaves almost exactly the same as Python properties:
class Parrot(object): def __init__(self): self._voltage = 100000 @vproperty def voltage(self): """Get the current voltage.""" return self._voltage
vproperty defines default fget, fset and fdel:
class Parrot(object): def __init__(self): self.voltage = 100000 voltage = vproperty()
vproperty adds ftype, instance and fdefault:
class Parrot(object): voltage = vproperty(type=int) def __init__(self): self.voltage = 100000 #OK self.voltage = '100000' #ValueError 'abc' is not convertable to int. self.voltage = 'abc'
or:
class Parrot(object): voltage = vproperty() @voltage.type def dynamic_range(self, value): return clamp(value, 0, self.max_volts)
defaults:
class Parrot(object): voltage = vproperty() @voltage.default def voltage_default(self): return 10000
-
delegates_to
(attr)¶ Delegates to an inner attribute. instance= argument must be set in constructor.
Used by __getattr__ for convinience. eg x.delegates_to(‘y’) can be written as x.y
-
getter
(value)¶
-
type
(method)¶ Set the type validation as a method of the containing class:
@x.type def check(self, value): ...
.
Traits¶
trait class¶
-
class
traity.traits.
trait
(fget=None, fset=None, fdel=None, type=None, ftype=None, instance=None, fdefault=None)¶ Parameters: - fget – Is a function to be used for getting an attribute value.
- fset – Is a function for setting
- fdel – a function for del’ing, an attribute.
- ftype – A type convert the argument to on set. type must be a function that accepts an argument and returns a single result. Like the builtin int
- instance – The argument must be of this instance.
- fdefault – Is a function to be called when the property is not set
Functions¶
-
traity.traits.
on_trait_change
(traits)¶ Statically Register a listener to a class:
@on_trait_change('attr') def attr_changed(self, event): print 'hello!'
.
-
traity.traits.
on_change
(instance, traits, function, weak=None)¶ Register a listener to an object.
Parameters: - traits – either a string, traity.events.listenable, or a tuple of strings and listenables.
- function – function to call when event with target target is triggered.
- instance – The object to listen to events for.
Tools¶
Initializable Properties¶
Properties that have knowlede of the container class.
-
traity.tools.initializable_property.
init_properties
(cls)¶ Class decorator calles __init_property__ on all initializable objects defined in a class
Instance properties¶
Example
class MyObj(iobject): pass
def get_x(any):
return 1
obj = MyObj()
set_iproperty(obj, 'x', get_x)
print obj.x
1
-
traity.tools.instance_properties.
set_iproperty
(instance, attr, prop)¶ set an instance property of an object
-
traity.tools.instance_properties.
get_iproperty
(instance, attr)¶ get an instance property of an object
-
class
traity.tools.instance_properties.
iobject
¶ class must be a subclass of iobject to support instance properties
Compat¶
Comparison with traits¶
My ideal traits’s like library.
traity.events + traity.statics == traity.traits.
### Objectives
#### Uphold the main principles and philosophy of traits
- Initialization:
- A may optionally have a default value.
- Validation:
- A trait attribute is explicitly typed. The type of a trait-based attribute is evident in the code, and only values that meet a programmer-specified set of criteria (i.e., the trait definition) can be assigned to that attribute.
- Deferral:
- The value of a trait attribute can be contained either in the defining object or in another object that is deferred to by the trait.
- Notification:
- Setting the value of a trait attribute can notify other parts of the program that the value has changed.
- Visualization:
- TBD - enaml?
#### Reduce codebase
- Traits is a huge project with > 92,000 lines and < %60 covered by unit-tests.
- Traity is a tiny project < 2,000 lines and > %95 covered by unit-tests.
Traity is designed to remain tiny kernel of stable code which add-ons and extension may be based on top of.
#### Extend the learning curve
It is my feeling that while traits may be a good learning tool for new scientists it’s monolithic structure makes it very hard for an advanced programmer to do specialized things.
Traity is designed from the ground up to be tiny and transparent. Separating event notification from static typing from other more specialized helpers.
#### Python 3
Just mentioning it here. Traity is Python 3 compliant.
### Highlights
# Optional decorator does two things # 1. Makes all vproperty’s including trait picklable. # 2. Allows static listeners to be defined on a class. @init_properties # Notice that the foo class does not have to inherit from any hastraits base class. class Foo(object):
#attr1 may emit events like changes attr1 = listenable()
#vproperty is a type checking propery. attr2 = vproperty(type=int)
#traits is a subclass of listenable and vproperty attr3 = trait(type=float)
- def __init__(self):
- #Optional: Alows listenable and trait properties to emit events. init_events(self)
@attr3.changed def notify(self, event):
pass
#### Building back up to traits
As I mentioned before, this is meant to be a tiny implementation and extensions can be built on top if traity.
Here is an example of how to re-create a simple HasTraits class from traity.
- def __init__(default=0):
- trait.__init__(self, type=int, fdefault=lambda self:default)
# Special method to allow trait to be called with or without parens ‘()’ # Method __init_property__ is invoked when init_properties is called @classmethod def __init_property__(cls, owner, key):
int_trait = cls() setattr(owner, key, int_trait) trait.__init_property__(int_trait, owner, key)
- class HasTraitsMeta(type):
- def __new__(mcs, name, bases, dict):
- cls = type.__new__(mcs, name, bases, dict) init_properties(cls) return cls
- class HasTraits(object):
__metaclass__ = HasTraitsMeta
- def __init__(**kwargs):
- self.__dict__.update(kwargs) init_events(self)
- class MyObject(HasTraits):
- i = Int