source: sasview/DataLoader/loader.py @ b94945d

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 b94945d was 0997158f, 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            # No reader was found. Default to the ascii reader.
79            ascii_loader = ascii_reader.Reader()
80            return ascii_loader.read(path)
81       
82    def find_plugins(self, dir):
83        """
84        Find readers in a given directory. This method
85        can be used to inspect user plug-in directories to
86        find new readers/writers.
87       
88        :param dir: directory to search into
89       
90        :return: number of readers found
91        """
92        readers_found = 0
93       
94        # Check whether the directory exists
95        if not os.path.isdir(dir): 
96            logging.warning("DataLoader couldn't load from %s" % dir)
97            return readers_found
98       
99        for item in os.listdir(dir):
100            full_path = os.path.join(dir, item)
101            if os.path.isfile(full_path):
102               
103                # Process python files
104                if item.endswith('.py'):
105                    toks = os.path.splitext(os.path.basename(item))
106                    try:
107                        sys.path.insert(0, os.path.abspath(dir))
108                        module = __import__(toks[0], globals(), locals())
109                        if self._identify_plugin(module):
110                            readers_found += 1
111                    except :
112                        logging.error("Loader: Error importing %s\n  %s" % (item, sys.exc_value))
113                           
114                # Process zip files
115                elif item.endswith('.zip'):
116                    try:
117                        # Find the modules in the zip file
118                        zfile = ZipFile(item)
119                        nlist = zfile.namelist()
120                       
121                        sys.path.insert(0, item)
122                        for mfile in nlist:
123                            try:
124                                # Change OS path to python path
125                                fullname = mfile.replace('/', '.')
126                                fullname = os.path.splitext(fullname)[0]
127                                module = __import__(fullname, globals(), locals(), [""])
128                                if self._identify_plugin(module):
129                                    readers_found += 1
130                            except:
131                                logging.error("Loader: Error importing %s\n  %s" % (mfile, sys.exc_value))
132                           
133                    except:
134                        logging.error("Loader: Error importing %s\n  %s" % (item, sys.exc_value))
135                     
136        return readers_found
137   
138    def associate_file_type(self, ext, module):
139        """
140        Look into a module to find whether it contains a
141        Reader class. If so, APPEND it to readers and (potentially)
142        to the list of writers for the given extension
143       
144        :param ext: file extension [string]
145        :param module: module object
146        """
147        reader_found = False
148       
149        if hasattr(module, "Reader"):
150            try:
151                # Find supported extensions
152                loader = module.Reader()
153                if ext not in self.loaders:
154                    self.loaders[ext] = []
155                # Append the new reader to the list
156                self.loaders[ext].append(loader.read)
157
158                reader_found = True
159               
160                # Keep track of wildcards
161                type_name = module.__name__
162                if hasattr(loader, 'type_name'):
163                    type_name = loader.type_name
164                   
165                wcard = "%s files (*%s)|*%s" % (type_name, ext.lower(), ext.lower())
166                if wcard not in self.wildcards:
167                    self.wildcards.append(wcard)
168                           
169                # Check whether writing is supported
170                if hasattr(loader, 'write'):
171                    if ext not in self.writers:
172                        self.writers[ext] = []
173                    # Append the new writer to the list
174                    self.writers[ext].append(loader.write)
175                       
176            except:
177                logging.error("Loader: Error accessing Reader in %s\n  %s" % (module.__name__, sys.exc_value))
178        return reader_found
179
180    def associate_file_reader(self, ext, loader):
181        """
182        Append a reader object to readers
183       
184        :param ext: file extension [string]
185        :param module: reader object
186        """
187        reader_found = False
188       
189        try:
190            # Find supported extensions
191            if ext not in self.loaders:
192                self.loaders[ext] = []
193            # Append the new reader to the list
194            self.loaders[ext].append(loader.read)
195
196            reader_found = True
197           
198            # Keep track of wildcards
199            if hasattr(loader, 'type_name'):
200                type_name = loader.type_name
201               
202                wcard = "%s files (*%s)|*%s" % (type_name, ext.lower(), ext.lower())
203                if wcard not in self.wildcards:
204                    self.wildcards.append(wcard)
205                 
206        except:
207            logging.error("Loader: Error accessing Reader in %s\n  %s" % (module.__name__, sys.exc_value))
208        return reader_found
209
210   
211    def _identify_plugin(self, module):
212        """
213        Look into a module to find whether it contains a
214        Reader class. If so, add it to readers and (potentially)
215        to the list of writers.
216        :param module: module object
217       
218        """
219        reader_found = False
220       
221        if hasattr(module, "Reader"):
222            try:
223                # Find supported extensions
224                loader = module.Reader()
225                for ext in loader.ext:
226                    if ext not in self.loaders:
227                        self.loaders[ext] = []
228                    # When finding a reader at run time, treat this reader as the new
229                    # default
230                    self.loaders[ext].insert(0,loader.read)
231
232                    reader_found = True
233                   
234                    # Keep track of wildcards
235                    type_name = module.__name__
236                    if hasattr(loader, 'type_name'):
237                        type_name = loader.type_name
238                    wcard = "%s files (*%s)|*%s" % (type_name, ext.lower(), ext.lower())
239                    if wcard not in self.wildcards:
240                        self.wildcards.append(wcard)
241                           
242                # Check whether writing is supported
243                if hasattr(loader, 'write'):
244                    for ext in loader.ext:
245                        if ext not in self.writers:
246                            self.writers[ext] = []
247                        self.writers[ext].insert(0,loader.write)
248                       
249            except:
250                logging.error("Loader: Error accessing Reader in %s\n  %s" % (module.__name__, sys.exc_value))
251        return reader_found
252
253    def lookup_writers(self, path):
254        """
255        :return: the loader associated with the file type of path.
256       
257        :Raises ValueError: if file type is not known.
258        """       
259        # Find matching extensions
260        extlist = [ext for ext in self.extensions() if path.endswith(ext)]
261        # Sort matching extensions by decreasing order of length
262        extlist.sort(lambda a,b: len(a)<len(b))
263        # Combine loaders for matching extensions into one big list
264        writers = []
265        for L in [self.writers[ext] for ext in extlist]:
266            writers.extend(L)
267        # Remove duplicates if they exist
268        if len(writers) != len(set(writers)):
269            result = []
270            for L in writers:
271                if L not in result: result.append(L)
272            writers = L
273        # Raise an error if there are no matching extensions
274        if len(writers) == 0:
275            raise ValueError, "Unknown file type for "+path
276        # All done
277        return writers
278
279    def save(self, path, data, format=None):
280        """
281        Call the writer for the file type of path.
282
283        Raises ValueError if no writer is available.
284        Raises KeyError if format is not available.
285       
286        May raise a writer-defined exception if writer fails.       
287        """
288        if format is None:
289            writers = self.lookup_writers(path)
290        else:
291            writers = self.writers[format]
292        for fn in writers:
293            try:
294                return fn(path, data)
295            except:
296                pass # give other loaders a chance to succeed
297        # If we get here it is because all loaders failed
298        raise # reraises last exception
299
300       
301class Loader(object):
302    """
303    Utility class to use the Registry as a singleton.
304    """
305    ## Registry instance
306    __registry = Registry()
307   
308    def associate_file_type(self, ext, module):
309        """
310        Look into a module to find whether it contains a
311        Reader class. If so, append it to readers and (potentially)
312        to the list of writers for the given extension
313       
314        :param ext: file extension [string]
315        :param module: module object
316        """
317        return self.__registry.associate_file_type(ext, module)
318
319    def associate_file_reader(self, ext, loader):
320        """
321        Append a reader object to readers
322       
323        :param ext: file extension [string]
324        :param module: reader object
325        """
326        return self.__registry.associate_file_reader(ext, loader)
327
328    def load(self, file, format=None):
329        """
330        Load a file
331       
332        :param file: file name (path)
333        :param format: specified format to use (optional)
334        :return: DataInfo object
335        """
336        return self.__registry.load(file, format)
337   
338    def save(self, file, data, format):
339        """
340        Save a DataInfo object to file
341        :param file: file name (path)
342        :param data: DataInfo object
343        :param format: format to write the data in
344        """
345        return self.__registry.save(file, data, format)
346       
347    def _get_registry_creation_time(self):
348        """
349        Internal method used to test the uniqueness
350        of the registry object
351        """
352        return self.__registry._created
353   
354    def find_plugins(self, dir):
355        """
356        Find plugins in a given directory
357       
358        :param dir: directory to look into to find new readers/writers
359        """
360        return self.__registry.find_plugins(dir)
361   
362    def get_wildcards(self):
363        return self.__registry.wildcards
364       
365if __name__ == "__main__": 
366    logging.basicConfig(level=logging.INFO,
367                        format='%(asctime)s %(levelname)s %(message)s',
368                        filename='loader.log',
369                        filemode='w')
370    l = Loader()
371    data = l.load('test/cansas1d.xml')
372    l.save('test_file.xml', data, '.xml')
373   
374    print l.get_wildcards()
375       
376       
377   
Note: See TracBrowser for help on using the repository browser.