2016-08-04 20 views
0

Каков рекомендуемый подход к обработке ошибок в расширении Mercurial? Мы не могли найти никаких документов для этого аспекта в Интернете.Как обрабатывать ошибки в расширении Mercurial

Следующий пример напечатает Hello world и установит errorlevel в 1 в оболочке Windows.

@command('print-parents', [('','', None, '')], '') 
def printparents(ui, repo, node, **opts): 
    print "Hello world" 
    return True 

Почему errorlevel набор для 1? Мы ожидали, что это будет 0. Как Python или Mercurial обрабатывают True и False в этом контексте? Смена на возврат False производит errorlevel0.

Мы видели несколько примеров из raise error.Abort(..), но это выводит очень подробный вызов, который не является обязательным. Простым текстовым сообщением и правилом errorlevel является то, что необходимо.

Использование Windows 7 и Mercurial 3.4.1

+0

Почему ваша команда возвращает 'True' вообще? Возвращаемое значение '@ command' интерпретируется как код выхода и в Python,' True == 1'. –

ответ

0

В @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 имеет значение 1 и False имеет целочисленное значение 0. Поскольку Mercurial ожидает функции @command для возврата целого числа для установки кода выхода (или None для кода выхода 0), вы устанавливаете код выхода 1, возвращая 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() плюс возвращая целое число, только если вам нужен код выхода, отличный от 255.

+0

Очень хорошее описание, спасибо :-) – Lars