Salome HOME
merge with master
[tools/sat.git] / src / callerName.py
1 #!/usr/bin/env python
2 #-*- coding:utf-8 -*-
3
4 # https://gist.github.com/techtonik/2151727
5 # Public Domain, i.e. feel free to copy/paste
6 # Considered a hack in Python 2
7
8 import inspect
9 import logging
10 import sys
11
12
13 def caller_name(skip=1):
14     """Get a name of a caller in the format module.class.method
15
16        `skip` specifies how many levels of stack to skip while getting caller
17        name. skip=1 means "who calls me", skip=2 "who calls my caller" etc.
18
19        An empty string is returned if skipped levels exceed stack height
20     """
21     def stack_(frame):
22         framelist = []
23         while frame:
24             framelist.append(frame)
25             frame = frame.f_back
26         return framelist
27
28     stack = stack_(sys._getframe(1))
29     start = 0 + skip
30     if len(stack) < start + 1:
31         return ''
32     parentframe = stack[start]
33
34     name = []
35     module = inspect.getmodule(parentframe)
36     # `modname` can be None when frame is executed directly in console
37     # TODO(techtonik): consider using __main__
38     if module:
39         name.append(module.__name__)
40     # detect classname
41     if 'self' in parentframe.f_locals:
42         # I don't know any way to detect call from the object method
43         # XXX: there seems to be no way to detect static method call - it will
44         #      be just a function call
45         name.append(parentframe.f_locals['self'].__class__.__name__)
46     codename = parentframe.f_code.co_name
47     lineno = inspect.currentframe().f_back.f_back.f_lineno
48     if codename != '<module>':  # top level usually
49         name.append(codename + "[%s]" % str(lineno))  # function or a method
50     del parentframe
51     return ".".join(name)