Source code for traits.trait_value

#------------------------------------------------------------------------------
#
#  Copyright (c) 2008, Enthought, Inc.
#  All rights reserved.
#
#  This software is provided without warranty under the terms of the BSD
#  license included in enthought/LICENSE.txt and may be redistributed only
#  under the conditions described in the aforementioned license.  The license
#  is also available online at http://www.enthought.com/licenses/BSD.txt
#
#  Thanks for using Enthought open source!
#
#  Author:        David C. Morrill
#  Original Date: 04/01/2008
#
#------------------------------------------------------------------------------

""" Defines the TraitValue class, used for creating special, dynamic trait
    values.
"""

#-------------------------------------------------------------------------------
#  Imports:
#-------------------------------------------------------------------------------

from __future__ import absolute_import

from .trait_base import Undefined
from .traits import CTrait
from .has_traits import HasTraits, HasPrivateTraits
from .trait_errors import TraitError
from .trait_types import Tuple, Dict, Any, Str, Instance, Event, Callable
from .trait_handlers import TraitType, _read_only, _write_only, _arg_count

#-------------------------------------------------------------------------------
#  'BaseTraitValue' class:
#-------------------------------------------------------------------------------

[docs]class BaseTraitValue ( HasPrivateTraits ): # Subclasses can define this trait as a property: # value = Property #-- Public Methods ---------------------------------------------------------
[docs] def as_ctrait ( self, original_trait ): """ Returns the low-level C-based trait for this TraitValue. """ notifiers = original_trait._notifiers( 0 ) if self._ctrait is not None: if (notifiers is None) or (len( notifiers ) == 0): return self._ctrait trait = CTrait( 0 ) trait.clone( self._ctrait ) else: trait = self._as_ctrait( original_trait ) if ((trait is not None) and (notifiers is not None) and (len( notifiers ) > 0)): trait._notifiers( 1 ).extend( notifiers ) return trait #-- Private Methods --------------------------------------------------------
def _as_ctrait ( self, original_trait ): """ Returns the low-level C-based trait for this TraitValue. """ value_trait = self.trait( 'value' ) if value_trait is None: return None if value_trait.type != 'property': raise TraitError( "Invalid TraitValue specified." ) metadata = { 'type': 'property', '_trait_value': self } getter, setter, validate = value_trait.property() read_only = (getter is _read_only) if not read_only: getter = self._getter metadata[ 'transient' ] = True if setter is not _write_only: if read_only: setter = self._read_only_setter else: setter = self._setter metadata[ 'transient' ] = True return self._property_trait( getter, setter, validate, metadata ) def _property_trait ( self, getter, setter, validate, metadata ): """ Returns a properly constructed 'property' trait. """ n = 0 if validate is not None: n = _arg_count( validate ) trait = CTrait( 4 ) trait.property( getter, _arg_count( getter ), setter, _arg_count( setter ), validate, n ) trait.value_allowed( True ) trait.value_property( True ) trait.__dict__ = metadata return trait def _getter ( self, object, name ): return self.value def _setter ( self, object, name, value ): old_value = self.value self.value = value new_value = self.value if new_value != old_value: object.trait_property_changed( name, old_value, new_value ) def _read_only_setter ( self, object, name, value ): self.value = value object.trait_property_changed( name, Undefined, value ) #------------------------------------------------------------------------------- # 'TraitValue' class: #-------------------------------------------------------------------------------
[docs]class TraitValue ( BaseTraitValue ): #: The callable used to define a default value: default = Callable #: The positional arguments to pass to the callable default value: args = Tuple #: The keyword arguments to pass to the callable default value: kw = Dict #: The trait to use as the new trait type: type = Any #: The object to delegate the new value to: delegate = Instance( HasTraits ) #: The name of the trait on the delegate object to get the new value from: name = Str #-- Private Methods -------------------------------------------------------- def _as_ctrait ( self, original_trait ): """ Returns the low-level C-based trait for this TraitValue. """ if self.default is not None: trait = CTrait( 0 ) trait.clone( original_trait ) if original_trait.__dict__ is not None: trait.__dict__ = original_trait.__dict__.copy() trait.default_value( 7, ( self.default, self.args, self.kw ) ) elif self.type is not None: type = self.type try: rc = issubclass( type, TraitType ) except: rc = False if rc: type = type( *self.args, **self.kw ) if not isinstance( type, TraitType ): raise TraitError( ("The 'type' attribute of a TraitValue " "instance must be a TraitType instance or subclass, but a " "value of %s was specified.") % self.trait ) self._ctrait = trait = type.as_ctrait() trait.value_allowed( True ) elif self.delegate is None: return None else: if self.name == '': raise TraitError( "You must specify a non-empty string " "value for the 'name' attribute when using the " "'delegate' trait of a TraitValue instance." ) metadata = { 'type': 'property', '_trait_value': self, 'transient': True } getter = self._delegate_getter setter = self._delegate_setter validate = None self.add_trait( 'value', Event() ) self.delegate.on_trait_change( self._delegate_modified, self.name ) trait = self._property_trait( getter, setter, validate, metadata ) return trait def _delegate_getter ( self, object, name ): return getattr( self.delegate, self.name ) def _delegate_setter ( self, object, name, value ): setattr( self.delegate, self.name, value ) #-- Traits Event Handlers -------------------------------------------------- def _delegate_modified ( self ): self.value = True #-- Helper Function Definitions ------------------------------------------------
[docs]def SyncValue ( delegate, name ): return TraitValue( delegate = delegate, name = name )
[docs]def TypeValue ( type ): return TraitValue( type = type )
[docs]def DefaultValue ( default, args = (), kw = {} ): return TraitValue( default = default, args = args, kw = kw ) #------------------------------------------------------------------------------- # Tell the C-based traits module about the 'BaseTraitValue' class: #-------------------------------------------------------------------------------
from . import ctraits ctraits._value_class( BaseTraitValue )