source: sasview/DataLoader/loader.py @ 03da8ed

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 03da8ed was 4e367f6, checked in by ajj, 14 years ago

Fixing error in plugin path finding.

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