|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2005 - 2022 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Package implementing class browsers for various languages. |
|
8 |
|
9 Currently it offers class browser support for the following |
|
10 programming languages. |
|
11 |
|
12 <ul> |
|
13 <li>CORBA IDL</li> |
|
14 <li>JavaScript</li> |
|
15 <li>ProtoBuf</li> |
|
16 <li>Python 3</li> |
|
17 <li>Ruby</li> |
|
18 </ul> |
|
19 """ |
|
20 |
|
21 import os |
|
22 import importlib |
|
23 |
|
24 import Preferences |
|
25 |
|
26 PY_SOURCE = 1 |
|
27 PTL_SOURCE = 128 |
|
28 RB_SOURCE = 129 |
|
29 IDL_SOURCE = 130 |
|
30 JS_SOURCE = 131 |
|
31 PROTO_SOURCE = 132 |
|
32 |
|
33 SUPPORTED_TYPES = [PY_SOURCE, PTL_SOURCE, RB_SOURCE, IDL_SOURCE, JS_SOURCE, |
|
34 PROTO_SOURCE] |
|
35 |
|
36 __extensions = { |
|
37 "IDL": [".idl"], |
|
38 "Python": [".py", ".pyw", ".ptl"], # currently not used |
|
39 "Ruby": [".rb"], |
|
40 "JavaScript": [".js"], |
|
41 "ProtoBuf": [".proto"], |
|
42 } |
|
43 |
|
44 |
|
45 def readmodule(module, path=None, isPyFile=False): |
|
46 """ |
|
47 Read a source file and return a dictionary of classes, functions, modules, |
|
48 etc. . |
|
49 |
|
50 The real work of parsing the source file is delegated to the individual |
|
51 file parsers. |
|
52 |
|
53 @param module name of the source file |
|
54 @type str |
|
55 @param path list of paths the file should be searched in |
|
56 @type list of str |
|
57 @param isPyFile flag indicating a Python file |
|
58 @type bool |
|
59 @return the resulting dictionary |
|
60 @rtype dict |
|
61 """ |
|
62 ext = os.path.splitext(module)[1].lower() |
|
63 path = [] if path is None else path[:] |
|
64 |
|
65 if ext in __extensions["IDL"]: |
|
66 from . import idlclbr |
|
67 dictionary = idlclbr.readmodule_ex(module, path) |
|
68 idlclbr._modules.clear() |
|
69 elif ext in __extensions["ProtoBuf"]: |
|
70 from . import protoclbr |
|
71 dictionary = protoclbr.readmodule_ex(module, path) |
|
72 protoclbr._modules.clear() |
|
73 elif ext in __extensions["Ruby"]: |
|
74 from . import rbclbr |
|
75 dictionary = rbclbr.readmodule_ex(module, path) |
|
76 rbclbr._modules.clear() |
|
77 elif ext in __extensions["JavaScript"]: |
|
78 from . import jsclbr |
|
79 dictionary = jsclbr.readmodule_ex(module, path) |
|
80 jsclbr._modules.clear() |
|
81 elif ( |
|
82 ext in Preferences.getPython("Python3Extensions") or |
|
83 isPyFile |
|
84 ): |
|
85 from . import pyclbr |
|
86 dictionary = pyclbr.readmodule_ex(module, path, isPyFile=isPyFile) |
|
87 pyclbr._modules.clear() |
|
88 else: |
|
89 # try Python if it is without extension |
|
90 from . import pyclbr |
|
91 dictionary = pyclbr.readmodule_ex(module, path) |
|
92 pyclbr._modules.clear() |
|
93 |
|
94 return dictionary |
|
95 |
|
96 |
|
97 def find_module(name, path, isPyFile=False): |
|
98 """ |
|
99 Module function to extend the Python module finding mechanism. |
|
100 |
|
101 This function searches for files in the given list of paths. If the |
|
102 file name doesn't have an extension or an extension of .py, the normal |
|
103 Python search implemented in the imp module is used. For all other |
|
104 supported files only the paths list is searched. |
|
105 |
|
106 @param name file name or module name to search for |
|
107 @type str |
|
108 @param path search paths |
|
109 @type list of str |
|
110 @param isPyFile flag indicating a Python file |
|
111 @type bool |
|
112 @return tuple of the open file, pathname and description. Description |
|
113 is a tuple of file suffix, file mode and file type) |
|
114 @rtype tuple |
|
115 @exception ImportError The file or module wasn't found. |
|
116 """ |
|
117 ext = os.path.splitext(name)[1].lower() |
|
118 |
|
119 if ext in __extensions["Ruby"]: |
|
120 for p in path: # only search in path |
|
121 pathname = os.path.join(p, name) |
|
122 if os.path.exists(pathname): |
|
123 return (open(pathname), pathname, (ext, 'r', RB_SOURCE)) |
|
124 # __IGNORE_WARNING_Y115__ |
|
125 raise ImportError |
|
126 |
|
127 elif ext in __extensions["IDL"]: |
|
128 for p in path: # only search in path |
|
129 pathname = os.path.join(p, name) |
|
130 if os.path.exists(pathname): |
|
131 return (open(pathname), pathname, (ext, 'r', IDL_SOURCE)) |
|
132 # __IGNORE_WARNING_Y115__ |
|
133 raise ImportError |
|
134 |
|
135 elif ext in __extensions["ProtoBuf"]: |
|
136 for p in path: # only search in path |
|
137 pathname = os.path.join(p, name) |
|
138 if os.path.exists(pathname): |
|
139 return (open(pathname), pathname, (ext, 'r', PROTO_SOURCE)) |
|
140 # __IGNORE_WARNING_Y115__ |
|
141 raise ImportError |
|
142 |
|
143 elif ext in __extensions["JavaScript"]: |
|
144 for p in path: # only search in path |
|
145 pathname = os.path.join(p, name) |
|
146 if os.path.exists(pathname): |
|
147 return (open(pathname), pathname, (ext, 'r', JS_SOURCE)) |
|
148 # __IGNORE_WARNING_Y115__ |
|
149 raise ImportError |
|
150 |
|
151 elif ext == '.ptl': |
|
152 for p in path: # only search in path |
|
153 pathname = os.path.join(p, name) |
|
154 if os.path.exists(pathname): |
|
155 return (open(pathname), pathname, (ext, 'r', PTL_SOURCE)) |
|
156 # __IGNORE_WARNING_Y115__ |
|
157 raise ImportError |
|
158 |
|
159 elif ( |
|
160 name.lower().endswith( |
|
161 tuple(Preferences.getPython("Python3Extensions"))) or |
|
162 isPyFile |
|
163 ): |
|
164 for p in path: # search in path |
|
165 pathname = os.path.join(p, name) |
|
166 if os.path.exists(pathname): |
|
167 return (open(pathname), pathname, (ext, 'r', PY_SOURCE)) |
|
168 # __IGNORE_WARNING_Y115__ |
|
169 raise ImportError |
|
170 |
|
171 # standard Python module file |
|
172 if name.lower().endswith('.py'): |
|
173 name = name[:-3] |
|
174 |
|
175 spec = importlib.machinery.PathFinder.find_spec(name, path) |
|
176 if spec is None: |
|
177 raise ImportError |
|
178 if isinstance(spec.loader, importlib.machinery.SourceFileLoader): |
|
179 ext = os.path.splitext(spec.origin)[-1] |
|
180 return (open(spec.origin), spec.origin, (ext, 'r', PY_SOURCE)) |
|
181 # __IGNORE_WARNING_Y115__ |
|
182 |
|
183 raise ImportError |