【问题标题】:How to handle errors in Mercurial extension如何处理 Mercurial 扩展中的错误
【发布时间】:2016-08-04 09:33:07
【问题描述】:

在 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 如何处理 TrueFalse?更改为返回 False 产生 errorlevel 0

我们已经看到了raise error.Abort(..) 的一些示例,但这会输出一个非常冗长的调用堆栈,这不是必需的。需要一条简单的短信和正确的errorlevel

使用 Windows 7 和 Mercurial 3.4.1

【问题讨论】:

  • 为什么你的命令返回True@command 的返回值被解释为退出代码,在 Python 中,True == 1

标签: python mercurial mercurial-extension


【解决方案1】:

@command 函数中,使用ui.warn() 显示错误消息,然后返回一个整数 值来设置退出代码:

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 的值为 1False 的整数值为 0。因为 Mercurial 期望 @command 函数返回一个整数来设置退出代码(或 None 用于退出代码 0),所以您可以通过返回 True 将退出代码设置为 1

我通常会查看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() 加上仅在您特别需要除 255 之外的退出代码时才返回一个整数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-27
    相关资源
    最近更新 更多