bee_python 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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