bee_python 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (488) hide show
  1. data/{build/README → README} +1 -1
  2. data/egg/egg/build.yml +11 -49
  3. data/egg/egg.yml +19 -27
  4. data/egg/http/build.erb +32 -36
  5. data/egg/http/libhttp.py +102 -0
  6. data/egg/http/pylint.cfg +236 -0
  7. data/egg/http/server.py +7 -0
  8. data/egg/http/test.erb +32 -0
  9. data/egg/http.yml +33 -29
  10. data/egg/mysql/mysql.py +8 -9
  11. data/egg/project/build.erb +21 -53
  12. data/egg/project/pylint.cfg +236 -0
  13. data/egg/project/test.py +2 -2
  14. data/egg/project.yml +23 -31
  15. data/egg/script/build.erb +18 -23
  16. data/egg/script/pylint.cfg +236 -0
  17. data/egg/script.yml +22 -18
  18. data/egg/source/source.py +6 -6
  19. data/egg/test/test.py +1 -1
  20. data/lib/bee_task_python.rb +3 -34
  21. data/python.yml +123 -0
  22. metadata +61 -503
  23. data/test/build.yml +0 -16
  24. data/test/tc_bee_task_python.rb +0 -27
  25. data/test/test_build.rb +0 -26
  26. data/test/test_build_listener.rb +0 -110
  27. data/test/ts_bee_python.rb +0 -26
  28. data/tools/common/__init__.py +0 -5
  29. data/tools/common/common/__init__.py +0 -140
  30. data/tools/common/common/__pkginfo__.py +0 -43
  31. data/tools/common/common/adbh.py +0 -35
  32. data/tools/common/common/cache.py +0 -114
  33. data/tools/common/common/changelog.py +0 -234
  34. data/tools/common/common/clcommands.py +0 -181
  35. data/tools/common/common/cli.py +0 -212
  36. data/tools/common/common/compat.py +0 -328
  37. data/tools/common/common/configuration.py +0 -1087
  38. data/tools/common/common/contexts.py +0 -58
  39. data/tools/common/common/corbautils.py +0 -117
  40. data/tools/common/common/daemon.py +0 -171
  41. data/tools/common/common/date.py +0 -279
  42. data/tools/common/common/db.py +0 -49
  43. data/tools/common/common/dbf.py +0 -229
  44. data/tools/common/common/debugger.py +0 -208
  45. data/tools/common/common/decorators.py +0 -190
  46. data/tools/common/common/deprecation.py +0 -118
  47. data/tools/common/common/fileutils.py +0 -409
  48. data/tools/common/common/graph.py +0 -259
  49. data/tools/common/common/html.py +0 -142
  50. data/tools/common/common/interface.py +0 -76
  51. data/tools/common/common/logging_ext.py +0 -166
  52. data/tools/common/common/modutils.py +0 -670
  53. data/tools/common/common/optik_ext.py +0 -383
  54. data/tools/common/common/optparser.py +0 -92
  55. data/tools/common/common/pdf_ext.py +0 -111
  56. data/tools/common/common/proc.py +0 -276
  57. data/tools/common/common/pyro_ext.py +0 -146
  58. data/tools/common/common/pytest.py +0 -754
  59. data/tools/common/common/shellutils.py +0 -383
  60. data/tools/common/common/sphinx_ext.py +0 -87
  61. data/tools/common/common/sphinxutils.py +0 -122
  62. data/tools/common/common/sqlgen.py +0 -31
  63. data/tools/common/common/table.py +0 -930
  64. data/tools/common/common/tasksqueue.py +0 -97
  65. data/tools/common/common/test/__init__.py +0 -1
  66. data/tools/common/common/test/data/ChangeLog +0 -184
  67. data/tools/common/common/test/data/MyPyPa-0.1.0-py2.5.egg +0 -0
  68. data/tools/common/common/test/data/__init__.py +0 -1
  69. data/tools/common/common/test/data/content_differ_dir/NOTHING +0 -0
  70. data/tools/common/common/test/data/content_differ_dir/README +0 -1
  71. data/tools/common/common/test/data/content_differ_dir/subdir/coin +0 -1
  72. data/tools/common/common/test/data/content_differ_dir/subdir/toto.txt +0 -53
  73. data/tools/common/common/test/data/file_differ_dir/NOTHING +0 -0
  74. data/tools/common/common/test/data/file_differ_dir/README +0 -1
  75. data/tools/common/common/test/data/file_differ_dir/subdir/toto.txt +0 -53
  76. data/tools/common/common/test/data/file_differ_dir/subdirtwo/Hello +0 -0
  77. data/tools/common/common/test/data/find_test/__init__.py +0 -0
  78. data/tools/common/common/test/data/find_test/foo.txt +0 -0
  79. data/tools/common/common/test/data/find_test/module.py +0 -0
  80. data/tools/common/common/test/data/find_test/module2.py +0 -0
  81. data/tools/common/common/test/data/find_test/newlines.txt +0 -0
  82. data/tools/common/common/test/data/find_test/noendingnewline.py +0 -0
  83. data/tools/common/common/test/data/find_test/nonregr.py +0 -0
  84. data/tools/common/common/test/data/find_test/normal_file.txt +0 -0
  85. data/tools/common/common/test/data/find_test/spam.txt +0 -0
  86. data/tools/common/common/test/data/find_test/sub/doc.txt +0 -0
  87. data/tools/common/common/test/data/find_test/sub/momo.py +0 -0
  88. data/tools/common/common/test/data/find_test/test.ini +0 -0
  89. data/tools/common/common/test/data/find_test/test1.msg +0 -0
  90. data/tools/common/common/test/data/find_test/test2.msg +0 -0
  91. data/tools/common/common/test/data/find_test/write_protected_file.txt +0 -0
  92. data/tools/common/common/test/data/foo.txt +0 -9
  93. data/tools/common/common/test/data/module.py +0 -88
  94. data/tools/common/common/test/data/module2.py +0 -77
  95. data/tools/common/common/test/data/newlines.txt +0 -3
  96. data/tools/common/common/test/data/noendingnewline.py +0 -36
  97. data/tools/common/common/test/data/nonregr.py +0 -14
  98. data/tools/common/common/test/data/normal_file.txt +0 -0
  99. data/tools/common/common/test/data/reference_dir/NOTHING +0 -0
  100. data/tools/common/common/test/data/reference_dir/README +0 -1
  101. data/tools/common/common/test/data/reference_dir/subdir/coin +0 -1
  102. data/tools/common/common/test/data/reference_dir/subdir/toto.txt +0 -53
  103. data/tools/common/common/test/data/same_dir/NOTHING +0 -0
  104. data/tools/common/common/test/data/same_dir/README +0 -1
  105. data/tools/common/common/test/data/same_dir/subdir/coin +0 -1
  106. data/tools/common/common/test/data/same_dir/subdir/toto.txt +0 -53
  107. data/tools/common/common/test/data/spam.txt +0 -9
  108. data/tools/common/common/test/data/sub/doc.txt +0 -1
  109. data/tools/common/common/test/data/sub/momo.py +0 -1
  110. data/tools/common/common/test/data/subdir_differ_dir/NOTHING +0 -0
  111. data/tools/common/common/test/data/subdir_differ_dir/README +0 -1
  112. data/tools/common/common/test/data/subdir_differ_dir/subdir/coin +0 -1
  113. data/tools/common/common/test/data/subdir_differ_dir/subdir/toto.txt +0 -53
  114. data/tools/common/common/test/data/test.ini +0 -20
  115. data/tools/common/common/test/data/test1.msg +0 -30
  116. data/tools/common/common/test/data/test2.msg +0 -42
  117. data/tools/common/common/test/data/write_protected_file.txt +0 -0
  118. data/tools/common/common/test/foomod.py +0 -17
  119. data/tools/common/common/test/unittest_cache.py +0 -129
  120. data/tools/common/common/test/unittest_changelog.py +0 -37
  121. data/tools/common/common/test/unittest_compat.py +0 -239
  122. data/tools/common/common/test/unittest_configuration.py +0 -348
  123. data/tools/common/common/test/unittest_date.py +0 -154
  124. data/tools/common/common/test/unittest_decorators.py +0 -62
  125. data/tools/common/common/test/unittest_deprecation.py +0 -76
  126. data/tools/common/common/test/unittest_fileutils.py +0 -133
  127. data/tools/common/common/test/unittest_graph.py +0 -50
  128. data/tools/common/common/test/unittest_html.py +0 -76
  129. data/tools/common/common/test/unittest_interface.py +0 -87
  130. data/tools/common/common/test/unittest_modutils.py +0 -244
  131. data/tools/common/common/test/unittest_pytest.py +0 -50
  132. data/tools/common/common/test/unittest_shellutils.py +0 -248
  133. data/tools/common/common/test/unittest_table.py +0 -448
  134. data/tools/common/common/test/unittest_taskqueue.py +0 -71
  135. data/tools/common/common/test/unittest_testlib.py +0 -956
  136. data/tools/common/common/test/unittest_textutils.py +0 -247
  137. data/tools/common/common/test/unittest_tree.py +0 -248
  138. data/tools/common/common/test/unittest_umessage.py +0 -55
  139. data/tools/common/common/test/unittest_ureports_html.py +0 -64
  140. data/tools/common/common/test/unittest_ureports_text.py +0 -105
  141. data/tools/common/common/test/unittest_xmlutils.py +0 -75
  142. data/tools/common/common/test/utils.py +0 -87
  143. data/tools/common/common/testlib.py +0 -1927
  144. data/tools/common/common/textutils.py +0 -476
  145. data/tools/common/common/tree.py +0 -372
  146. data/tools/common/common/umessage.py +0 -161
  147. data/tools/common/common/ureports/__init__.py +0 -174
  148. data/tools/common/common/ureports/docbook_writer.py +0 -139
  149. data/tools/common/common/ureports/html_writer.py +0 -131
  150. data/tools/common/common/ureports/nodes.py +0 -201
  151. data/tools/common/common/ureports/text_writer.py +0 -140
  152. data/tools/common/common/vcgutils.py +0 -216
  153. data/tools/common/common/visitor.py +0 -107
  154. data/tools/common/common/xmlrpcutils.py +0 -136
  155. data/tools/common/common/xmlutils.py +0 -61
  156. data/tools/coverage/coverage.py +0 -602
  157. data/tools/epydoc/__init__.py +0 -227
  158. data/tools/epydoc/__init__.pyc +0 -0
  159. data/tools/epydoc/apidoc.py +0 -2203
  160. data/tools/epydoc/apidoc.pyc +0 -0
  161. data/tools/epydoc/checker.py +0 -349
  162. data/tools/epydoc/checker.pyc +0 -0
  163. data/tools/epydoc/cli.py +0 -1470
  164. data/tools/epydoc/cli.pyc +0 -0
  165. data/tools/epydoc/compat.py +0 -250
  166. data/tools/epydoc/compat.pyc +0 -0
  167. data/tools/epydoc/docbuilder.py +0 -1358
  168. data/tools/epydoc/docbuilder.pyc +0 -0
  169. data/tools/epydoc/docintrospecter.py +0 -1056
  170. data/tools/epydoc/docintrospecter.pyc +0 -0
  171. data/tools/epydoc/docparser.py +0 -2113
  172. data/tools/epydoc/docparser.pyc +0 -0
  173. data/tools/epydoc/docstringparser.py +0 -1111
  174. data/tools/epydoc/docstringparser.pyc +0 -0
  175. data/tools/epydoc/docwriter/__init__.py +0 -12
  176. data/tools/epydoc/docwriter/__init__.pyc +0 -0
  177. data/tools/epydoc/docwriter/dotgraph.py +0 -1351
  178. data/tools/epydoc/docwriter/dotgraph.pyc +0 -0
  179. data/tools/epydoc/docwriter/html.py +0 -3491
  180. data/tools/epydoc/docwriter/html.pyc +0 -0
  181. data/tools/epydoc/docwriter/html_colorize.py +0 -909
  182. data/tools/epydoc/docwriter/html_colorize.pyc +0 -0
  183. data/tools/epydoc/docwriter/html_css.py +0 -550
  184. data/tools/epydoc/docwriter/html_css.pyc +0 -0
  185. data/tools/epydoc/docwriter/html_help.py +0 -190
  186. data/tools/epydoc/docwriter/html_help.pyc +0 -0
  187. data/tools/epydoc/docwriter/latex.py +0 -1187
  188. data/tools/epydoc/docwriter/latex.pyc +0 -0
  189. data/tools/epydoc/docwriter/plaintext.py +0 -276
  190. data/tools/epydoc/docwriter/plaintext.pyc +0 -0
  191. data/tools/epydoc/docwriter/xlink.py +0 -505
  192. data/tools/epydoc/docwriter/xlink.pyc +0 -0
  193. data/tools/epydoc/gui.py +0 -1148
  194. data/tools/epydoc/gui.pyc +0 -0
  195. data/tools/epydoc/log.py +0 -204
  196. data/tools/epydoc/log.pyc +0 -0
  197. data/tools/epydoc/markup/__init__.py +0 -623
  198. data/tools/epydoc/markup/__init__.pyc +0 -0
  199. data/tools/epydoc/markup/doctest.py +0 -311
  200. data/tools/epydoc/markup/doctest.pyc +0 -0
  201. data/tools/epydoc/markup/epytext.py +0 -2116
  202. data/tools/epydoc/markup/epytext.pyc +0 -0
  203. data/tools/epydoc/markup/javadoc.py +0 -250
  204. data/tools/epydoc/markup/javadoc.pyc +0 -0
  205. data/tools/epydoc/markup/plaintext.py +0 -78
  206. data/tools/epydoc/markup/plaintext.pyc +0 -0
  207. data/tools/epydoc/markup/pyval_repr.py +0 -532
  208. data/tools/epydoc/markup/pyval_repr.pyc +0 -0
  209. data/tools/epydoc/markup/restructuredtext.py +0 -906
  210. data/tools/epydoc/markup/restructuredtext.pyc +0 -0
  211. data/tools/epydoc/test/__init__.py +0 -97
  212. data/tools/epydoc/test/__init__.pyc +0 -0
  213. data/tools/epydoc/test/util.py +0 -226
  214. data/tools/epydoc/test/util.pyc +0 -0
  215. data/tools/epydoc/util.py +0 -289
  216. data/tools/epydoc/util.pyc +0 -0
  217. data/tools/logilab/logilab/__init__.py +0 -5
  218. data/tools/logilab/logilab/astng/__init__.py +0 -82
  219. data/tools/logilab/logilab/astng/__pkginfo__.py +0 -76
  220. data/tools/logilab/logilab/astng/_exceptions.py +0 -64
  221. data/tools/logilab/logilab/astng/_nodes_ast.py +0 -667
  222. data/tools/logilab/logilab/astng/_nodes_compiler.py +0 -758
  223. data/tools/logilab/logilab/astng/bases.py +0 -608
  224. data/tools/logilab/logilab/astng/builder.py +0 -239
  225. data/tools/logilab/logilab/astng/inference.py +0 -426
  226. data/tools/logilab/logilab/astng/inspector.py +0 -289
  227. data/tools/logilab/logilab/astng/manager.py +0 -421
  228. data/tools/logilab/logilab/astng/mixins.py +0 -165
  229. data/tools/logilab/logilab/astng/node_classes.py +0 -848
  230. data/tools/logilab/logilab/astng/nodes.py +0 -85
  231. data/tools/logilab/logilab/astng/nodes_as_string.py +0 -389
  232. data/tools/logilab/logilab/astng/patchcomptransformer.py +0 -159
  233. data/tools/logilab/logilab/astng/protocols.py +0 -333
  234. data/tools/logilab/logilab/astng/raw_building.py +0 -212
  235. data/tools/logilab/logilab/astng/rebuilder.py +0 -307
  236. data/tools/logilab/logilab/astng/scoped_nodes.py +0 -951
  237. data/tools/logilab/logilab/astng/test/__init__.py +0 -19
  238. data/tools/logilab/logilab/astng/test/data/MyPyPa-0.1.0-py2.5.egg +0 -0
  239. data/tools/logilab/logilab/astng/test/data/MyPyPa-0.1.0-py2.5.zip +0 -0
  240. data/tools/logilab/logilab/astng/test/data/SSL1/Connection1.py +0 -33
  241. data/tools/logilab/logilab/astng/test/data/SSL1/__init__.py +0 -20
  242. data/tools/logilab/logilab/astng/test/data/__init__.py +0 -20
  243. data/tools/logilab/logilab/astng/test/data/all.py +0 -29
  244. data/tools/logilab/logilab/astng/test/data/appl/__init__.py +0 -23
  245. data/tools/logilab/logilab/astng/test/data/appl/myConnection.py +0 -30
  246. data/tools/logilab/logilab/astng/test/data/format.py +0 -34
  247. data/tools/logilab/logilab/astng/test/data/module.py +0 -90
  248. data/tools/logilab/logilab/astng/test/data/module2.py +0 -112
  249. data/tools/logilab/logilab/astng/test/data/noendingnewline.py +0 -57
  250. data/tools/logilab/logilab/astng/test/data/nonregr.py +0 -76
  251. data/tools/logilab/logilab/astng/test/data/notall.py +0 -28
  252. data/tools/logilab/logilab/astng/test/data2/__init__.py +0 -20
  253. data/tools/logilab/logilab/astng/test/data2/clientmodule_test.py +0 -51
  254. data/tools/logilab/logilab/astng/test/data2/suppliermodule_test.py +0 -32
  255. data/tools/logilab/logilab/astng/test/regrtest.py +0 -135
  256. data/tools/logilab/logilab/astng/test/regrtest_data/absimport.py +0 -22
  257. data/tools/logilab/logilab/astng/test/regrtest_data/descriptor_crash.py +0 -31
  258. data/tools/logilab/logilab/astng/test/regrtest_data/import_package_subpackage_module.py +0 -68
  259. data/tools/logilab/logilab/astng/test/regrtest_data/package/__init__.py +0 -24
  260. data/tools/logilab/logilab/astng/test/regrtest_data/package/subpackage/__init__.py +0 -20
  261. data/tools/logilab/logilab/astng/test/regrtest_data/package/subpackage/module.py +0 -20
  262. data/tools/logilab/logilab/astng/test/unittest_builder.py +0 -684
  263. data/tools/logilab/logilab/astng/test/unittest_inference.py +0 -1112
  264. data/tools/logilab/logilab/astng/test/unittest_inspector.py +0 -105
  265. data/tools/logilab/logilab/astng/test/unittest_lookup.py +0 -302
  266. data/tools/logilab/logilab/astng/test/unittest_manager.py +0 -98
  267. data/tools/logilab/logilab/astng/test/unittest_nodes.py +0 -302
  268. data/tools/logilab/logilab/astng/test/unittest_scoped_nodes.py +0 -501
  269. data/tools/logilab/logilab/astng/test/unittest_utils.py +0 -104
  270. data/tools/logilab/logilab/astng/utils.py +0 -342
  271. data/tools/logilab/logilab/common/__init__.py +0 -140
  272. data/tools/logilab/logilab/common/__pkginfo__.py +0 -43
  273. data/tools/logilab/logilab/common/adbh.py +0 -35
  274. data/tools/logilab/logilab/common/cache.py +0 -114
  275. data/tools/logilab/logilab/common/changelog.py +0 -234
  276. data/tools/logilab/logilab/common/clcommands.py +0 -181
  277. data/tools/logilab/logilab/common/cli.py +0 -212
  278. data/tools/logilab/logilab/common/compat.py +0 -328
  279. data/tools/logilab/logilab/common/configuration.py +0 -1087
  280. data/tools/logilab/logilab/common/contexts.py +0 -58
  281. data/tools/logilab/logilab/common/corbautils.py +0 -117
  282. data/tools/logilab/logilab/common/daemon.py +0 -171
  283. data/tools/logilab/logilab/common/date.py +0 -279
  284. data/tools/logilab/logilab/common/db.py +0 -49
  285. data/tools/logilab/logilab/common/dbf.py +0 -229
  286. data/tools/logilab/logilab/common/debugger.py +0 -208
  287. data/tools/logilab/logilab/common/decorators.py +0 -190
  288. data/tools/logilab/logilab/common/deprecation.py +0 -118
  289. data/tools/logilab/logilab/common/fileutils.py +0 -409
  290. data/tools/logilab/logilab/common/graph.py +0 -259
  291. data/tools/logilab/logilab/common/html.py +0 -142
  292. data/tools/logilab/logilab/common/interface.py +0 -76
  293. data/tools/logilab/logilab/common/logging_ext.py +0 -166
  294. data/tools/logilab/logilab/common/modutils.py +0 -670
  295. data/tools/logilab/logilab/common/optik_ext.py +0 -383
  296. data/tools/logilab/logilab/common/optparser.py +0 -92
  297. data/tools/logilab/logilab/common/pdf_ext.py +0 -111
  298. data/tools/logilab/logilab/common/proc.py +0 -276
  299. data/tools/logilab/logilab/common/pyro_ext.py +0 -146
  300. data/tools/logilab/logilab/common/pytest.py +0 -754
  301. data/tools/logilab/logilab/common/shellutils.py +0 -383
  302. data/tools/logilab/logilab/common/sphinx_ext.py +0 -87
  303. data/tools/logilab/logilab/common/sphinxutils.py +0 -122
  304. data/tools/logilab/logilab/common/sqlgen.py +0 -31
  305. data/tools/logilab/logilab/common/table.py +0 -930
  306. data/tools/logilab/logilab/common/tasksqueue.py +0 -97
  307. data/tools/logilab/logilab/common/test/__init__.py +0 -1
  308. data/tools/logilab/logilab/common/test/data/ChangeLog +0 -184
  309. data/tools/logilab/logilab/common/test/data/MyPyPa-0.1.0-py2.5.egg +0 -0
  310. data/tools/logilab/logilab/common/test/data/__init__.py +0 -1
  311. data/tools/logilab/logilab/common/test/data/content_differ_dir/NOTHING +0 -0
  312. data/tools/logilab/logilab/common/test/data/content_differ_dir/README +0 -1
  313. data/tools/logilab/logilab/common/test/data/content_differ_dir/subdir/coin +0 -1
  314. data/tools/logilab/logilab/common/test/data/content_differ_dir/subdir/toto.txt +0 -53
  315. data/tools/logilab/logilab/common/test/data/file_differ_dir/NOTHING +0 -0
  316. data/tools/logilab/logilab/common/test/data/file_differ_dir/README +0 -1
  317. data/tools/logilab/logilab/common/test/data/file_differ_dir/subdir/toto.txt +0 -53
  318. data/tools/logilab/logilab/common/test/data/file_differ_dir/subdirtwo/Hello +0 -0
  319. data/tools/logilab/logilab/common/test/data/find_test/__init__.py +0 -0
  320. data/tools/logilab/logilab/common/test/data/find_test/foo.txt +0 -0
  321. data/tools/logilab/logilab/common/test/data/find_test/module.py +0 -0
  322. data/tools/logilab/logilab/common/test/data/find_test/module2.py +0 -0
  323. data/tools/logilab/logilab/common/test/data/find_test/newlines.txt +0 -0
  324. data/tools/logilab/logilab/common/test/data/find_test/noendingnewline.py +0 -0
  325. data/tools/logilab/logilab/common/test/data/find_test/nonregr.py +0 -0
  326. data/tools/logilab/logilab/common/test/data/find_test/normal_file.txt +0 -0
  327. data/tools/logilab/logilab/common/test/data/find_test/spam.txt +0 -0
  328. data/tools/logilab/logilab/common/test/data/find_test/sub/doc.txt +0 -0
  329. data/tools/logilab/logilab/common/test/data/find_test/sub/momo.py +0 -0
  330. data/tools/logilab/logilab/common/test/data/find_test/test.ini +0 -0
  331. data/tools/logilab/logilab/common/test/data/find_test/test1.msg +0 -0
  332. data/tools/logilab/logilab/common/test/data/find_test/test2.msg +0 -0
  333. data/tools/logilab/logilab/common/test/data/find_test/write_protected_file.txt +0 -0
  334. data/tools/logilab/logilab/common/test/data/foo.txt +0 -9
  335. data/tools/logilab/logilab/common/test/data/module.py +0 -88
  336. data/tools/logilab/logilab/common/test/data/module2.py +0 -77
  337. data/tools/logilab/logilab/common/test/data/newlines.txt +0 -3
  338. data/tools/logilab/logilab/common/test/data/noendingnewline.py +0 -36
  339. data/tools/logilab/logilab/common/test/data/nonregr.py +0 -14
  340. data/tools/logilab/logilab/common/test/data/normal_file.txt +0 -0
  341. data/tools/logilab/logilab/common/test/data/reference_dir/NOTHING +0 -0
  342. data/tools/logilab/logilab/common/test/data/reference_dir/README +0 -1
  343. data/tools/logilab/logilab/common/test/data/reference_dir/subdir/coin +0 -1
  344. data/tools/logilab/logilab/common/test/data/reference_dir/subdir/toto.txt +0 -53
  345. data/tools/logilab/logilab/common/test/data/same_dir/NOTHING +0 -0
  346. data/tools/logilab/logilab/common/test/data/same_dir/README +0 -1
  347. data/tools/logilab/logilab/common/test/data/same_dir/subdir/coin +0 -1
  348. data/tools/logilab/logilab/common/test/data/same_dir/subdir/toto.txt +0 -53
  349. data/tools/logilab/logilab/common/test/data/spam.txt +0 -9
  350. data/tools/logilab/logilab/common/test/data/sub/doc.txt +0 -1
  351. data/tools/logilab/logilab/common/test/data/sub/momo.py +0 -1
  352. data/tools/logilab/logilab/common/test/data/subdir_differ_dir/NOTHING +0 -0
  353. data/tools/logilab/logilab/common/test/data/subdir_differ_dir/README +0 -1
  354. data/tools/logilab/logilab/common/test/data/subdir_differ_dir/subdir/coin +0 -1
  355. data/tools/logilab/logilab/common/test/data/subdir_differ_dir/subdir/toto.txt +0 -53
  356. data/tools/logilab/logilab/common/test/data/test.ini +0 -20
  357. data/tools/logilab/logilab/common/test/data/test1.msg +0 -30
  358. data/tools/logilab/logilab/common/test/data/test2.msg +0 -42
  359. data/tools/logilab/logilab/common/test/data/write_protected_file.txt +0 -0
  360. data/tools/logilab/logilab/common/test/foomod.py +0 -17
  361. data/tools/logilab/logilab/common/test/unittest_cache.py +0 -129
  362. data/tools/logilab/logilab/common/test/unittest_changelog.py +0 -37
  363. data/tools/logilab/logilab/common/test/unittest_compat.py +0 -239
  364. data/tools/logilab/logilab/common/test/unittest_configuration.py +0 -348
  365. data/tools/logilab/logilab/common/test/unittest_date.py +0 -154
  366. data/tools/logilab/logilab/common/test/unittest_decorators.py +0 -62
  367. data/tools/logilab/logilab/common/test/unittest_deprecation.py +0 -76
  368. data/tools/logilab/logilab/common/test/unittest_fileutils.py +0 -133
  369. data/tools/logilab/logilab/common/test/unittest_graph.py +0 -50
  370. data/tools/logilab/logilab/common/test/unittest_html.py +0 -76
  371. data/tools/logilab/logilab/common/test/unittest_interface.py +0 -87
  372. data/tools/logilab/logilab/common/test/unittest_modutils.py +0 -244
  373. data/tools/logilab/logilab/common/test/unittest_pytest.py +0 -50
  374. data/tools/logilab/logilab/common/test/unittest_shellutils.py +0 -248
  375. data/tools/logilab/logilab/common/test/unittest_table.py +0 -448
  376. data/tools/logilab/logilab/common/test/unittest_taskqueue.py +0 -71
  377. data/tools/logilab/logilab/common/test/unittest_testlib.py +0 -956
  378. data/tools/logilab/logilab/common/test/unittest_textutils.py +0 -247
  379. data/tools/logilab/logilab/common/test/unittest_tree.py +0 -248
  380. data/tools/logilab/logilab/common/test/unittest_umessage.py +0 -55
  381. data/tools/logilab/logilab/common/test/unittest_ureports_html.py +0 -64
  382. data/tools/logilab/logilab/common/test/unittest_ureports_text.py +0 -105
  383. data/tools/logilab/logilab/common/test/unittest_xmlutils.py +0 -75
  384. data/tools/logilab/logilab/common/test/utils.py +0 -87
  385. data/tools/logilab/logilab/common/testlib.py +0 -1927
  386. data/tools/logilab/logilab/common/textutils.py +0 -476
  387. data/tools/logilab/logilab/common/tree.py +0 -372
  388. data/tools/logilab/logilab/common/umessage.py +0 -161
  389. data/tools/logilab/logilab/common/ureports/__init__.py +0 -174
  390. data/tools/logilab/logilab/common/ureports/docbook_writer.py +0 -139
  391. data/tools/logilab/logilab/common/ureports/html_writer.py +0 -131
  392. data/tools/logilab/logilab/common/ureports/nodes.py +0 -201
  393. data/tools/logilab/logilab/common/ureports/text_writer.py +0 -140
  394. data/tools/logilab/logilab/common/vcgutils.py +0 -216
  395. data/tools/logilab/logilab/common/visitor.py +0 -107
  396. data/tools/logilab/logilab/common/xmlrpcutils.py +0 -136
  397. data/tools/logilab/logilab/common/xmlutils.py +0 -61
  398. data/tools/pychecker/COPYRIGHT +0 -31
  399. data/tools/pychecker/ChangeLog +0 -349
  400. data/tools/pychecker/CodeChecks.py +0 -1969
  401. data/tools/pychecker/CodeChecks.pyc +0 -0
  402. data/tools/pychecker/CodeChecks.pyo +0 -0
  403. data/tools/pychecker/Config.py +0 -475
  404. data/tools/pychecker/Config.pyc +0 -0
  405. data/tools/pychecker/Config.pyo +0 -0
  406. data/tools/pychecker/KNOWN_BUGS +0 -100
  407. data/tools/pychecker/MAINTAINERS +0 -81
  408. data/tools/pychecker/NEWS +0 -406
  409. data/tools/pychecker/OP.py +0 -131
  410. data/tools/pychecker/OP.pyc +0 -0
  411. data/tools/pychecker/OP.pyo +0 -0
  412. data/tools/pychecker/OptionTypes.py +0 -117
  413. data/tools/pychecker/OptionTypes.pyc +0 -0
  414. data/tools/pychecker/OptionTypes.pyo +0 -0
  415. data/tools/pychecker/README +0 -152
  416. data/tools/pychecker/Stack.py +0 -115
  417. data/tools/pychecker/Stack.pyc +0 -0
  418. data/tools/pychecker/Stack.pyo +0 -0
  419. data/tools/pychecker/TODO +0 -101
  420. data/tools/pychecker/VERSION +0 -1
  421. data/tools/pychecker/Warning.py +0 -50
  422. data/tools/pychecker/Warning.pyc +0 -0
  423. data/tools/pychecker/Warning.pyo +0 -0
  424. data/tools/pychecker/__init__.py +0 -17
  425. data/tools/pychecker/__init__.pyc +0 -0
  426. data/tools/pychecker/__init__.pyo +0 -0
  427. data/tools/pychecker/checker.py +0 -961
  428. data/tools/pychecker/checker.pyc +0 -0
  429. data/tools/pychecker/checker.pyo +0 -0
  430. data/tools/pychecker/function.py +0 -159
  431. data/tools/pychecker/function.pyc +0 -0
  432. data/tools/pychecker/function.pyo +0 -0
  433. data/tools/pychecker/msgs.py +0 -175
  434. data/tools/pychecker/msgs.pyc +0 -0
  435. data/tools/pychecker/msgs.pyo +0 -0
  436. data/tools/pychecker/options.py +0 -275
  437. data/tools/pychecker/options.pyc +0 -0
  438. data/tools/pychecker/options.pyo +0 -0
  439. data/tools/pychecker/pcmodules.py +0 -19
  440. data/tools/pychecker/pcmodules.pyc +0 -0
  441. data/tools/pychecker/pcmodules.pyo +0 -0
  442. data/tools/pychecker/printer.py +0 -47
  443. data/tools/pychecker/printer.pyc +0 -0
  444. data/tools/pychecker/printer.pyo +0 -0
  445. data/tools/pychecker/python.py +0 -427
  446. data/tools/pychecker/python.pyc +0 -0
  447. data/tools/pychecker/python.pyo +0 -0
  448. data/tools/pychecker/utils.py +0 -102
  449. data/tools/pychecker/utils.pyc +0 -0
  450. data/tools/pychecker/utils.pyo +0 -0
  451. data/tools/pychecker/warn.py +0 -778
  452. data/tools/pychecker/warn.pyc +0 -0
  453. data/tools/pychecker/warn.pyo +0 -0
  454. data/tools/pylint2/pylint/__init__.py +0 -16
  455. data/tools/pylint2/pylint/__pkginfo__.py +0 -67
  456. data/tools/pylint2/pylint/checkers/__init__.py +0 -155
  457. data/tools/pylint2/pylint/checkers/base.py +0 -749
  458. data/tools/pylint2/pylint/checkers/classes.py +0 -527
  459. data/tools/pylint2/pylint/checkers/design_analysis.py +0 -344
  460. data/tools/pylint2/pylint/checkers/exceptions.py +0 -183
  461. data/tools/pylint2/pylint/checkers/format.py +0 -367
  462. data/tools/pylint2/pylint/checkers/imports.py +0 -379
  463. data/tools/pylint2/pylint/checkers/logging.py +0 -98
  464. data/tools/pylint2/pylint/checkers/misc.py +0 -128
  465. data/tools/pylint2/pylint/checkers/newstyle.py +0 -107
  466. data/tools/pylint2/pylint/checkers/raw_metrics.py +0 -125
  467. data/tools/pylint2/pylint/checkers/similar.py +0 -333
  468. data/tools/pylint2/pylint/checkers/string_format.py +0 -239
  469. data/tools/pylint2/pylint/checkers/typecheck.py +0 -364
  470. data/tools/pylint2/pylint/checkers/utils.py +0 -208
  471. data/tools/pylint2/pylint/checkers/variables.py +0 -498
  472. data/tools/pylint2/pylint/config.py +0 -149
  473. data/tools/pylint2/pylint/epylint.py +0 -149
  474. data/tools/pylint2/pylint/gui.py +0 -433
  475. data/tools/pylint2/pylint/interfaces.py +0 -98
  476. data/tools/pylint2/pylint/lint.py +0 -914
  477. data/tools/pylint2/pylint/pyreverse/__init__.py +0 -5
  478. data/tools/pylint2/pylint/pyreverse/diadefslib.py +0 -229
  479. data/tools/pylint2/pylint/pyreverse/diagrams.py +0 -247
  480. data/tools/pylint2/pylint/pyreverse/main.py +0 -123
  481. data/tools/pylint2/pylint/pyreverse/utils.py +0 -131
  482. data/tools/pylint2/pylint/pyreverse/writer.py +0 -196
  483. data/tools/pylint2/pylint/reporters/__init__.py +0 -67
  484. data/tools/pylint2/pylint/reporters/guireporter.py +0 -36
  485. data/tools/pylint2/pylint/reporters/html.py +0 -69
  486. data/tools/pylint2/pylint/reporters/text.py +0 -156
  487. data/tools/pylint2/pylint/utils.py +0 -518
  488. data/tools/pylint2/pylint.py +0 -16
