16 <li>Python 3</li> |
16 <li>Python 3</li> |
17 <li>Ruby</li> |
17 <li>Ruby</li> |
18 </ul> |
18 </ul> |
19 """ |
19 """ |
20 |
20 |
21 # TODO: move the IDL and Protobuf class browsers to the plugins. |
|
22 |
|
23 import importlib |
21 import importlib |
24 import os |
22 import os |
25 |
23 |
26 from eric7 import Preferences |
24 from eric7 import Preferences |
|
25 |
|
26 # The class browser registry |
|
27 # Dictionary with class browser name as key. Each entry is a dictionary with |
|
28 # 0. 'Extensions': list of associated file extensions with leading dot |
|
29 # 1. 'ReadModule': function to read and parse a module file |
|
30 # 2. 'Scan': function to parse a given source text |
|
31 # 3. 'FileIcon': function to get an icon name for the file type |
|
32 ClassBrowserRegistry = {} |
27 |
33 |
28 PY_SOURCE = 1 |
34 PY_SOURCE = 1 |
29 PTL_SOURCE = 128 |
35 PTL_SOURCE = 128 |
30 RB_SOURCE = 129 |
36 RB_SOURCE = 129 |
31 IDL_SOURCE = 130 |
37 JS_SOURCE = 130 |
32 JS_SOURCE = 131 |
|
33 PROTO_SOURCE = 132 |
|
34 UNKNOWN_SOURCE = 255 |
38 UNKNOWN_SOURCE = 255 |
35 |
39 |
36 SUPPORTED_TYPES = [ |
40 SUPPORTED_TYPES = [ |
37 PY_SOURCE, |
41 PY_SOURCE, |
38 PTL_SOURCE, |
42 PTL_SOURCE, |
39 RB_SOURCE, |
43 RB_SOURCE, |
40 IDL_SOURCE, |
|
41 JS_SOURCE, |
44 JS_SOURCE, |
42 PROTO_SOURCE, |
|
43 ] |
45 ] |
44 |
46 |
45 __extensions = { |
47 __extensions = { |
46 "IDL": [".idl"], |
|
47 "Python": [".py", ".pyw", ".ptl"], # currently not used |
48 "Python": [".py", ".pyw", ".ptl"], # currently not used |
48 "Ruby": [".rb"], |
49 "Ruby": [".rb"], |
49 "JavaScript": [".js"], |
50 "JavaScript": [".js"], |
50 "ProtoBuf": [".proto"], |
|
51 } |
51 } |
|
52 |
|
53 |
|
54 def registerClassBrowser(name, readModuleFunc, scanFunc, iconFunc, extensions): |
|
55 """ |
|
56 Function to register a class browser type. |
|
57 |
|
58 @param name name of the class browser |
|
59 @type str |
|
60 @param readModuleFunc function to read and parse a file returning a dictionary |
|
61 with the parsing result |
|
62 @type function |
|
63 @param scanFunc function to scan a given source text returning a dictionary with |
|
64 the parsing result |
|
65 @type function |
|
66 @param iconFunc function returning an icon name for the supported files |
|
67 @type function |
|
68 @param extensions list of associated file extensions |
|
69 @type list of str |
|
70 @exception KeyError raised if the class browser to be registered is already |
|
71 """ |
|
72 global ClassBrowserRegistry |
|
73 |
|
74 if name in ClassBrowserRegistry: |
|
75 raise KeyError('Class Browser "{0}" already registered.'.format(name)) |
|
76 else: |
|
77 ClassBrowserRegistry[name] = { |
|
78 "ReadModule": readModuleFunc, |
|
79 "Scan": scanFunc, |
|
80 "FileIcon": iconFunc, |
|
81 "Extensions": extensions, |
|
82 } |
|
83 |
|
84 |
|
85 def unregisterClassBrowser(name): |
|
86 """ |
|
87 Function to unregister a class browser type. |
|
88 |
|
89 @param name name of the class browser |
|
90 @type str |
|
91 """ |
|
92 global ClassBrowserRegistry |
|
93 |
|
94 if name in ClassBrowserRegistry: |
|
95 del ClassBrowserRegistry[name] |
52 |
96 |
53 |
97 |
54 def getClassBrowserModule(moduleType): |
98 def getClassBrowserModule(moduleType): |
55 """ |
99 """ |
56 Function to import a class browser module. |
100 Function to import a class browser module. |
93 @rtype dict |
135 @rtype dict |
94 """ |
136 """ |
95 ext = os.path.splitext(module)[1].lower() |
137 ext = os.path.splitext(module)[1].lower() |
96 path = [] if path is None else path[:] |
138 path = [] if path is None else path[:] |
97 |
139 |
98 if ext in __extensions["IDL"]: |
140 if not isPyFile: |
99 moduleType = "idl" |
141 for classBrowserName in ClassBrowserRegistry: |
100 elif ext in __extensions["ProtoBuf"]: |
142 if ext in ClassBrowserRegistry[classBrowserName]["Extensions"]: |
101 moduleType = "protobuf" |
143 return ClassBrowserRegistry[classBrowserName]["ReadModule"]( |
102 elif ext in __extensions["Ruby"]: |
144 module, path |
|
145 ) |
|
146 |
|
147 if ext in __extensions["Ruby"]: |
103 moduleType = "ruby" |
148 moduleType = "ruby" |
104 elif ext in __extensions["JavaScript"]: |
149 elif ext in __extensions["JavaScript"]: |
105 moduleType = "javascript" |
150 moduleType = "javascript" |
106 elif ext in Preferences.getPython("Python3Extensions") or isPyFile: |
151 elif ext in Preferences.getPython("Python3Extensions") or isPyFile: |
107 moduleType = "python" |
152 moduleType = "python" |
108 else: |
153 else: |
109 # try Python if it is without extension |
154 # try Python if it is without extension |
110 moduleType = "python" |
155 moduleType = "python" |
111 |
156 |
112 classBrowserModule = getClassBrowserModule(moduleType) |
157 classBrowserModule = getClassBrowserModule(moduleType) |
113 if classBrowserModule: |
158 dictionary = ( |
114 dictionary = classBrowserModule.readmodule_ex(module, path, isTypeFile=isPyFile) |
159 classBrowserModule.readmodule_ex(module, path, isTypeFile=isPyFile) |
115 classBrowserModule.clearModulesCache() |
160 if classBrowserModule |
116 else: |
161 else {} |
117 dictionary = {} |
162 ) |
|
163 |
|
164 return dictionary |
|
165 |
|
166 |
|
167 def scan(src, filename, module, isPyFile=False): |
|
168 """ |
|
169 Function to scan the given source text. |
|
170 |
|
171 @param src source text to be scanned |
|
172 @type str |
|
173 @param filename file name associated with the source text |
|
174 @type str |
|
175 @param module module name associated with the source text |
|
176 @type str |
|
177 @param isPyFile flag indicating a Python file |
|
178 @type bool |
|
179 @return dictionary containing the extracted data |
|
180 @rtype dict |
|
181 """ |
|
182 ext = os.path.splitext(filename)[1] |
|
183 for classBrowserName in ClassBrowserRegistry: |
|
184 if ext in ClassBrowserRegistry[classBrowserName]["Extensions"]: |
|
185 return ClassBrowserRegistry[classBrowserName]["Scan"](src, filename, module) |
|
186 |
|
187 if ext in __extensions["Ruby"]: |
|
188 moduleType = "ruby" |
|
189 elif ext in __extensions["JavaScript"]: |
|
190 moduleType = "javascript" |
|
191 elif ext in Preferences.getPython("Python3Extensions") or isPyFile: |
|
192 moduleType = "python" |
|
193 else: |
|
194 # try Python if it is without extension |
|
195 moduleType = "python" |
|
196 |
|
197 classBrowserModule = getClassBrowserModule(moduleType) |
|
198 dictionary = ( |
|
199 classBrowserModule.scan(src, filename, module) if classBrowserModule else None |
|
200 ) |
118 |
201 |
119 return dictionary |
202 return dictionary |
120 |
203 |
121 |
204 |
122 def find_module(name, path, isPyFile=False): |
205 def find_module(name, path, isPyFile=False): |
141 """ |
224 """ |
142 ext = os.path.splitext(name)[1].lower() |
225 ext = os.path.splitext(name)[1].lower() |
143 |
226 |
144 if ext in __extensions["Ruby"]: |
227 if ext in __extensions["Ruby"]: |
145 sourceType = RB_SOURCE |
228 sourceType = RB_SOURCE |
146 elif ext in __extensions["IDL"]: |
|
147 sourceType = IDL_SOURCE |
|
148 elif ext in __extensions["ProtoBuf"]: |
|
149 sourceType = PROTO_SOURCE |
|
150 elif ext in __extensions["JavaScript"]: |
229 elif ext in __extensions["JavaScript"]: |
151 sourceType = JS_SOURCE |
230 sourceType = JS_SOURCE |
152 elif ext == ".ptl": |
231 elif ext == ".ptl": |
153 sourceType = PTL_SOURCE |
232 sourceType = PTL_SOURCE |
154 elif ( |
233 elif ( |
178 ext = os.path.splitext(spec.origin)[-1] |
257 ext = os.path.splitext(spec.origin)[-1] |
179 return (open(spec.origin), spec.origin, (ext, "r", PY_SOURCE)) |
258 return (open(spec.origin), spec.origin, (ext, "r", PY_SOURCE)) |
180 # __IGNORE_WARNING_Y115__ |
259 # __IGNORE_WARNING_Y115__ |
181 |
260 |
182 raise ImportError |
261 raise ImportError |
|
262 |
|
263 |
|
264 def getIcon(filename): |
|
265 """ |
|
266 Function to get an icon name for the given file (only for class browsers provided |
|
267 via plugins). |
|
268 |
|
269 @param filename name of the file |
|
270 @type str |
|
271 @return icon name |
|
272 @rtype str |
|
273 """ |
|
274 ext = os.path.splitext(filename)[1].lower() |
|
275 |
|
276 for classBrowserRegistryEntry in ClassBrowserRegistry.values(): |
|
277 if ext in classBrowserRegistryEntry["Extensions"]: |
|
278 return classBrowserRegistryEntry["FileIcon"](filename) |
|
279 |
|
280 return "fileMisc" |
|
281 |
|
282 |
|
283 def isSupportedType(fileext): |
|
284 """ |
|
285 Function to check, if the given file extension indicates a supported file type. |
|
286 |
|
287 @param fileext file extension |
|
288 @type str |
|
289 @return flag indicating a supported file type |
|
290 @rtype bool |
|
291 """ |
|
292 supported = any(fileext in exts for exts in __extensions.values()) |
|
293 supported |= any( |
|
294 fileext in cb["Extensions"] for cb in ClassBrowserRegistry.values() |
|
295 ) |
|
296 return supported |