1 | # This program is public domain |
---|
2 | """ |
---|
3 | @organization: Module loader contains class Loader which uses |
---|
4 | some readers to return values contained in a file readed. |
---|
5 | |
---|
6 | """ |
---|
7 | import imp,os,sys |
---|
8 | import logging |
---|
9 | import os.path |
---|
10 | logging.basicConfig(level=logging.ERROR, |
---|
11 | format='%(asctime)s %(levelname)s %(message)s', |
---|
12 | filename='test_log.txt', |
---|
13 | filemode='w') |
---|
14 | |
---|
15 | def _findReaders(dir): |
---|
16 | # List of plugin objects |
---|
17 | plugins = [] |
---|
18 | # Go through files in plug-in directory |
---|
19 | try: |
---|
20 | |
---|
21 | list = os.listdir(dir) |
---|
22 | for item in list: |
---|
23 | |
---|
24 | toks = os.path.splitext(os.path.basename(item)) |
---|
25 | if toks[1]=='.py' and not toks[0]=='__init__': |
---|
26 | name = toks[0] |
---|
27 | path = [os.path.abspath(dir)] |
---|
28 | file = None |
---|
29 | try: |
---|
30 | (file, path, info) = imp.find_module(name, path) |
---|
31 | module = imp.load_module( name, file, item, info ) |
---|
32 | if hasattr(module, "Reader"): |
---|
33 | try: |
---|
34 | plugins.append(module.Reader()) |
---|
35 | except: |
---|
36 | logging.error("Error accessing Reader in %s\n %s" % (name, sys.exc_value)) |
---|
37 | except : |
---|
38 | logging.error("Error importing %s\n %s" % (name, sys.exc_value)) |
---|
39 | finally: |
---|
40 | if not file==None: |
---|
41 | file.close() |
---|
42 | except: |
---|
43 | # Should raise and catch at a higher level and display error on status bar |
---|
44 | pass |
---|
45 | return plugins |
---|
46 | |
---|
47 | |
---|
48 | class Loader(object): |
---|
49 | """ |
---|
50 | Loader class extracts data from a given file. |
---|
51 | This provides routines for opening files based on extension, |
---|
52 | and readers built-in file extensions. |
---|
53 | It uses functionalities for class Load |
---|
54 | @note: For loader to operate properly each readers used should |
---|
55 | contain a class name "Reader" that contains a field call ext. |
---|
56 | Can be used as follow: |
---|
57 | L=Loader() |
---|
58 | self.assertEqual(l.__contains__('.tiff'),True) |
---|
59 | #Recieves data |
---|
60 | data=L.load(path) |
---|
61 | """ |
---|
62 | #Store instance of class Load |
---|
63 | __load = None |
---|
64 | |
---|
65 | |
---|
66 | class Load(object): |
---|
67 | |
---|
68 | def __init__(self): |
---|
69 | #Dictionary containing readers and extension as keys |
---|
70 | self.readers = {} |
---|
71 | #Load all readers in plugins |
---|
72 | self.__setitem__() |
---|
73 | |
---|
74 | |
---|
75 | def __setitem__(self,dir=None, ext=None, reader=None): |
---|
76 | """ |
---|
77 | __setitem__ sets in a dictionary(self.readers) a given reader |
---|
78 | with a file extension that it can read. |
---|
79 | @param ext: extension given of type string |
---|
80 | @param reader:instance Reader class |
---|
81 | @param dir: directory name where plugins readers will be saved |
---|
82 | @raise : ValueError will be raise if a "plugins" directory is not found |
---|
83 | and the user didn't add a reader as parameter or if the user didn't |
---|
84 | add a reader as a parameter and plugins directory doesn't contain |
---|
85 | plugin reader. |
---|
86 | if an extension is not specified and a reader does not contain a field |
---|
87 | ext , a warning is printed in test_log.txt file. |
---|
88 | @note: when called without parameters __setitem__ will try to load |
---|
89 | readers inside a "readers" directory |
---|
90 | if call with a directory name will try find readers |
---|
91 | from that directory "dir" |
---|
92 | """ |
---|
93 | if dir==None: |
---|
94 | dir = 'readers' |
---|
95 | dir=os.path.join(os.path.dirname(os.path.abspath(__file__)),dir) |
---|
96 | |
---|
97 | if (reader==None and ext==None) or dir:#1st load |
---|
98 | plugReader=None |
---|
99 | if os.path.isdir(dir): |
---|
100 | plugReader=_findReaders(dir)# import all module in plugins |
---|
101 | if os.path.isdir('../'+dir): |
---|
102 | plugReader=_findReaders('../'+dir) |
---|
103 | |
---|
104 | |
---|
105 | if plugReader !=None: |
---|
106 | list=[] |
---|
107 | for preader in plugReader:# for each modules takes list of extensions |
---|
108 | try: |
---|
109 | list=preader.ext |
---|
110 | except AttributeError,msg: |
---|
111 | logging.warning(msg) |
---|
112 | pass |
---|
113 | #raise AttributeError," %s instance has no attribute 'ext'"\ |
---|
114 | #%(preader.__class__) |
---|
115 | if list !=[]: |
---|
116 | for item in list: |
---|
117 | ext=item |
---|
118 | if ext not in self.readers:#assign extension with its reader |
---|
119 | self.readers[ext] = [] |
---|
120 | self.readers[ext].insert(0,preader) |
---|
121 | #Reader and extension are given |
---|
122 | elif reader !=None and ext !=None: |
---|
123 | if ext not in self.readers: |
---|
124 | self.readers[ext] = [] |
---|
125 | self.readers[ext].insert(0,reader) |
---|
126 | elif reader!=None: |
---|
127 | #only reader is receive try to find a field ext |
---|
128 | try: |
---|
129 | list=preader.ext |
---|
130 | except: |
---|
131 | raise AttributeError," Reader instance has no attribute 'ext'" |
---|
132 | for item in list: |
---|
133 | |
---|
134 | ext=item |
---|
135 | if ext not in self.readers:#assign extension with its reader |
---|
136 | self.readers[ext] = [] |
---|
137 | self.readers[ext].insert(0,reader) |
---|
138 | |
---|
139 | else: |
---|
140 | raise ValueError,"missing reader" |
---|
141 | |
---|
142 | |
---|
143 | def __getitem__(self, ext): |
---|
144 | """ |
---|
145 | __getitem__ get a list of readers that can read a file with that extension |
---|
146 | @param ext: file extension |
---|
147 | @return self.readers[ext]:list of readers that can read a file |
---|
148 | with that extension |
---|
149 | """ |
---|
150 | return self.readers[ext] |
---|
151 | |
---|
152 | def __contains__(self, ext): |
---|
153 | """ |
---|
154 | @param ext:file extension |
---|
155 | @return: True or False whether there is a reader file with that extension |
---|
156 | """ |
---|
157 | return ext in self.readers |
---|
158 | |
---|
159 | |
---|
160 | def formats(self, name=True, ext=False): |
---|
161 | """ |
---|
162 | Return a list of the registered formats. If name=True then |
---|
163 | named formats are returned. If ext=True then extensions |
---|
164 | are returned. |
---|
165 | """ |
---|
166 | names = [a for a in self.readers.keys() if not a.startswith('.')] |
---|
167 | exts = [a for a in self.readers.keys() if a.startswith('.')] |
---|
168 | names.sort() |
---|
169 | exts.sort() |
---|
170 | ret = [] |
---|
171 | if name: ret += names |
---|
172 | if ext: ret += exts |
---|
173 | return ret |
---|
174 | |
---|
175 | def lookup(self, path): |
---|
176 | """ |
---|
177 | Return the loader associated with the file type of path. |
---|
178 | """ |
---|
179 | file = os.path.basename(path) |
---|
180 | idx = file.find('.') |
---|
181 | ext = file[idx:] if idx >= 0 else '' |
---|
182 | |
---|
183 | try: |
---|
184 | return self.readers[ext] |
---|
185 | except: |
---|
186 | logging.warning("Unknown file type '%s'"%ext) |
---|
187 | raise RuntimeError, "Unknown file type '%s'"%ext |
---|
188 | |
---|
189 | |
---|
190 | |
---|
191 | def load(self, path, format=None): |
---|
192 | """ |
---|
193 | Call reader for the file type of path. |
---|
194 | @param path: path to file to load |
---|
195 | @param format: extension of file to load |
---|
196 | @return Data if sucessful |
---|
197 | or None is not reader was able to read that file |
---|
198 | Raises ValueError if no reader is available. |
---|
199 | May raise a loader-defined exception if loader fails. |
---|
200 | """ |
---|
201 | try: |
---|
202 | os.path.isfile( os.path.abspath(path)) |
---|
203 | except: |
---|
204 | raise ValueError," file path unknown" |
---|
205 | |
---|
206 | if format is None: |
---|
207 | try: |
---|
208 | readers = self.lookup(path) |
---|
209 | except ValueError,msg: |
---|
210 | raise ValueError,str(msg) |
---|
211 | else: |
---|
212 | readers = self.readers[format] |
---|
213 | if readers!=None: |
---|
214 | for fn in readers: |
---|
215 | try: |
---|
216 | value=fn.read(path) |
---|
217 | return value |
---|
218 | except ValueError,msg: |
---|
219 | logging.error(str(msg)) |
---|
220 | else: |
---|
221 | raise ValueError,"Loader contains no reader" |
---|
222 | |
---|
223 | |
---|
224 | def __init__(self): |
---|
225 | """ Create singleton instance """ |
---|
226 | # Check whether we already have an instance |
---|
227 | if Loader.__load is None: |
---|
228 | # Create and remember instance |
---|
229 | Loader.__load = Loader.Load() |
---|
230 | Loader.__load.__setitem__() |
---|
231 | # Store instance reference as the only member in the handle |
---|
232 | self.__dict__['_Loader__load'] = Loader.__load |
---|
233 | |
---|
234 | def __getattr__(self, attr): |
---|
235 | """ Delegate access to implementation """ |
---|
236 | return getattr(self.__load, attr) |
---|
237 | |
---|
238 | def __setattr__(self, attr, value): |
---|
239 | """ Delegate access to implementation """ |
---|
240 | return setattr(self.__load, attr, value) |
---|