@@ -1,1927 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
3
- # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
4
- #
5
- # This file is part of logilab-common.
6
- #
7
- # logilab-common is free software: you can redistribute it and/or modify it under
8
- # the terms of the GNU Lesser General Public License as published by the Free
9
- # Software Foundation, either version 2.1 of the License, or (at your option) any
10
- # later version.
11
- #
12
- # logilab-common is distributed in the hope that it will be useful, but WITHOUT
13
- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14
- # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15
- # details.
16
- #
17
- # You should have received a copy of the GNU Lesser General Public License along
18
- # with logilab-common. If not, see <http://www.gnu.org/licenses/>.
19
- """Run tests.
20
-
21
- This will find all modules whose name match a given prefix in the test
22
- directory, and run them. Various command line options provide
23
- additional facilities.
24
-
25
- Command line options:
26
-
27
- -v verbose -- run tests in verbose mode with output to stdout
28
- -q quiet -- don't print anything except if a test fails
29
- -t testdir -- directory where the tests will be found
30
- -x exclude -- add a test to exclude
31
- -p profile -- profiled execution
32
- -c capture -- capture standard out/err during tests
33
- -d dbc -- enable design-by-contract
34
- -m match -- only run test matching the tag pattern which follow
35
-
36
- If no non-option arguments are present, prefixes used are 'test',
37
- 'regrtest', 'smoketest' and 'unittest'.
38
-
39
- """
40
- __docformat__ = "restructuredtext en"
41
- # modified copy of some functions from test/regrtest.py from PyXml
42
- # disable camel case warning
43
- # pylint: disable-msg=C0103
44
-
45
- import sys
46
- import os, os.path as osp
47
- import re
48
- import time
49
- import getopt
50
- import traceback
51
- import inspect
52
- import unittest
53
- import difflib
54
- import types
55
- import tempfile
56
- import math
57
- from shutil import rmtree
58
- from operator import itemgetter
59
- import warnings
60
- from compiler.consts import CO_GENERATOR
61
- from ConfigParser import ConfigParser
62
- from itertools import dropwhile
63
- from functools import wraps
64
-
65
- try:
66
- from test import test_support
67
- except ImportError:
68
- # not always available
69
- class TestSupport:
70
- def unload(self, test):
71
- pass
72
- test_support = TestSupport()
73
-
74
- # pylint: disable-msg=W0622
75
- from logilab.common.compat import set, enumerate, any, sorted
76
- # pylint: enable-msg=W0622
77
- from logilab.common.modutils import load_module_from_name
78
- from logilab.common.debugger import Debugger, colorize_source
79
- from logilab.common.decorators import cached, classproperty
80
- from logilab.common import textutils
81
-
82
-
83
- __all__ = ['main', 'unittest_main', 'find_tests', 'run_test', 'spawn']
84
-
85
- DEFAULT_PREFIXES = ('test', 'regrtest', 'smoketest', 'unittest',
86
- 'func', 'validation')
87
-
88
- ENABLE_DBC = False
89
-
90
- FILE_RESTART = ".pytest.restart"
91
-
92
- # used by unittest to count the number of relevant levels in the traceback
93
- __unittest = 1
94
-
95
-
96
- def with_tempdir(callable):
97
- """A decorator ensuring no temporary file left when the function return
98
- Work only for temporary file create with the tempfile module"""
99
- @wraps(callable)
100
- def proxy(*args, **kargs):
101
-
102
- old_tmpdir = tempfile.gettempdir()
103
- new_tmpdir = tempfile.mkdtemp(prefix="temp-lgc-")
104
- tempfile.tempdir = new_tmpdir
105
- try:
106
- return callable(*args, **kargs)
107
- finally:
108
- try:
109
- rmtree(new_tmpdir, ignore_errors=True)
110
- finally:
111
- tempfile.tempdir = old_tmpdir
112
- return proxy
113
-
114
- def in_tempdir(callable):
115
- """A decorator moving the enclosed function inside the tempfile.tempfdir
116
- """
117
- @wraps(callable)
118
- def proxy(*args, **kargs):
119
-
120
- old_cwd = os.getcwd()
121
- os.chdir(tempfile.tempdir)
122
- try:
123
- return callable(*args, **kargs)
124
- finally:
125
- os.chdir(old_cwd)
126
- return proxy
127
-
128
- def within_tempdir(callable):
129
- """A decorator run the enclosed function inside a tmpdir removed after execution
130
- """
131
- proxy = with_tempdir(in_tempdir(callable))
132
- proxy.__name__ = callable.__name__
133
- return proxy
134
-
135
- def run_tests(tests, quiet, verbose, runner=None, capture=0):
136
- """Execute a list of tests.
137
-
138
- :rtype: tuple
139
- :return: tuple (list of passed tests, list of failed tests, list of skipped tests)
140
- """
141
- good = []
142
- bad = []
143
- skipped = []
144
- all_result = None
145
- for test in tests:
146
- if not quiet:
147
- print
148
- print '-'*80
149
- print "Executing", test
150
- result = run_test(test, verbose, runner, capture)
151
- if type(result) is type(''):
152
- # an unexpected error occurred
153
- skipped.append( (test, result))
154
- else:
155
- if all_result is None:
156
- all_result = result
157
- else:
158
- all_result.testsRun += result.testsRun
159
- all_result.failures += result.failures
160
- all_result.errors += result.errors
161
- all_result.skipped += result.skipped
162
- if result.errors or result.failures:
163
- bad.append(test)
164
- if verbose:
165
- print "test", test, \
166
- "failed -- %s errors, %s failures" % (
167
- len(result.errors), len(result.failures))
168
- else:
169
- good.append(test)
170
-
171
- return good, bad, skipped, all_result
172
-
173
- def find_tests(testdir,
174
- prefixes=DEFAULT_PREFIXES, suffix=".py",
175
- excludes=(),
176
- remove_suffix=True):
177
- """
178
- Return a list of all applicable test modules.
179
- """
180
- tests = []
181
- for name in os.listdir(testdir):
182
- if not suffix or name.endswith(suffix):
183
- for prefix in prefixes:
184
- if name.startswith(prefix):
185
- if remove_suffix and name.endswith(suffix):
186
- name = name[:-len(suffix)]
187
- if name not in excludes:
188
- tests.append(name)
189
- tests.sort()
190
- return tests
191
-
192
-
193
- def run_test(test, verbose, runner=None, capture=0):
194
- """
195
- Run a single test.
196
-
197
- test -- the name of the test
198
- verbose -- if true, print more messages
199
- """
200
- test_support.unload(test)
201
- try:
202
- m = load_module_from_name(test, path=sys.path)
203
- # m = __import__(test, globals(), locals(), sys.path)
204
- try:
205
- suite = m.suite
206
- if callable(suite):
207
- suite = suite()
208
- except AttributeError:
209
- loader = unittest.TestLoader()
210
- suite = loader.loadTestsFromModule(m)
211
- if runner is None:
212
- runner = SkipAwareTextTestRunner(capture=capture) # verbosity=0)
213
- return runner.run(suite)
214
- except KeyboardInterrupt, v:
215
- raise KeyboardInterrupt, v, sys.exc_info()[2]
216
- except:
217
- # raise
218
- type, value = sys.exc_info()[:2]
219
- msg = "test %s crashed -- %s : %s" % (test, type, value)
220
- if verbose:
221
- traceback.print_exc()
222
- return msg
223
-
224
- def _count(n, word):
225
- """format word according to n"""
226
- if n == 1:
227
- return "%d %s" % (n, word)
228
- else:
229
- return "%d %ss" % (n, word)
230
-
231
-
232
-
233
-
234
- ## PostMortem Debug facilities #####
235
- def start_interactive_mode(result):
236
- """starts an interactive shell so that the user can inspect errors
237
- """
238
- debuggers = result.debuggers
239
- descrs = result.error_descrs + result.fail_descrs
240
- if len(debuggers) == 1:
241
- # don't ask for test name if there's only one failure
242
- debuggers[0].start()
243
- else:
244
- while True:
245
- testindex = 0
246
- print "Choose a test to debug:"
247
- # order debuggers in the same way than errors were printed
248
- print "\n".join(['\t%s : %s' % (i, descr) for i, (_, descr)
249
- in enumerate(descrs)])
250
- print "Type 'exit' (or ^D) to quit"
251
- print
252
- try:
253
- todebug = raw_input('Enter a test name: ')
254
- if todebug.strip().lower() == 'exit':
255
- print
256
- break
257
- else:
258
- try:
259
- testindex = int(todebug)
260
- debugger = debuggers[descrs[testindex][0]]
261
- except (ValueError, IndexError):
262
- print "ERROR: invalid test number %r" % (todebug, )
263
- else:
264
- debugger.start()
265
- except (EOFError, KeyboardInterrupt):
266
- print
267
- break
268
-
269
-
270
- # test utils ##################################################################
271
- from cStringIO import StringIO
272
-
273
- class SkipAwareTestResult(unittest._TextTestResult):
274
-
275
- def __init__(self, stream, descriptions, verbosity,
276
- exitfirst=False, capture=0, printonly=None,
277
- pdbmode=False, cvg=None, colorize=False):
278
- super(SkipAwareTestResult, self).__init__(stream,
279
- descriptions, verbosity)
280
- self.skipped = []
281
- self.debuggers = []
282
- self.fail_descrs = []
283
- self.error_descrs = []
284
- self.exitfirst = exitfirst
285
- self.capture = capture
286
- self.printonly = printonly
287
- self.pdbmode = pdbmode
288
- self.cvg = cvg
289
- self.colorize = colorize
290
- self.pdbclass = Debugger
291
- self.verbose = verbosity > 1
292
-
293
- def descrs_for(self, flavour):
294
- return getattr(self, '%s_descrs' % flavour.lower())
295
-
296
- def _create_pdb(self, test_descr, flavour):
297
- self.descrs_for(flavour).append( (len(self.debuggers), test_descr) )
298
- if self.pdbmode:
299
- self.debuggers.append(self.pdbclass(sys.exc_info()[2]))
300
-
301
-
302
- def _iter_valid_frames(self, frames):
303
- """only consider non-testlib frames when formatting traceback"""
304
- lgc_testlib = osp.abspath(__file__)
305
- std_testlib = osp.abspath(unittest.__file__)
306
- invalid = lambda fi: osp.abspath(fi[1]) in (lgc_testlib, std_testlib)
307
- for frameinfo in dropwhile(invalid, frames):
308
- yield frameinfo
309
-
310
- def _exc_info_to_string(self, err, test):
311
- """Converts a sys.exc_info()-style tuple of values into a string.
312
-
313
- This method is overridden here because we want to colorize
314
- lines if --color is passed, and display local variables if
315
- --verbose is passed
316
- """
317
- exctype, exc, tb = err
318
- output = ['Traceback (most recent call last)']
319
- frames = inspect.getinnerframes(tb)
320
- colorize = self.colorize
321
- frames = enumerate(self._iter_valid_frames(frames))
322
- for index, (frame, filename, lineno, funcname, ctx, ctxindex) in frames:
323
- filename = osp.abspath(filename)
324
- if ctx is None: # pyc files or C extensions for instance
325
- source = '<no source available>'
326
- else:
327
- source = ''.join(ctx)
328
- if colorize:
329
- filename = textutils.colorize_ansi(filename, 'magenta')
330
- source = colorize_source(source)
331
- output.append(' File "%s", line %s, in %s' % (filename, lineno, funcname))
332
- output.append(' %s' % source.strip())
333
- if self.verbose:
334
- output.append('%r == %r' % (dir(frame), test.__module__))
335
- output.append('')
336
- output.append(' ' + ' local variables '.center(66, '-'))
337
- for varname, value in sorted(frame.f_locals.items()):
338
- output.append(' %s: %r' % (varname, value))
339
- if varname == 'self': # special handy processing for self
340
- for varname, value in sorted(vars(value).items()):
341
- output.append(' self.%s: %r' % (varname, value))
342
- output.append(' ' + '-' * 66)
343
- output.append('')
344
- output.append(''.join(traceback.format_exception_only(exctype, exc)))
345
- return '\n'.join(output)
346
-
347
- def addError(self, test, err):
348
- """err == (exc_type, exc, tcbk)"""
349
- exc_type, exc, _ = err #
350
- if exc_type == TestSkipped:
351
- self.addSkipped(test, exc)
352
- else:
353
- if self.exitfirst:
354
- self.shouldStop = True
355
- descr = self.getDescription(test)
356
- super(SkipAwareTestResult, self).addError(test, err)
357
- self._create_pdb(descr, 'error')
358
-
359
- def addFailure(self, test, err):
360
- if self.exitfirst:
361
- self.shouldStop = True
362
- descr = self.getDescription(test)
363
- super(SkipAwareTestResult, self).addFailure(test, err)
364
- self._create_pdb(descr, 'fail')
365
-
366
- def addSkipped(self, test, reason):
367
- self.skipped.append((test, self.getDescription(test), reason))
368
- if self.showAll:
369
- self.stream.writeln("SKIPPED")
370
- elif self.dots:
371
- self.stream.write('S')
372
-
373
- def printErrors(self):
374
- super(SkipAwareTestResult, self).printErrors()
375
- self.printSkippedList()
376
-
377
- def printSkippedList(self):
378
- for _, descr, err in self.skipped: # test, descr, err
379
- self.stream.writeln(self.separator1)
380
- self.stream.writeln("%s: %s" % ('SKIPPED', descr))
381
- self.stream.writeln("\t%s" % err)
382
-
383
- def printErrorList(self, flavour, errors):
384
- for (_, descr), (test, err) in zip(self.descrs_for(flavour), errors):
385
- self.stream.writeln(self.separator1)
386
- if self.colorize:
387
- self.stream.writeln("%s: %s" % (
388
- textutils.colorize_ansi(flavour, color='red'), descr))
389
- else:
390
- self.stream.writeln("%s: %s" % (flavour, descr))
391
-
392
- self.stream.writeln(self.separator2)
393
- self.stream.writeln(err)
394
- try:
395
- output, errput = test.captured_output()
396
- except AttributeError:
397
- pass # original unittest
398
- else:
399
- if output:
400
- self.stream.writeln(self.separator2)
401
- self.stream.writeln("captured stdout".center(
402
- len(self.separator2)))
403
- self.stream.writeln(self.separator2)
404
- self.stream.writeln(output)
405
- else:
406
- self.stream.writeln('no stdout'.center(
407
- len(self.separator2)))
408
- if errput:
409
- self.stream.writeln(self.separator2)
410
- self.stream.writeln("captured stderr".center(
411
- len(self.separator2)))
412
- self.stream.writeln(self.separator2)
413
- self.stream.writeln(errput)
414
- else:
415
- self.stream.writeln('no stderr'.center(
416
- len(self.separator2)))
417
-
418
-
419
- def run(self, result, runcondition=None, options=None):
420
- for test in self._tests:
421
- if result.shouldStop:
422
- break
423
- try:
424
- test(result, runcondition, options)
425
- except TypeError:
426
- # this might happen if a raw unittest.TestCase is defined
427
- # and used with python (and not pytest)
428
- warnings.warn("%s should extend lgc.testlib.TestCase instead of unittest.TestCase"
429
- % test)
430
- test(result)
431
- return result
432
- unittest.TestSuite.run = run
433
-
434
- # backward compatibility: TestSuite might be imported from lgc.testlib
435
- TestSuite = unittest.TestSuite
436
-
437
- # python2.3 compat
438
- def __call__(self, *args, **kwds):
439
- return self.run(*args, **kwds)
440
- unittest.TestSuite.__call__ = __call__
441
-
442
-
443
- class SkipAwareTextTestRunner(unittest.TextTestRunner):
444
-
445
- def __init__(self, stream=sys.stderr, verbosity=1,
446
- exitfirst=False, capture=False, printonly=None,
447
- pdbmode=False, cvg=None, test_pattern=None,
448
- skipped_patterns=(), colorize=False, batchmode=False,
449
- options=None):
450
- super(SkipAwareTextTestRunner, self).__init__(stream=stream,
451
- verbosity=verbosity)
452
- self.exitfirst = exitfirst
453
- self.capture = capture
454
- self.printonly = printonly
455
- self.pdbmode = pdbmode
456
- self.cvg = cvg
457
- self.test_pattern = test_pattern
458
- self.skipped_patterns = skipped_patterns
459
- self.colorize = colorize
460
- self.batchmode = batchmode
461
- self.options = options
462
-
463
- def _this_is_skipped(self, testedname):
464
- return any([(pat in testedname) for pat in self.skipped_patterns])
465
-
466
- def _runcondition(self, test, skipgenerator=True):
467
- if isinstance(test, InnerTest):
468
- testname = test.name
469
- else:
470
- if isinstance(test, TestCase):
471
- meth = test._get_test_method()
472
- func = meth.im_func
473
- testname = '%s.%s' % (meth.im_class.__name__, func.__name__)
474
- elif isinstance(test, types.FunctionType):
475
- func = test
476
- testname = func.__name__
477
- elif isinstance(test, types.MethodType):
478
- func = test.im_func
479
- testname = '%s.%s' % (test.im_class.__name__, func.__name__)
480
- else:
481
- return True # Not sure when this happens
482
-
483
- if is_generator(func) and skipgenerator:
484
- return self.does_match_tags(func) # Let inner tests decide at run time
485
-
486
- # print 'testname', testname, self.test_pattern
487
- if self._this_is_skipped(testname):
488
- return False # this was explicitly skipped
489
- if self.test_pattern is not None:
490
- try:
491
- classpattern, testpattern = self.test_pattern.split('.')
492
- klass, name = testname.split('.')
493
- if classpattern not in klass or testpattern not in name:
494
- return False
495
- except ValueError:
496
- if self.test_pattern not in testname:
497
- return False
498
-
499
- return self.does_match_tags(test)
500
-
501
- def does_match_tags(self, test):
502
- if self.options is not None:
503
- tags_pattern = getattr(self.options, 'tags_pattern', None)
504
- if tags_pattern is not None:
505
- tags = getattr(test, 'tags', None)
506
- if tags is not None:
507
- return tags.match(tags_pattern)
508
- if isinstance(test, types.MethodType):
509
- tags = getattr(test.im_class, 'tags', Tags())
510
- return tags.match(tags_pattern)
511
- return False
512
- return True # no pattern
513
-
514
- def _makeResult(self):
515
- return SkipAwareTestResult(self.stream, self.descriptions,
516
- self.verbosity, self.exitfirst, self.capture,
517
- self.printonly, self.pdbmode, self.cvg,
518
- self.colorize)
519
-
520
- def run(self, test):
521
- "Run the given test case or test suite."
522
- result = self._makeResult()
523
- startTime = time.time()
524
- test(result, self._runcondition, self.options)
525
- stopTime = time.time()
526
- timeTaken = stopTime - startTime
527
- result.printErrors()
528
- if not self.batchmode:
529
- self.stream.writeln(result.separator2)
530
- run = result.testsRun
531
- self.stream.writeln("Ran %d test%s in %.3fs" %
532
- (run, run != 1 and "s" or "", timeTaken))
533
- self.stream.writeln()
534
- if not result.wasSuccessful():
535
- if self.colorize:
536
- self.stream.write(textutils.colorize_ansi("FAILED", color='red'))
537
- else:
538
- self.stream.write("FAILED")
539
- else:
540
- if self.colorize:
541
- self.stream.write(textutils.colorize_ansi("OK", color='green'))
542
- else:
543
- self.stream.write("OK")
544
- failed, errored, skipped = map(len, (result.failures, result.errors,
545
- result.skipped))
546
-
547
- det_results = []
548
- for name, value in (("failures", result.failures),
549
- ("errors",result.errors),
550
- ("skipped", result.skipped)):
551
- if value:
552
- det_results.append("%s=%i" % (name, len(value)))
553
- if det_results:
554
- self.stream.write(" (")
555
- self.stream.write(', '.join(det_results))
556
- self.stream.write(")")
557
- self.stream.writeln("")
558
- return result
559
-
560
-
561
- class keywords(dict):
562
- """Keyword args (**kwargs) support for generative tests."""
563
-
564
- class starargs(tuple):
565
- """Variable arguments (*args) for generative tests."""
566
- def __new__(cls, *args):
567
- return tuple.__new__(cls, args)
568
-
569
-
570
-
571
- class NonStrictTestLoader(unittest.TestLoader):
572
- """
573
- Overrides default testloader to be able to omit classname when
574
- specifying tests to run on command line.
575
-
576
- For example, if the file test_foo.py contains ::
577
-
578
- class FooTC(TestCase):
579
- def test_foo1(self): # ...
580
- def test_foo2(self): # ...
581
- def test_bar1(self): # ...
582
-
583
- class BarTC(TestCase):
584
- def test_bar2(self): # ...
585
-
586
- 'python test_foo.py' will run the 3 tests in FooTC
587
- 'python test_foo.py FooTC' will run the 3 tests in FooTC
588
- 'python test_foo.py test_foo' will run test_foo1 and test_foo2
589
- 'python test_foo.py test_foo1' will run test_foo1
590
- 'python test_foo.py test_bar' will run FooTC.test_bar1 and BarTC.test_bar2
591
- """
592
-
593
- def __init__(self):
594
- self.skipped_patterns = []
595
-
596
- def loadTestsFromNames(self, names, module=None):
597
- suites = []
598
- for name in names:
599
- suites.extend(self.loadTestsFromName(name, module))
600
- return self.suiteClass(suites)
601
-
602
- def _collect_tests(self, module):
603
- tests = {}
604
- for obj in vars(module).values():
605
- if (issubclass(type(obj), (types.ClassType, type)) and
606
- issubclass(obj, unittest.TestCase)):
607
- classname = obj.__name__
608
- if classname[0] == '_' or self._this_is_skipped(classname):
609
- continue
610
- methodnames = []
611
- # obj is a TestCase class
612
- for attrname in dir(obj):
613
- if attrname.startswith(self.testMethodPrefix):
614
- attr = getattr(obj, attrname)
615
- if callable(attr):
616
- methodnames.append(attrname)
617
- # keep track of class (obj) for convenience
618
- tests[classname] = (obj, methodnames)
619
- return tests
620
-
621
- def loadTestsFromSuite(self, module, suitename):
622
- try:
623
- suite = getattr(module, suitename)()
624
- except AttributeError:
625
- return []
626
- assert hasattr(suite, '_tests'), \
627
- "%s.%s is not a valid TestSuite" % (module.__name__, suitename)
628
- # python2.3 does not implement __iter__ on suites, we need to return
629
- # _tests explicitly
630
- return suite._tests
631
-
632
- def loadTestsFromName(self, name, module=None):
633
- parts = name.split('.')
634
- if module is None or len(parts) > 2:
635
- # let the base class do its job here
636
- return [super(NonStrictTestLoader, self).loadTestsFromName(name)]
637
- tests = self._collect_tests(module)
638
- # import pprint
639
- # pprint.pprint(tests)
640
- collected = []
641
- if len(parts) == 1:
642
- pattern = parts[0]
643
- if callable(getattr(module, pattern, None)
644
- ) and pattern not in tests:
645
- # consider it as a suite
646
- return self.loadTestsFromSuite(module, pattern)
647
- if pattern in tests:
648
- # case python unittest_foo.py MyTestTC
649
- klass, methodnames = tests[pattern]
650
- for methodname in methodnames:
651
- collected = [klass(methodname)
652
- for methodname in methodnames]
653
- else:
654
- # case python unittest_foo.py something
655
- for klass, methodnames in tests.values():
656
- collected += [klass(methodname)
657
- for methodname in methodnames]
658
- elif len(parts) == 2:
659
- # case "MyClass.test_1"
660
- classname, pattern = parts
661
- klass, methodnames = tests.get(classname, (None, []))
662
- for methodname in methodnames:
663
- collected = [klass(methodname) for methodname in methodnames]
664
- return collected
665
-
666
- def _this_is_skipped(self, testedname):
667
- return any([(pat in testedname) for pat in self.skipped_patterns])
668
-
669
- def getTestCaseNames(self, testCaseClass):
670
- """Return a sorted sequence of method names found within testCaseClass
671
- """
672
- is_skipped = self._this_is_skipped
673
- classname = testCaseClass.__name__
674
- if classname[0] == '_' or is_skipped(classname):
675
- return []
676
- testnames = super(NonStrictTestLoader, self).getTestCaseNames(
677
- testCaseClass)
678
- return [testname for testname in testnames if not is_skipped(testname)]
679
-
680
-
681
- class SkipAwareTestProgram(unittest.TestProgram):
682
- # XXX: don't try to stay close to unittest.py, use optparse
683
- USAGE = """\
684
- Usage: %(progName)s [options] [test] [...]
685
-
686
- Options:
687
- -h, --help Show this message
688
- -v, --verbose Verbose output
689
- -i, --pdb Enable test failure inspection
690
- -x, --exitfirst Exit on first failure
691
- -c, --capture Captures and prints standard out/err only on errors
692
- -p, --printonly Only prints lines matching specified pattern
693
- (implies capture)
694
- -s, --skip skip test matching this pattern (no regexp for now)
695
- -q, --quiet Minimal output
696
- --color colorize tracebacks
697
-
698
- -m, --match Run only test whose tag match this pattern
699
-
700
- -P, --profile FILE: Run the tests using cProfile and saving results
701
- in FILE
702
-
703
- Examples:
704
- %(progName)s - run default set of tests
705
- %(progName)s MyTestSuite - run suite 'MyTestSuite'
706
- %(progName)s MyTestCase.testSomething - run MyTestCase.testSomething
707
- %(progName)s MyTestCase - run all 'test*' test methods
708
- in MyTestCase
709
- """
710
- def __init__(self, module='__main__', defaultTest=None, batchmode=False,
711
- cvg=None, options=None, outstream=sys.stderr):
712
- self.batchmode = batchmode
713
- self.cvg = cvg
714
- self.options = options
715
- self.outstream = outstream
716
- super(SkipAwareTestProgram, self).__init__(
717
- module=module, defaultTest=defaultTest,
718
- testLoader=NonStrictTestLoader())
719
-
720
- def parseArgs(self, argv):
721
- self.pdbmode = False
722
- self.exitfirst = False
723
- self.capture = 0
724
- self.printonly = None
725
- self.skipped_patterns = []
726
- self.test_pattern = None
727
- self.tags_pattern = None
728
- self.colorize = False
729
- self.profile_name = None
730
- import getopt
731
- try:
732
- options, args = getopt.getopt(argv[1:], 'hHvixrqcp:s:m:P:',
733
- ['help', 'verbose', 'quiet', 'pdb',
734
- 'exitfirst', 'restart', 'capture', 'printonly=',
735
- 'skip=', 'color', 'match=', 'profile='])
736
- for opt, value in options:
737
- if opt in ('-h', '-H', '--help'):
738
- self.usageExit()
739
- if opt in ('-i', '--pdb'):
740
- self.pdbmode = True
741
- if opt in ('-x', '--exitfirst'):
742
- self.exitfirst = True
743
- if opt in ('-r', '--restart'):
744
- self.restart = True
745
- self.exitfirst = True
746
- if opt in ('-q', '--quiet'):
747
- self.verbosity = 0
748
- if opt in ('-v', '--verbose'):
749
- self.verbosity = 2
750
- if opt in ('-c', '--capture'):
751
- self.capture += 1
752
- if opt in ('-p', '--printonly'):
753
- self.printonly = re.compile(value)
754
- if opt in ('-s', '--skip'):
755
- self.skipped_patterns = [pat.strip() for pat in
756
- value.split(', ')]
757
- if opt == '--color':
758
- self.colorize = True
759
- if opt in ('-m', '--match'):
760
- #self.tags_pattern = value
761
- self.options["tag_pattern"] = value
762
- if opt in ('-P', '--profile'):
763
- self.profile_name = value
764
- self.testLoader.skipped_patterns = self.skipped_patterns
765
- if self.printonly is not None:
766
- self.capture += 1
767
- if len(args) == 0 and self.defaultTest is None:
768
- suitefunc = getattr(self.module, 'suite', None)
769
- if isinstance(suitefunc, (types.FunctionType,
770
- types.MethodType)):
771
- self.test = self.module.suite()
772
- else:
773
- self.test = self.testLoader.loadTestsFromModule(self.module)
774
- return
775
- if len(args) > 0:
776
- self.test_pattern = args[0]
777
- self.testNames = args
778
- else:
779
- self.testNames = (self.defaultTest, )
780
- self.createTests()
781
- except getopt.error, msg:
782
- self.usageExit(msg)
783
-
784
-
785
- def runTests(self):
786
- if self.profile_name:
787
- import cProfile
788
- cProfile.runctx('self._runTests()', globals(), locals(), self.profile_name )
789
- else:
790
- return self._runTests()
791
-
792
- def _runTests(self):
793
- if hasattr(self.module, 'setup_module'):
794
- try:
795
- self.module.setup_module(self.options)
796
- except Exception, exc:
797
- print 'setup_module error:', exc
798
- sys.exit(1)
799
- self.testRunner = SkipAwareTextTestRunner(verbosity=self.verbosity,
800
- stream=self.outstream,
801
- exitfirst=self.exitfirst,
802
- capture=self.capture,
803
- printonly=self.printonly,
804
- pdbmode=self.pdbmode,
805
- cvg=self.cvg,
806
- test_pattern=self.test_pattern,
807
- skipped_patterns=self.skipped_patterns,
808
- colorize=self.colorize,
809
- batchmode=self.batchmode,
810
- options=self.options)
811
-
812
- def removeSucceededTests(obj, succTests):
813
- """ Recursive function that removes succTests from
814
- a TestSuite or TestCase
815
- """
816
- if isinstance(obj, TestSuite):
817
- removeSucceededTests(obj._tests, succTests)
818
- if isinstance(obj, list):
819
- for el in obj[:]:
820
- if isinstance(el, TestSuite):
821
- removeSucceededTests(el, succTests)
822
- elif isinstance(el, TestCase):
823
- descr = '.'.join((el.__class__.__module__,
824
- el.__class__.__name__,
825
- el._testMethodName))
826
- if descr in succTests:
827
- obj.remove(el)
828
- # take care, self.options may be None
829
- if getattr(self.options, 'restart', False):
830
- # retrieve succeeded tests from FILE_RESTART
831
- try:
832
- restartfile = open(FILE_RESTART, 'r')
833
- try:
834
- try:
835
- succeededtests = list(elem.rstrip('\n\r') for elem in
836
- restartfile.readlines())
837
- removeSucceededTests(self.test, succeededtests)
838
- except Exception, e:
839
- raise e
840
- finally:
841
- restartfile.close()
842
- except Exception ,e:
843
- raise "Error while reading \
844
- succeeded tests into", osp.join(os.getcwd(),FILE_RESTART)
845
-
846
- result = self.testRunner.run(self.test)
847
- # help garbage collection: we want TestSuite, which hold refs to every
848
- # executed TestCase, to be gc'ed
849
- del self.test
850
- if hasattr(self.module, 'teardown_module'):
851
- try:
852
- self.module.teardown_module(self.options, result)
853
- except Exception, exc:
854
- print 'teardown_module error:', exc
855
- sys.exit(1)
856
- if result.debuggers and self.pdbmode:
857
- start_interactive_mode(result)
858
- if not self.batchmode:
859
- sys.exit(not result.wasSuccessful())
860
- self.result = result
861
-
862
-
863
-
864
-
865
- class FDCapture:
866
- """adapted from py lib (http://codespeak.net/py)
867
- Capture IO to/from a given os-level filedescriptor.
868
- """
869
- def __init__(self, fd, attr='stdout', printonly=None):
870
- self.targetfd = fd
871
- self.tmpfile = os.tmpfile() # self.maketempfile()
872
- self.printonly = printonly
873
- # save original file descriptor
874
- self._savefd = os.dup(fd)
875
- # override original file descriptor
876
- os.dup2(self.tmpfile.fileno(), fd)
877
- # also modify sys module directly
878
- self.oldval = getattr(sys, attr)
879
- setattr(sys, attr, self) # self.tmpfile)
880
- self.attr = attr
881
-
882
- def write(self, msg):
883
- # msg might be composed of several lines
884
- for line in msg.splitlines():
885
- line += '\n' # keepdend=True is not enough
886
- if self.printonly is None or self.printonly.search(line) is None:
887
- self.tmpfile.write(line)
888
- else:
889
- os.write(self._savefd, line)
890
-
891
- ## def maketempfile(self):
892
- ## tmpf = os.tmpfile()
893
- ## fd = os.dup(tmpf.fileno())
894
- ## newf = os.fdopen(fd, tmpf.mode, 0) # No buffering
895
- ## tmpf.close()
896
- ## return newf
897
-
898
- def restore(self):
899
- """restore original fd and returns captured output"""
900
- #XXX: hack hack hack
901
- self.tmpfile.flush()
902
- try:
903
- ref_file = getattr(sys, '__%s__' % self.attr)
904
- ref_file.flush()
905
- except AttributeError:
906
- pass
907
- if hasattr(self.oldval, 'flush'):
908
- self.oldval.flush()
909
- # restore original file descriptor
910
- os.dup2(self._savefd, self.targetfd)
911
- # restore sys module
912
- setattr(sys, self.attr, self.oldval)
913
- # close backup descriptor
914
- os.close(self._savefd)
915
- # go to beginning of file and read it
916
- self.tmpfile.seek(0)
917
- return self.tmpfile.read()
918
-
919
-
920
- def _capture(which='stdout', printonly=None):
921
- """private method, should not be called directly
922
- (cf. capture_stdout() and capture_stderr())
923
- """
924
- assert which in ('stdout', 'stderr'
925
- ), "Can only capture stdout or stderr, not %s" % which
926
- if which == 'stdout':
927
- fd = 1
928
- else:
929
- fd = 2
930
- return FDCapture(fd, which, printonly)
931
-
932
- def capture_stdout(printonly=None):
933
- """captures the standard output
934
-
935
- returns a handle object which has a `restore()` method.
936
- The restore() method returns the captured stdout and restores it
937
- """
938
- return _capture('stdout', printonly)
939
-
940
- def capture_stderr(printonly=None):
941
- """captures the standard error output
942
-
943
- returns a handle object which has a `restore()` method.
944
- The restore() method returns the captured stderr and restores it
945
- """
946
- return _capture('stderr', printonly)
947
-
948
-
949
- def unittest_main(module='__main__', defaultTest=None,
950
- batchmode=False, cvg=None, options=None,
951
- outstream=sys.stderr):
952
- """use this function if you want to have the same functionality
953
- as unittest.main"""
954
- return SkipAwareTestProgram(module, defaultTest, batchmode,
955
- cvg, options, outstream)
956
-
957
- class TestSkipped(Exception):
958
- """raised when a test is skipped"""
959
-
960
- class InnerTestSkipped(TestSkipped):
961
- """raised when a test is skipped"""
962
-
963
- def is_generator(function):
964
- flags = function.func_code.co_flags
965
- return flags & CO_GENERATOR
966
-
967
-
968
- def parse_generative_args(params):
969
- args = []
970
- varargs = ()
971
- kwargs = {}
972
- flags = 0 # 2 <=> starargs, 4 <=> kwargs
973
- for param in params:
974
- if isinstance(param, starargs):
975
- varargs = param
976
- if flags:
977
- raise TypeError('found starargs after keywords !')
978
- flags |= 2
979
- args += list(varargs)
980
- elif isinstance(param, keywords):
981
- kwargs = param
982
- if flags & 4:
983
- raise TypeError('got multiple keywords parameters')
984
- flags |= 4
985
- elif flags & 2 or flags & 4:
986
- raise TypeError('found parameters after kwargs or args')
987
- else:
988
- args.append(param)
989
-
990
- return args, kwargs
991
-
992
- class InnerTest(tuple):
993
- def __new__(cls, name, *data):
994
- instance = tuple.__new__(cls, data)
995
- instance.name = name
996
- return instance
997
-
998
-
999
- class TestCase(unittest.TestCase):
1000
- """unittest.TestCase with some additional methods"""
1001
-
1002
- capture = False
1003
- pdbclass = Debugger
1004
-
1005
- def __init__(self, methodName='runTest'):
1006
- super(TestCase, self).__init__(methodName)
1007
- # internal API changed in python2.5
1008
- if sys.version_info >= (2, 5):
1009
- self.__exc_info = self._exc_info
1010
- self.__testMethodName = self._testMethodName
1011
- else:
1012
- # let's give easier access to _testMethodName to every subclasses
1013
- self._testMethodName = self.__testMethodName
1014
- self._captured_stdout = ""
1015
- self._captured_stderr = ""
1016
- self._out = []
1017
- self._err = []
1018
- self._current_test_descr = None
1019
- self._options_ = None
1020
-
1021
- def datadir(cls): # pylint: disable-msg=E0213
1022
- """helper attribute holding the standard test's data directory
1023
-
1024
- NOTE: this is a logilab's standard
1025
- """
1026
- mod = __import__(cls.__module__)
1027
- return osp.join(osp.dirname(osp.abspath(mod.__file__)), 'data')
1028
- # cache it (use a class method to cache on class since TestCase is
1029
- # instantiated for each test run)
1030
- datadir = classproperty(cached(datadir))
1031
-
1032
- def datapath(cls, *fname):
1033
- """joins the object's datadir and `fname`"""
1034
- return osp.join(cls.datadir, *fname)
1035
- datapath = classmethod(datapath)
1036
-
1037
- def set_description(self, descr):
1038
- """sets the current test's description.
1039
- This can be useful for generative tests because it allows to specify
1040
- a description per yield
1041
- """
1042
- self._current_test_descr = descr
1043
-
1044
- # override default's unittest.py feature
1045
- def shortDescription(self):
1046
- """override default unitest shortDescription to handle correctly
1047
- generative tests
1048
- """
1049
- if self._current_test_descr is not None:
1050
- return self._current_test_descr
1051
- return super(TestCase, self).shortDescription()
1052
-
1053
-
1054
- def captured_output(self):
1055
- """return a two tuple with standard output and error stripped"""
1056
- return self._captured_stdout.strip(), self._captured_stderr.strip()
1057
-
1058
- def _start_capture(self):
1059
- """start_capture if enable"""
1060
- if self.capture:
1061
- warnings.simplefilter('ignore', DeprecationWarning)
1062
- self.start_capture()
1063
-
1064
- def _stop_capture(self):
1065
- """stop_capture and restore previous output"""
1066
- self._force_output_restore()
1067
-
1068
- def start_capture(self, printonly=None):
1069
- """start_capture"""
1070
- self._out.append(capture_stdout(printonly or self._printonly))
1071
- self._err.append(capture_stderr(printonly or self._printonly))
1072
-
1073
- def printonly(self, pattern, flags=0):
1074
- """set the pattern of line to print"""
1075
- rgx = re.compile(pattern, flags)
1076
- if self._out:
1077
- self._out[-1].printonly = rgx
1078
- self._err[-1].printonly = rgx
1079
- else:
1080
- self.start_capture(printonly=rgx)
1081
-
1082
- def stop_capture(self):
1083
- """stop output and error capture"""
1084
- if self._out:
1085
- _out = self._out.pop()
1086
- _err = self._err.pop()
1087
- return _out.restore(), _err.restore()
1088
- return '', ''
1089
-
1090
- def _force_output_restore(self):
1091
- """remove all capture set"""
1092
- while self._out:
1093
- self._captured_stdout += self._out.pop().restore()
1094
- self._captured_stderr += self._err.pop().restore()
1095
-
1096
- def quiet_run(self, result, func, *args, **kwargs):
1097
- self._start_capture()
1098
- try:
1099
- func(*args, **kwargs)
1100
- except (KeyboardInterrupt, SystemExit):
1101
- self._stop_capture()
1102
- raise
1103
- except:
1104
- self._stop_capture()
1105
- result.addError(self, self.__exc_info())
1106
- return False
1107
- self._stop_capture()
1108
- return True
1109
-
1110
- def _get_test_method(self):
1111
- """return the test method"""
1112
- return getattr(self, self.__testMethodName)
1113
-
1114
-
1115
- def optval(self, option, default=None):
1116
- """return the option value or default if the option is not define"""
1117
- return getattr(self._options_, option, default)
1118
-
1119
- def __call__(self, result=None, runcondition=None, options=None):
1120
- """rewrite TestCase.__call__ to support generative tests
1121
- This is mostly a copy/paste from unittest.py (i.e same
1122
- variable names, same logic, except for the generative tests part)
1123
- """
1124
- if result is None:
1125
- result = self.defaultTestResult()
1126
- result.pdbclass = self.pdbclass
1127
- # if self.capture is True here, it means it was explicitly specified
1128
- # in the user's TestCase class. If not, do what was asked on cmd line
1129
- self.capture = self.capture or getattr(result, 'capture', False)
1130
- self._options_ = options
1131
- self._printonly = getattr(result, 'printonly', None)
1132
- # if result.cvg:
1133
- # result.cvg.start()
1134
- testMethod = self._get_test_method()
1135
- if runcondition and not runcondition(testMethod):
1136
- return # test is skipped
1137
- result.startTest(self)
1138
- try:
1139
- if not self.quiet_run(result, self.setUp):
1140
- return
1141
- generative = is_generator(testMethod.im_func)
1142
- # generative tests
1143
- if generative:
1144
- self._proceed_generative(result, testMethod,
1145
- runcondition)
1146
- else:
1147
- status = self._proceed(result, testMethod)
1148
- success = (status == 0)
1149
- if not self.quiet_run(result, self.tearDown):
1150
- return
1151
- if not generative and success:
1152
- if hasattr(options, "exitfirst") and options.exitfirst:
1153
- # add this test to restart file
1154
- try:
1155
- restartfile = open(FILE_RESTART, 'a')
1156
- try:
1157
- try:
1158
- descr = '.'.join((self.__class__.__module__,
1159
- self.__class__.__name__,
1160
- self._testMethodName))
1161
- restartfile.write(descr+os.linesep)
1162
- except Exception, e:
1163
- raise e
1164
- finally:
1165
- restartfile.close()
1166
- except Exception, e:
1167
- print >> sys.__stderr__, "Error while saving \
1168
- succeeded test into", osp.join(os.getcwd(),FILE_RESTART)
1169
- raise e
1170
- result.addSuccess(self)
1171
- finally:
1172
- # if result.cvg:
1173
- # result.cvg.stop()
1174
- result.stopTest(self)
1175
-
1176
-
1177
-
1178
- def _proceed_generative(self, result, testfunc, runcondition=None):
1179
- # cancel startTest()'s increment
1180
- result.testsRun -= 1
1181
- self._start_capture()
1182
- success = True
1183
- try:
1184
- for params in testfunc():
1185
- if runcondition and not runcondition(testfunc,
1186
- skipgenerator=False):
1187
- if not (isinstance(params, InnerTest)
1188
- and runcondition(params)):
1189
- continue
1190
- if not isinstance(params, (tuple, list)):
1191
- params = (params, )
1192
- func = params[0]
1193
- args, kwargs = parse_generative_args(params[1:])
1194
- # increment test counter manually
1195
- result.testsRun += 1
1196
- status = self._proceed(result, func, args, kwargs)
1197
- if status == 0:
1198
- result.addSuccess(self)
1199
- success = True
1200
- else:
1201
- success = False
1202
- if status == 2:
1203
- result.shouldStop = True
1204
- if result.shouldStop: # either on error or on exitfirst + error
1205
- break
1206
- except:
1207
- # if an error occurs between two yield
1208
- result.addError(self, self.__exc_info())
1209
- success = False
1210
- self._stop_capture()
1211
- return success
1212
-
1213
- def _proceed(self, result, testfunc, args=(), kwargs=None):
1214
- """proceed the actual test
1215
- returns 0 on success, 1 on failure, 2 on error
1216
-
1217
- Note: addSuccess can't be called here because we have to wait
1218
- for tearDown to be successfully executed to declare the test as
1219
- successful
1220
- """
1221
- self._start_capture()
1222
- kwargs = kwargs or {}
1223
- try:
1224
- testfunc(*args, **kwargs)
1225
- self._stop_capture()
1226
- except self.failureException:
1227
- self._stop_capture()
1228
- result.addFailure(self, self.__exc_info())
1229
- return 1
1230
- except KeyboardInterrupt:
1231
- self._stop_capture()
1232
- raise
1233
- except InnerTestSkipped, e:
1234
- result.addSkipped(self, e)
1235
- return 1
1236
- except:
1237
- self._stop_capture()
1238
- result.addError(self, self.__exc_info())
1239
- return 2
1240
- return 0
1241
-
1242
- def defaultTestResult(self):
1243
- """return a new instance of the defaultTestResult"""
1244
- return SkipAwareTestResult()
1245
-
1246
- def skip(self, msg=None):
1247
- """mark a test as skipped for the <msg> reason"""
1248
- msg = msg or 'test was skipped'
1249
- raise TestSkipped(msg)
1250
-
1251
- def innerSkip(self, msg=None):
1252
- """mark a generative test as skipped for the <msg> reason"""
1253
- msg = msg or 'test was skipped'
1254
- raise InnerTestSkipped(msg)
1255
-
1256
- def assertIn(self, object, set):
1257
- """assert <object> are in <set>"""
1258
- self.assert_(object in set, "%s not in %s" % (object, set))
1259
-
1260
- def assertNotIn(self, object, set):
1261
- """assert <object> are not in <set>"""
1262
- self.assert_(object not in set, "%s in %s" % (object, set))
1263
-
1264
- def assertDictEquals(self, dict1, dict2):
1265
- """compares two dicts
1266
-
1267
- If the two dict differ, the first difference is shown in the error
1268
- message
1269
- """
1270
- dict1 = dict(dict1)
1271
- msgs = []
1272
- for key, value in dict2.items():
1273
- try:
1274
- if dict1[key] != value:
1275
- msgs.append('%r != %r for key %r' % (dict1[key], value,
1276
- key))
1277
- del dict1[key]
1278
- except KeyError:
1279
- msgs.append('missing %r key' % key)
1280
- if dict1:
1281
- msgs.append('dict2 is lacking %r' % dict1)
1282
- if msgs:
1283
- self.fail('\n'.join(msgs))
1284
- assertDictEqual = assertDictEquals
1285
-
1286
-
1287
-
1288
- def assertUnorderedIterableEquals(self, got, expected, msg=None):
1289
- """compares two iterable and shows difference between both"""
1290
- got, expected = list(got), list(expected)
1291
- self.assertSetEqual(set(got), set(expected), msg)
1292
- if len(got) != len(expected):
1293
- if msg is None:
1294
- msg = ['Iterable have the same elements but not the same number',
1295
- '\t<element>\t<expected>i\t<got>']
1296
- got_count = {}
1297
- expected_count = {}
1298
- for element in got:
1299
- got_count[element] = got_count.get(element,0) + 1
1300
- for element in expected:
1301
- expected_count[element] = expected_count.get(element,0) + 1
1302
- # we know that got_count.key() == expected_count.key()
1303
- # because of assertSetEquals
1304
- for element, count in got_count.iteritems():
1305
- other_count = expected_count[element]
1306
- if other_count != count:
1307
- msg.append('\t%s\t%s\t%s' % (element, other_count, count))
1308
-
1309
- self.fail(msg)
1310
-
1311
- assertUnorderedIterableEqual = assertUnorderedIterableEquals
1312
- assertUnordIterEquals = assertUnordIterEqual = assertUnorderedIterableEqual
1313
-
1314
- def assertSetEquals(self,got,expected, msg=None):
1315
- if not(isinstance(got, set) and isinstance(expected, set)):
1316
- warnings.warn("the assertSetEquals function if now intended for set only."\
1317
- "use assertUnorderedIterableEquals instead.",
1318
- DeprecationWarning, 2)
1319
- return self.assertUnorderedIterableEquals(got,expected, msg)
1320
-
1321
- items={}
1322
- items['missing'] = expected - got
1323
- items['unexpected'] = got - expected
1324
- if any(items.itervalues()):
1325
- if msg is None:
1326
- msg = '\n'.join('%s:\n\t%s' % (key,"\n\t".join(str(value) for value in values))
1327
- for key, values in items.iteritems() if values)
1328
- self.fail(msg)
1329
-
1330
-
1331
- assertSetEqual = assertSetEquals
1332
-
1333
- def assertListEquals(self, list_1, list_2, msg=None):
1334
- """compares two lists
1335
-
1336
- If the two list differ, the first difference is shown in the error
1337
- message
1338
- """
1339
- _l1 = list_1[:]
1340
- for i, value in enumerate(list_2):
1341
- try:
1342
- if _l1[0] != value:
1343
- from pprint import pprint
1344
- pprint(list_1)
1345
- pprint(list_2)
1346
- self.fail('%r != %r for index %d' % (_l1[0], value, i))
1347
- del _l1[0]
1348
- except IndexError:
1349
- if msg is None:
1350
- msg = 'list_1 has only %d elements, not %s '\
1351
- '(at least %r missing)'% (i, len(list_2), value)
1352
- self.fail(msg)
1353
- if _l1:
1354
- if msg is None:
1355
- msg = 'list_2 is lacking %r' % _l1
1356
- self.fail(msg)
1357
- assertListEqual = assertListEquals
1358
-
1359
- def assertLinesEquals(self, list_1, list_2, msg=None, striplines=False):
1360
- """assert list of lines are equal"""
1361
- lines1 = list_1.splitlines()
1362
- if striplines:
1363
- lines1 = [l.strip() for l in lines1]
1364
- lines2 = list_2.splitlines()
1365
- if striplines:
1366
- lines2 = [l.strip() for l in lines2]
1367
- self.assertListEquals(lines1, lines2, msg)
1368
- assertLineEqual = assertLinesEquals
1369
-
1370
- def assertXMLWellFormed(self, stream, msg=None, context=2):
1371
- """asserts the XML stream is well-formed (no DTD conformance check)
1372
- :context: number of context lines in standard msg. all data if negativ
1373
- only available with element tree
1374
- """
1375
- try:
1376
- from xml.etree.ElementTree import parse
1377
- self._assertETXMLWellFormed(stream, parse, msg)
1378
- except ImportError:
1379
- from xml.sax import make_parser, SAXParseException
1380
- parser = make_parser()
1381
- try:
1382
- parser.parse(stream)
1383
- except SAXParseException, ex:
1384
- if msg is None:
1385
- stream.seek(0)
1386
- for _ in xrange(ex.getLineNumber()):
1387
- line = stream.readline()
1388
- pointer = ('' * (ex.getLineNumber() - 1)) + '^'
1389
- msg = 'XML stream not well formed: %s\n%s%s' % (ex, line, pointer)
1390
- self.fail(msg)
1391
-
1392
- def assertXMLStringWellFormed(self, xml_string, msg=None, context=2):
1393
- """asserts the XML string is well-formed (no DTD conformance check)
1394
- :context: number of context lines in standard msg. all data if negativ
1395
- only available with element tree
1396
- """
1397
- try:
1398
- from xml.etree.ElementTree import fromstring
1399
- self._assertETXMLWellFormed(xml_string, fromstring, msg)
1400
- except ImportError:
1401
- raise
1402
- stream = StringIO(xml_string)
1403
- self.assertXMLWellFormed(stream, msg)
1404
-
1405
- def _assertETXMLWellFormed(self, data, parse, msg=None, context=2):
1406
- """internal function used by /assertXML(String)?WellFormed/ functions
1407
- :data: xml_data
1408
- :parse: appropriate parser function for this data
1409
- :msg: error message
1410
- :context: number of context lines in standard msg. all data if negativ
1411
- only available with element tree
1412
- """
1413
- from xml.parsers.expat import ExpatError
1414
- try:
1415
- parse(data)
1416
- except ExpatError, ex:
1417
- if msg is None:
1418
- if hasattr(data, 'readlines'): #file like object
1419
- stream.seek(0)
1420
- lines = stream.readlines()
1421
- else:
1422
- lines =data.splitlines(True)
1423
- nb_lines = len(lines)
1424
- context_lines = []
1425
-
1426
- if context < 0:
1427
- start = 1
1428
- end = nb_lines
1429
- else:
1430
- start = max(ex.lineno-context, 1)
1431
- end = min(ex.lineno+context, nb_lines)
1432
- line_number_length = len('%i' % end)
1433
- line_pattern = " %%%ii: %%s" % line_number_length
1434
-
1435
- for line_no in xrange(start, ex.lineno):
1436
- context_lines.append(line_pattern % (line_no, lines[line_no-1]))
1437
- context_lines.append(line_pattern % (ex.lineno, lines[ex.lineno-1]))
1438
- context_lines.append('%s^\n' % (' ' * (1 + line_number_length + 2 +ex.offset)))
1439
- for line_no in xrange(ex.lineno+1, end+1):
1440
- context_lines.append(line_pattern % (line_no, lines[line_no-1]))
1441
-
1442
- rich_context = ''.join(context_lines)
1443
- msg = 'XML stream not well formed: %s\n%s' % (ex, rich_context)
1444
- self.fail(msg)
1445
-
1446
-
1447
- def assertXMLEqualsTuple(self, element, tup):
1448
- """compare an ElementTree Element to a tuple formatted as follow:
1449
- (tagname, [attrib[, children[, text[, tail]]]])"""
1450
- # check tag
1451
- self.assertTextEquals(element.tag, tup[0])
1452
- # check attrib
1453
- if len(element.attrib) or len(tup)>1:
1454
- if len(tup)<=1:
1455
- self.fail( "tuple %s has no attributes (%s expected)"%(tup,
1456
- dict(element.attrib)))
1457
- self.assertDictEquals(element.attrib, tup[1])
1458
- # check children
1459
- if len(element) or len(tup)>2:
1460
- if len(tup)<=2:
1461
- self.fail( "tuple %s has no children (%i expected)"%(tup,
1462
- len(element)))
1463
- if len(element) != len(tup[2]):
1464
- self.fail( "tuple %s has %i children%s (%i expected)"%(tup,
1465
- len(tup[2]),
1466
- ('', 's')[len(tup[2])>1], len(element)))
1467
- for index in xrange(len(tup[2])):
1468
- self.assertXMLEqualsTuple(element[index], tup[2][index])
1469
- #check text
1470
- if element.text or len(tup)>3:
1471
- if len(tup)<=3:
1472
- self.fail( "tuple %s has no text value (%r expected)"%(tup,
1473
- element.text))
1474
- self.assertTextEquals(element.text, tup[3])
1475
- #check tail
1476
- if element.tail or len(tup)>4:
1477
- if len(tup)<=4:
1478
- self.fail( "tuple %s has no tail value (%r expected)"%(tup,
1479
- element.tail))
1480
- self.assertTextEquals(element.tail, tup[4])
1481
-
1482
- def _difftext(self, lines1, lines2, junk=None, msg_prefix='Texts differ'):
1483
- junk = junk or (' ', '\t')
1484
- # result is a generator
1485
- result = difflib.ndiff(lines1, lines2, charjunk=lambda x: x in junk)
1486
- read = []
1487
- for line in result:
1488
- read.append(line)
1489
- # lines that don't start with a ' ' are diff ones
1490
- if not line.startswith(' '):
1491
- self.fail('\n'.join(['%s\n'%msg_prefix]+read + list(result)))
1492
-
1493
- def assertTextEquals(self, text1, text2, junk=None,
1494
- msg_prefix='Text differ', striplines=False):
1495
- """compare two multiline strings (using difflib and splitlines())"""
1496
- msg = []
1497
- if not isinstance(text1, basestring):
1498
- msg.append('text1 is not a string (%s)'%(type(text1)))
1499
- if not isinstance(text2, basestring):
1500
- msg.append('text2 is not a string (%s)'%(type(text2)))
1501
- if msg:
1502
- self.fail('\n'.join(msg))
1503
- lines1 = text1.strip().splitlines(True)
1504
- lines2 = text2.strip().splitlines(True)
1505
- if striplines:
1506
- lines1 = [line.strip() for line in lines1]
1507
- lines2 = [line.strip() for line in lines2]
1508
- self._difftext(lines1, lines2, junk, msg_prefix)
1509
- assertTextEqual = assertTextEquals
1510
-
1511
- def assertStreamEquals(self, stream1, stream2, junk=None,
1512
- msg_prefix='Stream differ'):
1513
- """compare two streams (using difflib and readlines())"""
1514
- # if stream2 is stream2, readlines() on stream1 will also read lines
1515
- # in stream2, so they'll appear different, although they're not
1516
- if stream1 is stream2:
1517
- return
1518
- # make sure we compare from the beginning of the stream
1519
- stream1.seek(0)
1520
- stream2.seek(0)
1521
- # compare
1522
- self._difftext(stream1.readlines(), stream2.readlines(), junk,
1523
- msg_prefix)
1524
-
1525
- assertStreamEqual = assertStreamEquals
1526
- def assertFileEquals(self, fname1, fname2, junk=(' ', '\t')):
1527
- """compares two files using difflib"""
1528
- self.assertStreamEqual(file(fname1), file(fname2), junk,
1529
- msg_prefix='Files differs\n-:%s\n+:%s\n'%(fname1, fname2))
1530
- assertFileEqual = assertFileEquals
1531
-
1532
-
1533
- def assertDirEquals(self, path_a, path_b):
1534
- """compares two files using difflib"""
1535
- assert osp.exists(path_a), "%s doesn't exists" % path_a
1536
- assert osp.exists(path_b), "%s doesn't exists" % path_b
1537
-
1538
- all_a = [ (ipath[len(path_a):].lstrip('/'), idirs, ifiles)
1539
- for ipath, idirs, ifiles in os.walk(path_a)]
1540
- all_a.sort(key=itemgetter(0))
1541
-
1542
- all_b = [ (ipath[len(path_b):].lstrip('/'), idirs, ifiles)
1543
- for ipath, idirs, ifiles in os.walk(path_b)]
1544
- all_b.sort(key=itemgetter(0))
1545
-
1546
- iter_a, iter_b = iter(all_a), iter(all_b)
1547
- partial_iter = True
1548
- ipath_a, idirs_a, ifiles_a = data_a = None, None, None
1549
- while True:
1550
- try:
1551
- ipath_a, idirs_a, ifiles_a = datas_a = iter_a.next()
1552
- partial_iter = False
1553
- ipath_b, idirs_b, ifiles_b = datas_b = iter_b.next()
1554
- partial_iter = True
1555
-
1556
-
1557
- self.assert_(ipath_a == ipath_b,
1558
- "unexpected %s in %s while looking %s from %s" %
1559
- (ipath_a, path_a, ipath_b, path_b))
1560
-
1561
-
1562
- errors = {}
1563
- sdirs_a = set(idirs_a)
1564
- sdirs_b = set(idirs_b)
1565
- errors["unexpected directories"] = sdirs_a - sdirs_b
1566
- errors["missing directories"] = sdirs_b - sdirs_a
1567
-
1568
- sfiles_a = set(ifiles_a)
1569
- sfiles_b = set(ifiles_b)
1570
- errors["unexpected files"] = sfiles_a - sfiles_b
1571
- errors["missing files"] = sfiles_b - sfiles_a
1572
-
1573
-
1574
- msgs = [ "%s: %s"% (name, items)
1575
- for name, items in errors.iteritems() if items]
1576
-
1577
- if msgs:
1578
- msgs.insert(0,"%s and %s differ :" % (
1579
- osp.join(path_a, ipath_a),
1580
- osp.join(path_b, ipath_b),
1581
- ))
1582
- self.fail("\n".join(msgs))
1583
-
1584
- for files in (ifiles_a, ifiles_b):
1585
- files.sort()
1586
-
1587
- for index, path in enumerate(ifiles_a):
1588
- self.assertFileEquals(osp.join(path_a, ipath_a, path),
1589
- osp.join(path_b, ipath_b, ifiles_b[index]))
1590
-
1591
- except StopIteration:
1592
- break
1593
-
1594
-
1595
- assertDirEqual = assertDirEquals
1596
-
1597
-
1598
- def assertIsInstance(self, obj, klass, msg=None, strict=False):
1599
- """compares two files using difflib"""
1600
- if msg is None:
1601
- if strict:
1602
- msg = '%r is not of class %s but of %s'
1603
- else:
1604
- msg = '%r is not an instance of %s but of %s'
1605
- msg = msg % (obj, klass, type(obj))
1606
- if strict:
1607
- self.assert_(obj.__class__ is klass, msg)
1608
- else:
1609
- self.assert_(isinstance(obj, klass), msg)
1610
-
1611
- def assertIs(self, obj, other, msg=None):
1612
- """compares identity of two reference"""
1613
- if msg is None:
1614
- msg = "%r is not %r"%(obj, other)
1615
- self.assert_(obj is other, msg)
1616
-
1617
-
1618
- def assertIsNot(self, obj, other, msg=None):
1619
- """compares identity of two reference"""
1620
- if msg is None:
1621
- msg = "%r is %r"%(obj, other)
1622
- self.assert_(obj is not other, msg )
1623
-
1624
- def assertNone(self, obj, msg=None):
1625
- """assert obj is None"""
1626
- if msg is None:
1627
- msg = "reference to %r when None expected"%(obj,)
1628
- self.assert_( obj is None, msg )
1629
-
1630
- def assertNotNone(self, obj, msg=None):
1631
- """assert obj is not None"""
1632
- if msg is None:
1633
- msg = "unexpected reference to None"
1634
- self.assert_( obj is not None, msg )
1635
-
1636
- def assertFloatAlmostEquals(self, obj, other, prec=1e-5, msg=None):
1637
- """compares two floats"""
1638
- if msg is None:
1639
- msg = "%r != %r" % (obj, other)
1640
- self.assert_(math.fabs(obj - other) < prec, msg)
1641
-
1642
- def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
1643
- """override default failUnlessRaise method to return the raised
1644
- exception instance.
1645
-
1646
- Fail unless an exception of class excClass is thrown
1647
- by callableObj when invoked with arguments args and keyword
1648
- arguments kwargs. If a different type of exception is
1649
- thrown, it will not be caught, and the test case will be
1650
- deemed to have suffered an error, exactly as for an
1651
- unexpected exception.
1652
- """
1653
- try:
1654
- callableObj(*args, **kwargs)
1655
- except excClass, exc:
1656
- return exc
1657
- else:
1658
- if hasattr(excClass, '__name__'):
1659
- excName = excClass.__name__
1660
- else:
1661
- excName = str(excClass)
1662
- raise self.failureException, "%s not raised" % excName
1663
-
1664
- assertRaises = failUnlessRaises
1665
-
1666
- import doctest
1667
-
1668
- class SkippedSuite(unittest.TestSuite):
1669
- def test(self):
1670
- """just there to trigger test execution"""
1671
- self.skipped_test('doctest module has no DocTestSuite class')
1672
-
1673
-
1674
- # DocTestFinder was introduced in python2.4
1675
- if sys.version_info >= (2, 4):
1676
- class DocTestFinder(doctest.DocTestFinder):
1677
-
1678
- def __init__(self, *args, **kwargs):
1679
- self.skipped = kwargs.pop('skipped', ())
1680
- doctest.DocTestFinder.__init__(self, *args, **kwargs)
1681
-
1682
- def _get_test(self, obj, name, module, globs, source_lines):
1683
- """override default _get_test method to be able to skip tests
1684
- according to skipped attribute's value
1685
-
1686
- Note: Python (<=2.4) use a _name_filter which could be used for that
1687
- purpose but it's no longer available in 2.5
1688
- Python 2.5 seems to have a [SKIP] flag
1689
- """
1690
- if getattr(obj, '__name__', '') in self.skipped:
1691
- return None
1692
- return doctest.DocTestFinder._get_test(self, obj, name, module,
1693
- globs, source_lines)
1694
- else:
1695
- # this is a hack to make skipped work with python <= 2.3
1696
- class DocTestFinder(object):
1697
- def __init__(self, skipped):
1698
- self.skipped = skipped
1699
- self.original_find_tests = doctest._find_tests
1700
- doctest._find_tests = self._find_tests
1701
-
1702
- def _find_tests(self, module, prefix=None):
1703
- tests = []
1704
- for testinfo in self.original_find_tests(module, prefix):
1705
- testname, _, _, _ = testinfo
1706
- # testname looks like A.B.C.function_name
1707
- testname = testname.split('.')[-1]
1708
- if testname not in self.skipped:
1709
- tests.append(testinfo)
1710
- return tests
1711
-
1712
-
1713
- class DocTest(TestCase):
1714
- """trigger module doctest
1715
- I don't know how to make unittest.main consider the DocTestSuite instance
1716
- without this hack
1717
- """
1718
- skipped = ()
1719
- def __call__(self, result=None, runcondition=None, options=None):\
1720
- # pylint: disable-msg=W0613
1721
- try:
1722
- finder = DocTestFinder(skipped=self.skipped)
1723
- if sys.version_info >= (2, 4):
1724
- suite = doctest.DocTestSuite(self.module, test_finder=finder)
1725
- else:
1726
- suite = doctest.DocTestSuite(self.module)
1727
- except AttributeError:
1728
- suite = SkippedSuite()
1729
- return suite.run(result)
1730
- run = __call__
1731
-
1732
- def test(self):
1733
- """just there to trigger test execution"""
1734
-
1735
- MAILBOX = None
1736
-
1737
- class MockSMTP:
1738
- """fake smtplib.SMTP"""
1739
-
1740
- def __init__(self, host, port):
1741
- self.host = host
1742
- self.port = port
1743
- global MAILBOX
1744
- self.reveived = MAILBOX = []
1745
-
1746
- def set_debuglevel(self, debuglevel):
1747
- """ignore debug level"""
1748
-
1749
- def sendmail(self, fromaddr, toaddres, body):
1750
- """push sent mail in the mailbox"""
1751
- self.reveived.append((fromaddr, toaddres, body))
1752
-
1753
- def quit(self):
1754
- """ignore quit"""
1755
-
1756
-
1757
- class MockConfigParser(ConfigParser):
1758
- """fake ConfigParser.ConfigParser"""
1759
-
1760
- def __init__(self, options):
1761
- ConfigParser.__init__(self)
1762
- for section, pairs in options.iteritems():
1763
- self.add_section(section)
1764
- for key, value in pairs.iteritems():
1765
- self.set(section,key,value)
1766
- def write(self, _):
1767
- raise NotImplementedError()
1768
-
1769
-
1770
- class MockConnection:
1771
- """fake DB-API 2.0 connexion AND cursor (i.e. cursor() return self)"""
1772
-
1773
- def __init__(self, results):
1774
- self.received = []
1775
- self.states = []
1776
- self.results = results
1777
-
1778
- def cursor(self):
1779
- """Mock cursor method"""
1780
- return self
1781
- def execute(self, query, args=None):
1782
- """Mock execute method"""
1783
- self.received.append( (query, args) )
1784
- def fetchone(self):
1785
- """Mock fetchone method"""
1786
- return self.results[0]
1787
- def fetchall(self):
1788
- """Mock fetchall method"""
1789
- return self.results
1790
- def commit(self):
1791
- """Mock commiy method"""
1792
- self.states.append( ('commit', len(self.received)) )
1793
- def rollback(self):
1794
- """Mock rollback method"""
1795
- self.states.append( ('rollback', len(self.received)) )
1796
- def close(self):
1797
- """Mock close method"""
1798
- pass
1799
-
1800
-
1801
- def mock_object(**params):
1802
- """creates an object using params to set attributes
1803
- >>> option = mock_object(verbose=False, index=range(5))
1804
- >>> option.verbose
1805
- False
1806
- >>> option.index
1807
- [0, 1, 2, 3, 4]
1808
- """
1809
- return type('Mock', (), params)()
1810
-
1811
-
1812
- def create_files(paths, chroot):
1813
- """Creates directories and files found in <path>.
1814
-
1815
- :param paths: list of relative paths to files or directories
1816
- :param chroot: the root directory in which paths will be created
1817
-
1818
- >>> from os.path import isdir, isfile
1819
- >>> isdir('/tmp/a')
1820
- False
1821
- >>> create_files(['a/b/foo.py', 'a/b/c/', 'a/b/c/d/e.py'], '/tmp')
1822
- >>> isdir('/tmp/a')
1823
- True
1824
- >>> isdir('/tmp/a/b/c')
1825
- True
1826
- >>> isfile('/tmp/a/b/c/d/e.py')
1827
- True
1828
- >>> isfile('/tmp/a/b/foo.py')
1829
- True
1830
- """
1831
- dirs, files = set(), set()
1832
- for path in paths:
1833
- path = osp.join(chroot, path)
1834
- filename = osp.basename(path)
1835
- # path is a directory path
1836
- if filename == '':
1837
- dirs.add(path)
1838
- # path is a filename path
1839
- else:
1840
- dirs.add(osp.dirname(path))
1841
- files.add(path)
1842
- for dirpath in dirs:
1843
- if not osp.isdir(dirpath):
1844
- os.makedirs(dirpath)
1845
- for filepath in files:
1846
- file(filepath, 'w').close()
1847
-
1848
- def enable_dbc(*args):
1849
- """
1850
- Without arguments, return True if contracts can be enabled and should be
1851
- enabled (see option -d), return False otherwise.
1852
-
1853
- With arguments, return False if contracts can't or shouldn't be enabled,
1854
- otherwise weave ContractAspect with items passed as arguments.
1855
- """
1856
- if not ENABLE_DBC:
1857
- return False
1858
- try:
1859
- from logilab.aspects.weaver import weaver
1860
- from logilab.aspects.lib.contracts import ContractAspect
1861
- except ImportError:
1862
- sys.stderr.write(
1863
- 'Warning: logilab.aspects is not available. Contracts disabled.')
1864
- return False
1865
- for arg in args:
1866
- weaver.weave_module(arg, ContractAspect)
1867
- return True
1868
-
1869
-
1870
- class AttrObject: # XXX cf mock_object
1871
- def __init__(self, **kwargs):
1872
- self.__dict__.update(kwargs)
1873
-
1874
- def tag(*args):
1875
- """descriptor adding tag to a function"""
1876
- def desc(func):
1877
- assert not hasattr(func, 'tags')
1878
- func.tags = Tags(args)
1879
- return func
1880
- return desc
1881
-
1882
- class Tags(set):
1883
- """A set of tag able validate an expression"""
1884
- def __getitem__(self, key):
1885
- return key in self
1886
-
1887
- def match(self, exp):
1888
- return eval(exp, {}, self)
1889
-
1890
- def require_version(version):
1891
- """ Compare version of python interpreter to the given one. Skip the test
1892
- if older.
1893
- """
1894
- def check_require_version(f):
1895
- version_elements = version.split('.')
1896
- try:
1897
- compare = tuple([int(v) for v in version_elements])
1898
- except ValueError:
1899
- raise ValueError('%s is not a correct version : should be X.Y[.Z].' % version)
1900
- current = sys.version_info[:3]
1901
- #print 'comp', current, compare
1902
- if current < compare:
1903
- #print 'version too old'
1904
- def new_f(self, *args, **kwargs):
1905
- self.skip('Need at least %s version of python. Current version is %s.' % (version, '.'.join([str(element) for element in current])))
1906
- new_f.__name__ = f.__name__
1907
- return new_f
1908
- else:
1909
- #print 'version young enough'
1910
- return f
1911
- return check_require_version
1912
-
1913
- def require_module(module):
1914
- """ Check if the given module is loaded. Skip the test if not.
1915
- """
1916
- def check_require_module(f):
1917
- try:
1918
- __import__(module)
1919
- #print module, 'imported'
1920
- return f
1921
- except ImportError:
1922
- #print module, 'can not be imported'
1923
- def new_f(self, *args, **kwargs):
1924
- self.skip('%s can not be imported.' % module)
1925
- new_f.__name__ = f.__name__
1926
- return new_f
1927
- return check_require_module