Xio*_*iov 2 python django ipython
我有一个相当基本的doctestable文件:
class Foo():
"""
>>> 3+2
5
"""
if __name__ in ("__main__", "__console__"):
import doctest
doctest.testmod(verbose=True)
Run Code Online (Sandbox Code Playgroud)
直接通过python运行时,它按预期工作.
但是,在iPython中,我得到了
1 items had no tests:
__main__
0 tests in 1 items.
0 passed and 0 failed.
Test passed.
Run Code Online (Sandbox Code Playgroud)
由于这是Django项目的一部分,并且需要访问所有适当的变量并且manage.py设置,我也可以通过修改后的命令运行它,该命令使用code.InteractiveConsole,其中一个结果是__name__设置到' __console__'.
使用上面的代码,我获得与iPython相同的结果.我尝试将最后一行更改为:
this = __import__(__name__)
doctest.testmod(this, verbose=True)
Run Code Online (Sandbox Code Playgroud)
__console__我猜到了一个ImportError ,这是有道理的.这对python或ipython都没有影响.
所以,我希望能够通过所有这三种方法成功运行doctests,尤其是InteractiveConsole方法,因为我希望很快就会需要Django小马魔法.
只是为了澄清,这是我所期待的:
Trying:
3+2
Expecting:
5
ok
1 items had no tests:
__main__
1 items passed all tests:
1 tests in __main__.Foo
1 tests in 2 items.
1 passed and 0 failed.
Test passed.
Run Code Online (Sandbox Code Playgroud)
问题的根源是,ipython扮演古怪的招数与__main__(通过其自己的FakeModule模块),使得通过时间doctest通过其反思的是"涉嫌模块" __dict__,Foo是不存在-这样的doctest不会递归到它.
这是一个解决方案:
class Foo():
"""
>>> 3+2
5
"""
if __name__ in ("__main__", "__console__"):
import doctest, inspect, sys
m = sys.modules['__main__']
m.__test__ = dict((n,v) for (n,v) in globals().items()
if inspect.isclass(v))
doctest.testmod(verbose=True)
Run Code Online (Sandbox Code Playgroud)
这个DOES按要求生产:
$ ipython dot.py
Trying:
3+2
Expecting:
5
ok
1 items had no tests:
__main__
1 items passed all tests:
1 tests in __main__.__test__.Foo
1 tests in 2 items.
1 passed and 0 failed.
Test passed.
Python 2.5.1 (r251:54863, Feb 6 2009, 19:02:12)
[[ snip snip ]]
In [1]:
Run Code Online (Sandbox Code Playgroud)
设置全局__test__不起作用,再次因为将其设置为您正在考虑的全局,__main__并不实际将其放置在__dict__被恢复的实际对象中m = sys.modules['__main__'],而后者正是表达式doctest在内部使用(实际上它使用sys.modules.get,但这里没有必要采取额外的预防措施,因为我们知道它__main__存在于sys.modules......它不是你期望它的对象! - ).
此外,只设置m.__test__ = globals()直接也不管用,出于不同的原因:doctest检查在值__test__都是字符串,函数,类,或模块,并没有一些选择,你不能保证globals()会满足该条件(其实也不会) .在这里我只选择类,如果你还想要函数或者你可以在调用中的genexp or中的if子句中使用dict.
我不知道你究竟是如何运行的Django的外壳,是能够执行脚本(我相信python manage.py shell不接受参数,你必须做别的东西,我无法猜测到底是什么- !),但类似的方法应该有所帮助(无论你的Django shell是使用ipython,默认是可用的,还是普通的Python):__test__在你获得的对象中进行适当的设置sys.modules['__main__'](或者__console__,如果那是你传递给doctest.testmod的那个,我应该工作,因为它模仿doctest将在内部做什么来找到你的测试字符串.
并且,总而言之,对设计,建筑,简洁,透明度和"黑魔法"的哲学反思......:
所有这些努力基本上都是为了打败ipython(也许是Django,虽然它可能只是将那部分委托给ipython)的"黑魔法"所需要的,正是为了你的"方便"代表你做的......任何时候,两个框架(或更多;-)独立地做每个自己的黑魔法品牌,互操作性可能突然需要大量的努力,并成为任何但方便;-).
我不是说,同样的便利可能已经提供(通过任何一种或多种IPython中,Django和/或文档测试的)无黑魔法,自省,假模块等; 每个框架的设计师和维护者都是精湛的工程师,我希望他们能够彻底完成他们的作业,并且只执行最少量的黑魔法,这对于提供他们认为需要的用户便利性是不可或缺的.然而,即使在这种情况下,"黑魔法"突然从方便到调试的噩梦梦想,只要你想要做的事,甚至轻微外什么框架的作者曾设想变成.
好吧,也许在这种情况下不是一场噩梦,但我确实注意到这个问题已经开放了一段时间,即使有赏金的诱惑它还没有得到很多答案 - 尽管你现在有两个答案可以选择来自,我使用__test__doctest 的特殊功能,@ codeape使用ironpython的特殊__IP.magic_run功能.我更喜欢我的,因为它不依赖任何内部或无证的东西 - __test__这是doctest的记录特征,而__IP对于那两个迫在眉睫的领先下划线,尖叫"深入内部,不要触摸"给我; - )...如果它在下一个版本发布时会让我感到惊讶.仍然,品味问题 - 答案可能被认为更"方便".
但是,这正是我的观点:在放弃简单性,透明度和/或避免内部/无证件/不稳定特征方面,便利可能会付出巨大代价; 所以,作为我们所有人的一个教训,我们可以逃脱的黑魔法最少(即使以放弃方便ε的方式付出代价),从长远来看,我们都会更快乐(和我们会让其他需要利用我们当前努力的开发人员更快乐.
| 归档时间: |
|
| 查看次数: |
2029 次 |
| 最近记录: |