Patchwork extensions: add loadfailed to return extensions failed to load (API)

login
register
mail settings
Submitter Jun Wu
Date Feb. 10, 2016, 5:07 p.m.
Message ID <d58f659625ed84ce90f6.1455124072@x1c>
Download mbox | patch
Permalink /patch/13102/
State Changes Requested
Delegated to: Yuya Nishihara
Headers show

Comments

Jun Wu - Feb. 10, 2016, 5:07 p.m.
# HG changeset patch
# User Jun Wu <quark@fb.com>
# Date 1455123574 0
#      Wed Feb 10 16:59:34 2016 +0000
# Node ID d58f659625ed84ce90f6eef1403199ba4f18f037
# Parent  a036e1ae1fbe88ab99cb861ebfc2e4da7a3912ca
extensions: add loadfailed to return extensions failed to load (API)

chgserver is designed to preload all the extensions specified in config. The
server needs to know which extensions fail to load to take futher action, for
example, reload these extensions or refuse to continue. There is no easy way
to know this kind of information without duplicating part of extensions.py.

This patch adds extensions.loadfailed() to access names of extensions failed
to load.
Yuya Nishihara - Feb. 11, 2016, 1:22 p.m.
On Wed, 10 Feb 2016 17:07:52 +0000, Jun Wu wrote:
> # HG changeset patch
> # User Jun Wu <quark@fb.com>
> # Date 1455123574 0
> #      Wed Feb 10 16:59:34 2016 +0000
> # Node ID d58f659625ed84ce90f6eef1403199ba4f18f037
> # Parent  a036e1ae1fbe88ab99cb861ebfc2e4da7a3912ca
> extensions: add loadfailed to return extensions failed to load (API)

This isn't an incompatible API change, so (API) isn't necessary.

> chgserver is designed to preload all the extensions specified in config. The
> server needs to know which extensions fail to load to take futher action, for
> example, reload these extensions or refuse to continue. There is no easy way
> to know this kind of information without duplicating part of extensions.py.
> 
> This patch adds extensions.loadfailed() to access names of extensions failed
> to load.
> 
> diff --git a/mercurial/extensions.py b/mercurial/extensions.py
> --- a/mercurial/extensions.py
> +++ b/mercurial/extensions.py
> @@ -26,6 +26,7 @@
>  _order = []
>  _builtin = set(['hbisect', 'bookmarks', 'parentrevspec', 'progress', 'interhg',
>                  'inotify'])
> +_loadfailed = set()
>  
>  def extensions(ui=None):
>      if ui:
> @@ -130,6 +131,7 @@
>          except KeyboardInterrupt:
>              raise
>          except Exception as inst:
> +            _loadfailed.add(name)

load() has more logic to refuse to load extensions. I'm not sure if it should
be counted as a failure, but if it is, '_extensions[k] is None' means 'k' was
failed to load.

> +  $ cat <<EOF > printproblemic.py
> +  > from mercurial import cmdutil, commands, extensions
> +  > cmdtable = {}
> +  > command = cmdutil.command(cmdtable)
> +  > @command('badexts', norepo=True)
> +  > def badexts(*args):
> +  >     print('BADEXTS: %s' % ' '.join(sorted(extensions.loadfailed())))

Use ui.write() to avoid confusion of print statement/function.

Patch

diff --git a/mercurial/extensions.py b/mercurial/extensions.py
--- a/mercurial/extensions.py
+++ b/mercurial/extensions.py
@@ -26,6 +26,7 @@ 
 _order = []
 _builtin = set(['hbisect', 'bookmarks', 'parentrevspec', 'progress', 'interhg',
                 'inotify'])
+_loadfailed = set()
 
 def extensions(ui=None):
     if ui:
@@ -130,6 +131,7 @@ 
         except KeyboardInterrupt:
             raise
         except Exception as inst:
+            _loadfailed.add(name)
             if path:
                 ui.warn(_("*** failed to import extension %s from %s: %s\n")
                         % (name, path, inst))
@@ -456,6 +458,9 @@ 
 
     return exts
 
+def loadfailed():
+    return list(_loadfailed)
+
 def moduleversion(module):
     '''return version information from given module as a string'''
     if (util.safehasattr(module, 'getversion')
diff --git a/tests/test-bad-extension.t b/tests/test-bad-extension.t
--- a/tests/test-bad-extension.t
+++ b/tests/test-bad-extension.t
@@ -38,3 +38,16 @@ 
   *** failed to import extension badext2: No module named badext2
   Traceback (most recent call last):
   ImportError: No module named badext2
+
+names of extensions failed to load can be accessed via extensions.loadfailed()
+
+  $ cat <<EOF > printproblemic.py
+  > from mercurial import cmdutil, commands, extensions
+  > cmdtable = {}
+  > command = cmdutil.command(cmdtable)
+  > @command('badexts', norepo=True)
+  > def badexts(*args):
+  >     print('BADEXTS: %s' % ' '.join(sorted(extensions.loadfailed())))
+  > EOF
+  $ hg --config extensions.a=printproblemic.py badexts 2>&1 | grep ^BADEXTS
+  BADEXTS: badext badext2