使用预提交挂钩运行 Django 测试
我想使用 Mercurial 的预提交钩子运行所有 django 测试。每当测试失败时,提交就会中止。
目标是尽可能频繁地阻止破坏构建的提交。
编辑:最终使用外部脚本路由。这是我的 hgrc 的相关部分:
[hooks]
precommit = python ./pinax/projects/lgr/manage.py test lgr_photos --verbosity=0 --noinput
commit = hg push
这是我在钩子函数上的进展:
from os.path import join, dirname
import sys
from django.core.management import call_command
def hook(ui, repo, **kwargs):
project_path = join( dirname(repo.path), 'pinax', 'projects')
sys.path.insert(0, project_path)
from lgr.manage import *
output = call_command('test', verbosity=0, interactive=False)
#ui.warn(output)
我在这里做错了什么?
PS - 它给出了一个巨大的错误回溯,它完整地包含在下面,
jim@ubuntu:~/workspace/lgr$ hg ci -m 'testing hooks'
No username found, using '[email protected]' instead
error: precommit hook raised an exception: '_demandmod' object is not iterable
** unknown exception encountered, details follow
** report bug details to http://mercurial.selenic.com/bts/
** or [email protected]
** Mercurial Distributed SCM (version 1.3.1)
** Extensions loaded:
Traceback (most recent call last):
File "/usr/bin/hg", line 27, in <module>
mercurial.dispatch.run()
File "/usr/lib/pymodules/python2.6/mercurial/dispatch.py", line 16, in run
sys.exit(dispatch(sys.argv[1:]))
File "/usr/lib/pymodules/python2.6/mercurial/dispatch.py", line 27, in dispatch
return _runcatch(u, args)
File "/usr/lib/pymodules/python2.6/mercurial/dispatch.py", line 43, in _runcatch
return _dispatch(ui, args)
File "/usr/lib/pymodules/python2.6/mercurial/dispatch.py", line 449, in _dispatch
return runcommand(lui, repo, cmd, fullargs, ui, options, d)
File "/usr/lib/pymodules/python2.6/mercurial/dispatch.py", line 317, in runcommand
ret = _runcommand(ui, options, cmd, d)
File "/usr/lib/pymodules/python2.6/mercurial/dispatch.py", line 501, in _runcommand
return checkargs()
File "/usr/lib/pymodules/python2.6/mercurial/dispatch.py", line 454, in checkargs
return cmdfunc()
File "/usr/lib/pymodules/python2.6/mercurial/dispatch.py", line 448, in <lambda>
d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
File "/usr/lib/pymodules/python2.6/mercurial/util.py", line 402, in check
return func(*args, **kwargs)
File "/usr/lib/pymodules/python2.6/mercurial/commands.py", line 667, in commit
node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
File "/usr/lib/pymodules/python2.6/mercurial/cmdutil.py", line 1213, in commit
return commitfunc(ui, repo, message, match(repo, pats, opts), opts)
File "/usr/lib/pymodules/python2.6/mercurial/commands.py", line 665, in commitfunc
editor=e, extra=extra)
File "/usr/lib/pymodules/python2.6/mercurial/localrepo.py", line 886, in commit
ret = self.commitctx(cctx, True)
File "/usr/lib/pymodules/python2.6/mercurial/localrepo.py", line 915, in commitctx
self.hook("precommit", throw=True, parent1=xp1, parent2=xp2)
File "/usr/lib/pymodules/python2.6/mercurial/localrepo.py", line 139, in hook
return hook.hook(self.ui, self, name, throw, **args)
File "/usr/lib/pymodules/python2.6/mercurial/hook.py", line 119, in hook
r = _pythonhook(ui, repo, name, hname, hookfn, args, throw) or r
File "/usr/lib/pymodules/python2.6/mercurial/hook.py", line 52, in _pythonhook
r = obj(ui=ui, repo=repo, hooktype=name, **args)
这是重要的部分:
File "/home/jim/run_lgr_tests.py", line 11, in hook
output = call_command('test', verbosity=0, interactive=False)
其余的:
File "/usr/local/lib/python2.6/dist-packages/django/core/management/__init__.py", line 166, in call_command
return klass.execute(*args, **defaults)
File "/usr/local/lib/python2.6/dist-packages/django/core/management/base.py", line 213, in execute
translation.activate('en-us')
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/__init__.py", line 73, in activate
return real_activate(language)
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/__init__.py", line 43, in delayed_loader
return g['real_%s' % caller](*args, **kwargs)
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/trans_real.py", line 205, in activate
_active[currentThread()] = translation(language)
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/trans_real.py", line 194, in translation
default_translation = _fetch(settings.LANGUAGE_CODE)
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/trans_real.py", line 180, in _fetch
app = import_module(appname)
File "/usr/local/lib/python2.6/dist-packages/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 84, in _demandimport
return _origimport(name, globals, locals, fromlist)
File "/home/jim/workspace/lgr/pinax/projects/lgr/apps/lgr_hacks.py", line 5, in <module>
User.email = models.EmailField(_('email address'), blank=True, max_length=200)
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/__init__.py", line 62, in ugettext
return real_ugettext(message)
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/trans_real.py", line 286, in ugettext
return do_translate(message, 'ugettext')
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/trans_real.py", line 276, in do_translate
_default = translation(settings.LANGUAGE_CODE)
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/trans_real.py", line 194, in translation
default_translation = _fetch(settings.LANGUAGE_CODE)
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/trans_real.py", line 180, in _fetch
app = import_module(appname)
File "/usr/local/lib/python2.6/dist-packages/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 84, in _demandimport
return _origimport(name, globals, locals, fromlist)
File "/home/jim/workspace/lgr/pinax/apps/external_apps/djangodblog/__init__.py", line 1, in <module>
import djangodblog.admin
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 91, in _demandimport
return _origimport(name, globals, locals, fromlist)
File "/home/jim/workspace/lgr/pinax/apps/external_apps/djangodblog/admin.py", line 14, in <module>
admin.site.register(ErrorBatch, ErrorBatchAdmin)
File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/sites.py", line 90, in register
validate(admin_class, model)
File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/validation.py", line 22, in validate
models.get_apps()
File "/usr/local/lib/python2.6/dist-packages/django/db/models/loading.py", line 100, in get_apps
self._populate()
File "/usr/local/lib/python2.6/dist-packages/django/db/models/loading.py", line 58, in _populate
self.load_app(app_name, True)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/loading.py", line 74, in load_app
models = import_module('.models', app_name)
File "/usr/local/lib/python2.6/dist-packages/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 84, in _demandimport
return _origimport(name, globals, locals, fromlist)
File "/home/jim/workspace/lgr/pinax/projects/lgr/apps/account/models.py", line 7, in <module>
from timezones.fields import TimeZoneField
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 103, in _demandimport
mod = _origimport(name, globals, locals)
File "/home/jim/workspace/lgr/pinax/apps/external_apps/timezones/fields.py", line 12, in <module>
default_tz = pytz.timezone(getattr(settings, "TIME_ZONE", "UTC"))
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 75, in __getattribute__
self._load()
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 47, in _load
mod = _origimport(head, globals, locals)
File "/home/jim/workspace/lgr/pinax/libs/external_libs/pytz-2008b/pytz/__init__.py", line 29, in <module>
from pkg_resources import resource_stream
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 103, in _demandimport
mod = _origimport(name, globals, locals)
File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 2562, in <module>
working_set.require(__requires__)
File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 626, in require
needed = self.resolve(parse_requirements(requirements))
File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 505, in resolve
requirements = list(requirements)[::-1] # set up the stack
File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 2380, in parse_requirements
for line in lines:
File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 1814, in yield_lines
for s in yield_lines(ss):
File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 1813, in yield_lines
for ss in strs:
TypeError: '_demandmod' object is not iterable
I would like to run all my django tests using mercurial's precommit hook. Whenever a test fails the commit will be aborted.
The goal is to block build-breaking commits as often as possible.
edit: Ended up using the external script route. Here is the reletant portion of my hgrc:
[hooks]
precommit = python ./pinax/projects/lgr/manage.py test lgr_photos --verbosity=0 --noinput
commit = hg push
Here is my progress on the hook function:
from os.path import join, dirname
import sys
from django.core.management import call_command
def hook(ui, repo, **kwargs):
project_path = join( dirname(repo.path), 'pinax', 'projects')
sys.path.insert(0, project_path)
from lgr.manage import *
output = call_command('test', verbosity=0, interactive=False)
#ui.warn(output)
What am I doing wrong here?
PS - It's giving a HUGE error traceback, which is included in it's entirety below
jim@ubuntu:~/workspace/lgr$ hg ci -m 'testing hooks'
No username found, using '[email protected]' instead
error: precommit hook raised an exception: '_demandmod' object is not iterable
** unknown exception encountered, details follow
** report bug details to http://mercurial.selenic.com/bts/
** or [email protected]
** Mercurial Distributed SCM (version 1.3.1)
** Extensions loaded:
Traceback (most recent call last):
File "/usr/bin/hg", line 27, in <module>
mercurial.dispatch.run()
File "/usr/lib/pymodules/python2.6/mercurial/dispatch.py", line 16, in run
sys.exit(dispatch(sys.argv[1:]))
File "/usr/lib/pymodules/python2.6/mercurial/dispatch.py", line 27, in dispatch
return _runcatch(u, args)
File "/usr/lib/pymodules/python2.6/mercurial/dispatch.py", line 43, in _runcatch
return _dispatch(ui, args)
File "/usr/lib/pymodules/python2.6/mercurial/dispatch.py", line 449, in _dispatch
return runcommand(lui, repo, cmd, fullargs, ui, options, d)
File "/usr/lib/pymodules/python2.6/mercurial/dispatch.py", line 317, in runcommand
ret = _runcommand(ui, options, cmd, d)
File "/usr/lib/pymodules/python2.6/mercurial/dispatch.py", line 501, in _runcommand
return checkargs()
File "/usr/lib/pymodules/python2.6/mercurial/dispatch.py", line 454, in checkargs
return cmdfunc()
File "/usr/lib/pymodules/python2.6/mercurial/dispatch.py", line 448, in <lambda>
d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
File "/usr/lib/pymodules/python2.6/mercurial/util.py", line 402, in check
return func(*args, **kwargs)
File "/usr/lib/pymodules/python2.6/mercurial/commands.py", line 667, in commit
node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
File "/usr/lib/pymodules/python2.6/mercurial/cmdutil.py", line 1213, in commit
return commitfunc(ui, repo, message, match(repo, pats, opts), opts)
File "/usr/lib/pymodules/python2.6/mercurial/commands.py", line 665, in commitfunc
editor=e, extra=extra)
File "/usr/lib/pymodules/python2.6/mercurial/localrepo.py", line 886, in commit
ret = self.commitctx(cctx, True)
File "/usr/lib/pymodules/python2.6/mercurial/localrepo.py", line 915, in commitctx
self.hook("precommit", throw=True, parent1=xp1, parent2=xp2)
File "/usr/lib/pymodules/python2.6/mercurial/localrepo.py", line 139, in hook
return hook.hook(self.ui, self, name, throw, **args)
File "/usr/lib/pymodules/python2.6/mercurial/hook.py", line 119, in hook
r = _pythonhook(ui, repo, name, hname, hookfn, args, throw) or r
File "/usr/lib/pymodules/python2.6/mercurial/hook.py", line 52, in _pythonhook
r = obj(ui=ui, repo=repo, hooktype=name, **args)
here is the important part:
File "/home/jim/run_lgr_tests.py", line 11, in hook
output = call_command('test', verbosity=0, interactive=False)
and the rest:
File "/usr/local/lib/python2.6/dist-packages/django/core/management/__init__.py", line 166, in call_command
return klass.execute(*args, **defaults)
File "/usr/local/lib/python2.6/dist-packages/django/core/management/base.py", line 213, in execute
translation.activate('en-us')
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/__init__.py", line 73, in activate
return real_activate(language)
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/__init__.py", line 43, in delayed_loader
return g['real_%s' % caller](*args, **kwargs)
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/trans_real.py", line 205, in activate
_active[currentThread()] = translation(language)
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/trans_real.py", line 194, in translation
default_translation = _fetch(settings.LANGUAGE_CODE)
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/trans_real.py", line 180, in _fetch
app = import_module(appname)
File "/usr/local/lib/python2.6/dist-packages/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 84, in _demandimport
return _origimport(name, globals, locals, fromlist)
File "/home/jim/workspace/lgr/pinax/projects/lgr/apps/lgr_hacks.py", line 5, in <module>
User.email = models.EmailField(_('email address'), blank=True, max_length=200)
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/__init__.py", line 62, in ugettext
return real_ugettext(message)
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/trans_real.py", line 286, in ugettext
return do_translate(message, 'ugettext')
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/trans_real.py", line 276, in do_translate
_default = translation(settings.LANGUAGE_CODE)
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/trans_real.py", line 194, in translation
default_translation = _fetch(settings.LANGUAGE_CODE)
File "/usr/local/lib/python2.6/dist-packages/django/utils/translation/trans_real.py", line 180, in _fetch
app = import_module(appname)
File "/usr/local/lib/python2.6/dist-packages/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 84, in _demandimport
return _origimport(name, globals, locals, fromlist)
File "/home/jim/workspace/lgr/pinax/apps/external_apps/djangodblog/__init__.py", line 1, in <module>
import djangodblog.admin
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 91, in _demandimport
return _origimport(name, globals, locals, fromlist)
File "/home/jim/workspace/lgr/pinax/apps/external_apps/djangodblog/admin.py", line 14, in <module>
admin.site.register(ErrorBatch, ErrorBatchAdmin)
File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/sites.py", line 90, in register
validate(admin_class, model)
File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/validation.py", line 22, in validate
models.get_apps()
File "/usr/local/lib/python2.6/dist-packages/django/db/models/loading.py", line 100, in get_apps
self._populate()
File "/usr/local/lib/python2.6/dist-packages/django/db/models/loading.py", line 58, in _populate
self.load_app(app_name, True)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/loading.py", line 74, in load_app
models = import_module('.models', app_name)
File "/usr/local/lib/python2.6/dist-packages/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 84, in _demandimport
return _origimport(name, globals, locals, fromlist)
File "/home/jim/workspace/lgr/pinax/projects/lgr/apps/account/models.py", line 7, in <module>
from timezones.fields import TimeZoneField
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 103, in _demandimport
mod = _origimport(name, globals, locals)
File "/home/jim/workspace/lgr/pinax/apps/external_apps/timezones/fields.py", line 12, in <module>
default_tz = pytz.timezone(getattr(settings, "TIME_ZONE", "UTC"))
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 75, in __getattribute__
self._load()
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 47, in _load
mod = _origimport(head, globals, locals)
File "/home/jim/workspace/lgr/pinax/libs/external_libs/pytz-2008b/pytz/__init__.py", line 29, in <module>
from pkg_resources import resource_stream
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 103, in _demandimport
mod = _origimport(name, globals, locals)
File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 2562, in <module>
working_set.require(__requires__)
File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 626, in require
needed = self.resolve(parse_requirements(requirements))
File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 505, in resolve
requirements = list(requirements)[::-1] # set up the stack
File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 2380, in parse_requirements
for line in lines:
File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 1814, in yield_lines
for s in yield_lines(ss):
File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 1813, in yield_lines
for ss in strs:
TypeError: '_demandmod' object is not iterable
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
看起来 Mercurial 导入模块的方式与 Django 的方式有些冲突。
在尝试深入研究并解决这个问题之前,是否有任何理由不使用普通命令运行测试?
It looks like Mercurial's way of importing modules is clashing with Django's somehow.
Before trying to dive in and sort that out, is there any reason to not just run the tests with the normal command?