diff --git a/README.rst b/README.rst index 802c5d793..863672b41 100644 --- a/README.rst +++ b/README.rst @@ -31,8 +31,6 @@ that is commonly needed by many applications - **apptools.sweet_pickle**: Handles class-level versioning, to support loading of saved data that exist over several generations of internal class structures. -- **apptools.type_manager**: Manages type extensions, including factories - to generate adapters, and hooks for methods and functions. - **apptools.undo**: Supports undoing and scripting application commands. Prerequisites diff --git a/apptools/naming/adapter/__init__.py b/apptools/naming/adapter/__init__.py deleted file mode 100644 index cc14aac8d..000000000 --- a/apptools/naming/adapter/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from apptools.naming.adapter.api import * diff --git a/apptools/naming/adapter/api.py b/apptools/naming/adapter/api.py deleted file mode 100644 index 3f49410cd..000000000 --- a/apptools/naming/adapter/api.py +++ /dev/null @@ -1,12 +0,0 @@ -from .dict_context_adapter import DictContextAdapter -from .dict_context_adapter_factory import DictContextAdapterFactory -from .instance_context_adapter import InstanceContextAdapter -from .instance_context_adapter_factory import InstanceContextAdapterFactory -from .list_context_adapter import ListContextAdapter -from .list_context_adapter_factory import ListContextAdapterFactory -from .trait_list_context_adapter import TraitListContextAdapter -from .trait_list_context_adapter_factory import TraitListContextAdapterFactory -from .tuple_context_adapter import TupleContextAdapter -from .tuple_context_adapter_factory import TupleContextAdapterFactory - -from .trait_dict_context_adapter import TraitDictContextAdapter diff --git a/apptools/naming/adapter/dict_context_adapter.py b/apptools/naming/adapter/dict_context_adapter.py deleted file mode 100644 index 659eb3775..000000000 --- a/apptools/naming/adapter/dict_context_adapter.py +++ /dev/null @@ -1,106 +0,0 @@ -""" Context adapter for Python dictionaries. """ - - -# Enthought library imports. -from apptools.naming.api import Binding, ContextAdapter, naming_manager - - -class DictContextAdapter(ContextAdapter): - """ Context adapter for Python dictionaries. """ - - #### 'ContextAdapter' interface ########################################### - - # The object that we are adapting. - # - # - # fixme: We would like to specialize the 'adaptee' trait here, but if we - # make it of type 'Dict' then, on assignment, traits will create a *copy* - # of the actual dict which I think you'll agree is not very adapter-like! - ## adaptee = Dict - - ########################################################################### - # Protected 'Context' interface. - ########################################################################### - - def _is_bound(self, name): - """ Is a name bound in this context? """ - - return name in self.adaptee - - def _lookup(self, name): - """ Looks up a name in this context. """ - - obj = 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) - 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. """ - - del self.adaptee[name] - - return - - def _rename(self, old_name, new_name): - """ Renames an object in this context. """ - - # Bind the new name. - self._bind(new_name, self._lookup(old_name)) - - # Unbind the old one. - self._unbind(old_name) - - return - - def _create_subcontext(self, name): - """ Creates a sub-context of this context. """ - - # Create a dictionary of the same type as the one we are adapting. - sub = type(self.adaptee)() - - self.adaptee[name] = sub - - return DictContextAdapter(adaptee=sub) - - def _destroy_subcontext(self, name): - """ Destroys a sub-context of this context. """ - - del self.adaptee[name] - - return - - def _list_bindings(self): - """ Lists the bindings in this context. """ - - bindings = [] - for key in self.adaptee: - bindings.append( - Binding(name=str(key), obj=self._lookup(key), context=self) - ) - - return bindings - - def _list_names(self): - """ Lists the names bound in this context. """ - - return [str(key) for key in self.adaptee] diff --git a/apptools/naming/adapter/dict_context_adapter_factory.py b/apptools/naming/adapter/dict_context_adapter_factory.py deleted file mode 100644 index f89fa96e7..000000000 --- a/apptools/naming/adapter/dict_context_adapter_factory.py +++ /dev/null @@ -1,30 +0,0 @@ -""" Context adapter factory for Python dictionaries. """ - - -# Enthought library imports. -from apptools.naming.api import ContextAdapterFactory - -# Local imports. -from .dict_context_adapter import DictContextAdapter - - -class DictContextAdapterFactory(ContextAdapterFactory): - """ Context adapter factory for Python dictionaries. """ - - #### 'ContextAdapterFactory' interface #################################### - - # The type of object that we adapt. - adaptee_class = dict - - ########################################################################### - # Protected 'AbstractAdapterFactory' interface. - ########################################################################### - - def _adapt(self, adaptee, target_class, environment, context): - """ Returns an adapter that adapts an object to the target class. """ - - adapter = DictContextAdapter( - adaptee=adaptee, environment=environment, context=context - ) - - return adapter diff --git a/apptools/naming/adapter/instance_context_adapter.py b/apptools/naming/adapter/instance_context_adapter.py deleted file mode 100644 index 9d4da8265..000000000 --- a/apptools/naming/adapter/instance_context_adapter.py +++ /dev/null @@ -1,179 +0,0 @@ -""" 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 = list(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 diff --git a/apptools/naming/adapter/instance_context_adapter_factory.py b/apptools/naming/adapter/instance_context_adapter_factory.py deleted file mode 100644 index b1226ff64..000000000 --- a/apptools/naming/adapter/instance_context_adapter_factory.py +++ /dev/null @@ -1,49 +0,0 @@ -""" Context adapter factory for Python instances. """ - - -# Enthought library imports. -from apptools.naming.api import ContextAdapterFactory -from traits.api import List, Str -from apptools.type_manager import PythonObject - -# Local imports. -from .instance_context_adapter import InstanceContextAdapter - - -class InstanceContextAdapterFactory(ContextAdapterFactory): - """ Context adapter factoryfor Python instances. """ - - #### 'ContextAdapterFactory' interface #################################### - - # The type of object that we adapt. - adaptee_class = PythonObject - - #### 'InstanceContextAdapterFactory' 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_"]) - - ########################################################################### - # Protected 'AbstractAdapterFactory' interface. - ########################################################################### - - def _adapt(self, adaptee, target_class, environment, context): - """ Returns an adapter that adapts an object to the target class. """ - - adapter = InstanceContextAdapter( - adaptee=adaptee, - environment=environment, - context=context, - include=self.include, - exclude=self.exclude, - ) - - return adapter diff --git a/apptools/naming/adapter/list_context_adapter.py b/apptools/naming/adapter/list_context_adapter.py deleted file mode 100644 index d39a0190d..000000000 --- a/apptools/naming/adapter/list_context_adapter.py +++ /dev/null @@ -1,175 +0,0 @@ -""" Context adapter for Python lists. """ - - -# Enthought library imports. -from apptools.naming.api import Binding, ContextAdapter, naming_manager -from traits.api import List, Property - - -class ListContextAdapter(ContextAdapter): - """ Context adapter for Python lists. """ - - #### 'ContextAdapter' interface ########################################### - - # The object that we are adapting. - # - # fixme: We would like to specialize the 'adaptee' trait here, but if we - # make it of type 'List' then, on assignment, traits will create a *copy* - # of the actual list which I think you'll agree is not very adapter-like! - ## adaptee = List - - #### 'ListContextAdapter' interface ####################################### - - # The list that we are adapting. - collection = Property(List) - - ########################################################################### - # 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. """ - - binding = self._get_binding_with_name(name) - - return naming_manager.get_object_instance(binding.obj, name, 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) - self.collection.append(state) - - return - - def _rebind(self, name, obj): - """ Rebinds a name to an object in this context. """ - - index = 0 - for binding in self.list_bindings(""): - if binding.name == name: - self.collection[index] = obj - break - - index = index + 1 - - # The name is not already bound. - else: - self._bind(name, obj) - - return - - def _unbind(self, name): - """ Unbinds a name from this context. """ - - index = 0 - for binding in self.list_bindings(""): - if binding.name == name: - del self.collection[index] - break - - index = index + 1 - - else: - raise SystemError("no binding with name %s" % name) - - return - - def _rename(self, old_name, new_name): - """ Renames an object in this context. """ - - binding = self._get_binding_with_name(old_name) - - self._set_name(binding.obj, new_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 obj in self.collection: - # Bindings have to have a string name. - name = self._get_name(obj) - - # Create the binding. - bindings.append(Binding(name=name, obj=obj, context=self)) - - return bindings - - def _list_names(self): - """ Lists the names bound in this context. """ - - return [self._get_name(obj) for obj in self.collection] - - ########################################################################### - # Protected 'ListContext' interface. - ########################################################################### - - def _get_collection(self): - """ Returns the collection that we are adapting. """ - - return self.adaptee - - ########################################################################### - # Private interface. - ########################################################################### - - # fixme: Allow an item name trait to be specified instead of guessing at - # 'name' or 'id'! - def _get_name(self, obj): - """ Returns the name of an object. """ - - if hasattr(obj, "name"): - name = str(obj.name) - - elif hasattr(obj, "id"): - name = str(obj.id) - - else: - name = str(obj) - - return name - - def _set_name(self, obj, name): - """ Sets the name of an object. """ - - if hasattr(obj, "name"): - obj.name = name - - elif hasattr(obj, "id"): - obj.id = name - - return - - def _get_binding_with_name(self, name): - """ Returns the binding with the specified name. """ - - for binding in self.list_bindings(""): - if binding.name == name: - break - - # The reason that this is a system error and not just a naming error - # is that this method is only called from inside the protected - # 'Context' interface when we have already determined that the name - # is bound - else: - raise SystemError("no binding with name %s" % name) - - return binding diff --git a/apptools/naming/adapter/list_context_adapter_factory.py b/apptools/naming/adapter/list_context_adapter_factory.py deleted file mode 100644 index 0284b1e21..000000000 --- a/apptools/naming/adapter/list_context_adapter_factory.py +++ /dev/null @@ -1,30 +0,0 @@ -""" Context adapter factory for Python lists. """ - - -# Enthought library imports. -from apptools.naming.api import ContextAdapterFactory - -# Local imports. -from .list_context_adapter import ListContextAdapter - - -class ListContextAdapterFactory(ContextAdapterFactory): - """ Context adapter factory for Python lists. """ - - #### 'ContextAdapterFactory' interface #################################### - - # The type of object that we adapt. - adaptee_class = list - - ########################################################################### - # Protected 'AbstractAdapterFactory' interface. - ########################################################################### - - def _adapt(self, adaptee, target_class, environment, context): - """ Returns an adapter that adapts an object to the target class. """ - - adapter = ListContextAdapter( - adaptee=adaptee, environment=environment, context=context - ) - - return adapter diff --git a/apptools/naming/adapter/trait_dict_context_adapter.py b/apptools/naming/adapter/trait_dict_context_adapter.py deleted file mode 100644 index 8812f12cd..000000000 --- a/apptools/naming/adapter/trait_dict_context_adapter.py +++ /dev/null @@ -1,36 +0,0 @@ -""" Context adapter for trait dictionaries. """ - - -# Enthought library imports. -from traits.api import Dict, Property, Str - -# Local imports. -from .dict_context_adapter import DictContextAdapter - - -class TraitDictContextAdapter(DictContextAdapter): - """ Context adapter for trait dictionaries. """ - - #### 'Context' interface ################################################## - - # The name of the context within its own namespace. - namespace_name = Property(Str) - - #### 'ContextAdapter' interface ########################################### - - # The object that we are adapting. - adaptee = Dict - - #### 'TraitDictContextAdapter' interface ################################## - - # The name of the object's trait that provides the dictionary. - trait_name = Str - - ########################################################################### - # 'Context' interface. - ########################################################################### - - def _get_namespace_name(self): - """ Returns the name of the context within its own namespace. """ - - return self.context.namespace_name + "/" + self.trait_name diff --git a/apptools/naming/adapter/trait_dict_context_adapter_factory.py b/apptools/naming/adapter/trait_dict_context_adapter_factory.py deleted file mode 100644 index 0e9eff8bf..000000000 --- a/apptools/naming/adapter/trait_dict_context_adapter_factory.py +++ /dev/null @@ -1,39 +0,0 @@ -""" Context adapter factory for trait dicts. """ - - -# Enthought library imports. -from apptools.naming.api import ContextAdapterFactory -from traits.api import Str, TraitDict - -# Local imports. -from .trait_dict_context_adapter import TraitDictContextAdapter - - -class TraitDictContextAdapterFactory(ContextAdapterFactory): - """ Context adapter factoryfor Python trait dicts. """ - - #### 'ContextAdapterFactory' interface #################################### - - # The type of object that we adapt. - adaptee_class = TraitDict - - #### 'TraitDictContextAdapterFactory' interface ########################### - - # The name of the trait (on the adaptee) that provides the trait dict. - trait_name = Str - - ########################################################################### - # Protected 'AbstractAdapterFactory' interface. - ########################################################################### - - def _adapt(self, adaptee, target_class, environment, context): - """ Returns an adapter that adapts an object to the target class. """ - - adapter = TraitDictContextAdapter( - adaptee=adaptee, - environment=environment, - context=context, - trait_name=self.trait_name, - ) - - return adapter diff --git a/apptools/naming/adapter/trait_list_context_adapter.py b/apptools/naming/adapter/trait_list_context_adapter.py deleted file mode 100644 index 12ea88a56..000000000 --- a/apptools/naming/adapter/trait_list_context_adapter.py +++ /dev/null @@ -1,64 +0,0 @@ -""" Context adapter for trait lists. """ - - -# Enthought library imports. -from traits.api import Any, List, Property, Str - -# Local imports. -from .list_context_adapter import ListContextAdapter - - -class TraitListContextAdapter(ListContextAdapter): - """ Context adapter for trait lists. """ - - #### 'Context' interface ################################################## - - # The name of the context within its own namespace. - namespace_name = Property(Str) - - #### 'ContextAdapter' interface ########################################### - - # The object that we are adapting. - adaptee = Any - - #### 'ListContextAdapter' interface ####################################### - - # The list that we are adapting. - collection = Property(List) - - #### 'TraitListContextAdapter' interface ################################## - - # The name of the object's trait that provides the list. - trait_name = Str - - ########################################################################### - # 'Context' interface. - ########################################################################### - - def _get_namespace_name(self): - """ Returns the name of the context within its own namespace. """ - - return self.context.namespace_name + "/" + self.trait_name - - ########################################################################### - # Protected 'ListContext' interface. - ########################################################################### - - #### 'Properties' ######################################################### - - def _get_collection(self): - """ Returns the collection that we are adapting. """ - - components = self.trait_name.split(".") - if len(components) == 1: - collection = getattr(self.adaptee, self.trait_name) - - else: - # Find the object that contains the trait. - obj = self.adaptee - for component in components[:-1]: - obj = getattr(obj, component) - - collection = getattr(obj, components[-1]) - - return collection diff --git a/apptools/naming/adapter/trait_list_context_adapter_factory.py b/apptools/naming/adapter/trait_list_context_adapter_factory.py deleted file mode 100644 index cf45a3764..000000000 --- a/apptools/naming/adapter/trait_list_context_adapter_factory.py +++ /dev/null @@ -1,39 +0,0 @@ -""" Context adapter factory for trait lists. """ - - -# Enthought library imports. -from apptools.naming.api import ContextAdapterFactory -from traits.api import Str, TraitList - -# Local imports. -from .trait_list_context_adapter import TraitListContextAdapter - - -class TraitListContextAdapterFactory(ContextAdapterFactory): - """ Context adapter factoryfor Python trait lists. """ - - #### 'ContextAdapterFactory' interface #################################### - - # The type of object that we adapt. - adaptee_class = TraitList - - #### 'TraitListContextAdapterFactory' interface ########################### - - # The name of the trait (on the adaptee) that provides the trait list. - trait_name = Str - - ########################################################################### - # Protected 'AbstractAdapterFactory' interface. - ########################################################################### - - def _adapt(self, adaptee, target_class, environment, context): - """ Returns an adapter that adapts an object to the target class. """ - - adapter = TraitListContextAdapter( - adaptee=adaptee, - environment=environment, - context=context, - trait_name=self.trait_name, - ) - - return adapter diff --git a/apptools/naming/adapter/tuple_context_adapter.py b/apptools/naming/adapter/tuple_context_adapter.py deleted file mode 100644 index e7086ca3b..000000000 --- a/apptools/naming/adapter/tuple_context_adapter.py +++ /dev/null @@ -1,17 +0,0 @@ -""" Context adapter for Python tuples. """ - - -# Enthought library imports. -from traits.api import Tuple - -# Local imports. -from .list_context_adapter import ListContextAdapter - - -class TupleContextAdapter(ListContextAdapter): - """ Context adapter for Python tuples. """ - - #### 'ContextAdapter' interface ########################################### - - # The object that we are adapting. - adaptee = Tuple diff --git a/apptools/naming/adapter/tuple_context_adapter_factory.py b/apptools/naming/adapter/tuple_context_adapter_factory.py deleted file mode 100644 index b0fc4b355..000000000 --- a/apptools/naming/adapter/tuple_context_adapter_factory.py +++ /dev/null @@ -1,30 +0,0 @@ -""" Context adapter factory for Python tuple. """ - - -# Enthought library imports. -from apptools.naming.api import ContextAdapterFactory - -# Local imports. -from .tuple_context_adapter import TupleContextAdapter - - -class TupleContextAdapterFactory(ContextAdapterFactory): - """ Context adapter factoryfor Python tuples. """ - - #### 'ContextAdapterFactory' interface #################################### - - # The type of object that we adapt. - adaptee_class = tuple - - ########################################################################### - # Protected 'AbstractAdapterFactory' interface. - ########################################################################### - - def _adapt(self, adaptee, target_class, environment, context): - """ Returns an adapter that adapts an object to the target class. """ - - adapter = TupleContextAdapter( - adaptee=adaptee, environment=environment, context=context - ) - - return adapter diff --git a/apptools/naming/api.py b/apptools/naming/api.py index f6e8cc845..b01d5580d 100644 --- a/apptools/naming/api.py +++ b/apptools/naming/api.py @@ -18,8 +18,6 @@ from .address import Address from .binding import Binding from .context import Context -from .context_adapter import ContextAdapter -from .context_adapter_factory import ContextAdapterFactory from .dynamic_context import DynamicContext from .dir_context import DirContext from .initial_context import InitialContext diff --git a/apptools/naming/context.py b/apptools/naming/context.py index 2c5d0756b..e72fabf07 100644 --- a/apptools/naming/context.py +++ b/apptools/naming/context.py @@ -17,7 +17,6 @@ # Enthought library imports. from traits.api import Any, Dict, Event, HasTraits, Instance from traits.api import Property, Str -from apptools.type_manager.api import TypeManager # Local imports. from .binding import Binding @@ -36,17 +35,12 @@ OBJECT_FACTORIES = "apptools.naming.factory.object" STATE_FACTORIES = "apptools.naming.factory.state" -# Non-JNDI. -TYPE_MANAGER = "apptools.naming.factory.type.manager" - # The default environment. ENVIRONMENT = { # 'Context' properties. OBJECT_FACTORIES: [], STATE_FACTORIES: [], - # Non-JNDI. - TYPE_MANAGER: None, } @@ -58,9 +52,6 @@ class Context(HasTraits): OBJECT_FACTORIES = OBJECT_FACTORIES STATE_FACTORIES = STATE_FACTORIES - # Non-JNDI. - TYPE_MANAGER = TYPE_MANAGER - #### 'Context' interface ################################################## # The naming environment in effect for this context. @@ -69,14 +60,6 @@ class Context(HasTraits): # The name of the context within its own namespace. namespace_name = Property(Str) - # The type manager in the context's environment (used to create context - # adapters etc.). - # - # fixme: This is an experimental 'convenience' trait, since it is common - # to get hold of the context's type manager to see if some object has a - # context adapter. - type_manager = Property(Instance(TypeManager)) - #### Events #### # Fired when an object has been added to the context (either via 'bind' or @@ -133,16 +116,6 @@ def _get_namespace_name(self): # raise OperationNotSupportedError() return "" - def _get_type_manager(self): - """Returns the type manager in the context's environment. - - This will return None if no type manager was used to create the initial - context. - - """ - - return self.environment.get(self.TYPE_MANAGER) - #### Methods ############################################################## def bind(self, name, obj, make_contexts=False): @@ -391,8 +364,7 @@ def lookup_binding(self, name): def lookup_context(self, name): """Resolves a name relative to this context. - The name MUST resolve to a context. This method is useful to return - context adapters. + The name MUST resolve to a context. """ @@ -711,16 +683,8 @@ def _get_next_context(self, name): # If the object is a context then everything is just dandy. if isinstance(obj, Context): next_context = obj - - # Otherwise, instead of just giving up, see if the context has a type - # manager that knows how to adapt the object to make it quack like a - # context. else: - next_context = self._get_context_adapter(obj) - - # If no adapter was found then we cannot continue name resolution. - if next_context is None: - raise NotContextError(name) + raise NotContextError(name) return next_context @@ -747,24 +711,3 @@ def _search(self, obj, names, path, searched): path.pop() return - - ########################################################################### - # Private interface. - ########################################################################### - - def _get_context_adapter(self, obj): - """Returns a context adapter for an object. - - Returns None if no such adapter is available. - - """ - - if self.type_manager is not None: - adapter = self.type_manager.object_as( - obj, Context, environment=self.environment, context=self - ) - - else: - adapter = None - - return adapter diff --git a/apptools/naming/context_adapter.py b/apptools/naming/context_adapter.py deleted file mode 100644 index 3274a2433..000000000 --- a/apptools/naming/context_adapter.py +++ /dev/null @@ -1,33 +0,0 @@ -# ------------------------------------------------------------------------------ -# Copyright (c) 2005, 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: Enthought, Inc. -# Description: -# ------------------------------------------------------------------------------ -""" The base class for all context adapters. """ - - -# Enthought library imports. -from traits.api import Any, Dict, Instance, Property, Str - -# Local imports. -from .context import Context - - -class ContextAdapter(Context): - """ The base class for all context adapters. """ - - #### 'ContextAdapter' interface ########################################### - - # The object that we are adapting. - adaptee = Any - - # The context that the object is in. - context = Instance(Context) diff --git a/apptools/naming/context_adapter_factory.py b/apptools/naming/context_adapter_factory.py deleted file mode 100644 index 48a467b3f..000000000 --- a/apptools/naming/context_adapter_factory.py +++ /dev/null @@ -1,43 +0,0 @@ -# ------------------------------------------------------------------------------ -# Copyright (c) 2005, 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: Enthought, Inc. -# Description: -# ------------------------------------------------------------------------------ -""" The base class for all context adapter factories. """ - - -# Enthought library imports. -from apptools.type_manager.api import AdapterFactory - -# Local imports. -from .context import Context - - -class ContextAdapterFactory(AdapterFactory): - """ The base class for all context adapter factories. """ - - #### 'AdapterFactory' interface ########################################### - - # The target class (the class that the factory can adapt objects to). - target_class = Context - - ########################################################################### - # Protected 'AbstractAdapterFactory' interface. - ########################################################################### - - def _adapt(self, adaptee, target_class, environment, context): - """ Returns an adapter that adapts an object to the target class. """ - - adapter = self.adapter_class( - adaptee=adaptee, environment=environment, context=context - ) - - return adapter diff --git a/apptools/type_manager/__init__.py b/apptools/type_manager/__init__.py deleted file mode 100644 index 76918b36d..000000000 --- a/apptools/type_manager/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -# ------------------------------------------------------------------------------ -# Copyright (c) 2006 by Enthought, Inc. -# All rights reserved. -# ------------------------------------------------------------------------------ -""" Manages type extensions, including factories to generate adapters, and - hooks for methods and functions. Part of the AppTools project of the - Enthought Tool Suite. -""" -from apptools.type_manager.api import * diff --git a/apptools/type_manager/abstract_adapter_factory.py b/apptools/type_manager/abstract_adapter_factory.py deleted file mode 100644 index aff875837..000000000 --- a/apptools/type_manager/abstract_adapter_factory.py +++ /dev/null @@ -1,86 +0,0 @@ -""" Abstract base class for all adapter factories. """ - -# Standard library imports. -import logging - -# Enthought library imports. -from traits.api import Delegate, HasTraits, Instance - -# Local imports. -from .adapter_manager import AdapterManager - - -logger = logging.getLogger(__name__) - - -class AbstractAdapterFactory(HasTraits): - """Abstract base class for all adapter factories. - - Adapter factories define behavioural extensions for classes. - - """ - - #### 'AbstractAdapterFactory' interface ################################### - - # The adapter manager that the factory is registered with (this will be - # None iff the factory is not registered with a manager). - adapter_manager = Instance(AdapterManager) - - # The type system used by the factory (it determines 'is_a' relationships - # and type MROs etc). By default we use standard Python semantics. - type_system = Delegate("adapter_manager") - - ########################################################################### - # 'AbstractAdapterFactory' interface. - ########################################################################### - - def adapt(self, adaptee, target_class, *args, **kw): - """Returns an adapter that adapts an object to the target class. - - Returns None if the factory cannot produce such an adapter. - - """ - - if self._can_adapt(adaptee, target_class, *args, **kw): - adapter = self._adapt(adaptee, target_class, *args, **kw) - if adapter is None: - logger.warn(self._get_warning_message(adaptee, target_class)) - - else: - adapter = None - - return adapter - - ########################################################################### - # Protected 'AbstractAdapterFactory' interface. - ########################################################################### - - def _can_adapt(self, adaptee, target_class, *args, **kw): - """ Returns True if the factory can produce an appropriate adapter. """ - - raise NotImplementedError - - def _adapt(self, adaptee, target_class, *args, **kw): - """ Returns an adapter that adapts an object to the target class. """ - - raise NotImplementedError - - ########################################################################### - # Private interface. - ########################################################################### - - def _get_warning_message(self, adaptee, target_class): - """Returns a warning message. - - The warning message is used when a factory fails to adapt something - that it said it could! - - """ - - message = "%s failed to adapt %s to %s" % ( - self.__class__.__name__, - str(adaptee), - target_class.__name__, - ) - - return message diff --git a/apptools/type_manager/abstract_factory.py b/apptools/type_manager/abstract_factory.py deleted file mode 100644 index 5742b3d53..000000000 --- a/apptools/type_manager/abstract_factory.py +++ /dev/null @@ -1,69 +0,0 @@ -""" Abstract base class for all object factories. """ - -# Standard library imports. -import logging - -# Enthought library imports. -from traits.api import HasTraits - - -logger = logging.getLogger(__name__) - - -class AbstractFactory(HasTraits): - """ Abstract base class for all object factories. """ - - ########################################################################### - # 'AbstractFactory' interface. - ########################################################################### - - def create(self, target_class, *args, **kw): - """Creates an object of the specified target class. - - Returns None if the factory cannot produce an object of the target - class. - - """ - - if self._can_create(target_class, *args, **kw): - obj = self._create(target_class, *args, **kw) - if obj is None: - logger.warn(self._get_warning_message(target_class)) - - else: - obj = None - - return obj - - ########################################################################### - # Protected 'AbstractFactory' interface. - ########################################################################### - - def _can_create(self, target_class, *args, **kw): - """ Returns True if the factory can create objects of a class. """ - - return NotImplementedError - - def _create(self, target_class, *args, **kw): - """ Creates an object of the specified target class. """ - - raise NotImplementedError - - ########################################################################### - # Private interface. - ########################################################################### - - def _get_warning_message(self, target_class): - """Returns a warning message. - - The warning message is used when a factory fails to create something - that it said it could! - - """ - - message = "%s failed to create a %s" % ( - self.__class__.__name__, - target_class.__name__, - ) - - return message diff --git a/apptools/type_manager/abstract_type_system.py b/apptools/type_manager/abstract_type_system.py deleted file mode 100644 index 487b9baa7..000000000 --- a/apptools/type_manager/abstract_type_system.py +++ /dev/null @@ -1,33 +0,0 @@ -""" The abstract base class for type systems. """ - - -# Enthought library imports. -from traits.api import HasTraits - - -class AbstractTypeSystem(HasTraits): - """The abstract base class for type systems. - - A type system is responsible for:- - - 1) Determining whether an object is of a particular type. - 2) Determining the MRO of a type. - - See 'PythonTypeSystem' for an implementation with standard Python - semantics. - - """ - - ########################################################################### - # 'AbstractTypeSystem' interface. - ########################################################################### - - def is_a(self, obj, type): - """ Is an object an instance of the specified type? """ - - raise NotImplementedError - - def get_mro(self, type): - """ Returns the MRO of a type. """ - - raise NotImplementedError diff --git a/apptools/type_manager/adaptable.py b/apptools/type_manager/adaptable.py deleted file mode 100644 index 354423a7f..000000000 --- a/apptools/type_manager/adaptable.py +++ /dev/null @@ -1,34 +0,0 @@ -""" The base class for adaptable objects. """ - - -# Enthought library imports. -from traits.api import HasTraits, Instance - -# Local imports. -from .adapter_manager import AdapterManager - - -class Adaptable(HasTraits): - """ The base class for adaptable objects. """ - - #### 'Adaptable' interface ################################################ - - # The adapter manager in effect for the object. - adapter_manager = Instance(AdapterManager) - - ########################################################################### - # 'Adaptable' interface. - ########################################################################### - - def adapt(self, target_class, *args, **kw): - """ Returns True if the factory can produce an appropriate adapter. """ - - if self.adapter_manager is not None: - adapter = self.adapter_manager.adapt( - self, target_class, *args, **kw - ) - - else: - adapter = None - - return adapter diff --git a/apptools/type_manager/adapter.py b/apptools/type_manager/adapter.py deleted file mode 100644 index 089cc87f4..000000000 --- a/apptools/type_manager/adapter.py +++ /dev/null @@ -1,19 +0,0 @@ -""" A default adapter class. """ - - -# Enthought library imports. -from traits.api import Any, HasTraits - - -class Adapter(HasTraits): - """A default adapter class. - - This comes in handy when using the default 'AdapterFactory' as it expects - the adpter class to have an 'adaptee' trait. - - """ - - #### 'Adapter' interface ################################################## - - # The object that we are adapting. - adaptee = Any diff --git a/apptools/type_manager/adapter_factory.py b/apptools/type_manager/adapter_factory.py deleted file mode 100644 index c3134a920..000000000 --- a/apptools/type_manager/adapter_factory.py +++ /dev/null @@ -1,60 +0,0 @@ -""" An adapter factory. """ - - -# Enthought library imports. -from traits.api import Any - -# Local imports. -from .abstract_adapter_factory import AbstractAdapterFactory - - -class AdapterFactory(AbstractAdapterFactory): - """An adapter factory. - - This implementation provides the common case where the factory adapts - exactly one type of object to exactly one target type using exactly one - adapter. - - This class requires the adapter class to have an 'adaptee' trait. The - default 'Adapter' class provides exactly that. - - """ - - #### 'AdapterFactory' interface ########################################### - - # fixme: These trait definitions should be 'Class' but currently this only - # allows old-style classes! - # - # The type of object that the factory can adapt. - adaptee_class = Any - - # The adapter class (the class that adapts the adaptee to the target - # class). - adapter_class = Any - - # The target class (the class that the factory can adapt objects to). - target_class = Any - - ########################################################################### - # Protected 'AbstractAdapterFactory' interface. - ########################################################################### - - def _can_adapt(self, adaptee, target_class, *args, **kw): - """ Returns True if the factory can produce an appropriate adapter. """ - - can_adapt = ( - target_class is self.target_class - and self.type_system.is_a(adaptee, self.adaptee_class) - ) - - return can_adapt - - def _adapt(self, adaptee, target_class, *args, **kw): - """Returns an adapter that adapts an object to the target class. - - This requires the adapter class to have an 'adaptee' trait. The default - 'Adapter' class provides exactly that. - - """ - - return self.adapter_class(adaptee=adaptee, *args, **kw) diff --git a/apptools/type_manager/adapter_manager.py b/apptools/type_manager/adapter_manager.py deleted file mode 100644 index aafe55d92..000000000 --- a/apptools/type_manager/adapter_manager.py +++ /dev/null @@ -1,246 +0,0 @@ -""" A manager for adapter factories. """ - -# Standard library imports -import warnings - -# Enthought library imports. -from traits.api import Dict, HasTraits, Instance, Property - -# Local imports. -from .abstract_type_system import AbstractTypeSystem -from .python_type_system import PythonTypeSystem - - -class AdapterManager(HasTraits): - """ A manager for adapter factories. """ - - #### 'AdapterManager' interface ########################################### - - # All registered type-scope factories by the type of object that they - # adapt. - # - # The dictionary is keyed by the *name* of the class rather than the class - # itself to allow for adapter factory proxies to register themselves - # without having to load and create the factories themselves (i.e., to - # allow us to lazily load adapter factories contributed by plugins). This - # is a slight compromise as it is obviously geared towards use in Envisage, - # but it doesn't affect the API other than allowing a class OR a string to - # be passed to 'register_adapters'. - # - # { String adaptee_class_name : List(AdapterFactory) factories } - type_factories = Property(Dict) - - # All registered instance-scope factories by the object that they adapt. - # - # { id(obj) : List(AdapterFactory) factories } - instance_factories = Property(Dict) - - # The type system used by the manager (it determines 'is_a' relationships - # and type MROs etc). By default we use standard Python semantics. - type_system = Instance(AbstractTypeSystem, PythonTypeSystem()) - - #### Private interface #################################################### - - # All registered type-scope factories by the type of object that they - # adapt. - _type_factories = Dict - - # All registered instance-scope factories by the object that they adapt. - _instance_factories = Dict - - ########################################################################### - # 'AdapterManager' interface. - ########################################################################### - - #### Properties ########################################################### - - def _get_type_factories(self): - """ Returns all registered type-scope factories. """ - - return self._type_factories.copy() - - def _get_instance_factories(self): - """ Returns all registered instance-scope factories. """ - - return self._instance_factories.copy() - - #### Methods ############################################################## - - def adapt(self, adaptee, target_class, *args, **kw): - """Returns an adapter that adapts an object to the target class. - - 'adaptee' is the object that we want to adapt. - 'target_class' is the class that the adaptee should be adapted to. - - Returns None if no such adapter exists. - - """ - - # If the object is already an instance of the target class then we - # simply return it. - if self.type_system.is_a(adaptee, target_class): - adapter = adaptee - - # Otherwise, look at each class in the adaptee's MRO to see if there - # is an adapter factory registered that can adapt the object to the - # target class. - else: - # Look for instance-scope adapters first. - adapter = self._adapt_instance(adaptee, target_class, *args, **kw) - - # If no instance-scope adapter was found then try type-scope - # adapters. - if adapter is None: - for adaptee_class in self.type_system.get_mro(type(adaptee)): - adapter = self._adapt_type( - adaptee, adaptee_class, target_class, *args, **kw - ) - if adapter is not None: - break - - return adapter - - def register_instance_adapters(self, factory, obj): - """Registers an instance-scope adapter factory. - - A factory can be in exactly one manager (as it uses the manager's type - system). - - """ - - factories = self._instance_factories.setdefault(id(obj), []) - factories.append(factory) - - # A factory can be in exactly one manager. - factory.adapter_manager = self - - return - - def unregister_instance_adapters(self, factory, obj): - """Unregisters an instance scope adapter factory. - - A factory can be in exactly one manager (as it uses the manager's type - system). - - """ - - factories = self._instance_factories.setdefault(id(obj), []) - if factory in factories: - factories.remove(factory) - - # A factory can be in exactly one manager. - factory.adapter_manager = None - - return - - def register_type_adapters(self, factory, adaptee_class): - """Registers a type-scope adapter factory. - - 'adaptee_class' can be either a class object or the name of a class. - - A factory can be in exactly one manager (as it uses the manager's type - system). - - """ - - if isinstance(adaptee_class, str): - adaptee_class_name = adaptee_class - - else: - adaptee_class_name = self._get_class_name(adaptee_class) - - factories = self._type_factories.setdefault(adaptee_class_name, []) - factories.append(factory) - - # A factory can be in exactly one manager. - factory.adapter_manager = self - - return - - def unregister_type_adapters(self, factory): - """ Unregisters a type-scope adapter factory. """ - - for adaptee_class_name, factories in self._type_factories.items(): - if factory in factories: - factories.remove(factory) - - # The factory is no longer deemed to be part of this manager. - factory.adapter_manager = None - - return - - #### DEPRECATED ########################################################### - - def register_adapters(self, factory, adaptee_class): - """Registers an adapter factory. - - 'adaptee_class' can be either a class object or the name of a class. - - A factory can be in exactly one manager (as it uses the manager's type - system). - - """ - - warnings.warn( - 'Use "register_type_adapters" instead.', DeprecationWarning - ) - - self.register_type_adapters(factory, adaptee_class) - - return - - def unregister_adapters(self, factory): - """ Unregisters an adapter factory. """ - - warnings.warn( - 'use "unregister_type_adapters" instead.', DeprecationWarning - ) - - self.unregister_type_adapters(factory) - - return - - ########################################################################### - # Private interface. - ########################################################################### - - def _adapt_instance(self, adaptee, target_class, *args, **kw): - """Returns an adapter that adaptes an object to the target class. - - Returns None if no such adapter exists. - - """ - - for factory in self._instance_factories.get(id(adaptee), []): - adapter = factory.adapt(adaptee, target_class, *args, **kw) - if adapter is not None: - break - - else: - adapter = None - - return adapter - - def _adapt_type(self, adaptee, adaptee_class, target_class, *args, **kw): - """Returns an adapter that adapts an object to the target class. - - Returns None if no such adapter exists. - - """ - - adaptee_class_name = self._get_class_name(adaptee_class) - - for factory in self._type_factories.get(adaptee_class_name, []): - adapter = factory.adapt(adaptee, target_class, *args, **kw) - if adapter is not None: - break - - else: - adapter = None - - return adapter - - def _get_class_name(self, klass): - """ Returns the full class name for a class. """ - - return "%s.%s" % (klass.__module__, klass.__name__) diff --git a/apptools/type_manager/api.py b/apptools/type_manager/api.py deleted file mode 100644 index 6779c3937..000000000 --- a/apptools/type_manager/api.py +++ /dev/null @@ -1,11 +0,0 @@ -from .abstract_adapter_factory import AbstractAdapterFactory -from .abstract_factory import AbstractFactory -from .abstract_type_system import AbstractTypeSystem -from .adaptable import Adaptable -from .adapter import Adapter -from .adapter_factory import AdapterFactory -from .adapter_manager import AdapterManager -from .factory import Factory -from .hook import add_pre, add_post, remove_pre, remove_post -from .python_type_system import PythonObject, PythonTypeSystem -from .type_manager import TypeManager diff --git a/apptools/type_manager/factory.py b/apptools/type_manager/factory.py deleted file mode 100644 index 8aca760a6..000000000 --- a/apptools/type_manager/factory.py +++ /dev/null @@ -1,39 +0,0 @@ -""" A generic object factory. """ - - -# Enthought library imports. -from traits.api import Any - -# Local imports. -from .abstract_factory import AbstractFactory - - -class Factory(AbstractFactory): - """A generic object factory. - - This implementation of the abstract factory interface provides for the - common scenario where the factory produces objects of exactly one type. - - """ - - #### 'Factory' interface ################################################## - - # The type of object that we create. - # - # fixme: This trait definition should be 'Class' but currently this only - # allows old-style classes! - target_class = Any - - ########################################################################### - # 'AbstractFactory' interface. - ########################################################################### - - def can_create(self, target_class, *args, **kw): - """ Returns True if the factory can create objects of a class. """ - - return target_class is self.target_class - - def create(self, *args, **kw): - """ Creates an object! """ - - return self.target_class(*args, **kw) diff --git a/apptools/type_manager/hook.py b/apptools/type_manager/hook.py deleted file mode 100644 index 4d87e51b8..000000000 --- a/apptools/type_manager/hook.py +++ /dev/null @@ -1,139 +0,0 @@ -# ------------------------------------------------------------------------------ -# Copyright (c) 2005, 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: Enthought, Inc. -# Description: -# ------------------------------------------------------------------------------ -""" Implementation of hooked methods. """ - - -def add_pre(klass, method_name, callable): - """ Adds a pre-hook to method 'method_name' on class 'klass'. """ - - _add_hook(klass, method_name, callable, pre=True) - - return - - -def add_post(klass, method_name, callable): - """ Adds a post-hook to method 'method_name' on class 'klass'. """ - - _add_hook(klass, method_name, callable, pre=False) - - return - - -def remove_pre(klass, method_name, callable): - """ Removes a pre-hook from method 'method_name' on class 'klass'. """ - - _remove_hook(klass, method_name, callable, pre=True) - - return - - -def remove_post(klass, method_name, callable): - """ Removes a post-hook from method 'method_name' on class 'klass'. """ - - _remove_hook(klass, method_name, callable, pre=False) - - return - - -############################################################################### -# Private functions. -############################################################################### - - -def _add_hook(klass, method_name, callable, pre): - """ Adds a pre/post hook to method 'method_name' on class 'klass'. """ - - # Get the method on the klass. - method = getattr(klass, method_name) - - # Have we already hooked it? - if hasattr(method, "__pre__"): - hooked_method = method - - # Obviously not! - else: - - def hooked_method(self, *args, **kw): - for pre in hooked_method.__pre__: - pre(self, *args, **kw) - - result = method(self, *args, **kw) - - for post in hooked_method.__post__: - result = post(self, result, *args, **kw) - - return result - - # Python < 2.4 does not allow this. - try: - hooked_method.__name__ = method_name - - except: - pass - - hooked_method.__pre__ = [] - hooked_method.__post__ = [] - - # Is the original method actually defined on the class, or is it - # inherited? - hooked_method.__inherited__ = method_name not in klass.__dict__ - - # Save the original method... - # - # fixme: Twisted uses 'method.im_func' instead of 'method' here, but - # both seem to work just as well! - setattr(klass, "__hooked__" + method_name, method) - - # ... and put in the hooked one! - setattr(klass, method_name, hooked_method) - - if pre: - hooked_method.__pre__.append(callable) - - else: - hooked_method.__post__.append(callable) - - return - - -def _remove_hook(klass, method_name, callable, pre): - """ Removes a pre/post hook from method 'method_name' on class 'klass'. """ - - # Get the method on the klass. - method = klass.__dict__[method_name] - - # Is it actually hooked? - if hasattr(method, "__pre__"): - # Remove the hook. - if pre: - method.__pre__.remove(callable) - - else: - method.__post__.remove(callable) - - # If there are no more hooks left then cleanup. - if len(method.__pre__) == 0 and len(method.__post__) == 0: - # If the method is inherited then just delete the hooked version. - if method.__inherited__: - delattr(klass, method_name) - - # Otherwise, reinstate the original method. - else: - original = getattr(klass, "__hooked__" + method_name) - setattr(klass, method_name, original) - - # Remove the saved original method. - delattr(klass, "__hooked__" + method_name) - - return diff --git a/apptools/type_manager/python_type_system.py b/apptools/type_manager/python_type_system.py deleted file mode 100644 index 1458accd1..000000000 --- a/apptools/type_manager/python_type_system.py +++ /dev/null @@ -1,38 +0,0 @@ -""" A type system with standard(ish) Python semantics. """ - - -# Standard library imports. -import inspect - -# Local imports. -from .abstract_type_system import AbstractTypeSystem - - -class PythonObject: - """The root type in the type system. - - fixme: Python is currently a bit broken as it has dual type hierarchies, - one for old-style and one for new-style classes. This class is used to - create a fake root to unify them. - - """ - - __class__ = type - - -class PythonTypeSystem(AbstractTypeSystem): - """ A type system with standard(ish) Python semantics. """ - - ########################################################################### - # 'AbstractTypeSystem' interface. - ########################################################################### - - def is_a(self, obj, type): - """ Is an object and instance of the specified type? """ - - return isinstance(obj, type) or type is PythonObject - - def get_mro(self, type): - """ Returns the MRO of a type. """ - - return list(inspect.getmro(type)) + [PythonObject] diff --git a/apptools/type_manager/tests/__init__.py b/apptools/type_manager/tests/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/apptools/type_manager/tests/test_type_manager.py b/apptools/type_manager/tests/test_type_manager.py deleted file mode 100644 index af87b3e23..000000000 --- a/apptools/type_manager/tests/test_type_manager.py +++ /dev/null @@ -1,426 +0,0 @@ -""" Tests the type manager. """ - - -# Standard library imports. -import unittest - -# Enthought library imports. -from traits.api import HasTraits, Instance, Str -from apptools.type_manager import AdapterFactory, Factory, TypeManager - - -# Test classes. -class Foo(HasTraits): - name = Str - - def foogle(self): - return "Foo.foogle.%s" % self.name - - -class SubOfFoo(Foo): - def foogle(self): - return "Sub.foogle.%s" % self.name - - -class EmptySubOfFoo(Foo): - pass - - -class Bar(HasTraits): - name = Str - - def blargle(self): - return "Bar.blargle.%s" % self.name - - -# Test adapters and factories. -class FooToBarAdapter(HasTraits): - adaptee = Instance(Foo) - - def blargle(self): - return self.adaptee.foogle() - - -class FooToBarAdapterFactory(AdapterFactory): - - #### 'AdapterFactory' interface ########################################### - - # The type of object that the factory can adapt. - adaptee_class = Foo - - # The adapter class (the class that adapts the adaptee to the target - # class). - adapter_class = FooToBarAdapter - - # The target class (the class that the factory can adapt objects to). - target_class = Bar - - -class SubOfFooToBarAdapter(HasTraits): - adaptee = Instance(SubOfFoo) - - def blargle(self): - return self.adaptee.foogle() - - -class SubOfFooToBarAdapterFactory(AdapterFactory): - #### 'AdapterFactory' interface ########################################### - - # The type of object that the factory can adapt. - adaptee_class = SubOfFoo - - # The adapter class (the class that adapts the adaptee to the target - # class). - adapter_class = SubOfFooToBarAdapter - - # The target class (the class that the factory can adapt objects to). - target_class = Bar - - -class BarFactory(Factory): - def can_create(self, target_class, *args, **kw): - return target_class is Bar - - def create(self, target_class, *args, **kw): - return Bar(*args, **kw) - - -class TypeManagerTestCase(unittest.TestCase): - """ Tests the type manager. """ - - ########################################################################### - # 'TestCase' interface. - ########################################################################### - - def setUp(self): - """ Prepares the test fixture before each test method is called. """ - - # An empty type manager. - self.type_manager = TypeManager() - - return - - def tearDown(self): - """ Called immediately after each test method has been called. """ - - return - - ########################################################################### - # Tests. - ########################################################################### - - def test_no_adapter_required(self): - """ no adapter required """ - - # Create a Bar. - b = Bar() - - # Try to adapt it to a Bar. - bar = self.type_manager.object_as(b, Bar) - - # The type manager should simply return the same object. - self.assertIs(bar, b) - - return - - def test_no_adapter(self): - """ no adapter available """ - - # Create a Foo. - foo = Foo(name="fred") - - # Try to adapt it to a bar. - bar = self.type_manager.object_as(foo, Bar) - - # There should be no way to adapt a Foo to a Bar. - self.assertIsNone(bar) - - return - - def test_instance_adapter(self): - """ instance adapter """ - - # Create a Foo. - foo = Foo(name="fred") - - # Register an adapter Foo->Bar on the INSTANCE (this one should take - # precedence). - self.type_manager.register_instance_adapters( - FooToBarAdapterFactory(), foo - ) - - # Register an adapter Foo->Bar on the TYPE (this will fail if it gets - # picked up since it won't actually adapt 'Foo' objects!). - self.type_manager.register_instance_adapters( - SubOfFooToBarAdapterFactory(), Foo - ) - - # Adapt it to a Bar. - bar = self.type_manager.object_as(foo, Bar) - self.assertIsNotNone(bar) - self.assertEqual(bar.blargle(), "Foo.foogle.fred") - - return - - def test_unregister_instance_adapter(self): - """ unregister instance adapter """ - - # Create a Foo. - foo = Foo(name="fred") - - # The factory. - factory = FooToBarAdapterFactory() - - # Register an adapter Foo->Bar on the INSTANCE (this one should take - # precedence). - self.type_manager.register_instance_adapters(factory, foo) - - # Adapt it to a Bar. - bar = self.type_manager.object_as(foo, Bar) - self.assertIsNotNone(bar) - self.assertEqual(bar.blargle(), "Foo.foogle.fred") - - # Remove the adapter. - self.type_manager.unregister_instance_adapters(factory, foo) - - # Now we shouldn't be able to adapt the object. - # - # Try to adapt it to a bar. - bar = self.type_manager.object_as(foo, Bar) - - # There should be no way to adapt a Foo to a Bar. - self.assertIsNone(bar) - - return - - def test_adapter_on_class(self): - """ an adapter registered on an object's actual class. """ - - # Register an adapter Foo->Bar. - self.type_manager.register_type_adapters(FooToBarAdapterFactory(), Foo) - - # Create a Foo. - foo = Foo(name="fred") - - # Adapt it to a Bar. - bar = self.type_manager.object_as(foo, Bar) - self.assertIsNotNone(bar) - self.assertEqual(bar.blargle(), "Foo.foogle.fred") - - return - - def test_adapter_on_base_class(self): - """ an adapter registered on one of an object's base classes. """ - - # Register an adapter Foo->Bar. - self.type_manager.register_type_adapters(FooToBarAdapterFactory(), Foo) - - # Create an instance of a class derived from Foo. - sub = SubOfFoo(name="fred") - - # Adapt it to a Bar. - bar = self.type_manager.object_as(sub, Bar) - self.assertIsNotNone(bar) - self.assertEqual(bar.blargle(), "Sub.foogle.fred") - - return - - def test_ignore_adapter_on_class(self): - """ ignore an adapter on an object's actual class. """ - - # Register an adapter SubOfFoo->Bar on the Foo class. - self.type_manager.register_type_adapters( - SubOfFooToBarAdapterFactory(), Foo - ) - - # Create a Foo. - foo = Foo(name="fred") - - # Adapt it to a Bar. - bar = self.type_manager.object_as(foo, Bar) - - # There should be no way to adapt a Foo to a Bar. - self.assertIsNone(bar) - - return - - def test_ignore_adapter_on_derived_class(self): - """ ignore an adapter registered on a derived class. """ - - # Register an adapter Foo->Bar on the SubOfFoo class. - self.type_manager.register_type_adapters( - FooToBarAdapterFactory(), SubOfFoo - ) - - # Create a Foo. - foo = Foo(name="fred") - - # Adapt it to a Bar. - bar = self.type_manager.object_as(foo, Bar) - - # There should be no way to adapt a Foo to a Bar. - self.assertIsNone(bar) - - return - - def test_unregister_adapter(self): - """ unregister an adapter. """ - - factory = FooToBarAdapterFactory() - - # Register an adapter Foo->Bar. - self.type_manager.register_type_adapters(factory, Foo) - - # Create a Foo. - foo = Foo(name="fred") - - # Adapt it to a Bar. - bar = self.type_manager.object_as(foo, Bar) - self.assertIsNotNone(bar) - self.assertEqual(bar.blargle(), "Foo.foogle.fred") - - # Unregister the adapter. - self.type_manager.unregister_type_adapters(factory) - - # Try to adapt it to a Bar. - bar = self.type_manager.object_as(foo, Bar) - - # There should be no way to adapt a Foo to a Bar. - self.assertIsNone(bar) - - return - - def test_factory(self): - """ simple factory """ - - # Create a Bar factory. - factory = BarFactory() - - # Try to create a Bar using the factory. - bar = self.type_manager.object_as(factory, Bar, name="joe") - self.assertIsNotNone(bar) - self.assertEqual(bar.blargle(), "Bar.blargle.joe") - - return - - def test_pre_hook(self): - """ pre hook """ - - l = [] - - def hook(*args, **kw): - l.append("Hello") - - # Create a Foo. - foo = Foo(name="fred") - - # Hook a method. - self.type_manager.add_pre(Foo, "foogle", hook) - - # Call the method that we have hooked. - foo.foogle() - - # Make sure that the hook was called. - self.assertEqual(len(l), 1) - - # Remove the hook. - self.type_manager.remove_pre(Foo, "foogle", hook) - - # Call the method that we have hooked. - foo.foogle() - - # Make sure that the hook was NOT called. - self.assertEqual(len(l), 1) - - return - - def test_post_hook(self): - """ post hook """ - - def hook(result, *args, **kw): - return "Hello" - - # Create a Foo. - foo = Foo(name="fred") - - # Hook a method. - self.type_manager.add_post(Foo, "foogle", hook) - - # Call the method that we have hooked. - self.assertEqual(foo.foogle(), "Hello") - - # Remove the hook. - self.type_manager.remove_post(Foo, "foogle", hook) - - # Call the method that we have hooked. - foo.foogle() - - # Make sure that the hook was NOT called. - self.assertEqual(foo.foogle(), "Foo.foogle.fred") - - return - - def test_pre_hook_on_inherited_method(self): - """ test pre hook on an inherited method """ - - l = [] - - def hook(*args, **kw): - l.append("Hello") - - # Create an instance of a subclass of Foo that does NOT override - # 'foogle'. - esof = EmptySubOfFoo(name="fred") - - # Prove that it does not override 'foogle'! - method = EmptySubOfFoo.__dict__.get("foogle") - self.assertIsNone(method) - - # Hook a method. - self.type_manager.add_pre(EmptySubOfFoo, "foogle", hook) - - # Make sure that the method was added to the class dictionary. - method = EmptySubOfFoo.__dict__.get("foogle") - self.assertIsNotNone(method) - - # Call the method that we have hooked. - esof.foogle() - - # Make sure that the hook was called. - self.assertEqual(len(l), 1) - - # Remove the hook. - self.type_manager.remove_pre(EmptySubOfFoo, "foogle", hook) - - # Call the method that we have hooked. - esof.foogle() - - # Make sure that the hook was NOT called. - self.assertEqual(len(l), 1) - - # Make sure that we didn't put the original method back onto - # 'EmptySubOfFoo'(since it didn't override it in the first place). - method = EmptySubOfFoo.__dict__.get("foogle") - self.assertIsNone(method) - - return - - def test_type_manager_hierarchy(self): - """ type manager hierarchy """ - - # Register an adapter Foo->Bar. - self.type_manager.register_type_adapters(FooToBarAdapterFactory(), Foo) - - # Create an empy type manager with the main type manager as its - # parent. - type_manager = TypeManager(parent=self.type_manager) - - # Create a Foo. - foo = Foo(name="fred") - - # Adapt it to a Bar. - bar = type_manager.object_as(foo, Bar) - self.assertIsNotNone(bar) - self.assertEqual(bar.blargle(), "Foo.foogle.fred") - - return diff --git a/apptools/type_manager/type_manager.py b/apptools/type_manager/type_manager.py deleted file mode 100644 index 7a66a62a3..000000000 --- a/apptools/type_manager/type_manager.py +++ /dev/null @@ -1,218 +0,0 @@ -""" A type manager. """ - - -# Enthought library imports. -from traits.api import HasTraits, Instance, Property, Str - -# Local imports. -from .abstract_type_system import AbstractTypeSystem -from .adapter_manager import AdapterManager -from .factory import Factory -from .hook import add_pre, add_post, remove_pre, remove_post -from .python_type_system import PythonTypeSystem - - -class TypeManager(HasTraits): - """A type manager. - - The type manager allows for objects to be created/adapted to a particular - type. - - """ - - #### 'TypeManager' interface ############################################## - - # The adapter manager looks after errr, all adapters. - adapter_manager = Property(Instance(AdapterManager)) - - # The type manager's globally unique identifier (only required if you have - # more than one type manager of course!). - id = Str - - # The parent type manager. - # - # By default this is None, but you can use it to set up a hierarchy of - # type managers. If a type manager fails to adapt or create an object of - # some target class then it will give its parent a chance to do so. - parent = Instance("TypeManager") - - # The type system used by the manager (it determines 'is_a' relationships - # and type MROs etc). - # - # By default we use standard Python semantics. - type_system = Instance(AbstractTypeSystem, PythonTypeSystem()) - - #### Private interface #################################################### - - # The adapter manager looks after errr, all adapters. - _adapter_manager = Instance(AdapterManager) - - ########################################################################### - # 'TypeManager' interface. - ########################################################################### - - #### Properties ########################################################### - - def _get_adapter_manager(self): - """ Returns the adapter manager. """ - - return self._adapter_manager - - #### Methods ############################################################## - - def object_as(self, obj, target_class, *args, **kw): - """Adapts or creates an object of the target class. - - Returns None if no appropriate adapter or factory is available. - - """ - - # If the object is already an instance of the target class then we - # simply return it. - if self.type_system.is_a(obj, target_class): - result = obj - - # If the object is a factory that creates instances of the target class - # then ask it to produce one. - elif self._is_factory_for(obj, target_class, *args, **kw): - result = obj.create(target_class, *args, **kw) - - # Otherwise, see if the object can be adapted to the target class. - else: - result = self._adapter_manager.adapt( - obj, target_class, *args, **kw - ) - - # If this type manager couldn't do the job, then give its parent a go! - if result is None and self.parent is not None: - result = self.parent.object_as(obj, target_class, *args, **kw) - - return result - - # Adapters. - def register_adapters(self, factory, adaptee_class): - """Registers an adapter factory. - - 'adaptee_class' can be either a class or the name of a class. - - """ - - self._adapter_manager.register_adapters(factory, adaptee_class) - - return - - def unregister_adapters(self, factory): - """ Unregisters an adapter factory. """ - - self._adapter_manager.unregister_adapters(factory) - - return - - def register_instance_adapters(self, factory, obj): - """Registers an adapter factory for an individual instance. - - A factory can be in exactly one manager (as it uses the manager's type - system). - - """ - - self._adapter_manager.register_instance_adapters(factory, obj) - - return - - def unregister_instance_adapters(self, factory, obj): - """Unregisters an adapter factory for an individual instance. - - A factory can be in exactly one manager (as it uses the manager's type - system). - - """ - - self._adapter_manager.unregister_instance_adapters(factory, obj) - - return - - def register_type_adapters(self, factory, adaptee_class): - """Registers an adapter factory. - - 'adaptee_class' can be either a class or the name of a class. - - """ - - self._adapter_manager.register_type_adapters(factory, adaptee_class) - - return - - def unregister_type_adapters(self, factory): - """ Unregisters an adapter factory. """ - - self._adapter_manager.unregister_type_adapters(factory) - - return - - # Categories. - # - # Currently, there is no technical reason why we have this convenience - # method to add categories. However, it may well turn out to be useful to - # track all categories added via the type manager. - def add_category(self, klass, category_class): - """ Adds a category to a class. """ - - klass.add_trait_category(category_class) - - return - - # Hooks. - # - # Currently, there is no technical reason why we have these convenience - # methods to add and remove hooks. However, it may well turn out to be - # useful to track all hooks added via the type manager. - def add_pre(self, klass, method_name, callable): - """ Adds a pre-hook to method 'method_name' on class 'klass. """ - - add_pre(klass, method_name, callable) - - return - - def add_post(self, klass, method_name, callable): - """ Adds a post-hook to method 'method_name' on class 'klass. """ - - add_post(klass, method_name, callable) - - return - - def remove_pre(self, klass, method_name, callable): - """ Removes a pre-hook to method 'method_name' on class 'klass. """ - - remove_pre(klass, method_name, callable) - - return - - def remove_post(self, klass, method_name, callable): - """ Removes a post-hook to method 'method_name' on class 'klass. """ - - remove_post(klass, method_name, callable) - - return - - ########################################################################### - # Private interface. - ########################################################################### - - #### Initializers ######################################################### - - def __adapter_manager_default(self): - """ Initializes the '_adapter_manager' trait. """ - - return AdapterManager(type_system=self.type_system) - - #### Methods ############################################################## - - def _is_factory_for(self, obj, target_class, *args, **kw): - """ Returns True iff the object is a factory for the target class. """ - - is_factory_for = self.type_system.is_a( - obj, Factory - ) and obj.can_create(target_class, *args, **kw) - - return is_factory_for diff --git a/apptools/type_manager/util.py b/apptools/type_manager/util.py deleted file mode 100644 index de49fa81b..000000000 --- a/apptools/type_manager/util.py +++ /dev/null @@ -1,57 +0,0 @@ -""" Useful functions to do with types! - -fixme: I don't really like collections of functions, but I'm not sure where -these should go? Class methods on 'TypeManager'? - -""" - - -# Standard library imports. -from inspect import getclasstree - - -def sort_by_class_tree(objs): - """Sorts a list of objects by their class tree. - - Each item in the list should inherit from a common base class. - - The list is returned ordered from the most specific to the least specific. - - """ - - # Since all objects must inherit from a common base class the list - # returned by 'getclasstree' will be of length two:- - # - # The first element is a tuple of the form:- - # - # (CommonBaseClass, (HasTraits,)) - # - # The second element is a possibly nested list containing all of the - # classes derived from 'CommonBaseClass'. - hierarchy = getclasstree([type(obj) for obj in objs]) - - # Do an in-order traversal of the tree and return just the classes. - # - # This returns them ordered from least specific to most specific. - classes = get_classes(hierarchy) - - # Note the reverse comparison (i.e., compare y with x). This is - # because we want to return the classes ordered from the MOST - # specfic to the least specific. - objs.sort(key=lambda x: classes.index(type(x)), reverse=True) - - return - - -def get_classes(hierarchy): - """ Walks a class hierarchy and returns all of the classes. """ - - classes = [] - for item in hierarchy: - if type(item) is tuple: - classes.append(item[0]) - - else: - classes.extend(get_classes(item)) - - return classes diff --git a/docs/releases/upcoming/219.removal.rst b/docs/releases/upcoming/219.removal.rst new file mode 100644 index 000000000..56c4e0a04 --- /dev/null +++ b/docs/releases/upcoming/219.removal.rst @@ -0,0 +1 @@ +Remove use of ``apptools.type_manage`r`` from ``apptools.naming``. Then, remove ``apptools.type_manager`` entirely. Finally, remove ``apptools.naming.adapter``. (#219) \ No newline at end of file diff --git a/examples/naming/data/foo.txt b/examples/naming/data/foo.txt deleted file mode 100644 index 980a0d5f1..000000000 --- a/examples/naming/data/foo.txt +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/examples/naming/explorer.py b/examples/naming/explorer.py index f5babf895..14b6b3251 100644 --- a/examples/naming/explorer.py +++ b/examples/naming/explorer.py @@ -13,86 +13,31 @@ #------------------------------------------------------------------------------ """ A naming system explorer. """ - -# Standard library imports. -import os, sys - -# FIXME: The below won't work in an egg-based distribution. The real question -# is why it was here in the first place. -## Put the Enthought library on the Python path. -#sys.path.append(os.path.abspath(r'..\..\..')) - # Enthought library imports. -from apptools.naming.api import Binding, Context, ContextAdapterFactory -from apptools.naming.api import PyFSContext -from apptools.naming.adapter import * +from apptools.naming.api import Binding +from apptools.naming.api import PyContext from apptools.naming.ui.explorer import Explorer from pyface.api import GUI -from traits.api import TraitDict, TraitList -from apptools.type_manager import TypeManager -from traits.util.resource import find_resource - - -# Application entry point. -if __name__ == '__main__': - - # Create the GUI (this does NOT start the GUI event loop). - gui = GUI() - - # Create a type manager to manage context adapters. - type_manager = TypeManager() - - # Add some interesting context adapters. - # - # Trait dictionaries. - type_manager.register_type_adapters( - ContextAdapterFactory( - adaptee_class=TraitDict, adapter_class=TraitDictContextAdapter, - ), - - TraitDict - ) - - # Trait lists. - type_manager.register_type_adapters( - ContextAdapterFactory( - adaptee_class=TraitList, adapter_class=TraitListContextAdapter, - ), +from traits.api import HasTraits, Instance, List, Str - TraitList - ) - # Python dictionaries. - type_manager.register_type_adapters( - ContextAdapterFactory( - adaptee_class=dict, adapter_class=DictContextAdapter, - ), +class Foo(HasTraits): + name = Str() + names = List(Str()) - dict - ) - # Python lists. - type_manager.register_type_adapters( - ContextAdapterFactory( - adaptee_class=list, adapter_class=ListContextAdapter, - ), +class Bar(HasTraits): + foo = Instance(Foo) - list - ) - # Python objects. - type_manager.register_type_adapters( - InstanceContextAdapterFactory(), object - ) +# Application entry point. +if __name__ == '__main__': - # Get the path to the data directory - data_path = os.path.join('examples','naming','data') - full_path = find_resource('AppTools', data_path, alt_path='data', - return_path=True) + # Create the GUI (this does NOT start the GUI event loop). + gui = GUI() # Create the root context. - root = PyFSContext(path=full_path) - root.environment[Context.TYPE_MANAGER] = type_manager + root = PyContext(namespace=Bar(foo=Foo(name="Hello", names=["1", "2"]))) # Create and open the main window. window = Explorer(root=Binding(name='Root', obj=root)) diff --git a/setup.cfg b/setup.cfg index fa9b1715c..857e39b5f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -8,7 +8,6 @@ exclude = apptools/scripting/* apptools/selection/* apptools/sweet_pickle/* - apptools/type_manager/* apptools/type_registry/* apptools/undo/* docs/source/conf.py