source: sasview/DataLoader/loader.py @ 126a761

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 126a761 was 1ed9c57, checked in by Mathieu Doucet <doucetm@…>, 16 years ago

Added wildcards list to data loader

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