source: sasview/DataLoader/loader.py @ e7430b6

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since e7430b6 was 84545dd, checked in by Mathieu Doucet <doucetm@…>, 16 years ago

Added module importing from zip files.

  • Property mode set to 100644
File size: 7.9 KB
RevLine 
[a916ccc]1"""
[daa56d0]2    File handler to support different file extensions.
3    Uses reflectometry's registry utility.
[a916ccc]4"""
[daa56d0]5
6"""
7This software was developed by the University of Tennessee as part of the
8Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
9project funded by the US National Science Foundation.
10
11See the license text in license.txt
12
13copyright 2008, University of Tennessee
14"""
15
16from data_util.registry import ExtensionRegistry
17import os 
18import sys
[a916ccc]19import logging
[daa56d0]20import time
[84545dd]21from zipfile import ZipFile
[d22da51]22
[daa56d0]23class Registry(ExtensionRegistry):
24    """
25        Registry class for file format extensions.
26        Readers and writers are supported.
27    """
28   
29    def __init__(self):
30        super(Registry, self).__init__()
31       
32        ## Writers
33        self.writers = {}
[a916ccc]34       
[daa56d0]35        ## Creation time, for testing
36        self._created = time.time()
37       
38        # Find internal readers
39        try:
40            cwd = os.path.split(__file__)[0]
41        except:
42            cwd = os.getcwd()
43            logging.error("Registry: could not find the installed reader's directory\n %s" % sys.exc_value)
44           
45        dir = os.path.join(cwd, 'readers')
46        n = self.find_plugins(dir)
47        logging.info("Loader found %i readers" % n)
48       
49    def find_plugins(self, dir):
50        """
51            Find readers in a given directory
[a916ccc]52           
[daa56d0]53            @param dir: directory to search into
54            @return: number of readers found
55        """
56        readers_found = 0
57        for item in os.listdir(dir):
58            full_path = os.path.join(dir, item)
[84545dd]59            if os.path.isfile(full_path):
60               
61                # Process python files
62                if item.endswith('.py'):
63                    toks = os.path.splitext(os.path.basename(item))
64                    try:
65                        sys.path.insert(0, os.path.abspath(dir))
66                        module = __import__(toks[0], globals(), locals())
67                        if self._identify_plugin(module):
[daa56d0]68                            readers_found += 1
[84545dd]69                    except :
70                        logging.error("Loader: Error importing %s\n  %s" % (name, sys.exc_value))
[daa56d0]71                           
[84545dd]72                # Process zip files
73                elif item.endswith('.zip'):
74                    try:
75                        # Find the modules in the zip file
76                        zfile = ZipFile(item)
77                        nlist = zfile.namelist()
78                       
79                        sys.path.insert(0, item)
80                        for mfile in nlist:
81                            try:
82                                # Change OS path to python path
83                                fullname = mfile.replace('/', '.')
84                                fullname = os.path.splitext(fullname)[0]
85                                module = __import__(fullname, globals(), locals(), [""])
86                                if self._identify_plugin(module):
87                                    readers_found += 1
88                            except:
89                                logging.error("Loader: Error importing %s\n  %s" % (mfile, sys.exc_value))
90                           
91                    except:
92                        logging.error("Loader: Error importing %s\n  %s" % (item, sys.exc_value))
93                     
[daa56d0]94        return readers_found
[84545dd]95   
96    def _identify_plugin(self, module):
97        """
98            Look into a module to find whether it contains a
99            Reader class. If so, add it to readers and (potentially)
100            to the list of writers.
101            @param module: module object
102        """
103        reader_found = False
104       
105        if hasattr(module, "Reader"):
106            try:
107                # Find supported extensions
108                loader = module.Reader()
109                for ext in loader.ext:
110                    if ext not in self.loaders:
111                        self.loaders[ext] = []
112                    self.loaders[ext].insert(0,loader.read)
113                    reader_found = True
114                     
115                # Check whether writing is supported
116                if hasattr(loader, 'write'):
117                    for ext in loader.ext:
118                        if ext not in self.writers:
119                            self.writers[ext] = []
120                        self.writers[ext].insert(0,loader.write)
121            except:
122                logging.error("Loader: Error accessing Reader in %s\n  %s" % (name, sys.exc_value))
123        return reader_found
[d22da51]124
[daa56d0]125    def lookup_writers(self, path):
126        """
127        Return the loader associated with the file type of path.
128       
129        Raises ValueError if file type is not known.
130        """       
131        # Find matching extensions
132        extlist = [ext for ext in self.extensions() if path.endswith(ext)]
133        # Sort matching extensions by decreasing order of length
134        extlist.sort(lambda a,b: len(a)<len(b))
135        # Combine loaders for matching extensions into one big list
136        writers = []
137        for L in [self.writers[ext] for ext in extlist]:
138            writers.extend(L)
139        # Remove duplicates if they exist
140        if len(writers) != len(set(writers)):
141            result = []
142            for L in writers:
143                if L not in result: result.append(L)
144            writers = L
145        # Raise an error if there are no matching extensions
146        if len(writers) == 0:
147            raise ValueError, "Unknown file type for "+path
148        # All done
149        return writers
150
151    def save(self, path, data, format=None):
152        """
153        Call the writer for the file type of path.
[d22da51]154
[daa56d0]155        Raises ValueError if no writer is available.
156        Raises KeyError if format is not available.
157        May raise a writer-defined exception if writer fails.       
158        """
159        if format is None:
160            writers = self.lookup_writers(path)
161        else:
162            writers = self.writers[format]
163        for fn in writers:
164            try:
165                return fn(path, data)
166            except:
167                pass # give other loaders a chance to succeed
168        # If we get here it is because all loaders failed
169        raise # reraises last exception
170
171       
[1b0b3ca]172class Loader(object):
[d22da51]173    """
[daa56d0]174        Utility class to use the Registry as a singleton.
[d22da51]175    """
[daa56d0]176    ## Registry instance
177    __registry = Registry()
178   
179    def load(self, file, format=None):
180        """
181            Load a file
182           
183            @param file: file name (path)
184            @param format: specified format to use (optional)
185            @return: DataInfo object
186        """
187        return self.__registry.load(file, format)
[d22da51]188   
[daa56d0]189    def save(self, file, data, format):
190        """
191            Save a DataInfo object to file
192            @param file: file name (path)
193            @param data: DataInfo object
194            @param format: format to write the data in
195        """
196        return self.__registry.save(file, data, format)
197       
198    def _get_registry_creation_time(self):
199        """
200            Internal method used to test the uniqueness
201            of the registry object
202        """
203        return self.__registry._created
[d22da51]204   
[daa56d0]205    def find_plugins(self, dir):
206        """
207            Find plugins in a given directory
208            @param dir: directory to look into to find new readers/writers
209        """
210        return self.__registry.find_plugins(dir)
[a916ccc]211   
212       
[daa56d0]213if __name__ == "__main__": 
214    logging.basicConfig(level=logging.INFO,
215                        format='%(asctime)s %(levelname)s %(message)s',
216                        filename='loader.log',
217                        filemode='w')
218    l = Loader()
219    data = l.load('test/cansas1d.xml')
220    l.save('test_file.xml', data)
[a916ccc]221       
222       
[daa56d0]223   
Note: See TracBrowser for help on using the repository browser.