Patchwork [3,of,6,py3] extensions: tapdance to get reasonable import error formatting

login
register
mail settings
Submitter Augie Fackler
Date March 7, 2017, 4:25 p.m.
Message ID <adf7419abb89aef332ac.1488903917@augie-macbookair2.roam.corp.google.com>
Download mbox | patch
Permalink /patch/18965/
State Superseded
Headers show

Comments

Augie Fackler - March 7, 2017, 4:25 p.m.
# HG changeset patch
# User Augie Fackler <raf@durin42.com>
# Date 1488568082 18000
#      Fri Mar 03 14:08:02 2017 -0500
# Node ID adf7419abb89aef332ac5eac48a0f1c9d3eab527
# Parent  3e82376d7d3f3e11d11f09fceb8b4c79233057a8
extensions: tapdance to get reasonable import error formatting

I'm not thrilled with this, but it seems to work.
Durham Goode - March 8, 2017, 2:59 a.m.
On 3/7/17 8:25 AM, Augie Fackler wrote:
> # HG changeset patch
> # User Augie Fackler <raf@durin42.com>
> # Date 1488568082 18000
> #      Fri Mar 03 14:08:02 2017 -0500
> # Node ID adf7419abb89aef332ac5eac48a0f1c9d3eab527
> # Parent  3e82376d7d3f3e11d11f09fceb8b4c79233057a8
> extensions: tapdance to get reasonable import error formatting
>
> I'm not thrilled with this, but it seems to work.
>
> diff --git a/mercurial/extensions.py b/mercurial/extensions.py
> --- a/mercurial/extensions.py
> +++ b/mercurial/extensions.py
> @@ -18,6 +18,7 @@ from .i18n import (
>
>  from . import (
>      cmdutil,
> +    encoding,
>      error,
>      pycompat,
>      util,
> @@ -104,11 +105,19 @@ def _importext(name, path=None, reportfu
>                  mod = _importh(name)
>      return mod
>
> +def _forbytes(inst):
> +    """Portably format an import error into a form suitable for
> +    %-formatting into bytestrings."""
> +    if pycompat.ispy3:
> +        return str(inst).encode('utf-8')
> +    return inst
> +
>  def _reportimporterror(ui, err, failed, next):
>      # note: this ui.debug happens before --debug is processed,
>      #       Use --config ui.debug=1 to see them.
> -    ui.debug('could not import %s (%s): trying %s\n'
> -             % (failed, err, next))
> +    msg = 'could not import %s (%s): trying %s\n' % (
> +        failed, _forbytes(err), next)
> +    ui.debug(encoding.tolocal(msg))
>      if ui.debugflag:
>          ui.traceback()
>
> @@ -168,12 +177,13 @@ def loadall(ui):
>          except KeyboardInterrupt:
>              raise
>          except Exception as inst:
> +            inst = _forbytes(inst)
>              if path:
> -                ui.warn(_("*** failed to import extension %s from %s: %s\n")
> -                        % (name, path, inst))
> +                fmt = _("*** failed to import extension %s from %s: %s\n")
> +                ui.warn(encoding.tolocal(fmt % (name, path, inst)))
>              else:
> -                ui.warn(_("*** failed to import extension %s: %s\n")
> -                        % (name, inst))
> +                fmt = _("*** failed to import extension %s: %s\n")
> +                ui.warn(encoding.tolocal(fmt % (name, inst)))
>              ui.traceback()
>
>      for name in _order[newindex:]:
> diff --git a/tests/test-check-py3-commands.t b/tests/test-check-py3-commands.t
> --- a/tests/test-check-py3-commands.t
> +++ b/tests/test-check-py3-commands.t
> @@ -12,3 +12,12 @@ The full traceback is hidden to have a s
>    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
>    debuginstall
>    TypeError: Can't convert 'bytes' object to str implicitly
> +
> +  $ cat > included-hgrc <<EOF
> +  > [extensions]
> +  > babar = imaginary_elephant
> +  > EOF
> +  $ cat >> $HGRCPATH <<EOF
> +  > %include $TESTTMP/included-hgrc
> +  > EOF
> +  $ $PYTHON3 `which hg` version --config ui.debug=1

Should this have outputted an error?
Durham Goode - March 8, 2017, 3 a.m.
On 3/7/17 6:59 PM, Durham Goode wrote:
>
>
> On 3/7/17 8:25 AM, Augie Fackler wrote:
>> # HG changeset patch
>> # User Augie Fackler <raf@durin42.com>
>> # Date 1488568082 18000
>> #      Fri Mar 03 14:08:02 2017 -0500
>> # Node ID adf7419abb89aef332ac5eac48a0f1c9d3eab527
>> # Parent  3e82376d7d3f3e11d11f09fceb8b4c79233057a8
>> extensions: tapdance to get reasonable import error formatting
>>
>> I'm not thrilled with this, but it seems to work.
>>
>> diff --git a/mercurial/extensions.py b/mercurial/extensions.py
>> --- a/mercurial/extensions.py
>> +++ b/mercurial/extensions.py
>> @@ -18,6 +18,7 @@ from .i18n import (
>>
>>  from . import (
>>      cmdutil,
>> +    encoding,
>>      error,
>>      pycompat,
>>      util,
>> @@ -104,11 +105,19 @@ def _importext(name, path=None, reportfu
>>                  mod = _importh(name)
>>      return mod
>>
>> +def _forbytes(inst):
>> +    """Portably format an import error into a form suitable for
>> +    %-formatting into bytestrings."""
>> +    if pycompat.ispy3:
>> +        return str(inst).encode('utf-8')
>> +    return inst
>> +
>>  def _reportimporterror(ui, err, failed, next):
>>      # note: this ui.debug happens before --debug is processed,
>>      #       Use --config ui.debug=1 to see them.
>> -    ui.debug('could not import %s (%s): trying %s\n'
>> -             % (failed, err, next))
>> +    msg = 'could not import %s (%s): trying %s\n' % (
>> +        failed, _forbytes(err), next)
>> +    ui.debug(encoding.tolocal(msg))
>>      if ui.debugflag:
>>          ui.traceback()
>>
>> @@ -168,12 +177,13 @@ def loadall(ui):
>>          except KeyboardInterrupt:
>>              raise
>>          except Exception as inst:
>> +            inst = _forbytes(inst)
>>              if path:
>> -                ui.warn(_("*** failed to import extension %s from %s:
>> %s\n")
>> -                        % (name, path, inst))
>> +                fmt = _("*** failed to import extension %s from %s:
>> %s\n")
>> +                ui.warn(encoding.tolocal(fmt % (name, path, inst)))
>>              else:
>> -                ui.warn(_("*** failed to import extension %s: %s\n")
>> -                        % (name, inst))
>> +                fmt = _("*** failed to import extension %s: %s\n")
>> +                ui.warn(encoding.tolocal(fmt % (name, inst)))
>>              ui.traceback()
>>
>>      for name in _order[newindex:]:
>> diff --git a/tests/test-check-py3-commands.t
>> b/tests/test-check-py3-commands.t
>> --- a/tests/test-check-py3-commands.t
>> +++ b/tests/test-check-py3-commands.t
>> @@ -12,3 +12,12 @@ The full traceback is hidden to have a s
>>    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
>> PURPOSE.
>>    debuginstall
>>    TypeError: Can't convert 'bytes' object to str implicitly
>> +
>> +  $ cat > included-hgrc <<EOF
>> +  > [extensions]
>> +  > babar = imaginary_elephant
>> +  > EOF
>> +  $ cat >> $HGRCPATH <<EOF
>> +  > %include $TESTTMP/included-hgrc
>> +  > EOF
>> +  $ $PYTHON3 `which hg` version --config ui.debug=1
>
> Should this have outputted an error?

Er, I see the next patch has the error?  Did this file belong in the 
next patch?
Augie Fackler - March 8, 2017, 3:01 a.m.
> On Mar 7, 2017, at 21:59, Durham Goode <durham@fb.com> wrote:
> 
> 
> 
> On 3/7/17 8:25 AM, Augie Fackler wrote:
>> # HG changeset patch
>> # User Augie Fackler <raf@durin42.com>
>> # Date 1488568082 18000
>> #      Fri Mar 03 14:08:02 2017 -0500
>> # Node ID adf7419abb89aef332ac5eac48a0f1c9d3eab527
>> # Parent  3e82376d7d3f3e11d11f09fceb8b4c79233057a8
>> extensions: tapdance to get reasonable import error formatting
>> 
>> I'm not thrilled with this, but it seems to work.
>> 
>> diff --git a/mercurial/extensions.py b/mercurial/extensions.py
>> --- a/mercurial/extensions.py
>> +++ b/mercurial/extensions.py
>> @@ -18,6 +18,7 @@ from .i18n import (
>> 
>> from . import (
>>     cmdutil,
>> +    encoding,
>>     error,
>>     pycompat,
>>     util,
>> @@ -104,11 +105,19 @@ def _importext(name, path=None, reportfu
>>                 mod = _importh(name)
>>     return mod
>> 
>> +def _forbytes(inst):
>> +    """Portably format an import error into a form suitable for
>> +    %-formatting into bytestrings."""
>> +    if pycompat.ispy3:
>> +        return str(inst).encode('utf-8')
>> +    return inst
>> +
>> def _reportimporterror(ui, err, failed, next):
>>     # note: this ui.debug happens before --debug is processed,
>>     #       Use --config ui.debug=1 to see them.
>> -    ui.debug('could not import %s (%s): trying %s\n'
>> -             % (failed, err, next))
>> +    msg = 'could not import %s (%s): trying %s\n' % (
>> +        failed, _forbytes(err), next)
>> +    ui.debug(encoding.tolocal(msg))
>>     if ui.debugflag:
>>         ui.traceback()
>> 
>> @@ -168,12 +177,13 @@ def loadall(ui):
>>         except KeyboardInterrupt:
>>             raise
>>         except Exception as inst:
>> +            inst = _forbytes(inst)
>>             if path:
>> -                ui.warn(_("*** failed to import extension %s from %s: %s\n")
>> -                        % (name, path, inst))
>> +                fmt = _("*** failed to import extension %s from %s: %s\n")
>> +                ui.warn(encoding.tolocal(fmt % (name, path, inst)))
>>             else:
>> -                ui.warn(_("*** failed to import extension %s: %s\n")
>> -                        % (name, inst))
>> +                fmt = _("*** failed to import extension %s: %s\n")
>> +                ui.warn(encoding.tolocal(fmt % (name, inst)))
>>             ui.traceback()
>> 
>>     for name in _order[newindex:]:
>> diff --git a/tests/test-check-py3-commands.t b/tests/test-check-py3-commands.t
>> --- a/tests/test-check-py3-commands.t
>> +++ b/tests/test-check-py3-commands.t
>> @@ -12,3 +12,12 @@ The full traceback is hidden to have a s
>>   warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
>>   debuginstall
>>   TypeError: Can't convert 'bytes' object to str implicitly
>> +
>> +  $ cat > included-hgrc <<EOF
>> +  > [extensions]
>> +  > babar = imaginary_elephant
>> +  > EOF
>> +  $ cat >> $HGRCPATH <<EOF
>> +  > %include $TESTTMP/included-hgrc
>> +  > EOF
>> +  $ $PYTHON3 `which hg` version --config ui.debug=1
> 
> Should this have outputted an error?

D'oh. I must have missed something here. I'll take a look in the morning (it's late here) and do a resend.

Patch

diff --git a/mercurial/extensions.py b/mercurial/extensions.py
--- a/mercurial/extensions.py
+++ b/mercurial/extensions.py
@@ -18,6 +18,7 @@  from .i18n import (
 
 from . import (
     cmdutil,
+    encoding,
     error,
     pycompat,
     util,
@@ -104,11 +105,19 @@  def _importext(name, path=None, reportfu
                 mod = _importh(name)
     return mod
 
+def _forbytes(inst):
+    """Portably format an import error into a form suitable for
+    %-formatting into bytestrings."""
+    if pycompat.ispy3:
+        return str(inst).encode('utf-8')
+    return inst
+
 def _reportimporterror(ui, err, failed, next):
     # note: this ui.debug happens before --debug is processed,
     #       Use --config ui.debug=1 to see them.
-    ui.debug('could not import %s (%s): trying %s\n'
-             % (failed, err, next))
+    msg = 'could not import %s (%s): trying %s\n' % (
+        failed, _forbytes(err), next)
+    ui.debug(encoding.tolocal(msg))
     if ui.debugflag:
         ui.traceback()
 
@@ -168,12 +177,13 @@  def loadall(ui):
         except KeyboardInterrupt:
             raise
         except Exception as inst:
+            inst = _forbytes(inst)
             if path:
-                ui.warn(_("*** failed to import extension %s from %s: %s\n")
-                        % (name, path, inst))
+                fmt = _("*** failed to import extension %s from %s: %s\n")
+                ui.warn(encoding.tolocal(fmt % (name, path, inst)))
             else:
-                ui.warn(_("*** failed to import extension %s: %s\n")
-                        % (name, inst))
+                fmt = _("*** failed to import extension %s: %s\n")
+                ui.warn(encoding.tolocal(fmt % (name, inst)))
             ui.traceback()
 
     for name in _order[newindex:]:
diff --git a/tests/test-check-py3-commands.t b/tests/test-check-py3-commands.t
--- a/tests/test-check-py3-commands.t
+++ b/tests/test-check-py3-commands.t
@@ -12,3 +12,12 @@  The full traceback is hidden to have a s
   warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   debuginstall
   TypeError: Can't convert 'bytes' object to str implicitly
+
+  $ cat > included-hgrc <<EOF
+  > [extensions]
+  > babar = imaginary_elephant
+  > EOF
+  $ cat >> $HGRCPATH <<EOF
+  > %include $TESTTMP/included-hgrc
+  > EOF
+  $ $PYTHON3 `which hg` version --config ui.debug=1