summaryrefslogtreecommitdiff
path: root/Lib
diff options
context:
space:
mode:
authorVinay Sajip <vinay_sajip@yahoo.co.uk>2018-06-05 17:24:18 +0100
committerGitHub <noreply@github.com>2018-06-05 17:24:18 +0100
commitdde9fdbe453925279ac3d2a6a72102f6f9ef247c (patch)
treeae9970f3597b3ee855a468c49d7007fa6f57ba16 /Lib
parent9ef1b0690b90c526798b6b3125b0fa7ae98319a2 (diff)
downloadcpython-git-dde9fdbe453925279ac3d2a6a72102f6f9ef247c.tar.gz
bpo-33165: Added stacklevel parameter to logging APIs. (GH-7424)
Diffstat (limited to 'Lib')
-rw-r--r--Lib/logging/__init__.py13
-rw-r--r--Lib/test/test_logging.py31
2 files changed, 41 insertions, 3 deletions
diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py
index a3617b16c4..e6c9f3280e 100644
--- a/Lib/logging/__init__.py
+++ b/Lib/logging/__init__.py
@@ -1397,7 +1397,7 @@ class Logger(Filterer):
if self.isEnabledFor(level):
self._log(level, msg, args, **kwargs)
- def findCaller(self, stack_info=False):
+ def findCaller(self, stack_info=False, stacklevel=1):
"""
Find the stack frame of the caller so that we can note the source
file name, line number and function name.
@@ -1407,6 +1407,12 @@ class Logger(Filterer):
#IronPython isn't run with -X:Frames.
if f is not None:
f = f.f_back
+ orig_f = f
+ while f and stacklevel > 1:
+ f = f.f_back
+ stacklevel -= 1
+ if not f:
+ f = orig_f
rv = "(unknown file)", 0, "(unknown function)", None
while hasattr(f, "f_code"):
co = f.f_code
@@ -1442,7 +1448,8 @@ class Logger(Filterer):
rv.__dict__[key] = extra[key]
return rv
- def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False):
+ def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False,
+ stacklevel=1):
"""
Low-level logging routine which creates a LogRecord and then calls
all the handlers of this logger to handle the record.
@@ -1453,7 +1460,7 @@ class Logger(Filterer):
#exception on some versions of IronPython. We trap it here so that
#IronPython can use logging.
try:
- fn, lno, func, sinfo = self.findCaller(stack_info)
+ fn, lno, func, sinfo = self.findCaller(stack_info, stacklevel)
except ValueError: # pragma: no cover
fn, lno, func = "(unknown file)", 0, "(unknown function)"
else: # pragma: no cover
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index e02bb31c33..5098866237 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -4057,6 +4057,37 @@ class LoggerTest(BaseTest):
self.assertEqual(len(called), 1)
self.assertEqual('Stack (most recent call last):\n', called[0])
+ def test_find_caller_with_stacklevel(self):
+ the_level = 1
+
+ def innermost():
+ self.logger.warning('test', stacklevel=the_level)
+
+ def inner():
+ innermost()
+
+ def outer():
+ inner()
+
+ records = self.recording.records
+ outer()
+ self.assertEqual(records[-1].funcName, 'innermost')
+ lineno = records[-1].lineno
+ the_level += 1
+ outer()
+ self.assertEqual(records[-1].funcName, 'inner')
+ self.assertGreater(records[-1].lineno, lineno)
+ lineno = records[-1].lineno
+ the_level += 1
+ outer()
+ self.assertEqual(records[-1].funcName, 'outer')
+ self.assertGreater(records[-1].lineno, lineno)
+ lineno = records[-1].lineno
+ the_level += 1
+ outer()
+ self.assertEqual(records[-1].funcName, 'test_find_caller_with_stacklevel')
+ self.assertGreater(records[-1].lineno, lineno)
+
def test_make_record_with_extra_overwrite(self):
name = 'my record'
level = 13