source: sasview/DataLoader/loader.py @ d292959

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 d292959 was bbc8013, checked in by Mathieu Doucet <doucetm@…>, 16 years ago

Modify the way default readers are loaded.

  • Property mode set to 100644
File size: 8.8 KB
Line 
1"""
2    File handler to support different file extensions.
3    Uses reflectometry's registry utility.
4   
5    The default readers are found in the 'readers' sub-module
6    and registered by default at initialization time.
7   
8    To add a new default reader, one must register it in
9    the register_readers method found in readers/__init__.py.
10   
11    A utility method (find_plugins) is available to inspect
12    a directory (for instance, a user plug-in directory) and
13    look for new readers/writers.
14"""
15
16"""
17This software was developed by the University of Tennessee as part of the
18Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
19project funded by the US National Science Foundation.
20
21See the license text in license.txt
22
23copyright 2008, University of Tennessee
24"""
25
26from data_util.registry import ExtensionRegistry
27import os 
28import sys
29import logging
30import time
31from zipfile import ZipFile
32
33# Default readers are defined in the readers sub-module
34import readers
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.register_readers(self._identify_plugin)
56       
57    def find_plugins(self, dir):
58        """
59            Find readers in a given directory. This method
60            can be used to inspect user plug-in directories to
61            find new readers/writers.
62           
63            @param dir: directory to search into
64            @return: number of readers found
65        """
66        readers_found = 0
67       
68        # Check whether the directory exists
69        if not os.path.isdir(dir): 
70            logging.warning("DataLoader couldn't load from %s" % dir)
71            return readers_found
72       
73        for item in os.listdir(dir):
74            full_path = os.path.join(dir, item)
75            if os.path.isfile(full_path):
76               
77                # Process python files
78                if item.endswith('.py'):
79                    toks = os.path.splitext(os.path.basename(item))
80                    try:
81                        sys.path.insert(0, os.path.abspath(dir))
82                        module = __import__(toks[0], globals(), locals())
83                        if self._identify_plugin(module):
84                            readers_found += 1
85                    except :
86                        logging.error("Loader: Error importing %s\n  %s" % (item, sys.exc_value))
87                           
88                # Process zip files
89                elif item.endswith('.zip'):
90                    try:
91                        # Find the modules in the zip file
92                        zfile = ZipFile(item)
93                        nlist = zfile.namelist()
94                       
95                        sys.path.insert(0, item)
96                        for mfile in nlist:
97                            try:
98                                # Change OS path to python path
99                                fullname = mfile.replace('/', '.')
100                                fullname = os.path.splitext(fullname)[0]
101                                module = __import__(fullname, globals(), locals(), [""])
102                                if self._identify_plugin(module):
103                                    readers_found += 1
104                            except:
105                                logging.error("Loader: Error importing %s\n  %s" % (mfile, sys.exc_value))
106                           
107                    except:
108                        logging.error("Loader: Error importing %s\n  %s" % (item, sys.exc_value))
109                     
110        return readers_found
111   
112    def _identify_plugin(self, module):
113        """
114            Look into a module to find whether it contains a
115            Reader class. If so, add it to readers and (potentially)
116            to the list of writers.
117            @param module: module object
118        """
119        reader_found = False
120       
121        if hasattr(module, "Reader"):
122            try:
123                # Find supported extensions
124                loader = module.Reader()
125                for ext in loader.ext:
126                    if ext not in self.loaders:
127                        self.loaders[ext] = []
128                    self.loaders[ext].insert(0,loader.read)
129                    reader_found = True
130                       
131                    # Keep track of wildcards
132                    for wcard in loader.type:
133                        if wcard not in self.wildcards:
134                            self.wildcards.append(wcard)
135                           
136                # Check whether writing is supported
137                if hasattr(loader, 'write'):
138                    for ext in loader.ext:
139                        if ext not in self.writers:
140                            self.writers[ext] = []
141                        self.writers[ext].insert(0,loader.write)
142            except:
143                logging.error("Loader: Error accessing Reader in %s\n  %s" % (name, sys.exc_value))
144        return reader_found
145
146    def lookup_writers(self, path):
147        """
148        Return the loader associated with the file type of path.
149       
150        Raises ValueError if file type is not known.
151        """       
152        # Find matching extensions
153        extlist = [ext for ext in self.extensions() if path.endswith(ext)]
154        # Sort matching extensions by decreasing order of length
155        extlist.sort(lambda a,b: len(a)<len(b))
156        # Combine loaders for matching extensions into one big list
157        writers = []
158        for L in [self.writers[ext] for ext in extlist]:
159            writers.extend(L)
160        # Remove duplicates if they exist
161        if len(writers) != len(set(writers)):
162            result = []
163            for L in writers:
164                if L not in result: result.append(L)
165            writers = L
166        # Raise an error if there are no matching extensions
167        if len(writers) == 0:
168            raise ValueError, "Unknown file type for "+path
169        # All done
170        return writers
171
172    def save(self, path, data, format=None):
173        """
174        Call the writer for the file type of path.
175
176        Raises ValueError if no writer is available.
177        Raises KeyError if format is not available.
178        May raise a writer-defined exception if writer fails.       
179        """
180        if format is None:
181            writers = self.lookup_writers(path)
182        else:
183            writers = self.writers[format]
184        for fn in writers:
185            try:
186                return fn(path, data)
187            except:
188                pass # give other loaders a chance to succeed
189        # If we get here it is because all loaders failed
190        raise # reraises last exception
191
192       
193class Loader(object):
194    """
195        Utility class to use the Registry as a singleton.
196    """
197    ## Registry instance
198    __registry = Registry()
199   
200    def load(self, file, format=None):
201        """
202            Load a file
203           
204            @param file: file name (path)
205            @param format: specified format to use (optional)
206            @return: DataInfo object
207        """
208        return self.__registry.load(file, format)
209   
210    def save(self, file, data, format):
211        """
212            Save a DataInfo object to file
213            @param file: file name (path)
214            @param data: DataInfo object
215            @param format: format to write the data in
216        """
217        return self.__registry.save(file, data, format)
218       
219    def _get_registry_creation_time(self):
220        """
221            Internal method used to test the uniqueness
222            of the registry object
223        """
224        return self.__registry._created
225   
226    def find_plugins(self, dir):
227        """
228            Find plugins in a given directory
229            @param dir: directory to look into to find new readers/writers
230        """
231        return self.__registry.find_plugins(dir)
232   
233    def get_wildcards(self):
234        return self.__registry.wildcards
235       
236if __name__ == "__main__": 
237    logging.basicConfig(level=logging.INFO,
238                        format='%(asctime)s %(levelname)s %(message)s',
239                        filename='loader.log',
240                        filemode='w')
241    l = Loader()
242    data = l.load('test/cansas1d.xml')
243    l.save('test_file.xml', data, '.xml')
244   
245    print l.get_wildcards()
246       
247       
248   
Note: See TracBrowser for help on using the repository browser.