source: sasview/DataLoader/loader.py @ cf9b6950

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 cf9b6950 was a7a5886, checked in by Gervaise Alina <gervyh@…>, 14 years ago

working pylint

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