Package sourceinfo ::
Module objectinfo
1
2 """PySourceInfo - runtime type and source information on Python.
3
4 Based on the stack-frames of **inspect**, main parameter is **spos**
5 - stack position.
6
7 * *spos=1* is caller, *spos=2* is caller-of-caller, etc..
8
9 * 'r' is a regular expression for 'search()'.
10
11 Details see [@local-manuals or @[https://pythonhosted.org/pysourceinfo/]
12 """
13 from __future__ import absolute_import
14
15 import os
16 import sys
17 import re
18 from inspect import stack, getmodule, ismodule
19
20 from imp import is_builtin, is_frozen, find_module
21 from types import ModuleType, BuiltinFunctionType, BuiltinMethodType
22
23 from pythonids import PYV35Plus, PYVxyz, PYV34
24 from sourceinfo import SourceInfoError, \
25 MT_UNKNOWN, MT_SOURCE, MT_COMPILED, MT_EXTENSION, MT_DIRECTORY, MT_BUILTIN, MT_FROZEN, \
26 MT_COMPILED_OPT, MT_COMPILED_OPT1, MT_COMPILED_OPT2, MT_COMPILED_DEBUG
27
28 if PYV35Plus:
29 if PYVxyz > PYV34:
30 from importlib.util import find_spec
31 else:
32 from importlib import find_loader
33
34
35
36 __author__ = 'Arno-Can Uestuensoez'
37 __license__ = "Artistic-License-2.0 + Forced-Fairplay-Constraints"
38 __copyright__ = "Copyright (C) 2010-2017 Arno-Can Uestuensoez" \
39 " @Ingenieurbuero Arno-Can Uestuensoez"
40 __version__ = '0.1.34'
41 __uuid__ = '9de52399-7752-4633-9fdc-66c87a9200b8'
42
43 __docformat__ = "restructuredtext en"
44
46 """Checks imported modules and sys.builtin_module_names.
47 Returns True is either is true.
48 """
49 return (ismodule(mod) or mod.__name__ in sys.builtin_module_names)
50
52 """Caller module.
53
54 Args:
55 spos:
56 Caller position on the stack.
57
58 Returns:
59 Returns the caller module.
60
61 Raises:
62 pass-through
63
64 """
65 _sf = stack()
66 if spos >= len(_sf):
67 return None
68 return getmodule(_sf[spos][0])
69
70
72 """Name of caller module, else *None*.
73 Both approaches for evaluation the actual relative
74 module name seem to have their own challenges,
75 *module.__name__* and *getmodule_name()*.
76
77 Args:
78
79 spos:
80 Caller position on the stack.
81
82 Returns:
83 Returns the name of caller module.
84 The dotted object path is relative to
85 the actual used sys.path item.
86
87 Raises:
88 pass-through
89
90 """
91 _sf = stack()
92 if len(_sf) <= spos:
93 return None
94 module = getmodule(_sf[spos][0])
95 if module:
96 if module.__name__ == '__main__':
97 return os.path.basename(os.path.splitext(_sf[spos][1])[0])
98 return module.__name__
99
100
102 """Name from package to module.
103
104 Args:
105 spos:
106 Caller position on the stack.
107
108 Returns:
109 Returns the sub-name as the portion from package to module.
110
111 Raises:
112 pass-through
113
114 """
115
116
117 _sf = stack()
118 if len(_sf) <= spos:
119 return None
120 module = getmodule(_sf[spos][0])
121 if module:
122 return module.__name__
123
124
126 """OID of caller module.
127
128 Args:
129 spos:
130 Caller position on the stack.
131
132 Returns:
133 Returns the OID of the module.
134
135 Raises:
136 pass-through
137
138 """
139 return getmodule_oid(getcaller_module(spos + 1))
140
141
143 """OID of caller module.
144
145 Args:
146 spos:
147 Caller position on the stack.
148
149 Returns:
150 Returns the sub-OID of the module.
151
152 Raises:
153 pass-through
154
155 """
156 return getmodule_oid_sub(getcaller_module_oid(spos))
157
158
160 """Name of caller.
161
162 Args:
163 spos:
164 Caller position on the stack.
165
166 Returns:
167 Returns the name.
168
169 Raises:
170 pass-through
171
172 """
173 return stack()[spos][3]
174
175
177 """Name of first matching package containing the caller.
178 The package is defined as the the first part
179 of the module name. Relies on 'inspect'.
180
181 Args:
182 spos:
183 Caller position on the stack.
184
185 Returns:
186 Returns the package name when defined, else None.
187
188 Raises:
189 pass-through
190
191 """
192 _sf = stack()
193 if len(_sf) < spos:
194 return None
195 module = getmodule(_sf[spos][0])
196 try:
197 return re.sub("^([^.]+).*", r'\1', module.__package__)
198 except:
199 return re.sub("^([^.]+).*", r'\1', getcaller_module_name(spos + 1))
200
201
203 """Loaded module by ID.
204
205 Args:
206 n:
207 ID of loaded module.
208
209 Returns:
210 Returns the loaded module.
211
212 Raises:
213 passed through exceptions
214
215 """
216 if i:
217 return [x for x in sys.modules.values() if id(x) == i][0]
218
219
221 """Loaded module by given name.
222
223 Args:
224 n:
225 Name of the loaded module.
226
227 Returns:
228 Returns the loaded module.
229
230 Raises:
231 pass-through
232
233 """
234 if n and sys.modules.get(n):
235 return sys.modules[n]
236
237
238 _gmn = re.compile(r'^.*[.]')
239
240
242 """Name similar to basename of loaded module, same as getmodule_oid.
243
244 Args:
245 mod:
246 Module.
247
248 Returns:
249 Returns the name of the loaded module.
250
251 Raises:
252 pass-through
253
254 """
255 if mod and _ismodule(mod) and hasattr(mod, '__name__'):
256 return _gmn.sub('', mod.__name__)
257
258
260 """Name relative to PYTHONPATH/sys.path of loaded module, same as getmodule_oid_sub.
261
262 Args:
263
264 mod:
265 Module.
266
267 Returns:
268 Returns the sub-name of the loaded module.
269
270 Raises:
271 passed through exceptions
272
273 """
274 if mod and _ismodule(mod) and hasattr(mod, '__name__'):
275 return re.sub(r'^[^.]*[.]', r'', mod.__name__)
276
277
279 """Name relative to PYTHONPATH/sys.path of loaded module.
280
281 Args:
282 mod:
283 Module.
284
285 Returns:
286 Returns the package name.
287
288 Raises:
289 pass-through
290
291 """
292 if mod and _ismodule(mod) and hasattr(mod, '__name__'):
293 return mod.__name__
294
295
297 """Name relative to PYTHONPATH/sys.path of loaded module.
298
299 Args:
300 mod:
301 Module.
302
303 Returns:
304 Returns the package name.
305
306 Raises:
307 pass-through
308
309 """
310 if mod and _ismodule(mod):
311 if hasattr(mod, '__name__'):
312 return re.sub(r'^[^.]*[.]', r'', mod.__name__)
313
314
316 """Name of package for loaded module.
317
318 Args:
319 mod:
320 Reference to a loaded module.
321
322 Returns:
323 Returns the package name of the loaded module.
324
325 Raises:
326 pass-through
327
328 """
329 mn = getmodule_name(mod)
330 if mn:
331 if hasattr(mod, '__name__'):
332 return mod.__name__
333
334
336 """Type for loaded module as defined by module 'imp.*'
337
338 Args:
339 mod:
340 Reference to a loaded module.
341
342 Returns:
343 Returns the module type as defined by imp, else None. ::
344
345 ret:=(
346 C_BUILTIN
347 | C_EXTENSION
348 | PKG_DIRECTORY
349 | PY_COMPILED
350 | PY_FROZEN
351 | PY_SOURCE
352 | None
353 )
354
355 Raises:
356 passed through exceptions
357
358 """
359 if not PYV35Plus:
360 try:
361 ret = find_module(getmodule_oid(mod))
362 if ret and ret[2]:
363 if type(ret[2]) is int:
364 return ret[2]
365 elif type(ret[2]) is tuple:
366 return ret[2][2]
367
368 except:
369 if _ismodule(mod) or type(mod) is ModuleType:
370 try:
371 _n = getmodule_oid(mod)
372 if _n in sys.builtin_module_names or is_builtin(_n):
373 return MT_BUILTIN
374 else:
375 bn = sys.modules[_n].__file__
376 if bn:
377 bn = os.path.basename(bn)
378 if bn.startswith('__init__'):
379 return MT_DIRECTORY
380 elif bn[-2:] == 'py':
381 return MT_SOURCE
382 elif bn.endswith('$py.class'):
383 return MT_COMPILED
384 elif bn[-3:] in ('pyc',):
385 return MT_COMPILED_DEBUG
386 elif bn[-3:] in ('pyo'):
387 return MT_COMPILED_OPT
388
389 elif bn[-3:] in ('so',):
390 return MT_EXTENSION
391 elif is_frozen(_n):
392 return MT_FROZEN
393 except ImportError:
394 pass
395 except:
396 raise
397 return MT_UNKNOWN
398 else:
399
400 if PYVxyz > PYV34:
401 ret = find_spec(getmodule_oid(mod))
402 else:
403
404 ret = find_loader(getmodule_oid(mod))
405
406 if ret and hasattr(ret, 'path'):
407
408 cdir = os.path.dirname(ret.path) + os.path.sep + '__pycache__'
409 if os.path.exists(cdir):
410 mname = re.sub(r"^.*[.]", '', ret.name) + '.' + sys.implementation.cache_tag
411 for xf in os.walk(cdir):
412 for xi in xf[2]:
413 if xi.startswith(mname):
414
415
416
417 if xi[-3:]== "pyc":
418 return MT_COMPILED_DEBUG
419 elif xi[-3:]== "pyo":
420 if xi[-9:-4]== "opt-1":
421 return MT_COMPILED_OPT1
422 if xi[-9:-4]== "opt-2":
423 return MT_COMPILED_OPT2
424 else:
425 raise SourceInfoError("Extension unknown:" + str(xi))
426
427 else:
428 return MT_SOURCE
429
430 elif type(ret) in (BuiltinFunctionType, BuiltinMethodType,):
431 return MT_BUILTIN
432
433 else:
434 _n = None
435 if ret:
436
437 if not hasattr(ret, 'name'):
438 if type(ret) == type:
439 return MT_BUILTIN
440 else:
441 return MT_UNKNOWN
442 else:
443 _n = ret.name
444 else:
445 try:
446 _n = getmodule_oid(mod)
447 except ImportError:
448 pass
449 except:
450 raise
451
452 if _n in sys.builtin_module_names or is_builtin(_n):
453 return MT_BUILTIN
454 elif is_frozen(_n):
455 return MT_FROZEN
456 else:
457 bn = sys.modules[_n].__file__
458 if bn:
459 bn = os.path.basename(bn)
460 if bn.startswith('__init__'):
461 return MT_DIRECTORY
462 elif bn[-2:] == 'py':
463 return MT_SOURCE
464 elif bn[-3:] in ('pyc', 'pyo'):
465 return MT_COMPILED
466 elif bn[-3:] in ('so',):
467 return MT_EXTENSION
468
469 return MT_UNKNOWN
470