1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
""" Context adapter for Python instances. """
# Standard library imports.
import re
# Enthought library imports.
from apptools.naming.api import Binding, ContextAdapter
from apptools.naming.api import OperationNotSupportedError, naming_manager
from traits.api import HasTraits, List, Property, Str
class InstanceContextAdapter(ContextAdapter):
""" Context adapter for Python instances. """
#### 'Context' interface ##################################################
# The name of the context within its own namespace.
namespace_name = Property(Str)
#### 'InstanceContextAdapter' interface ###################################
# By default every public attribute of an instance is exposed. Use the
# following traits to either include or exclude attributes as appropriate.
#
# Regular expressions that describe the names of attributes to include.
include = List(Str)
# Regular expressions that describe the names of attributes to exclude. By
# default we exclude 'protected' and 'private' attributes and any
# attributes that are artifacts of the traits mechanism.
exclude = List(Str, ['_', 'trait_'])
###########################################################################
# 'Context' interface.
###########################################################################
#### Properties ###########################################################
def _get_namespace_name(self):
""" Returns the name of the context within its own namespace. """
base = self.context.namespace_name
if len(base) > 0:
base += '/'
names = self.context.search(self.adaptee)
return base + names[0]
###########################################################################
# Protected 'Context' interface.
###########################################################################
def _is_bound(self, name):
""" Is a name bound in this context? """
return name in self._list_names()
def _lookup(self, name):
""" Looks up a name in this context. """
obj = getattr(self.adaptee, name)
return naming_manager.get_object_instance(obj, name, self)
def _lookup_binding(self, name):
""" Looks up the binding for a name in this context. """
return Binding(name=name, obj=self._lookup(name), context=self)
def _bind(self, name, obj):
""" Binds a name to an object in this context. """
state = naming_manager.get_state_to_bind(obj, name, self)
setattr(self.adaptee, name, state)
return
def _rebind(self, name, obj):
""" Rebinds a name to an object in this context. """
self._bind(name, obj)
return
def _unbind(self, name):
""" Unbinds a name from this context. """
delattr(self.adaptee, name)
return
def _rename(self, old_name, new_name):
""" Renames an object in this context. """
# Bind the new name.
setattr(self.adaptee, new_name, self._lookup(old_name))
# Unbind the old one.
delattr(self.adaptee, old_name)
return
def _create_subcontext(self, name):
""" Creates a sub-context of this context. """
raise OperationNotSupportedError()
def _destroy_subcontext(self, name):
""" Destroys a sub-context of this context. """
raise OperationNotSupportedError()
def _list_bindings(self):
""" Lists the bindings in this context. """
bindings = []
for name in self._list_names():
try:
obj = self._lookup(name)
bindings.append(Binding(name=name, obj=obj, context=self))
# We get attribute errors when we try to look up Event traits (they
# are write-only).
except AttributeError:
pass
return bindings
def _list_names(self):
""" Lists the names bound in this context. """
return self._get_public_attribute_names(self.adaptee)
###########################################################################
# Private interface.
###########################################################################
def _get_public_attribute_names(self, obj):
""" Returns the names of an object's public attributes. """
if isinstance(obj, HasTraits):
names = obj.trait_names()
elif hasattr(obj, '__dict__'):
names = self.adaptee.__dict__.keys()
else:
names = []
return [name for name in names if self._is_exposed(name)]
def _is_exposed(self, name):
""" Returns True iff a name should be exposed. """
if len(self.include) > 0:
is_exposed = self._matches(self.include, name)
elif len(self.exclude) > 0:
is_exposed = not self._matches(self.exclude, name)
else:
is_exposed = True
return is_exposed
def _matches(self, expressions, name):
""" Returns True iff a name matches any of a list of expressions. """
for expression in expressions:
if re.match(expression, name) is not None:
matches = True
break
else:
matches = False
return matches
#### EOF ######################################################################
|