Patchwork [2,of,5] ui: add a 'stacklevel' argument to 'develwarn'

login
register
mail settings
Submitter Pierre-Yves David
Date Dec. 6, 2015, 8:45 p.m.
Message ID <eca257699f241e8490ff.1449434712@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/11862/
State Superseded
Commit 82910fdc216f1f1ec1345819d15a63934ef5690b
Delegated to: Yuya Nishihara
Headers show

Comments

Pierre-Yves David - Dec. 6, 2015, 8:45 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1449385533 28800
#      Sat Dec 05 23:05:33 2015 -0800
# Node ID eca257699f241e8490ff79a0a2e869fd241ad596
# Parent  847325e9c631e096019eb97a882cba0cb91cedb8
# EXP-Topic deprecationwarning
# Available At http://hg.netv6.net/marmoute-wip/mercurial/
#              hg pull http://hg.netv6.net/marmoute-wip/mercurial/ -r eca257699f24
ui: add a 'stacklevel' argument to 'develwarn'

This allows helper functions (like deprecation warning) to prepare a devel
warning for higher up in the stack. The argument is named after the one in the
Python's 'warning,warn' function.
Yuya Nishihara - Dec. 7, 2015, 2:07 p.m.
On Sun, 06 Dec 2015 12:45:12 -0800, Pierre-Yves David wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david@fb.com>
> # Date 1449385533 28800
> #      Sat Dec 05 23:05:33 2015 -0800
> # Node ID eca257699f241e8490ff79a0a2e869fd241ad596
> # Parent  847325e9c631e096019eb97a882cba0cb91cedb8
> # EXP-Topic deprecationwarning
> # Available At http://hg.netv6.net/marmoute-wip/mercurial/
> #              hg pull http://hg.netv6.net/marmoute-wip/mercurial/ -r eca257699f24
> ui: add a 'stacklevel' argument to 'develwarn'
> 
> This allows helper functions (like deprecation warning) to prepare a devel
> warning for higher up in the stack. The argument is named after the one in the
> Python's 'warning,warn' function.
> 
> diff --git a/mercurial/ui.py b/mercurial/ui.py
> --- a/mercurial/ui.py
> +++ b/mercurial/ui.py
> @@ -1042,19 +1042,25 @@ class ui(object):
>          ui.write(s, 'label') is equivalent to
>          ui.write(ui.label(s, 'label')).
>          '''
>          return msg
>  
> -    def develwarn(self, msg):
> -        """issue a developer warning message"""
> +    def develwarn(self, msg, stacklevel=0):
> +        """issue a developer warning message
> +
> +        Use 'stacklevel' to report the offender some layers further up in the
> +        stack.
> +        """
>          msg = 'devel-warn: ' + msg
> +        stacklevel += 2 # get out of develwarn

I might be paranoid, but if we copy the behavior of warnings.warn, the default
stacklevel should be 1.

   stacklevel=0: develwarn()
   stacklevel=1: caller of develwarn()
   stacklevel=2: wrapper function that calls develwarn()

https://docs.python.org/2.7/library/warnings.html#warnings.warn

>          if self.tracebackflag:
> -            util.debugstacktrace(msg, 2, self.ferr, self.fout)
> +            util.debugstacktrace(msg, stacklevel, self.ferr, self.fout)
>          else:
>              curframe = inspect.currentframe()
> -            calframe = inspect.getouterframes(curframe, 2)
> -            self.write_err('%s at: %s:%s (%s)\n' % ((msg,) + calframe[2][1:4]))
> +            calframe = inspect.getouterframes(curframe, stacklevel)

getouterframes() doesn't need stacklevel. The second argument is the number of
lines to be returned as a context.

https://docs.python.org/2.7/library/inspect.html#inspect.getouterframes
Pierre-Yves David - Dec. 8, 2015, 9:50 a.m.
On 12/07/2015 06:07 AM, Yuya Nishihara wrote:
> On Sun, 06 Dec 2015 12:45:12 -0800, Pierre-Yves David wrote:
>> # HG changeset patch
>> # User Pierre-Yves David <pierre-yves.david@fb.com>
>> # Date 1449385533 28800
>> #      Sat Dec 05 23:05:33 2015 -0800
>> # Node ID eca257699f241e8490ff79a0a2e869fd241ad596
>> # Parent  847325e9c631e096019eb97a882cba0cb91cedb8
>> # EXP-Topic deprecationwarning
>> # Available At http://hg.netv6.net/marmoute-wip/mercurial/
>> #              hg pull http://hg.netv6.net/marmoute-wip/mercurial/ -r eca257699f24
>> ui: add a 'stacklevel' argument to 'develwarn'
>>
>> This allows helper functions (like deprecation warning) to prepare a devel
>> warning for higher up in the stack. The argument is named after the one in the
>> Python's 'warning,warn' function.
>>
>> diff --git a/mercurial/ui.py b/mercurial/ui.py
>> --- a/mercurial/ui.py
>> +++ b/mercurial/ui.py
>> @@ -1042,19 +1042,25 @@ class ui(object):
>>           ui.write(s, 'label') is equivalent to
>>           ui.write(ui.label(s, 'label')).
>>           '''
>>           return msg
>>
>> -    def develwarn(self, msg):
>> -        """issue a developer warning message"""
>> +    def develwarn(self, msg, stacklevel=0):
>> +        """issue a developer warning message
>> +
>> +        Use 'stacklevel' to report the offender some layers further up in the
>> +        stack.
>> +        """
>>           msg = 'devel-warn: ' + msg
>> +        stacklevel += 2 # get out of develwarn
>
> I might be paranoid, but if we copy the behavior of warnings.warn, the default
> stacklevel should be 1.
>
>     stacklevel=0: develwarn()
>     stacklevel=1: caller of develwarn()
>     stacklevel=2: wrapper function that calls develwarn()
>
> https://docs.python.org/2.7/library/warnings.html#warnings.warn

