lsst.utils  16.0-6-g3610b4f
get_caller_name.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 #
4 # Copyright 2008-2017 AURA/LSST.
5 #
6 # This product includes software developed by the
7 # LSST Project (http://www.lsst.org/).
8 #
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the LSST License Statement and
20 # the GNU General Public License along with this program. If not,
21 # see <https://www.lsstcorp.org/LegalNotices/>.
22 #
23 import inspect
24 
25 __all__ = ["get_caller_name"]
26 
27 
28 def get_caller_name(skip=2):
29  """Get the name of the caller method.
30 
31  Any item that cannot be determined (or is not relevant, e.g. a free
32  function has no class) is silently omitted, along with an
33  associated separator.
34 
35  Parameters
36  ----------
37  skip : `int`
38  How many levels of stack to skip while getting caller name;
39  1 means "who calls me", 2 means "who calls my caller", etc.
40 
41  Returns
42  -------
43  name : `str`
44  Name of the caller as a string in the form ``module.class.method``.
45  An empty string is returned if ``skip`` exceeds the stack height.
46 
47  Notes
48  -----
49  Adapted from from http://stackoverflow.com/a/9812105
50  by adding support to get the class from ``parentframe.f_locals['cls']``
51  """
52  stack = inspect.stack()
53  start = 0 + skip
54  if len(stack) < start + 1:
55  return ''
56  parentframe = stack[start][0]
57 
58  name = []
59  module = inspect.getmodule(parentframe)
60  if module:
61  name.append(module.__name__)
62  # add class name, if any
63  if 'self' in parentframe.f_locals:
64  name.append(type(parentframe.f_locals['self']).__name__)
65  elif 'cls' in parentframe.f_locals:
66  name.append(parentframe.f_locals['cls'].__name__)
67  codename = parentframe.f_code.co_name
68  if codename != '<module>': # top level usually
69  name.append(codename) # function or a method
70  return ".".join(name)