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