ha, true, will send a V2

>
>>           if self.tracebackflag:
>> -            util.debugstacktrace(msg, 2, self.ferr, self.fout)
>> +            util.debugstacktrace(msg, stacklevel, self.ferr, self.fout)
>>           else:
>>               curframe = inspect.currentframe()
>> -            calframe = inspect.getouterframes(curframe, 2)
>> -            self.write_err('%s at: %s:%s (%s)\n' % ((msg,) + calframe[2][1:4]))
>> +            calframe = inspect.getouterframes(curframe, stacklevel)
>
> getouterframes() doesn't need stacklevel. The second argument is the number of
> lines to be returned as a context.


good catch.

Patch

diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -1042,19 +1042,25 @@  class ui(object):
         ui.write(s, 'label') is equivalent to
         ui.write(ui.label(s, 'label')).
         '''
         return msg
 
-    def develwarn(self, msg):
-        """issue a developer warning message"""
+    def develwarn(self, msg, stacklevel=0):
+        """issue a developer warning message
+
+        Use 'stacklevel' to report the offender some layers further up in the
+        stack.
+        """
         msg = 'devel-warn: ' + msg
+        stacklevel += 2 # get out of develwarn
         if self.tracebackflag:
-            util.debugstacktrace(msg, 2, self.ferr, self.fout)
+            util.debugstacktrace(msg, stacklevel, self.ferr, self.fout)
         else:
             curframe = inspect.currentframe()
-            calframe = inspect.getouterframes(curframe, 2)
-            self.write_err('%s at: %s:%s (%s)\n' % ((msg,) + calframe[2][1:4]))
+            calframe = inspect.getouterframes(curframe, stacklevel)
+            self.write_err('%s at: %s:%s (%s)\n'
+                           % ((msg,) + calframe[stacklevel][1:4]))
 
 class paths(dict):
     """Represents a collection of paths and their configs.
 
     Data is initially derived from ui instances and the config files they have