我如何知道Python的contract.py哪个合约失败了?
我正在使用 contract.py,Terrence Way 的 Python 按合同设计的参考实现。 当违反契约(前置条件/后置条件/不变式)时,实现会引发异常,但如果有多个契约与一个方法关联,它不会为您提供快速识别哪个特定契约失败的方法。
例如,如果我采用 circbuf.py 示例,并且违反了前提条件通过传入一个负参数,如下所示:
circbuf(-5)
然后我得到如下所示的回溯:
Traceback (most recent call last):
File "circbuf.py", line 115, in <module>
circbuf(-5)
File "<string>", line 3, in __assert_circbuf___init___chk
File "build/bdist.macosx-10.5-i386/egg/contract.py", line 1204, in call_constructor_all
File "build/bdist.macosx-10.5-i386/egg/contract.py", line 1293, in _method_call_all
File "build/bdist.macosx-10.5-i386/egg/contract.py", line 1332, in _call_all
File "build/bdist.macosx-10.5-i386/egg/contract.py", line 1371, in _check_preconditions
contract.PreconditionViolationError: ('__main__.circbuf.__init__', 4)
我的预感是 PreconditionViolationError (4) 中的第二个参数引用 circbuf 中的行号。init包含断言的文档字符串:
def __init__(self, leng):
"""Construct an empty circular buffer.
pre::
leng > 0
post[self]::
self.is_empty() and len(self.buf) == leng
"""
但是,必须打开文件并计算文档字符串行号是一件很痛苦的事情。 有人有更快的解决方案来识别哪个合同失败了吗?
(请注意,在此示例中,有一个前提条件,因此很明显,但也可以有多个前提条件)。
I'm playing with contract.py, Terrence Way's reference implementation of design-by-contract for Python. The implementation throws an exception when a contract (precondition/postcondition/invariant) is violated, but it doesn't provide you a quick way of identifying which specific contract has failed if there are multiple ones associated with a method.
For example, if I take the circbuf.py example, and violate the precondition by passing in a negative argument, like so:
circbuf(-5)
Then I get a traceback that looks like this:
Traceback (most recent call last):
File "circbuf.py", line 115, in <module>
circbuf(-5)
File "<string>", line 3, in __assert_circbuf___init___chk
File "build/bdist.macosx-10.5-i386/egg/contract.py", line 1204, in call_constructor_all
File "build/bdist.macosx-10.5-i386/egg/contract.py", line 1293, in _method_call_all
File "build/bdist.macosx-10.5-i386/egg/contract.py", line 1332, in _call_all
File "build/bdist.macosx-10.5-i386/egg/contract.py", line 1371, in _check_preconditions
contract.PreconditionViolationError: ('__main__.circbuf.__init__', 4)
My hunch is that the second argument in the PreconditionViolationError (4) refers to the line number in the circbuf.init docstring that contains the assertion:
def __init__(self, leng):
"""Construct an empty circular buffer.
pre::
leng > 0
post[self]::
self.is_empty() and len(self.buf) == leng
"""
However, it's a pain to have to open the file and count the docstring line numbers. Does anybody have a quicker solution for identifying which contract has failed?
(Note that in this example, there's a single precondition, so it's obvious, but multiple preconditions are possible).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是一个老问题,但我不妨回答一下。 我添加了一些输出,您将在注释 #jlr001 中看到它。 将下面的行添加到您的contract.py中,当它引发异常时,它将显示文档行号和触发它的语句。 仅此而已,但它至少会让您无需猜测触发它的条件。
This is an old question but I may as well answer it. I added some output, you'll see it at the comment # jlr001. Add the line below to your contract.py and when it raises an exception it will show the doc line number and the statement that triggered it. Nothing more than that, but it will at least stop you from needing to guess which condition triggered it.
如果不修改他的代码,我认为你不能,但因为这是 python...
如果你寻找他向用户引发异常的位置,我认为可以将你正在寻找的信息推送到其中...不过,我不希望您能够更好地进行回溯,因为代码实际上包含在注释块中,然后进行处理。
代码非常复杂,但这可能是一个值得一看的块 - 也许如果你转储一些参数,你可以弄清楚发生了什么......
Without modifying his code, I don't think you can, but since this is python...
If you look for where he raises the exception to the user, it I think is possible to push the info you're looking for into it... I wouldn't expect you to be able to get the trace-back to be any better though because the code is actually contained in a comment block and then processed.
The code is pretty complicated, but this might be a block to look at - maybe if you dump out some of the args you can figure out whats going on...