source: sasview/DataLoader/loader.py @ 80a6775

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 80a6775 was 480ddb4, checked in by Gervaise Alina <gervyh@…>, 14 years ago

working on documentation

  • Property mode set to 100644
File size: 13.5 KB
Line 
1
2#####################################################################
3#This software was developed by the University of Tennessee as part of the
4#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
5#project funded by the US National Science Foundation.
6#See the license text in license.txt
7#copyright 2008, University of Tennessee
8######################################################################
9
10"""
11    File handler to support different file extensions.
12    Uses reflectometry's registry utility.
13   
14    The default readers are found in the 'readers' sub-module
15    and registered by default at initialization time.
16   
17    To add a new default reader, one must register it in
18    the register_readers method found in readers/__init__.py.
19   
20    A utility method (find_plugins) is available to inspect
21    a directory (for instance, a user plug-in directory) and
22    look for new readers/writers.
23"""
24
25from data_util.registry import ExtensionRegistry
26import os 
27import sys
28import logging
29import time
30from zipfile import ZipFile
31
32# Default readers are defined in the readers sub-module
33import readers
34from readers import ascii_reader
35
36class Registry(ExtensionRegistry):
37    """
38    Registry class for file format extensions.
39    Readers and writers are supported.
40    """
41   
42    def __init__(self):
43        super(Registry, self).__init__()
44       
45        ## Writers
46        self.writers = {}
47       
48        ## List of wildcards
49        self.wildcards = ['All (*.*)|*.*']
50       
51        ## Creation time, for testing
52        self._created = time.time()
53       
54        # Register default readers
55        readers.read_associations(self)
56       
57        #TODO: remove the following line when ready to switch to the new default readers
58        #readers.register_readers(self._identify_plugin)
59       
60        # Look for plug-in readers
61        self.find_plugins('plugins')
62
63       
64    def load(self, path, format=None):
65        """
66        Call the loader for the file type of path.
67
68        :param path: file path
69        :param format: explicit extension, to force the use of a particular reader
70
71        Defaults to the ascii (multi-column) reader
72        if no reader was registered for the file's
73        extension.   
74        """
75        try:
76            return super(Registry, self).load(path, format=format)
77        except:
78            raise
79            # No reader was found. Default to the ascii reader.
80            #ascii_loader = ascii_reader.Reader()
81            #return ascii_loader.read(path)
82       
83    def find_plugins(self, dir):
84        """
85        Find readers in a given directory. This method
86        can be used to inspect user plug-in directories to
87        find new readers/writers.
88       
89        :param dir: directory to search into
90       
91        :return: number of readers found
92        """
93        readers_found = 0
94       
95        # Check whether the directory exists
96        if not os.path.isdir(dir): 
97            logging.warning("DataLoader couldn't load from %s" % dir)
98            return readers_found
99       
100        for item in os.listdir(dir):
101            full_path = os.path.join(dir, item)
102            if os.path.isfile(full_path):
103               
104                # Process python files
105                if item.endswith('.py'):
106                    toks = os.path.splitext(os.path.basename(item))
107                    try:
108                        sys.path.insert(0, os.path.abspath(dir))
109                        module = __import__(toks[0], globals(), locals())
110                        if self._identify_plugin(module):
111                            readers_found += 1
112                    except :
113                        logging.error("Loader: Error importing %s\n  %s" % (item, sys.exc_value))
114                           
115                # Process zip files
116                elif item.endswith('.zip'):
117                    try:
118                        # Find the modules in the zip file
119                        zfile = ZipFile(item)
120                        nlist = zfile.namelist()
121                       
122                        sys.path.insert(0, item)
123                        for mfile in nlist:
124                            try:
125                                # Change OS path to python path
126                                fullname = mfile.replace('/', '.')
127                                fullname = os.path.splitext(fullname)[0]
128                                module = __import__(fullname, globals(), locals(), [""])
129                                if self._identify_plugin(module):
130                                    readers_found += 1
131                            except:
132                                logging.error("Loader: Error importing %s\n  %s" % (mfile, sys.exc_value))
133                           
134                    except:
135                        logging.error("Loader: Error importing %s\n  %s" % (item, sys.exc_value))
136                     
137        return readers_found
138   
139    def associate_file_type(self, ext, module):
140        """
141        Look into a module to find whether it contains a
142        Reader class. If so, APPEND it to readers and (potentially)
143        to the list of writers for the given extension
144       
145        :param ext: file extension [string]
146        :param module: module object
147        """
148        reader_found = False
149       
150        if hasattr(module, "Reader"):
151            try:
152                # Find supported extensions
153                loader = module.Reader()
154                if ext not in self.loaders:
155                    self.loaders[ext] = []
156                # Append the new reader to the list
157                self.loaders[ext].append(loader.read)
158
159                reader_found = True
160               
161                # Keep track of wildcards
162                type_name = module.__name__
163                if hasattr(loader, 'type_name'):
164                    type_name = loader.type_name
165                   
166                wcard = "%s files (*%s)|*%s" % (type_name, ext.lower(), ext.lower())
167                if wcard not in self.wildcards:
168                    self.wildcards.append(wcard)
169                           
170                # Check whether writing is supported
171                if hasattr(loader, 'write'):
172                    if ext not in self.writers:
173                        self.writers[ext] = []
174                    # Append the new writer to the list
175                    self.writers[ext].append(loader.write)
176                       
177            except:
178                logging.error("Loader: Error accessing Reader in %s\n  %s" % (module.__name__, sys.exc_value))
179        return reader_found
180
181    def associate_file_reader(self, ext, loader):
182        """
183        Append a reader object to readers
184       
185        :param ext: file extension [string]
186        :param module: reader object
187        """
188        reader_found = False
189       
190        try:
191            # Find supported extensions
192            if ext not in self.loaders:
193                self.loaders[ext] = []
194            # Append the new reader to the list
195            self.loaders[ext].append(loader.read)
196
197            reader_found = True
198           
199            # Keep track of wildcards
200            if hasattr(loader, 'type_name'):
201                type_name = loader.type_name
202               
203                wcard = "%s files (*%s)|*%s" % (type_name, ext.lower(), ext.lower())
204                if wcard not in self.wildcards:
205                    self.wildcards.append(wcard)
206                 
207        except:
208            logging.error("Loader: Error accessing Reader in %s\n  %s" % (module.__name__, sys.exc_value))
209        return reader_found
210
211   
212    def _identify_plugin(self, module):
213        """
214        Look into a module to find whether it contains a
215        Reader class. If so, add it to readers and (potentially)
216        to the list of writers.
217        :param module: module object
218       
219        """
220        reader_found = False
221       
222        if hasattr(module, "Reader"):
223            try:
224                # Find supported extensions
225                loader = module.Reader()
226                for ext in loader.ext:
227                    if ext not in self.loaders:
228                        self.loaders[ext] = []
229                    # When finding a reader at run time, treat this reader as the new
230                    # default
231                    self.loaders[ext].insert(0,loader.read)
232
233                    reader_found = True
234                   
235                    # Keep track of wildcards
236                    type_name = module.__name__
237                    if hasattr(loader, 'type_name'):
238                        type_name = loader.type_name
239                    wcard = "%s files (*%s)|*%s" % (type_name, ext.lower(), ext.lower())
240                    if wcard not in self.wildcards:
241                        self.wildcards.append(wcard)
242                           
243                # Check whether writing is supported
244                if hasattr(loader, 'write'):
245                    for ext in loader.ext:
246                        if ext not in self.writers:
247                            self.writers[ext] = []
248                        self.writers[ext].insert(0,loader.write)
249                       
250            except:
251                logging.error("Loader: Error accessing Reader in %s\n  %s" % (module.__name__, sys.exc_value))
252        return reader_found
253
254    def lookup_writers(self, path):
255        """
256        :return: the loader associated with the file type of path.
257       
258        :Raises ValueError: if file type is not known.
259        """       
260        # Find matching extensions
261        extlist = [ext for ext in self.extensions() if path.endswith(ext)]
262        # Sort matching extensions by decreasing order of length
263        extlist.sort(lambda a,b: len(a)<len(b))
264        # Combine loaders for matching extensions into one big list
265        writers = []
266        for L in [self.writers[ext] for ext in extlist]:
267            writers.extend(L)
268        # Remove duplicates if they exist
269        if len(writers) != len(set(writers)):
270            result = []
271            for L in writers:
272                if L not in result: result.append(L)
273            writers = L
274        # Raise an error if there are no matching extensions
275        if len(writers) == 0:
276            raise ValueError, "Unknown file type for "+path
277        # All done
278        return writers
279
280    def save(self, path, data, format=None):
281        """
282        Call the writer for the file type of path.
283
284        Raises ValueError if no writer is available.
285        Raises KeyError if format is not available.
286       
287        May raise a writer-defined exception if writer fails.       
288        """
289        if format is None:
290            writers = self.lookup_writers(path)
291        else:
292            writers = self.writers[format]
293        for fn in writers:
294            try:
295                return fn(path, data)
296            except:
297                pass # give other loaders a chance to succeed
298        # If we get here it is because all loaders failed
299        raise # reraises last exception
300
301       
302class Loader(object):
303    """
304    Utility class to use the Registry as a singleton.
305    """
306    ## Registry instance
307    __registry = Registry()
308   
309    def associate_file_type(self, ext, module):
310        """
311        Look into a module to find whether it contains a
312        Reader class. If so, append it to readers and (potentially)
313        to the list of writers for the given extension
314       
315        :param ext: file extension [string]
316        :param module: module object
317        """
318        return self.__registry.associate_file_type(ext, module)
319
320    def associate_file_reader(self, ext, loader):
321        """
322        Append a reader object to readers
323       
324        :param ext: file extension [string]
325        :param module: reader object
326        """
327        return self.__registry.associate_file_reader(ext, loader)
328
329    def load(self, file, format=None):
330        """
331        Load a file
332       
333        :param file: file name (path)
334        :param format: specified format to use (optional)
335        :return: DataInfo object
336        """
337        return self.__registry.load(file, format)
338   
339    def save(self, file, data, format):
340        """
341        Save a DataInfo object to file
342        :param file: file name (path)
343        :param data: DataInfo object
344        :param format: format to write the data in
345        """
346        return self.__registry.save(file, data, format)
347       
348    def _get_registry_creation_time(self):
349        """
350        Internal method used to test the uniqueness
351        of the registry object
352        """
353        return self.__registry._created
354   
355    def find_plugins(self, dir):
356        """
357        Find plugins in a given directory
358       
359        :param dir: directory to look into to find new readers/writers
360        """
361        return self.__registry.find_plugins(dir)
362   
363    def get_wildcards(self):
364        return self.__registry.wildcards
365       
366if __name__ == "__main__": 
367    logging.basicConfig(level=logging.INFO,
368                        format='%(asctime)s %(levelname)s %(message)s',
369                        filename='loader.log',
370                        filemode='w')
371    l = Loader()
372    data = l.load('test/cansas1d.xml')
373    l.save('test_file.xml', data, '.xml')
374   
375    print l.get_wildcards()
376       
377       
378   
Note: See TracBrowser for help on using the repository browser.