Logo Search packages:      
Sourcecode: mayavi2 version File versions  Download package

repository.py

#-------------------------------------------------------------------------------
#  
#  Define a repository
#  
#  Written by: David C. Morrill
#  
#  Date: 03/22/2006
#  
#  (c) Copyright 2006 by Enthought, Inc.
#  
#-------------------------------------------------------------------------------

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

from os \
    import listdir, makedirs
    
from os.path \
    import basename, dirname, exists, isfile, join, normpath, splitext, sep

from enthought.traits.api \
    import HasPrivateTraits, List, Instance, Event
    
from enthought.envisage \
    import Application, get_active_window
    
from enthought.envisage.resource.resource_plugin \
    import ResourcePlugin    

from enthought.pyface.api \
    import Window
    
from enthought.naming.exception \
    import NameNotFoundError
    
# Local imports:    
from repository_root \
    import RepositoryRoot

REPOSITORY_METADATA = '.repository_metadata'
    
#-------------------------------------------------------------------------------
#  'Repository' class:  
#-------------------------------------------------------------------------------

class Repository ( HasPrivateTraits ):
    
    #---------------------------------------------------------------------------
    #  Trait definitions:  
    #---------------------------------------------------------------------------
    
    # The list of repository roots used to define this repository:
    roots = List( RepositoryRoot )
    
    # Reference to the envisage application object:
    application = Instance( Application )
    
    # Event fired when the contents of the repository are modified:
    modified = Event
    
    #---------------------------------------------------------------------------
    #  Methods:  
    #---------------------------------------------------------------------------
        
    def import_object ( self, types, 
             view  = 'enthought.envisage.repository',
             id    = 'enthought.envisage.repository.repository_import_handler',
             title = 'Import Item' ):
        """ Imports an object of one of the specified types from the repository.
        
            The *types* parameter should be a list of resource type IDs for any
            of the legal types that can be imported.
            
            The user is presented with a browser dialog that allows them to
            select the object to be imported. Only files containing an object
            belonging to one of the specified types are displayed in the dialog.
            
            The optional *view* parameter can be used to specify the name of the
            view to use within the import dialog to 'browse' a selected object.
            The view must be a defined view for the selected resource type.
            The *view* parameter can be specified as None, in which case no 
            'browse' view of the selected object is provided.
            
            The return value is None if the user cancels the import dialog or
            an error occurs. Otherwise, the result is an object which is an
            instance of one of the specified types.
        """
        from repository_handler import RepositoryImportHandler
        
        if isinstance( types, basestring ):
            types = [ types ]
        parent = get_active_window()
        if isinstance( parent, Window):
            parent = parent.control
            
        return RepositoryImportHandler(
                   repository = self,
                   types      = types,
                   view       = view,
                   title      = title,
                   parent     = parent ).process( id )
        
    def export_object ( self, object, 
             view  = '',
             id    = 'enthought.envisage.repository.repository_export_handler',
             title = 'Export Item' ):
        """ Exports the specified object to the repository.
        
            The user is presented with a dialog which allows them to navigate
            to the repository directory they wish to store the object in. Only
            repository directories that have metadata allowing the type of
            object specified are displayed in the dialog. If desired, the user
            can also create new directories for storing the specified object.
            Any new directories are automatically marked as allowing objects of
            the specified type to be stored there.
                                
            The optional *view* parameter can be used to specify the name of the
            view to use within the export dialog to browse the object being 
            exported. The view must be a defined view for the resource type of
            the specified object. The default value is None, which means that
            no browse view of the object is provided.
            
            The result is True if the object is exported successfully; otherwise
            the result is False.
        """
        from repository_handler import RepositoryExportHandler
        
        parent = get_active_window()
        if isinstance( parent, Window):
            parent = parent.control
            
        return RepositoryExportHandler(
                   repository = self,
                   object     = object,
                   view       = view,
                   title      = title,
                   parent     = parent ).process( id )
                   
    def import_from_path(self, path):
        """
        Returns the object at "path".  
        Path should be in the form "/root/path/to/the/file"
        """
        full_path = self.abspath(path)
        
        if not exists(full_path):
            raise NameNotFoundError(path)

        object = None
        
        rm = self.application.get_service(ResourcePlugin.IRESOURCE_MANAGER )
        for rt in rm.resource_types:
            if rt.serializer is not None and rt.serializer.can_load( full_path ):
                object = rt.serializer.load(full_path)
                break

        if object is None:
            raise NameNotFoundError(path)

        return object
    
    def export_to_path(self, path, object):
        """ Export the object to the specified path.
        Overwrites any existing file at path.
        
        raises NameNotFoundError if the root of path is unknown.
        raises NotImplemented if no serializer exists for object.
        """
        full_path = self.abspath(path)
        directory = dirname( full_path )

        if not exists( directory ):
            self.makedirs( directory )
        
        rm = self.application.get_service(ResourcePlugin.IRESOURCE_MANAGER )

        resource_type = rm.get_type_of( object )
        
        serializer = resource_type.serializer
        
        if serializer is not None and serializer.can_save( object ):
            serializer.save( full_path, object )
        
        else:
            raise NotImplemented, "cannot serialize object %s" % object
        
        return
        
    def abspath(self, path):
        """ Returns the absolute file system path for the provided
        symbolic path.  The first component of path is required to be the
        name of a known RepositoryRoot.
        
        raises NameNotFoundError
        """
        path = path.strip()
        path = normpath(path)
        
        names = path.split( sep )
        
        # Clean up the front of the list if needed
        while names[0] == '':
            del names[0]

        while names[0].isspace():
            del names[0]
            
        if len(names) < 1:
            raise ValueError, "Empty path: %s" % path
            
        root = self.get_root( names[0] )
        
        # Path to the file is repository root and the non-symbolic part of path.
        abs_path = join( root.path, *names[1:] )

        return abs_path
    
    def makedirs(self, path, types=None):
        """ Create all missing directories in path.
        For new directories and those without a metadata file, copy the
        metadata file from the parent directory or the specified types list.
        """
        
        names = path.split(sep)
        
        tmp_types = []
        
        # Find the deepest directory with metadata.
        while len( names ) > 0:
            tmp_path = sep.join( names )
            if exists( tmp_path ):
                tmp_types = self.get_metadata( tmp_path )
                if len(tmp_types) > 0:
                    break
                else:
                    names = names[:-1]
            else:
                names = names[:-1]
                
        # Use the found types if types not specified by caller.
        if types is None:
            types = tmp_types
            
        # tmp_path is the deepest directory that exists and has metadata
        # types are the types for the metadata file.
        
        # Have OS make the directories.
        makedirs(path)
        
        # Find the portion of path that does not have metadata files.
        remainder = path.replace( tmp_path + sep, '', 1)
        names = remainder.split(sep)
        
        # Add metadata to each subdirectory in turn.
        for name in names:
            tmp_path = tmp_path + sep + name
            self.set_metadata( tmp_path, types )

        return
    
    
    def get_root(self, name):
        """ Returns the RepositoryRoot with the specified name.
        """
        for r in self.roots:
            if r.name == name:
                root = r
                break

        else:
            raise NameNotFoundError(name)

        return root


    ###########################################################################
    # Metadata methods
    ###########################################################################
    
    def get_metadata( self, path ):
        """ Returns the type metadata for the specified directory.
        """
        fn    = join( path, REPOSITORY_METADATA )
        types = []
        if isfile( fn ):
            try:
                file  = open( fn, 'rb' )
                types = [ line.strip() for line in file ]
                file.close()
            except:
                pass

        return types

    def set_metadata( self, path, types ):
        """ Saves the type metadata for the specified directory.
        """
        fn = join( path, REPOSITORY_METADATA )
        try:
            file = open( fn, 'wb' )
            file.write( '\n'.join( types ) )
            file.close()
            return True
        except:
            error( self.handler.parent,
                   "An error occurred updating the '%s' repository metadata" %
                   path )
            return False

    def update_metadata( self, path, types ):
        """ Add resource types from types to the metadata for the specified
        directory.
        """
        # Update the directory metadata:                
        path_types    = self.get_metadata( path )
        
        modified = False

        for type in types:
            if type not in path_types:
                path_types.append( type )
                modified = True
                
        if modified:
            self.set_metadata( path, path_types )
        
        return
    
    def remove_metadata(self, path, types ):
        """ Remove the resource types from types from the metadata for
        the specified directory.
        """
        path_types = self.get_metadata( path )

        if len( path_types ) > 0:
            modified = False
            
            for type in self.handler.types:
                if type in path_types:
                    path_types.remove( type )

            if modified:
                self.set_metadata( path, path_types )
        
        return
        
    def allows_type( self, path, types ):
        """ Returns whether or not the specified path allows any of the 
            specified list of resource type ids. The possible results:
            - True:  Definitely allows
            - False: Definitely does not allow
            - None:  Unknown whether it allows any of the types or not
        """
        fn = join( path, REPOSITORY_METADATA )
        if not isfile( fn ):
            return None
        try:
            file = open( fn, 'rb' )
            for line in file:
                if line.strip() in types:
                    return True
        finally:
            file.close()
        return False
    
###### EOF ##########################################################################           
        
           
            
            
        

Generated by  Doxygen 1.6.0   Back to index