source: sasview/src/sans/dataloader/loader.py @ 786685e

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 786685e was ffbe487, checked in by Mathieu Doucet <doucetm@…>, 11 years ago

Update loader imports for latest move

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