class HelpDoc(PreferencesHelper): """ The implementation for help docs. A help doc is defined by a UI label, a filename, and a viewer program. """ implements(IHelpDoc) #### IHelpDoc interface / Preferences ###################################### # NOTE: This class inherits preferences_path from PreferencesHelper. # The UI label for the help doc, which appears in menus or dialogs. label = Str # The path to the document, which can be full, or relative to the Python # installation directory (sys.prefix). filename = File # Is this a url? url = Bool(False) # The program to use to view the document. 'browser' means the platform # default web browser. Otherwise, it is a command to run, which may be # in the program search path of the current environment, or an absolute # path to a program. viewer = Either('browser', Str)
class AboutDialog(MAboutDialog, Dialog): """ The toolkit specific implementation of an AboutDialog. See the IAboutDialog interface for the API documentation. """ implements(IAboutDialog) #### 'IAboutDialog' interface ############################################# additions = List(Unicode) image = Instance(ImageResource, ImageResource('about')) ########################################################################### # Protected 'IDialog' interface. ########################################################################### def _create_contents(self, parent): label = QtGui.QLabel() if parent.parent() is not None: title = parent.parent().windowTitle() else: title = "" # Set the title. self.title = "About %s" % title # Load the image to be displayed in the about box. image = self.image.create_image() #path = self.image.absolute_path path = './radpy/images/about.png' # The additional strings. additions = '<br />'.join(self.additions) # Get the version numbers. py_version = sys.version[0:sys.version.find("(")] pyqt_version = QtCore.PYQT_VERSION_STR qt_version = QtCore.QT_VERSION_STR # Set the page contents. label.setText(_DIALOG_TEXT % (path, additions, py_version, pyqt_version, qt_version)) # Create the button. buttons = QtGui.QDialogButtonBox() if self.ok_label: buttons.addButton(self.ok_label, QtGui.QDialogButtonBox.AcceptRole) else: buttons.addButton(QtGui.QDialogButtonBox.Ok) buttons.connect(buttons, QtCore.SIGNAL('accepted()'), parent, QtCore.SLOT('accept()')) lay = QtGui.QVBoxLayout() lay.addWidget(label) lay.addWidget(buttons) parent.setLayout(lay)
class MyClass(object): implements(IMyMarkerInterface) def __init__(self): self.val = 2 def blah(self): pass
class Person(HasTraits): implements(IName) first_name = Str( 'John' ) last_name = Str( 'Doe' ) # Implementation of the 'IName' interface: def get_name ( self ): """ Returns the name of an object. """ return ('%s %s' % ( self.first_name, self.last_name ))
class MutableTemplate(Template): """ A concrete base class that implements the IMutableTemplate interface. """ implements(IMutableTemplate) #-- IMutableTemplate Interface Implementation ------------------------------ # An event fired when the template mutates (i.e. changes in some way that # may affect the number of data sources it exposes, and so on): template_mutated = Event
class Clipboard(BaseClipboard): """ A dummy clipboard implementationf for the null backend. """ implements(IClipboard) #--------------------------------------------------------------------------- # 'data' property methods: #--------------------------------------------------------------------------- def _get_has_data(self): return False #--------------------------------------------------------------------------- # 'object_data' property methods: #--------------------------------------------------------------------------- def _get_object_data(self): pass def _set_object_data(self, data): pass def _get_has_object_data(self): return False def _get_object_type(self): return '' #--------------------------------------------------------------------------- # 'text_data' property methods: #--------------------------------------------------------------------------- def _get_text_data(self): return False def _set_text_data(self, data): pass def _get_has_text_data(self): pass #--------------------------------------------------------------------------- # 'file_data' property methods: #--------------------------------------------------------------------------- def _get_file_data(self): pass def _set_file_data(self, data): pass def _get_has_file_data(self): return False
class PersonINameAdapter( Adapter ): # Declare what interfaces this adapter implements for its # client: implements( IName ) # Declare the type of client it supports: adaptee = Instance( Person ) # Implement the 'IName' interface on behalf of its client: def get_name ( self ): return ('%s %s' % ( self.adaptee.first_name, self.adaptee.last_name ))
class BindEvent(HasTraits): """The default implementation of the bind event interface.""" implements(IBindEvent) #### 'IBindEvent' interface ############################################### # This is the name being bound or unbound. name = Str # This is the object being bound to the name. It is None if the name is # being unbound. obj = Any
class User(HasTraits): """The user implementation. We don't store any extra information other than that defined by IUser.""" implements(IUser) #### 'IUser' interface #################################################### name = Unicode authenticated = Bool(False) description = Unicode blob = Dict
class PolicyStorage(HasTraits): """This implements a policy database accessed via XML RPC.""" implements(IPolicyStorage) ########################################################################### # 'IPolicyStorage' interface. ########################################################################### def add_role(self, name, description, perm_ids): """Add a new role.""" try: ProxyServer.add_role(name, description, perm_ids, ProxyServer.key) except Exception, e: raise PolicyStorageError(ProxyServer.error(e))
class ImageResource(MImageResource, HasTraits): """ The 'null' toolkit specific implementation of an ImageResource. See the IImageResource interface for the API documentation. """ implements(IImageResource) #### Private interface #################################################### # The resource manager reference for the image. _ref = Any #### 'ImageResource' interface ############################################ absolute_path = Property(Unicode) name = Unicode search_path = List ########################################################################### # 'ImageResource' interface. ########################################################################### def create_bitmap(self, size=None): return self.create_image(size) def create_icon(self, size=None): return self.create_image(size) ########################################################################### # Private interface. ########################################################################### def _get_absolute_path(self): # FIXME: This doesn't quite work with the new notion of image size. We # should find out who is actually using this trait, and for what! # (AboutDialog uses it to include the path name in some HTML.) ref = self._get_ref() if ref is not None: absolute_path = os.path.abspath(self._ref.filename) else: absolute_path = self._get_image_not_found().absolute_path return absolute_path
class PerspectiveItem(HasTraits): """ An item in a Perspective contents list. """ implements(IPerspectiveItem) # The Id of the view to display in the perspective. id = Str # The position of the view relative to the item specified in the # 'relative_to' trait. # # 'top' puts the view above the 'relative_to' item. # 'bottom' puts the view below the 'relative_to' item. # 'left' puts the view to the left of the 'relative_to' item. # 'right' puts the view to the right of the 'relative_to' item. # 'with' puts the view in the same region as the 'relative_to' item. # # If the position is specified as 'with' you must specify a 'relative_to' # item other than the editor area (i.e., you cannot position a view 'with' # the editor area). position = Enum('left', 'top', 'bottom', 'right', 'with') # The Id of the view to position relative to. If this is not specified # (or if no view exists with this Id) then the view will be placed relative # to the editor area. relative_to = Str # The width of the item (as a fraction of the window width). # # e.g. 0.5 == half the window width. # # Note that this is treated as a suggestion, and it may not be possible # for the workbench to allocate the space requested. width = Float(-1) # The height of the item (as a fraction of the window height). # # e.g. 0.5 == half the window height. # # Note that this is treated as a suggestion, and it may not be possible # for the workbench to allocate the space requested. height = Float(-1) # The style of the dock control created. style_hint = Enum('tab', 'vertical', 'horizontal', 'fixed')
class MWorkbenchPart(HasTraits): """ Mixin containing common code for toolkit-specific implementations. """ implements(IWorkbenchPart) #### 'IWorkbenchPart' interface ########################################### # The toolkit-specific control that represents the part. # # The framework sets this to the value returned by 'create_control'. control = Any # Does the part currently have the focus? has_focus = Bool(False) # The part's globally unique identifier. id = Str # The part's name (displayed to the user). name = Unicode # The current selection within the part. selection = List # The workbench window that the part is in. # # The framework sets this when the part is created. window = Instance('enthought.pyface.workbench.api.WorkbenchWindow') #### Methods ############################################################## def create_control(self, parent): """ Create the toolkit-specific control that represents the part. """ raise NotImplementedError def destroy_control(self): """ Destroy the toolkit-specific control that represents the part. """ raise NotImplementedError def set_focus(self): """ Set the focus to the appropriate control in the part. """ raise NotImplementedError
class ExampleAction(WorkbenchAction): """ (Pyface) Action for displaying a help example. """ implements(IExtensionPointUser) ### IExtensionPointUser interface extension_registry = Property(Instance(IExtensionRegistry)) def _get_extension_registry(self): return self.window.application.extension_registry ### HelpExampleAction interface # Help code associated with this action. my_help_code = Instance(HelpCode) # Preferences for examples preferences = Instance(ExamplesPreferences) def _my_help_code_default(self): exns = self.extension_registry.get_extensions(PARENT + '.help_examples') for he in exns: if he.label == self.name: return he return None def perform(self, event): """ Perform the action by displaying the document. """ if self.my_help_code is not None: filename = get_sys_prefix_relative_filename( self.my_help_code.filename) if filename is not None: logger.info('Perform ExampleAction on %s' % filename) if self.preferences.editor is not None: # Run the editor, passing it the filename try: Popen([self.preferences.editor, filename]) except OSError, err: logger.error( 'Could not execute program for Example "%s":\n\n ' \ % self.my_help_code.label + str(err) + '\n\nTry ' +\ 'changing Examples Preferences.')
class Widget(MWidget, HasTraits): """ The toolkit specific implementation of a Widget. See the IWidget interface for the API documentation. """ implements(IWidget) #### 'IWidget' interface ################################################## control = Any parent = Any ########################################################################### # 'IWidget' interface. ########################################################################### def destroy(self): self.control = None
class UserStorage(HasTraits): """This implements a user database accessed via XML RPC.""" implements(IUserStorage) #### 'IUserStorage' interface ############################################# capabilities = List(Str) ########################################################################### # 'IUserStorage' interface. ########################################################################### def add_user(self, name, description, password): """Add a new user.""" try: ProxyServer.add_user(name, description, password, ProxyServer.key) except Exception, e: raise UserStorageError(ProxyServer.error(e))
class HelpCode(PreferencesHelper): """ The implementation for help codes. A help code is defined by a UI label and a filename. """ implements(IHelpCode) #### IHelpCode interface / Preferences ##################################### # NOTE: This class inherits preferences_page from PreferencesHelper. # The UI label for the help code, which appears in menus or dialogs. label = Str # The path to the entry point, which can be full, or relative to the Python # installation directory (sys.prefix). filename = File # The code to execute. This is executed when filename is None or an empty # string. code = Str
class ParametricCurve(BasePlot): """ """ n_x = -1 #any number of independent variable n_y = 2 #two independent variable implements(IPlot) def render(self, Xs=None, Ys=None, fmts=None, labels=None, axis_scaling='equal', pickable=[], **kwargs): data = self._convert_data(Ys=Ys) Ys = data['Ys'] if fmts is None: fmts = [] if labels is None: labels = [] axes = self.figure.add_subplot(111) for Y, fmt, label in map(None, Ys, fmts, labels): kwargs['label'] = label #array Y contains the x,y point data if not Y is None: x, y = Y self._plot(x, y, fmt, axes=axes, **kwargs) #post-plot adjustments axes.axis(axis_scaling) #set the relative scaling of the axes if labels: axes.legend() #set up the plot point object selection for ind in pickable: line = axes.lines[ind] line.set_picker(5.0)
class Perspective(HasTraits): """ The default perspective. """ implements(IPerspective) # The ID of the default perspective. DEFAULT_ID = 'enthought.pyface.workbench.default' # The name of the default perspective. DEFAULT_NAME = 'Default' #### 'IPerspective' interface ############################################# # The perspective's unique identifier (unique within a workbench window). id = Str(DEFAULT_ID) # The perspective's name. name = Str(DEFAULT_NAME) # The contents of the perspective. contents = List(PerspectiveItem) # The size of the editor area in this perspective. A value of (-1, -1) # indicates that the workbench window should choose an appropriate size # based on the sizes of the views in the perspective. editor_area_size = Tuple((-1, -1)) # Is the perspective enabled? enabled = Bool(True) # Should the editor area be shown in this perspective? show_editor_area = Bool(True) ########################################################################### # 'object' interface. ########################################################################### def __str__(self): """ Return an informal string representation of the object. """ return 'Perspective(%s)' % self.id ########################################################################### # 'Perspective' interface. ########################################################################### #### Initializers ######################################################### def _id_default(self): """ Trait initializer. """ # If no Id is specified then use the name. return self.name #### Methods ############################################################## def create(self, window): """ Create the perspective in a workbench window. For most cases you should just be able to set the 'contents' trait to lay out views as required. However, you can override this method if you want to have complete control over how the perspective is created. """ # Set the size of the editor area. if self.editor_area_size != (-1, -1): window.editor_area_size = self.editor_area_size # If the perspective has specific contents then add just those. if len(self.contents) > 0: self._add_contents(window, self.contents) # Otherwise, add all of the views defined in the window at their # default positions realtive to the editor area. else: self._add_all(window) # Activate the first view in every region. window.reset_views() return def show(self, window): """ Called when the perspective is shown in a workbench window. The default implementation does nothing, but you can override this method if you want to do something whenever the perspective is activated. """ return ########################################################################### # Private interface. ########################################################################### def _add_contents(self, window, contents): """ Adds the specified contents. """ # If we are adding specific contents then we ignore any default view # visibility. # # fixme: This is a bit ugly! Why don't we pass the visibility in to # 'window.add_view'? for view in window.views: view.visible = False for item in contents: self._add_perspective_item(window, item) return def _add_perspective_item(self, window, item): """ Adds a perspective item to a window. """ # If no 'relative_to' is specified then the view is positioned # relative to the editor area. if len(item.relative_to) > 0: relative_to = window.get_view_by_id(item.relative_to) else: relative_to = None # fixme: This seems a bit ugly, having to reach back up to the # window to get the view. Maybe its not that bad? view = window.get_view_by_id(item.id) if view is not None: # fixme: This is probably not the ideal way to sync view traits # and perspective_item traits. view.style_hint = item.style_hint # Add the view to the window. window.add_view(view, item.position, relative_to, (item.width, item.height)) else: # The reason that we don't just barf here is that a perspective # might use views from multiple plugins, and we probably want to # continue even if one or two of them aren't present. # # fixme: This is worth keeping an eye on though. If we end up with # a strict mode that throws exceptions early and often for # developers, then this might be a good place to throw one ;^) logger.error('missing view for perspective item <%s>' % item.id) return def _add_all(self, window): """ Adds *all* of the window's views defined in the window. """ for view in window.views: if view.visible: self._add_view(window, view) return def _add_view(self, window, view): """ Adds a view to a window. """ # If no 'relative_to' is specified then the view is positioned # relative to the editor area. if len(view.relative_to) > 0: relative_to = window.get_view_by_id(view.relative_to) else: relative_to = None # Add the view to the window. window.add_view(view, view.position, relative_to, (view.width, view.height)) return
class WizardController(HasTraits): """ A wizard controller that has a static list of pages. """ implements(IWizardController) #### 'IWizardController' interface ######################################## # The pages under the control of this controller. pages = Property(List(IWizardPage)) # The current page. current_page = Instance(IWizardPage) # Set if the wizard is complete. complete = Bool(False) #### Protected 'IWizardController' interface ############################## # Shadow trait for the 'pages' property. _pages = List(IWizardPage) ########################################################################### # 'IWizardController' interface. ########################################################################### def get_first_page(self): """ Returns the first page. """ if self._pages: return self._pages[0] return None def get_next_page(self, page): """ Returns the next page. """ if page.last_page: pass elif page.next_id: for p in self._pages: if p.id == page.next_id: return p else: index = self._pages.index(page) + 1 if index < len(self._pages): return self._pages[index] return None def get_previous_page(self, page): """ Returns the previous page. """ for p in self._pages: next = self.get_next_page(p) if next is page: return p return None def is_first_page(self, page): """ Is the page the first page? """ return page is self._pages[0] def is_last_page(self, page): """ Is the page the last page? """ if page.last_page: return True if page.next_id: return False return page is self._pages[-1] def dispose_pages(self): """ Dispose the wizard pages. """ for page in self._pages: page.dispose_page() return ########################################################################### # 'WizardController' interface. ########################################################################### def _get_pages(self): """ Returns the pages in the wizard. """ return self._pages[:] def _set_pages(self, pages): """ Sets the pages in the wizard. """ self._pages = pages # Make sure the current page is valid. # If the current page is None (i.e., the current page has # not been set yet), do not set it here. The current page will # get set when the wizard calls _show_page. if self.current_page is not None and \ self.current_page not in self._pages: self.current_page = self._pages[0] else: self._update() return ########################################################################### # Private interface. ########################################################################### def _update(self): """ Checks the completion status of the controller. """ # The entire wizard is complete when the last page is complete. if self.current_page is None: self.complete = False elif self.is_last_page(self.current_page): self.complete = self.current_page.complete else: self.complete = False return #### Trait event handlers ################################################# #### Static #### def _current_page_changed(self, old, new): """ Called when the current page is changed. """ if old is not None: old.on_trait_change(self._on_page_complete, 'complete',remove=True) if new is not None: new.on_trait_change(self._on_page_complete, 'complete') self._update() return #### Dynamic #### def _on_page_complete(self, obj, trait_name, old, new): """ Called when the current page is complete. """ self._update() return
class DocAction(WorkbenchAction): """ (Pyface) Action for displaying a help doc. """ implements(IExtensionPointUser) ### Action interface ############################################## # Image associated with this action instance. image = Property ### IExtensionPointUser interface extension_registry = Property(Instance(IExtensionRegistry)) def _get_extension_registry(self): return self.window.application.extension_registry def _get_image(self): """ Returns the image to be used for this DocAction instance. """ # The current implementation searches for an image file matching # 'name' in all of the image paths. If such a file is not to be found, # the '_image_not_found' file for the DocImageResourceClass is used. return DocImageResource(self.name) ### HelpDocAction interface # Help doc associated with this action. my_help_doc = Instance(HelpDoc) def _my_help_doc_default(self): exns = self.extension_registry.get_extensions(PARENT + '.help_docs') for hd in exns: if hd.label == self.name: return hd return None def _get_filename(self, doc): filename = None if doc is not None: if doc.url: filename = doc.filename else: filename = get_sys_prefix_relative_filename(doc.filename) return filename def perform(self, event): """ Perform the action by displaying the document. """ filename = self._get_filename(self.my_help_doc) if filename is not None: if self.my_help_doc.url or self.my_help_doc.viewer == 'browser': import webbrowser try: webbrowser.open(filename) except (OSError, webbrowser.Error), msg: logger.error('Could not open page in browser for '+ \ 'Document "%s":\n\n' % self.my_help_doc.label + \ str(msg) + '\n\nTry changing Dcoument Preferences.') elif self.my_help_doc.viewer is not None: # Run the viewer, passing it the filename try: Popen([self.my_help_doc.viewer, filename]) except OSError, msg: logger.error('Could not execute program for Document' + \ ' "%s":\n\n ' % self.my_help_doc.label + str(msg) + \ '\n\nTry changing Document Preferences.')
class ScriptManager(HasTraits): """ The ScriptManager class is the default implementation of IScriptManager. """ implements(IScriptManager) #### 'IScriptManager' interface ########################################### # This event is fired whenever a scriptable object is bound or unbound. It # is intended to be used by an interactive Python shell to give the # advanced user access to the scriptable objects. If an object is created # via a factory then the event is fired when the factory is called, and not # when the factory is bound. bind_event = Event(IBindEvent) # This is set if user actions are being recorded as a script. It is # maintained by the script manager. recording = Bool(False) # This is the text of the script currently being recorded (or the last # recorded script if none is currently being recorded). It is updated # automatically as the user performs actions. script = Property(Unicode) # This event is fired when the recorded script changes. The value of the # event will be the ScriptManager instance. script_updated = Event(IScriptManager) #### Private interface #################################################### # The list of calls to scriptable calls. _calls = List(Instance(_ScriptCall)) # The dictionary of bound names. The value is the next numerical suffix # to use when the binding policy is 'auto'. _names = Dict # The dictionary of _BoundObject instances keyed by the name the object is # bound to. _namespace = Dict # The next sequential result number. _next_result_nr = Int # The results returned by previous scriptable calls. The key is the id() # of the result object. The value is a two element tuple of the sequential # result number (easier for the user to use than the id()) and the result # object itself. _results = Dict # The dictionary of _ScriptObject instances keyed by the object's id(). _so_by_id = Dict # The dictionary of _ScriptObject instances keyed by the a weak reference # to the object. _so_by_ref = Dict # The date and time when the script was recorded. _when_started = Any ########################################################################### # 'IScriptManager' interface. ########################################################################### def bind(self, obj, name=None, bind_policy='unique', api=None, includes=None, excludes=None): """ Bind obj to name and make (by default) its public methods and traits (ie. those not beginning with an underscore) scriptable. The default value of name is the type of obj with the first character forced to lower case. name may be a dotted name (eg. 'abc.def.xyz'). bind_policy determines what happens if the name is already bound. If the policy is 'auto' then a numerical suffix will be added to the name, if necessary, to make it unique. If the policy is 'unique' then an exception is raised. If the policy is 'rebind' then the previous binding is discarded. The default is 'unique' If api is given then it is a class, or a list of classes, that define the attributes that will be made scriptable. Otherwise if includes is given it is a list of names of attributes that will be made scriptable. Otherwise all the public attributes of scripted_type will be made scriptable except those in the excludes list. """ # Register the object. self.new_object(obj, obj.__class__, name=name, bind_policy=bind_policy) # Make it scriptable. make_object_scriptable(obj, api=api, includes=includes, excludes=excludes) def bind_factory(self, factory, name, bind_policy='unique', api=None, includes=None, excludes=None): """ Bind factory to name. This does the same as the bind() method except that it uses a factory that will be called later on to create the object only if the object is needed. See the documentation for bind() for a description of the remaining arguments. """ name = self._unique_name(name, bind_policy) self._namespace[name] = _FactoryObject(name=name, factory=factory, api=api, includes=includes, excludes=excludes) def run(self, script): """ Run the given script, either a string or a file-like object. """ # Initialise the namespace with all explicitly bound objects. nspace = LazyNamespace() for name, bo in self._namespace.iteritems(): if bo.explicitly_bound: add_to_namespace(bo.obj, name, nspace) exec script in nspace def run_file(self, file_name): """ Run the given script file. """ f = open(file_name) self.run(f) f.close() def start_recording(self): """ Start the recording of user actions. The 'script' trait is cleared and all subsequent actions are added to 'script'. The 'recording' trait is updated appropriately. """ self._calls = [] self._next_result_nr = 0 self._results = {} self.recording = True self.script_updated = self def stop_recording(self): """ Stop the recording of user actions. The 'recording' trait is updated appropriately. """ self.recording = False ########################################################################### # 'ScriptManager' interface. ########################################################################### def record_method(self, func, args, kwargs): """ Record the call of a method of a ScriptableObject instance and return the result. This is intended to be used only by the scriptable decorator. """ if self.recording: # Record the arguments before the function has a chance to modify # them. srec = self._new_method(func, args, kwargs) result = func(*args, **kwargs) self._add_method(srec, result) self.script_updated = self else: result = func(*args, **kwargs) return result def record_trait_get(self, obj, name, result): """ Record the get of a trait of a scriptable object. This is intended to be used only by the Scriptable trait getter. """ if self.recording: side_effects = self._add_trait_get(obj, name, result) # Don't needlessly fire the event if there are no side effects. if side_effects: self.script_updated = self def record_trait_set(self, obj, name, value): """ Record the set of a trait of a scriptable object. This is intended to be used only by the Scriptable trait getter. """ if self.recording: self._add_trait_set(obj, name, value) self.script_updated = self def new_object(self, obj, scripted_type, args=None, kwargs=None, name=None, bind_policy='auto'): """ Register a scriptable object and the arguments used to create it. If no arguments were provided then assume the object is being explicitly bound. """ # The name defaults to the type name. if not name: name = scripted_type.__name__ name = name[0].lower() + name[1:] name = self._unique_name(name, bind_policy) obj_id = id(obj) obj_ref = weakref.ref(obj, self._gc_script_obj) so = _ScriptObject(name=name, obj_id=obj_id, obj_ref=obj_ref, scripted_type=scripted_type) # If we are told how to create the object then it must be implicitly # bound. if args is not None: # Convert each argument to its string representation if possible. # Doing this now avoids problems with mutable arguments. so.args = [self._scriptable_object_as_string(a) for a in args] for n, value in kwargs.iteritems(): so.kwargs[n] = self._scriptable_object_as_string(value) so.explicitly_bound = False # Remember the scriptable object via the different access methods. self._so_by_id[obj_id] = so self._so_by_ref[obj_ref] = so self._namespace[name] = so # Note that if anything listening to this event doesn't use weak # references then the object will be kept alive. self.bind_event = BindEvent(name=name, obj=obj) @staticmethod def args_as_string_list(args, kwargs, so_needed=None): """ Return a complete argument list from sets of positional and keyword arguments. Update the optional so_needed list for those arguments that refer to a scriptable object. """ if so_needed is None: so_needed = [] all_args = [] for arg in args: s = ScriptManager.arg_as_string(arg, so_needed) all_args.append(s) for name, value in kwargs.iteritems(): s = ScriptManager.arg_as_string(value, so_needed) all_args.append('%s=%s' % (name, s)) return all_args @staticmethod def arg_as_string(arg, so_needed): """ Return the string representation of an argument. Update the so_needed list if the argument refers to a scriptable object. Any delayed conversion exception is handled here. """ if isinstance(arg, Exception): raise arg if isinstance(arg, _ScriptObject): # Check it hasn't been unbound. if not arg.name: raise NameError("%s has been unbound but is needed by the script" % arg.obj_ref()) # Add it to the needed list if it isn't already there. if arg not in so_needed: so_needed.append(arg) arg = arg.name return arg ########################################################################### # Private interface. ########################################################################### def _new_method(self, func, args, kwargs): """ Return an object that encapsulates a call to a scriptable method. _add_method() must be called to add it to the current script. """ # Convert each argument to its string representation if possible. # Doing this now avoids problems with mutable arguments. nargs = [self._object_as_string(arg) for arg in args] if type(func) is types.FunctionType: so = None else: so = nargs[0] nargs = nargs[1:] nkwargs = {} for name, value in kwargs.iteritems(): nkwargs[name] = self._object_as_string(value) return _ScriptMethod(name=func.func_name, so=so, args=nargs, kwargs=nkwargs) def _add_method(self, entry, result): """ Add a method call (returned by _new_method()), with it's associated result and ID, to the current script. """ self._start_script() if result is not None: # Assume that a tuple represents multiple returned values - not # necessarily a valid assumption unless we make it a rule for # scriptable functions. if type(result) is type(()): for r in result: self._save_result(r) else: self._save_result(result) entry.result = result self._calls.append(entry) def _add_trait_get(self, obj, name, result): """ Add a call to a trait getter, with it's associated result and ID, to the current script. Return True if the get had side effects. """ self._start_script() side_effects = obj.trait(name).has_side_effects if side_effects is None: side_effects = False so = self._object_as_string(obj) if result is not None: self._save_result(result) self._calls.append(_ScriptTraitGet(so=so, name=name, result=result, has_side_effects=side_effects)) return side_effects def _add_trait_set(self, obj, name, value): """ Add a call to a trait setter, with it's associated value and ID, to the current script. """ self._start_script() so = self._object_as_string(obj) value = self._object_as_string(value) self._calls.append(_ScriptTraitSet(so=so, name=name, value=value)) def _unique_name(self, name, bind_policy): """ Return a name that is guaranteed to be unique according to the bind policy. """ # See if the name is already is use. bo = self._namespace.get(name) if bo is None: self._names[name] = 1 elif bind_policy == 'auto': suff = self._names[name] self._names[name] = suff + 1 name = '%s%d' % (name, suff) elif bind_policy == 'rebind': self._unbind(bo) else: raise NameError("\"%s\" is already bound to a scriptable object" % name) return name def _unbind(self, bo): """Unbind the given bound object.""" # Tell everybody it is no longer bound. Don't bother if it is a # factory because the corresponding bound event wouldn't have been # fired. if not isinstance(bo, _FactoryObject): self.bind_event = BindEvent(name=bo.name, obj=None) # Forget about it. del self._namespace[bo.name] bo.name = '' @staticmethod def _gc_script_obj(obj_ref): """ The callback invoked when a scriptable object is garbage collected. """ # Avoid recursive imports. from package_globals import get_script_manager sm = get_script_manager() so = sm._so_by_ref[obj_ref] if so.name: sm._unbind(so) del sm._so_by_id[so.obj_id] del sm._so_by_ref[so.obj_ref] def _start_script(self): """ Save when a script recording is started. """ if len(self._calls) == 0: self._when_started = datetime.datetime.now().strftime('%c') def _object_as_string(self, obj): """ Convert an object to a string as it will appear in a script. An exception may be returned (not raised) if there was an error in the conversion. """ obj_id = id(obj) # See if the argument is the result of a previous call. nr, _ = self._results.get(obj_id, (None, None)) if nr is not None: if nr < 0: nr = self._next_result_nr self._next_result_nr += 1 # Key on the ID of the argument (which is hashable) rather than # the argument itself (which might not be). self._results[obj_id] = (nr, obj) return "r%d" % nr return self._scriptable_object_as_string(obj) def _scriptable_object_as_string(self, obj): """ Convert an object to a string as it will appear in a script. An exception may be returned (not raised) if there was an error in the conversion. """ obj_id = id(obj) # If it is a scriptable object we return the object and convert it to a # string later when we know it is really needed. so = self._so_by_id.get(obj_id) if so is not None: return so # Use the repr result if it doesn't appear to be the generic response, # ie. it doesn't contain its own address as a hex string. s = repr(obj) if hex(obj_id) not in s: return s # We don't know how to represent the argument as a string. This is # most likely because an appropriate __init__ hasn't been made # scriptable. We don't raise an exception until the user decides to # convert the calls to a script. return ValueError("unable to create a script representation of %s" % obj) def _save_result(self, result): """ Save the result of a call to a scriptable method so that it can be recognised later. """ if id(result) not in self._results: self._results[id(result)] = (-1, result) def _get_script(self): """ Convert the current list of calls to a script. """ # Handle the trivial case. if len(self._calls) == 0: return "" # Generate the header. header = "# Script generated %s" % self._when_started # Generate the calls. so_needed = [] calls = [] for call in self._calls: s = call.as_str(self, so_needed) if s: calls.append(s) calls = "\n".join(calls) # Generate the scriptable object constructors. types_needed = [] ctors = [] for so in so_needed: if so.explicitly_bound: continue so_type = so.scripted_type args = self.args_as_string_list(so.args, so.kwargs) ctors.append("%s = %s(%s)" % (so.name, so_type.__name__, ", ".join(args))) # See if a new import is needed. if so_type not in types_needed: types_needed.append(so_type) ctors = "\n".join(ctors) # Generate the import statements. imports = [] for so_type in types_needed: imports.append("from %s import %s" % (so_type.__module__, so_type.__name__)) imports = "\n".join(imports) return "\n\n".join([header, imports, ctors, calls]) + "\n"
class Window(MWindow, Widget): """ The toolkit specific implementation of a Window. See the IWindow interface for the API documentation. """ implements(IWindow) #### 'IWindow' interface ################################################## position = Property(Tuple) size = Property(Tuple) title = Unicode #### Events ##### activated = Event closed = Event closing = Event deactivated = Event key_pressed = Event(KeyPressedEvent) opened = Event opening = Event #### Private interface #################################################### # Shadow trait for position. _position = Tuple((-1, -1)) # Shadow trait for size. _size = Tuple((-1, -1)) ########################################################################### # 'IWindow' interface. ########################################################################### def show(self, visible): pass ########################################################################### # Protected 'IWindow' interface. ########################################################################### def _add_event_listeners(self): pass ########################################################################### # Private interface. ########################################################################### def _get_position(self): """ Property getter for position. """ return self._position def _set_position(self, position): """ Property setter for position. """ old = self._position self._position = position self.trait_property_changed('position', old, position) def _get_size(self): """ Property getter for size. """ return self._size def _set_size(self, size): """ Property setter for size. """ old = self._size self._size = size self.trait_property_changed('size', old, size)
class EditorManager(HasTraits): """ The default editor manager. """ implements(IEditorManager) #### 'IEditorManager' interface ########################################### # The workbench window that the editor manager manages editors for ;^) window = Instance('enthought.pyface.workbench.api.WorkbenchWindow') ########################################################################### # 'object' interface. ########################################################################### def __init__(self, **traits): """ Constructor. """ super(EditorManager, self).__init__(**traits) # A mapping from editor to editor kind (the factory that created them). self._editor_to_kind_map = weakref.WeakKeyDictionary() return ########################################################################### # 'IEditorManager' interface. ########################################################################### def add_editor(self, editor, kind): """ Registers an existing editor. """ self._editor_to_kind_map[editor] = kind def create_editor(self, window, obj, kind): """ Create an editor for an object. """ editor = TraitsUIEditor(window=window, obj=obj) self.add_editor(editor, kind) return editor def get_editor(self, window, obj, kind): """ Get the editor that is currently editing an object. """ for editor in window.editors: if self._is_editing(editor, obj, kind): break else: editor = None return editor def get_editor_kind(self, editor): """ Return the 'kind' associated with 'editor'. """ return self._editor_to_kind_map[editor] def get_editor_memento(self, editor): """ Return the state of an editor suitable for pickling etc. By default we don't save the state of editors. """ return None def set_editor_memento(self, memento): """ Restore the state of an editor from a memento. By default we don't try to restore the state of editors. """ return None ########################################################################### # 'Protected' 'EditorManager' interface. ########################################################################### def _is_editing(self, editor, obj, kind): """ Return True if the editor is editing the object. """ return editor.obj == obj
class CommandStack(HasTraits): """ The CommandStack class is the default implementation of the ICommandStack interface. """ implements(ICommandStack) #### 'ICommandStack' interface ############################################ # This is the clean state of the stack. Its value changes as commands are # undone and redone. It can also be explicity set to mark the current # stack position as being clean (when the data is saved to disk for # example). clean = Property(Bool) # This is the name of the command that can be redone. It will be empty if # there is no command that can be redone. It is maintained by the undo # stack. redo_name = Property(Unicode) # This is the undo manager that manages this stack. undo_manager = Instance(IUndoManager) # This is the name of the command that can be undone. It will be empty if # there is no command that can be undone. It is maintained by the undo # stack. undo_name = Property(Unicode) #### Private interface #################################################### # The current index into the stack (ie. the last command that was done). _index = Int(-1) # The current macro stack. _macro_stack = List(Instance(_MacroCommand)) # The stack itself. _stack = List(Instance(_StackEntry)) ########################################################################### # 'ICommandStack' interface. ########################################################################### def begin_macro(self, name): """ This begins a macro by creating an empty command with the given 'name'. All subsequent calls to 'push()' create commands that will be children of the empty command until the next call to 'end_macro()'. Macros may be nested. The stack is disabled (ie. nothing can be undone or redone) while a macro is being created (ie. while there is an outstanding 'end_macro()' call). """ command = _MacroCommand(name=name) self.push(command) self._macro_stack.append(command) def clear(self): """ This clears the stack, without undoing or redoing any commands, and leaves the stack in a clean state. It is typically used when all changes to the data have been abandoned. """ self._index = -1 self._stack = [] self._macro_stack = [] self.undo_manager.stack_updated = self def end_macro(self): """ This ends a macro. """ try: self._macro_stack.pop() except IndexError: pass def push(self, command): """ This executes a command and saves it on the command stack so that it can be subsequently undone and redone. 'command' is an instance that implements the ICommand interface. Its 'do()' method is called to execute the command. If any value is returned by 'do()' then it is returned by 'push()'. """ # See if the command can be merged with the previous one. if len(self._macro_stack) == 0: if self._index >= 0: merged = self._stack[self._index].command.merge(command) else: merged = False else: merged = self._macro_stack[-1].merge(command) # Increment the global sequence number. if not merged: self.undo_manager.sequence_nr += 1 # Execute the command. result = command.do() # Do nothing more if the command was merged. if merged: return result # Only update the command stack if there is no current macro. if len(self._macro_stack) == 0: # Remove everything on the stack after the last command that was # done. self._index += 1 del self._stack[self._index:] # Create a new stack entry and add it to the stack. entry = _StackEntry(command=command, sequence_nr=self.undo_manager.sequence_nr) self._stack.append(entry) self.undo_manager.stack_updated = self else: # Add the command to the parent macro command. self._macro_stack[-1].macro_commands.append(command) return result def redo(self, sequence_nr=0): """ If 'sequence_nr' is 0 then the last command that was undone is redone and any result returned. Otherwise commands are redone up to and including the given 'sequence_nr' and any result of the last of these is returned. """ # Make sure a redo is valid in the current context. if self.redo_name == "": return None if sequence_nr == 0: result = self._redo_one() else: result = None while self._index + 1 < len(self._stack): if self._stack[self._index + 1].sequence_nr > sequence_nr: break result = self._redo_one() self.undo_manager.stack_updated = self return result def undo(self, sequence_nr=0): """ If 'sequence_nr' is 0 then the last command is undone. Otherwise commands are undone up to and including the given 'sequence_nr'. """ # Make sure an undo is valid in the current context. if self.undo_name == "": return if sequence_nr == 0: self._undo_one() else: while self._index >= 0: if self._stack[self._index].sequence_nr <= sequence_nr: break self._undo_one() self.undo_manager.stack_updated = self ########################################################################### # Private interface. ########################################################################### def _redo_one(self): """ Redo the command at the current index and return the result. """ self._index += 1 entry = self._stack[self._index] return entry.command.redo() def _undo_one(self): """ Undo the command at the current index. """ entry = self._stack[self._index] self._index -= 1 entry.command.undo() def _get_clean(self): """ Get the clean state of the stack. """ if self._index >= 0: clean = self._stack[self._index].clean else: clean = True return clean def _set_clean(self, clean): """ Set the clean state of the stack. """ if self._index >= 0: self._stack[self._index].clean = clean def _get_redo_name(self): """ Get the name of the redo command, if any. """ redo_name = "" if len(self._macro_stack) == 0 and self._index + 1 < len(self._stack): redo_name = self._stack[self._index + 1].command.name.replace( '&', '') return redo_name def _get_undo_name(self): """ Get the name of the undo command, if any. """ undo_name = "" if len(self._macro_stack) == 0 and self._index >= 0: command = self._stack[self._index].command undo_name = command.name.replace('&', '') return undo_name
class UserManager(HasTraits): """The default user manager implementation.""" implements(IUserManager) #### 'IUserManager' interface ############################################# management_actions = List(Instance(Action)) user = Instance(IUser) user_actions = List(Instance(Action)) user_authenticated = Event(IUser) #### 'UserManager' interface ############################################## # The user database. user_db = Instance(IUserDatabase) ########################################################################### # 'IUserManager' interface. ########################################################################### def bootstrapping(self): """Return True if we are bootstrapping, ie. no users have been defined. """ return self.user_db.bootstrapping() def authenticate_user(self): """Authenticate the user.""" if self.user_db.authenticate_user(self.user): self.user.authenticated = True # Tell the policy manager before everybody else. get_permissions_manager().policy_manager.load_policy(self.user) self.user_authenticated = self.user def unauthenticate_user(self): """Unauthenticate the user.""" if self.user.authenticated and self.user_db.unauthenticate_user( self.user): self.user.authenticated = False # Tell the policy manager before everybody else. get_permissions_manager().policy_manager.load_policy(None) self.user_authenticated = None def matching_user(self, name): """Select a user.""" return self.user_db.matching_user(name) ########################################################################### # Trait handlers. ########################################################################### def _management_actions_default(self): """Return the list of management actions.""" from enthought.permissions.secure_proxy import SecureProxy user_db = self.user_db actions = [] perm = ManageUsersPermission() if user_db.can_add_user: act = Action(name="&Add a User...", on_perform=user_db.add_user) actions.append(SecureProxy(act, permissions=[perm], show=False)) if user_db.can_modify_user: act = Action(name="&Modify a User...", on_perform=user_db.modify_user) actions.append(SecureProxy(act, permissions=[perm], show=False)) if user_db.can_delete_user: act = Action(name="&Delete a User...", on_perform=user_db.delete_user) actions.append(SecureProxy(act, permissions=[perm], show=False)) return actions def _user_actions_default(self): """Return the list of user actions.""" actions = [] if self.user_db.can_change_password: actions.append(_ChangePasswordAction()) return actions def _user_default(self): """Return the default current user.""" return self.user_db.user_factory() def _user_db_default(self): """Return the default user database.""" # Defer to an external user database if there is one. try: from enthought.permissions.external.user_database import UserDatabase except ImportError: from enthought.permissions.default.user_database import UserDatabase return UserDatabase()
class Preferences(HasTraits): """ The default implementation of a node in a preferences hierarchy. """ implements(IPreferences) #### 'IPreferences' interface ############################################# # The absolute path to this node from the root node (the empty string if # this node *is* the root node). path = Property(Str) # The parent node (None if this node *is* the root node). parent = Instance(IPreferences) # The name of the node relative to its parent (the empty string if this # node *is* the root node). name = Str #### 'Preferences' interface ############################################## # The default name of the file used to persist the preferences (if no # filename is passed in to the 'load' and 'save' methods, then this is # used instead). filename = Str #### Protected 'Preferences' interface #################################### # A lock to make access to the node thread-safe. # # fixme: There *should* be no need to declare this as a trait, but if we # don't then we have problems using nodes in the preferences manager UI. # It is something to do with 'cloning' the node for use in a 'modal' traits # UI... Hmmm... _lk = Any # The node's children. _children = Dict(Str, IPreferences) # The node's preferences. _preferences = Dict(Str, Any) # Listeners for changes to the node's preferences. # # The callable must take 4 arguments, e.g:: # # listener(node, key, old, new) _preferences_listeners = List(Callable) ########################################################################### # 'object' interface. ########################################################################### def __init__(self, **traits): """ Constructor. """ # A lock to make access to the '_children', '_preferences' and # '_preferences_listeners' traits thread-safe. self._lk = threading.Lock() # Base class constructor. super(Preferences, self).__init__(**traits) # If a filename has been specified then load the preferences from it. if len(self.filename) > 0: self.load() return ########################################################################### # 'IPreferences' interface. ########################################################################### #### Trait properties ##################################################### def _get_path(self): """ Property getter. """ names = [] node = self while node.parent is not None: names.append(node.name) node = node.parent names.reverse() return '.'.join(names) #### Methods ############################################################## #### Methods where 'path' refers to a preference #### def get(self, path, default=None, inherit=False): """ Get the value of the preference at the specified path. """ if len(path) == 0: raise ValueError('empty path') components = path.split('.') # If there is only one component in the path then the operation takes # place in this node. if len(components) == 1: value = self._get(path, Undefined) # Otherwise, find the next node and pass the rest of the path to that. else: node = self._get_child(components[0]) if node is not None: value = node.get('.'.join(components[1:]), Undefined) else: value = Undefined # If inherited values are allowed then try those as well. # # e.g. 'acme.ui.widget.bgcolor' # 'acme.ui.bgcolor' # 'acme.bgcolor' # 'bgcolor' while inherit and value is Undefined and len(components) > 1: # Remove the penultimate component... # # e.g. 'acme.ui.widget.bgcolor' -> 'acme.ui.bgcolor' del components[-2] # ... and try that. value = self.get('.'.join(components), default=Undefined) if value is Undefined: value = default return value def remove(self, path): """ Remove the preference at the specified path. """ if len(path) == 0: raise ValueError('empty path') components = path.split('.') # If there is only one component in the path then the operation takes # place in this node. if len(components) == 1: self._remove(path) # Otherwise, find the next node and pass the rest of the path to that. else: node = self._get_child(components[0]) if node is not None: node.remove('.'.join(components[1:])) return def set(self, path, value): """ Set the value of the preference at the specified path. """ if len(path) == 0: raise ValueError('empty path') components = path.split('.') # If there is only one component in the path then the operation takes # place in this node. if len(components) == 1: self._set(path, value) # Otherwise, find the next node (creating it if it doesn't exist) # and pass the rest of the path to that. else: node = self._node(components[0]) node.set('.'.join(components[1:]), value) return #### Methods where 'path' refers to a node #### def clear(self, path=''): """ Remove all preferences from the node at the specified path. """ # If the path is empty then the operation takes place in this node. if len(path) == 0: self._clear() # Otherwise, find the next node and pass the rest of the path to that. else: components = path.split('.') node = self._get_child(components[0]) if node is not None: node.clear('.'.join(components[1:])) return def keys(self, path=''): """ Return the preference keys of the node at the specified path. """ # If the path is empty then the operation takes place in this node. if len(path) == 0: keys = self._keys() # Otherwise, find the next node and pass the rest of the path to that. else: components = path.split('.') node = self._get_child(components[0]) if node is not None: keys = node.keys('.'.join(components[1:])) else: keys = [] return keys def node(self, path=''): """ Return the node at the specified path. """ # If the path is empty then the operation takes place in this node. if len(path) == 0: node = self # Otherwise, find the next node and pass the rest of the path to that. else: components = path.split('.') node = self._node(components[0]) node = node.node('.'.join(components[1:])) return node def node_exists(self, path=''): """ Return True if the node at the specified path exists. """ # If the path is empty then the operation takes place in this node. if len(path) == 0: exists = True # Otherwise, find the next node and pass the rest of the path to that. else: components = path.split('.') node = self._get_child(components[0]) if node is not None: exists = node.node_exists('.'.join(components[1:])) else: exists = False return exists def node_names(self, path=''): """ Return the names of the children of the node at the specified path. """ # If the path is empty then the operation takes place in this node. if len(path) == 0: names = self._node_names() # Otherwise, find the next node and pass the rest of the path to that. else: components = path.split('.') node = self._get_child(components[0]) if node is not None: names = node.node_names('.'.join(components[1:])) else: names = [] return names #### Persistence methods #### def flush(self): """ Force any changes in the node to the backing store. This includes any changes to the node's descendants. """ self.save() return ########################################################################### # 'Preferences' interface. ########################################################################### #### Listener methods #### def add_preferences_listener(self, listener, path=''): """ Add a listener for changes to a node's preferences. """ # If the path is empty then the operation takes place in this node. if len(path) == 0: names = self._add_preferences_listener(listener) # Otherwise, find the next node and pass the rest of the path to that. else: components = path.split('.') node = self._node(components[0]) node.add_preferences_listener(listener, '.'.join(components[1:])) return def remove_preferences_listener(self, listener, path=''): """ Remove a listener for changes to a node's preferences. """ # If the path is empty then the operation takes place in this node. if len(path) == 0: names = self._remove_preferences_listener(listener) # Otherwise, find the next node and pass the rest of the path to that. else: components = path.split('.') node = self._node(components[0]) node.remove_preferences_listener(listener, '.'.join(components[1:])) return #### Persistence methods #### def load(self, file_or_filename=None): """ Load preferences from a file. This is a *merge* operation i.e. the contents of the file are added to the node. This implementation uses 'ConfigObj' files. """ if file_or_filename is None: file_or_filename = self.filename logger.debug('loading preferences from <%s>', file_or_filename) # Do the import here so that we don't make 'ConfigObj' a requirement # if preferences aren't ever persisted (or a derived class chooses to # use a different persistence mechanism). from configobj import ConfigObj config_obj = ConfigObj(file_or_filename) # 'name' is the section name, 'value' is a dictionary containing the # name/value pairs in the section (the actual preferences ;^). for name, value in config_obj.items(): # Create/get the node from the section name. components = name.split('.') node = self for component in components: node = node._node(component) # Add the contents of the section to the node. self._add_dictionary_to_node(node, value) return def save(self, file_or_filename=None): """ Save the node's preferences to a file. This implementation uses 'ConfigObj' files. """ if file_or_filename is None: file_or_filename = self.filename # If no file or filename is specified then don't save the preferences! if len(file_or_filename) > 0: # Do the import here so that we don't make 'ConfigObj' a # requirement if preferences aren't ever persisted (or a derived # class chooses to use a different persistence mechanism). from configobj import ConfigObj logger.debug('saving preferences to <%s>', file_or_filename) config_obj = ConfigObj(file_or_filename) self._add_node_to_dictionary(self, config_obj) config_obj.write() return ########################################################################### # Protected 'Preferences' interface. # # These are the only methods that should access the protected '_children' # and '_preferences' traits. This helps make it easy to subclass this class # to create other implementations (all the subclass has to do is to # implement these protected methods). # ########################################################################### def _add_dictionary_to_node(self, node, dictionary): """ Add the contents of a dictionary to a node's preferences. """ self._lk.acquire() node._preferences.update(dictionary) self._lk.release() return def _add_node_to_dictionary(self, node, dictionary): """ Add a node's preferences to a dictionary. """ # This method never manipulates the '_preferences' trait directly. # Instead it does eveything via the other protected methods and hence # doesn't need to grab the lock. if len(node._keys()) > 0: dictionary[node.path] = {} for key in node._keys(): dictionary[node.path][key] = node._get(key) for name in node._node_names(): self._add_node_to_dictionary(node._get_child(name), dictionary) return def _add_preferences_listener(self, listener): """ Add a listener for changes to thisnode's preferences. """ self._lk.acquire() self._preferences_listeners.append(listener) self._lk.release() return def _clear(self): """ Remove all preferences from this node. """ self._lk.acquire() self._preferences.clear() self._lk.release() return def _create_child(self, name): """ Create a child of this node with the specified name. """ self._lk.acquire() child = self._children[name] = Preferences(name=name, parent=self) self._lk.release() return child def _get(self, key, default=None): """ Get the value of a preference in this node. """ self._lk.acquire() value = self._preferences.get(key, default) self._lk.release() return value def _get_child(self, name): """ Return the child of this node with the specified name. Return None if no such child exists. """ self._lk.acquire() child = self._children.get(name) self._lk.release() return child def _keys(self): """ Return the preference keys of this node. """ self._lk.acquire() keys = self._preferences.keys() self._lk.release() return keys def _node(self, name): """ Return the child of this node with the specified name. Create the child node if it does not exist. """ node = self._get_child(name) if node is None: node = self._create_child(name) return node def _node_names(self): """ Return the names of the children of this node. """ self._lk.acquire() node_names = self._children.keys() self._lk.release() return node_names def _remove(self, name): """ Remove a preference value from this node. """ self._lk.acquire() if name in self._preferences: del self._preferences[name] self._lk.release() return def _remove_preferences_listener(self, listener): """ Remove a listener for changes to the node's preferences. """ self._lk.acquire() if listener in self._preferences_listeners: self._preferences_listeners.remove(listener) self._lk.release() return def _set(self, key, value): """ Set the value of a preference in this node. """ # Preferences are *always* stored as strings. value = str(value) self._lk.acquire() old = self._preferences.get(key) self._preferences[key] = value # If the value is unchanged then don't call the listeners! if old == value: listeners = [] else: listeners = self._preferences_listeners[:] self._lk.release() for listener in listeners: listener(self, key, old, value) return ########################################################################### # Debugging interface. ########################################################################### def dump(self, indent=''): """ Dump the preferences hierarchy to stdout. """ if indent == '': print print indent, 'Node(%s)' % self.name, self._preferences indent += ' ' for child in self._children.values(): child.dump(indent) return
class BasePlot(HasTraits): """ An interface defining an object which can render a plot on a figure object """ implements(IPlot) n_x = Int(1) n_y = Int(1) figure = Instance(Figure, ()) view = View( Item( 'figure', #height = 600, #width = 800, style='custom', show_label=False, editor=MPLFigureEditor( ), #this editor will automatically find and connect the _handle_onpick method for handling matplotlib's object picking events ) ), ) def clear(self): self.figure.clear() def render(self, Xs, Ys, fmts=None, labels=None, pickable=[], **kwargs): ''' Plots data from 'Xs', 'Ys' on 'figure' and returns the figure object''' data = self._convert_data(Xs, Ys) Xs = data['Xs'] Ys = data['Ys'] if fmts is None: fmts = [] if labels is None: labels = [] axes = self.figure.add_subplot(111) #kwargs['axes'] = axes #kwargs['figure'] = self.figure for X, Y, fmt, label in map(None, Xs, Ys, fmts, labels): if not (X is None or Y is None): kwargs['label'] = label self._plot(X, Y, fmt, axes=axes, **kwargs) if labels: axes.legend() #set up the plot point object selection for ind in pickable: line = axes.lines[ind] line.set_picker(5.0) def redraw(self): if not self.figure.canvas is None: self.figure.canvas.draw() def register_onpick_handler(self, handler): self._handle_onpick = handler def _plot(self, x, y, fmt=None, axes=None, **kwargs): if axes is None: raise TypeError, "an 'axes' object must be supplied" if fmt is None: axes.plot(x, y, **kwargs) else: axes.plot(x, y, fmt, **kwargs) def _convert_data(self, Xs=None, Ys=None): #convert the data for the independent variables data_args = {'Xs': (Xs, self.n_x), 'Ys': (Ys, self.n_y)} data = {} for name, args in data_args.items(): D, n = args #data array, expected number of variables if not D is None: for d in D: print d.shape D = array(D) #convert to a numpy array dim = len(D.shape) if dim == 1: if n == 1: #upconvert 1D array to 2D D = D.reshape((1, -1)) else: raise TypeError, "'%s' dimension must be 2 or 3 for n > 1, detected incommensurate data of dimension %d" % ( name, dim) elif dim == 2: d1, d2 = D.shape if n == 1: pass #no conversion needed elif not (d1 == n): raise TypeError, "'%s' shape (%d,%d) must match (n=%d,:)" % ( name, d1, d2, n) else: #up convert 2D array to 3D D = D.reshape((1, d1, d2)) elif dim == 3: d1, d2, d3 = D.shape if n == 1 and d2 == 1: #down convert 3D array to 2D D = D.reshape((d1, d3)) elif not (d2 == n): raise TypeError, "'%s' shape (%d,%d,%d) must match (:,n=%d,:)" % ( name, d1, d2, d3, n) else: raise TypeError, "'%s' dimension must be 1, 2 or 3, detected incommensurate data of dimension %d" % ( name, dim) data[name] = D else: #default to an empty array data[name] = array([]) return data
class TemplateDataContext(HasPrivateTraits): """ A concrete implementation of the ITemplateDataContext interface intended to be used for creating the *output_data_context* value of an **ITemplateDataNameItem** implementation (although they are not required to use it). """ implements(ITemplateDataContext) #-- 'ITemplateDataContext' Interface Traits -------------------------------- # The path to this data context (does not include the 'data_context_name'): data_context_path = Str # The name of the data context: data_context_name = Str # A list of the names of the data values in this context: data_context_values = Property # List( Str ) # The list of the names of the sub-contexts of this context: data_contexts = Property # List( Str ) #-- Public Traits --------------------------------------------------------- # The data context values dictionary: values = Dict(Str, Any) # The data contexts dictionary: contexts = Dict(Str, ITemplateDataContext) #-- 'ITemplateDataContext' Property Implementations ------------------------ @cached_property def _get_data_context_values(self): values = self.values.keys() values.sort() return values @cached_property def _get_data_contexts(self): contexts = self.contexts.keys() contexts.sort() return contexts #-- 'ITemplateDataContext' Interface Implementation ------------------------ def get_data_context_value(self, name): """ Returns the data value with the specified *name*. Raises a **ITemplateDataContextError** if *name* is not defined as a data value in the context. Parameters ---------- name : A string specifying the name of the context data value to be returned. Returns ------- The data value associated with *name* in the context. The type of the data is application dependent. Raises **ITemplateDataContextError** if *name* is not associated with a data value in the context. """ try: return self.values[name] except: raise ITemplateDataContextError("Value '%s' not found." % name) def get_data_context(self, name): """ Returns the **ITemplateDataContext** value associated with the specified *name*. Raises **ITemplateDataContextError** if *name* is not defined as a data context in the context. Parameters ---------- name : A string specifying the name of the data context to be returned. Returns ------- The **ITemplateDataContext** associated with *name* in the context. Raises **ITemplateDataContextError** if *name* is not associated with a data context in the context. """ try: return self.context[name] except: raise ITemplateDataContextError("Context '%s' not found." % name)
class TemplateChoice(HasPrivateTraits): implements(ITemplateChoice) # The user interface string for this choice: choice_value = Str