如何处理 Mercurial 扩展中的错误
How to handle errors in Mercurial extension
在 Mercurial 扩展中处理错误的推荐方法是什么?我们无法在线找到这方面的任何文档。
以下示例将在 Windows shell 中打印 Hello world
并将 errorlevel
设置为 1
。
@command('print-parents', [('','', None, '')], '')
def printparents(ui, repo, node, **opts):
print "Hello world"
return True
为什么 errorlevel
设置为 1
?我们预计它会是 0
。在这种情况下,Python 或 Mercurial 如何处理 True
和 False
?更改为 return False
会产生 errorlevel
0
.
我们已经看到了一些 raise error.Abort(..)
的例子,但是这输出了一个非常冗长的调用堆栈,这不是必需的。需要一条简单的短信和正确的errorlevel
。
使用 Windows 7 和 Mercurial 3.4.1
在 @command
函数中,使用 ui.warn()
显示错误消息,然后 return 使用 整数 值设置退出代码:
if something_is_wrong:
ui.warn(_('Something is wrong, please correct this'))
return 1
但是,使用 raise mercurial.error.Abort()
也很好并且不会导致回溯,除非您将 ui.traceback
设置为 True
(默认为 False
)。提高 Abort()
通常会导致 ui.warn('abort: ' + msg_from_exception)
和 return -1
组合(导致 255 退出代码):
$ cat demo.py
from mercurial import cmdutil, error
cmdtable = {}
command = cmdutil.command(cmdtable)
@command('demo1', [], '')
def demo1(ui, repo, *args, **opts):
ui.warn('Error message written directly to ui.warn')
return 1
@command('demo2', [], '')
def demo2(ui, repo, *args, **opts):
raise error.Abort('Error message raised with Abort')
$ hg --config extensions.demo=`pwd`/demo.py demo1
Error message written directly to ui.warn
$ echo $?
1
$ hg --config extensions.demo=`pwd`/demo.py demo2
abort: Error message raised with Abort
$?
255
$ hg --config extensions.demo=`pwd`/demo.py --config ui.traceback=true demo2
Traceback (most recent call last):
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 204, in _runcatch
return _dispatch(req)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 880, in _dispatch
cmdpats, cmdoptions)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/extensions.py", line 210, in closure
return func(*(args + a), **kw)
File "/opt/facebook/hg/lib/python2.7/site-packages/fastmanifest/cachemanager.py", line 318, in runcommandtrigger
result = orig(*args, **kwargs)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/extensions.py", line 210, in closure
return func(*(args + a), **kw)
File "/opt/facebook/hg/lib/python2.7/site-packages/fastmanifest/__init__.py", line 174, in _logonexit
r = orig(ui, repo, cmd, fullargs, *args)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/extensions.py", line 210, in closure
return func(*(args + a), **kw)
File "/opt/facebook/hg/lib/python2.7/site-packages/hgext/journal.py", line 79, in runcommand
return orig(lui, repo, cmd, fullargs, *args)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 637, in runcommand
ret = _runcommand(ui, options, cmd, d)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/extensions.py", line 210, in closure
return func(*(args + a), **kw)
File "/opt/facebook/hg/lib/python2.7/site-packages/hgext/pager.py", line 160, in pagecmd
return orig(ui, options, cmd, cmdfunc)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/extensions.py", line 210, in closure
return func(*(args + a), **kw)
File "/opt/facebook/hg/lib/python2.7/site-packages/hgext/color.py", line 503, in colorcmd
return orig(ui_, opts, cmd, cmdfunc)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 1010, in _runcommand
return checkargs()
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 971, in checkargs
return cmdfunc()
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 877, in <lambda>
d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/util.py", line 1036, in check
return func(*args, **kwargs)
File "/tmp/demo/demo.py", line 13, in demo2
raise error.Abort('Error message raised with Abort')
Abort: Error message raised with Abort
abort: Error message raised with Abort
请注意,我必须明确启用回溯!
在Python中,bool
类型是int
的子类,True
的值为1
和False
具有 0
的整数值。因为 Mercurial 期望 @command
函数为 return 一个整数来设置退出代码(或 None
用于退出代码 0),您将退出代码设置为 1
通过 returning True
.
我通常会查看 mercurial.commands
模块和各种 hgext
扩展,以了解其他人如何解决特定问题。例如,hg grep
命令包含处理错误的示例:
try:
regexp = util.re.compile(pattern, reflags)
except re.error as inst:
ui.warn(_("grep: invalid match pattern: %s\n") % inst)
return 1
而 hg addremove
代码引发 error.Abort()
:
try:
sim = float(opts.get('similarity') or 100)
except ValueError:
raise error.Abort(_('similarity must be a number'))
我会使用 error.Abort()
来处理命令错误,并且 ui.warn()
加上 return 只有当您特别需要 255 以外的退出代码时才使用整数。
在 Mercurial 扩展中处理错误的推荐方法是什么?我们无法在线找到这方面的任何文档。
以下示例将在 Windows shell 中打印 Hello world
并将 errorlevel
设置为 1
。
@command('print-parents', [('','', None, '')], '')
def printparents(ui, repo, node, **opts):
print "Hello world"
return True
为什么 errorlevel
设置为 1
?我们预计它会是 0
。在这种情况下,Python 或 Mercurial 如何处理 True
和 False
?更改为 return False
会产生 errorlevel
0
.
我们已经看到了一些 raise error.Abort(..)
的例子,但是这输出了一个非常冗长的调用堆栈,这不是必需的。需要一条简单的短信和正确的errorlevel
。
使用 Windows 7 和 Mercurial 3.4.1
在 @command
函数中,使用 ui.warn()
显示错误消息,然后 return 使用 整数 值设置退出代码:
if something_is_wrong:
ui.warn(_('Something is wrong, please correct this'))
return 1
但是,使用 raise mercurial.error.Abort()
也很好并且不会导致回溯,除非您将 ui.traceback
设置为 True
(默认为 False
)。提高 Abort()
通常会导致 ui.warn('abort: ' + msg_from_exception)
和 return -1
组合(导致 255 退出代码):
$ cat demo.py
from mercurial import cmdutil, error
cmdtable = {}
command = cmdutil.command(cmdtable)
@command('demo1', [], '')
def demo1(ui, repo, *args, **opts):
ui.warn('Error message written directly to ui.warn')
return 1
@command('demo2', [], '')
def demo2(ui, repo, *args, **opts):
raise error.Abort('Error message raised with Abort')
$ hg --config extensions.demo=`pwd`/demo.py demo1
Error message written directly to ui.warn
$ echo $?
1
$ hg --config extensions.demo=`pwd`/demo.py demo2
abort: Error message raised with Abort
$?
255
$ hg --config extensions.demo=`pwd`/demo.py --config ui.traceback=true demo2
Traceback (most recent call last):
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 204, in _runcatch
return _dispatch(req)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 880, in _dispatch
cmdpats, cmdoptions)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/extensions.py", line 210, in closure
return func(*(args + a), **kw)
File "/opt/facebook/hg/lib/python2.7/site-packages/fastmanifest/cachemanager.py", line 318, in runcommandtrigger
result = orig(*args, **kwargs)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/extensions.py", line 210, in closure
return func(*(args + a), **kw)
File "/opt/facebook/hg/lib/python2.7/site-packages/fastmanifest/__init__.py", line 174, in _logonexit
r = orig(ui, repo, cmd, fullargs, *args)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/extensions.py", line 210, in closure
return func(*(args + a), **kw)
File "/opt/facebook/hg/lib/python2.7/site-packages/hgext/journal.py", line 79, in runcommand
return orig(lui, repo, cmd, fullargs, *args)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 637, in runcommand
ret = _runcommand(ui, options, cmd, d)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/extensions.py", line 210, in closure
return func(*(args + a), **kw)
File "/opt/facebook/hg/lib/python2.7/site-packages/hgext/pager.py", line 160, in pagecmd
return orig(ui, options, cmd, cmdfunc)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/extensions.py", line 210, in closure
return func(*(args + a), **kw)
File "/opt/facebook/hg/lib/python2.7/site-packages/hgext/color.py", line 503, in colorcmd
return orig(ui_, opts, cmd, cmdfunc)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 1010, in _runcommand
return checkargs()
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 971, in checkargs
return cmdfunc()
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 877, in <lambda>
d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/util.py", line 1036, in check
return func(*args, **kwargs)
File "/tmp/demo/demo.py", line 13, in demo2
raise error.Abort('Error message raised with Abort')
Abort: Error message raised with Abort
abort: Error message raised with Abort
请注意,我必须明确启用回溯!
在Python中,bool
类型是int
的子类,True
的值为1
和False
具有 0
的整数值。因为 Mercurial 期望 @command
函数为 return 一个整数来设置退出代码(或 None
用于退出代码 0),您将退出代码设置为 1
通过 returning True
.
我通常会查看 mercurial.commands
模块和各种 hgext
扩展,以了解其他人如何解决特定问题。例如,hg grep
命令包含处理错误的示例:
try:
regexp = util.re.compile(pattern, reflags)
except re.error as inst:
ui.warn(_("grep: invalid match pattern: %s\n") % inst)
return 1
而 hg addremove
代码引发 error.Abort()
:
try:
sim = float(opts.get('similarity') or 100)
except ValueError:
raise error.Abort(_('similarity must be a number'))
我会使用 error.Abort()
来处理命令错误,并且 ui.warn()
加上 return 只有当您特别需要 255 以外的退出代码时才使用整数。