source: sasview/src/sas/sascalc/data_util/registry.py @ 3ece5dd

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.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 3ece5dd was 3ece5dd, checked in by lewis, 7 years ago

Raise and catch correct exceptions in CanSAS XML reader

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