コード例 #1
0
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)
コード例 #2
0
ファイル: about_dialog.py プロジェクト: liq07lzucn/radpy
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)
コード例 #3
0
class MyClass(object):

    implements(IMyMarkerInterface)

    def __init__(self):
        self.val = 2

    def blah(self):
        pass
コード例 #4
0
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 ))
コード例 #5
0
ファイル: mutable_template.py プロジェクト: sjl421/code-2
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
コード例 #6
0
ファイル: clipboard.py プロジェクト: sjl421/code-2
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
コード例 #7
0
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 ))
コード例 #8
0
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
コード例 #9
0
ファイル: user_database.py プロジェクト: sjl421/code-2
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
コード例 #10
0
ファイル: policy_storage.py プロジェクト: sjl421/code-2
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))
コード例 #11
0
ファイル: image_resource.py プロジェクト: sjl421/code-2
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
コード例 #12
0
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')
コード例 #13
0
ファイル: i_workbench_part.py プロジェクト: sjl421/code-2
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
コード例 #14
0
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.')
コード例 #15
0
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
コード例 #16
0
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))
コード例 #17
0
ファイル: help_code.py プロジェクト: sjl421/code-2
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
コード例 #18
0
ファイル: plots.py プロジェクト: cversek/python-mathstuff
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)
コード例 #19
0
ファイル: perspective.py プロジェクト: sjl421/code-2
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
コード例 #20
0
ファイル: wizard_controller.py プロジェクト: sjl421/code-2
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
コード例 #21
0
ファイル: doc_action.py プロジェクト: sjl421/code-2
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.')
コード例 #22
0
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"
コード例 #23
0
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)
コード例 #24
0
ファイル: editor_manager.py プロジェクト: sjl421/code-2
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
コード例 #25
0
ファイル: command_stack.py プロジェクト: sjl421/code-2
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
コード例 #26
0
ファイル: user_manager.py プロジェクト: sjl421/code-2
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()
コード例 #27
0
ファイル: preferences.py プロジェクト: sjl421/code-2
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
コード例 #28
0
ファイル: plots.py プロジェクト: cversek/python-mathstuff
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
コード例 #29
0
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)
コード例 #30
0
class TemplateChoice(HasPrivateTraits):

    implements(ITemplateChoice)

    # The user interface string for this choice:
    choice_value = Str