Package sourceinfo :: Module objectinfo

Source Code for Module sourceinfo.objectinfo

  1  # -*- coding: utf-8 -*- 
  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  # @UnresolvedImport 
 31      else: 
 32          from importlib import find_loader  # @UnresolvedImport 
 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   
45 -def _ismodule(mod):
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
51 -def getcaller_module(spos=1):
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
71 -def getcaller_module_name(spos=1):
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: # seems to be more accurate than getmodule_name 96 if module.__name__ == '__main__': 97 return os.path.basename(os.path.splitext(_sf[spos][1])[0]) 98 return module.__name__
99 100
101 -def getcaller_module_name_sub(spos=1):
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 # TODO: 117 _sf = stack() 118 if len(_sf) <= spos: 119 return None 120 module = getmodule(_sf[spos][0]) 121 if module: 122 return module.__name__ # seems to be more accurate than getmodule_name
123 124
125 -def getcaller_module_oid(spos=1):
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
142 -def getcaller_module_oid_sub(spos=1):
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
159 -def getcaller_name(spos=1):
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
176 -def getcaller_package_name(spos=1):
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
202 -def getmodule_by_id(i):
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
220 -def getmodule_by_name(n):
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
241 -def getmodule_name(mod):
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
259 -def getmodule_name_sub(mod):
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
278 -def getmodule_oid(mod):
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
296 -def getmodule_oid_sub(mod):
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
315 -def getmodule_package_name(mod):
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
335 -def getmodule_type(mod):
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: # MT_SOURCE,MT_COMPILED,MT_EXTENSION 364 return ret[2] 365 elif type(ret[2]) is tuple: # MT_DIRECTORY,MT_BUILTIN 366 return ret[2][2] 367 # TODO: PY_FROZEN 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 # either O1 or O2 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 # PEP 3147 -- PYC Repository Directories 400 if PYVxyz > PYV34: 401 ret = find_spec(getmodule_oid(mod)) 402 else: 403 # deprecated with 3.4 404 ret = find_loader(getmodule_oid(mod)) 405 406 if ret and hasattr(ret, 'path'): 407 # check python native 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 # @UndefinedVariable 411 for xf in os.walk(cdir): 412 for xi in xf[2]: 413 if xi.startswith(mname): 414 # 415 # for now supports: Python3, Pypy3 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