source: sasview/src/sas/sascalc/data_util/registry.py

ESS_GUI
Last change on this file was 8db20a9, checked in by Piotr Rozyczko <piotr.rozyczko@…>, 6 years ago

Updated cansas read (cherrypicked and fixed from master).
Fixes: hdf5 returns byte strings so these need to be recasted properly.
https://github.com/h5py/h5py/issues/379

  • Property mode set to 100644
File size: 4.6 KB
Line 
1"""
2File extension registry.
3
4This provides routines for opening files based on extension,
5and registers the built-in file extensions.
6"""
7from __future__ import print_function
8
9from sas.sascalc.dataloader.loader_exceptions import NoKnownLoaderException
10
11
12class ExtensionRegistry(object):
13    """
14    Associate a file loader with an extension.
15
16    Note that there may be multiple loaders for the same extension.
17
18    Example: ::
19
20        registry = ExtensionRegistry()
21
22        # Add an association by setting an element
23        registry['.zip'] = unzip
24
25        # Multiple extensions for one loader
26        registry['.tgz'] = untar
27        registry['.tar.gz'] = untar
28
29        # Generic extensions to use after trying more specific extensions;
30        # these will be checked after the more specific extensions fail.
31        registry['.gz'] = gunzip
32
33        # Multiple loaders for one extension
34        registry['.cx'] = cx1
35        registry['.cx'] = cx2
36        registry['.cx'] = cx3
37
38        # Show registered extensions
39        print registry.extensions()
40
41        # Can also register a format name for explicit control from caller
42        registry['cx3'] = cx3
43        print registry.formats()
44
45        # Retrieve loaders for a file name
46        registry.lookup('hello.cx') -> [cx3,cx2,cx1]
47
48        # Run loader on a filename
49        registry.load('hello.cx') ->
50            try:
51                return cx3('hello.cx')
52            except:
53                try:
54                    return cx2('hello.cx')
55                except:
56                    return cx1('hello.cx')
57
58        # Load in a specific format ignoring extension
59        registry.load('hello.cx',format='cx3') ->
60            return cx3('hello.cx')
61    """
62    def __init__(self, **kw):
63        self.loaders = {}
64
65    def __setitem__(self, ext, loader):
66        if ext not in self.loaders:
67            self.loaders[ext] = []
68        self.loaders[ext].insert(0,loader)
69
70    def __getitem__(self, ext):
71        return self.loaders[ext]
72
73    def __contains__(self, ext):
74        return ext in self.loaders
75
76    def formats(self):
77        """
78        Return a sorted list of the registered formats.
79        """
80        names = [a for a in self.loaders.keys() if not a.startswith('.')]
81        names.sort()
82        return names
83
84    def extensions(self):
85        """
86        Return a sorted list of registered extensions.
87        """
88        exts = [a for a in self.loaders.keys() if a.startswith('.')]
89        exts.sort()
90        return exts
91
92    def lookup(self, path):
93        """
94        Return the loader associated with the file type of path.
95
96        :param path: Data file path
97        :raises ValueError: When no loaders are found for the file.
98        :return: List of available readers for the file extension
99        """
100        # Find matching extensions
101        extlist = [ext for ext in self.extensions() if path.endswith(ext)]
102        # Sort matching extensions by decreasing order of length
103        extlist.sort(key=len)
104        # Combine loaders for matching extensions into one big list
105        loaders = []
106        for L in [self.loaders[ext] for ext in extlist]:
107            loaders.extend(L)
108        # Remove duplicates if they exist
109        if len(loaders) != len(set(loaders)):
110            result = []
111            for L in loaders:
112                if L not in result: result.append(L)
113            loaders = result
114            #loaders = L
115        # Raise an error if there are no matching extensions
116        if len(loaders) == 0:
117            raise ValueError("Unknown file type for "+path)
118        return loaders
119
120    def load(self, path, format=None):
121        """
122        Call the loader for the file type of path.
123
124        :raises ValueError: if no loader is available.
125        :raises KeyError: if format is not available.
126
127        May raise a loader-defined exception if loader fails.
128        """
129        loaders = []
130        if format is None:
131            try:
132                loaders = self.lookup(path)
133            except ValueError as e:
134                pass
135        else:
136            try:
137                loaders = self.loaders[format]
138            except KeyError as e:
139                pass
140        last_exc = None
141        for fn in loaders:
142            try:
143                return fn(path)
144            except Exception as e:
145                last_exc = e
146                pass  # give other loaders a chance to succeed
147        # If we get here it is because all loaders failed
148        if last_exc is not None and len(loaders) != 0:
149            # If file has associated loader(s) and they;ve failed
150            raise last_exc
151        raise NoKnownLoaderException(e.message)  # raise generic exception
Note: See TracBrowser for help on using the repository browser.