bee_python 0.0.1

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 (503) hide show
  1. data/LICENSE +202 -0
  2. data/build/README +23 -0
  3. data/egg/egg/build.yml +70 -0
  4. data/egg/egg/ez_setup.py +280 -0
  5. data/egg/egg/script.py +12 -0
  6. data/egg/egg/setup.erb +11 -0
  7. data/egg/egg/suite.py +37 -0
  8. data/egg/egg/test.py +31 -0
  9. data/egg/egg.yml +69 -0
  10. data/egg/http/build.erb +53 -0
  11. data/egg/http/server.py +34 -0
  12. data/egg/http.yml +50 -0
  13. data/egg/mysql/mysql.py +43 -0
  14. data/egg/mysql.yml +44 -0
  15. data/egg/project/build.erb +77 -0
  16. data/egg/project/script.py +42 -0
  17. data/egg/project/test.py +31 -0
  18. data/egg/project.yml +59 -0
  19. data/egg/script/build.erb +35 -0
  20. data/egg/script/script.py +42 -0
  21. data/egg/script.yml +50 -0
  22. data/egg/soap/build.erb +52 -0
  23. data/egg/soap/client.py +18 -0
  24. data/egg/soap/server.py +30 -0
  25. data/egg/soap.yml +58 -0
  26. data/egg/source/source.py +42 -0
  27. data/egg/source.yml +47 -0
  28. data/egg/test/test.py +28 -0
  29. data/egg/test.yml +44 -0
  30. data/egg/xmlrpc/build.erb +52 -0
  31. data/egg/xmlrpc/client.py +22 -0
  32. data/egg/xmlrpc/server.py +24 -0
  33. data/egg/xmlrpc.yml +51 -0
  34. data/lib/bee_task_python.rb +390 -0
  35. data/test/build.yml +16 -0
  36. data/test/tc_bee_task_python.rb +27 -0
  37. data/test/test_build.rb +26 -0
  38. data/test/test_build_listener.rb +62 -0
  39. data/test/ts_bee_python.rb +26 -0
  40. data/tools/common/__init__.py +5 -0
  41. data/tools/common/common/__init__.py +140 -0
  42. data/tools/common/common/__pkginfo__.py +43 -0
  43. data/tools/common/common/adbh.py +35 -0
  44. data/tools/common/common/cache.py +114 -0
  45. data/tools/common/common/changelog.py +234 -0
  46. data/tools/common/common/clcommands.py +181 -0
  47. data/tools/common/common/cli.py +212 -0
  48. data/tools/common/common/compat.py +328 -0
  49. data/tools/common/common/configuration.py +1087 -0
  50. data/tools/common/common/contexts.py +58 -0
  51. data/tools/common/common/corbautils.py +117 -0
  52. data/tools/common/common/daemon.py +171 -0
  53. data/tools/common/common/date.py +279 -0
  54. data/tools/common/common/db.py +49 -0
  55. data/tools/common/common/dbf.py +229 -0
  56. data/tools/common/common/debugger.py +208 -0
  57. data/tools/common/common/decorators.py +190 -0
  58. data/tools/common/common/deprecation.py +118 -0
  59. data/tools/common/common/fileutils.py +409 -0
  60. data/tools/common/common/graph.py +259 -0
  61. data/tools/common/common/html.py +142 -0
  62. data/tools/common/common/interface.py +76 -0
  63. data/tools/common/common/logging_ext.py +166 -0
  64. data/tools/common/common/modutils.py +670 -0
  65. data/tools/common/common/optik_ext.py +383 -0
  66. data/tools/common/common/optparser.py +92 -0
  67. data/tools/common/common/pdf_ext.py +111 -0
  68. data/tools/common/common/proc.py +276 -0
  69. data/tools/common/common/pyro_ext.py +146 -0
  70. data/tools/common/common/pytest.py +754 -0
  71. data/tools/common/common/shellutils.py +383 -0
  72. data/tools/common/common/sphinx_ext.py +87 -0
  73. data/tools/common/common/sphinxutils.py +122 -0
  74. data/tools/common/common/sqlgen.py +31 -0
  75. data/tools/common/common/table.py +930 -0
  76. data/tools/common/common/tasksqueue.py +97 -0
  77. data/tools/common/common/test/__init__.py +1 -0
  78. data/tools/common/common/test/data/ChangeLog +184 -0
  79. data/tools/common/common/test/data/MyPyPa-0.1.0-py2.5.egg +0 -0
  80. data/tools/common/common/test/data/__init__.py +1 -0
  81. data/tools/common/common/test/data/content_differ_dir/NOTHING +0 -0
  82. data/tools/common/common/test/data/content_differ_dir/README +1 -0
  83. data/tools/common/common/test/data/content_differ_dir/subdir/coin +1 -0
  84. data/tools/common/common/test/data/content_differ_dir/subdir/toto.txt +53 -0
  85. data/tools/common/common/test/data/file_differ_dir/NOTHING +0 -0
  86. data/tools/common/common/test/data/file_differ_dir/README +1 -0
  87. data/tools/common/common/test/data/file_differ_dir/subdir/toto.txt +53 -0
  88. data/tools/common/common/test/data/file_differ_dir/subdirtwo/Hello +0 -0
  89. data/tools/common/common/test/data/find_test/__init__.py +0 -0
  90. data/tools/common/common/test/data/find_test/foo.txt +0 -0
  91. data/tools/common/common/test/data/find_test/module.py +0 -0
  92. data/tools/common/common/test/data/find_test/module2.py +0 -0
  93. data/tools/common/common/test/data/find_test/newlines.txt +0 -0
  94. data/tools/common/common/test/data/find_test/noendingnewline.py +0 -0
  95. data/tools/common/common/test/data/find_test/nonregr.py +0 -0
  96. data/tools/common/common/test/data/find_test/normal_file.txt +0 -0
  97. data/tools/common/common/test/data/find_test/spam.txt +0 -0
  98. data/tools/common/common/test/data/find_test/sub/doc.txt +0 -0
  99. data/tools/common/common/test/data/find_test/sub/momo.py +0 -0
  100. data/tools/common/common/test/data/find_test/test.ini +0 -0
  101. data/tools/common/common/test/data/find_test/test1.msg +0 -0
  102. data/tools/common/common/test/data/find_test/test2.msg +0 -0
  103. data/tools/common/common/test/data/find_test/write_protected_file.txt +0 -0
  104. data/tools/common/common/test/data/foo.txt +9 -0
  105. data/tools/common/common/test/data/module.py +88 -0
  106. data/tools/common/common/test/data/module2.py +77 -0
  107. data/tools/common/common/test/data/newlines.txt +3 -0
  108. data/tools/common/common/test/data/noendingnewline.py +36 -0
  109. data/tools/common/common/test/data/nonregr.py +14 -0
  110. data/tools/common/common/test/data/normal_file.txt +0 -0
  111. data/tools/common/common/test/data/reference_dir/NOTHING +0 -0
  112. data/tools/common/common/test/data/reference_dir/README +1 -0
  113. data/tools/common/common/test/data/reference_dir/subdir/coin +1 -0
  114. data/tools/common/common/test/data/reference_dir/subdir/toto.txt +53 -0
  115. data/tools/common/common/test/data/same_dir/NOTHING +0 -0
  116. data/tools/common/common/test/data/same_dir/README +1 -0
  117. data/tools/common/common/test/data/same_dir/subdir/coin +1 -0
  118. data/tools/common/common/test/data/same_dir/subdir/toto.txt +53 -0
  119. data/tools/common/common/test/data/spam.txt +9 -0
  120. data/tools/common/common/test/data/sub/doc.txt +1 -0
  121. data/tools/common/common/test/data/sub/momo.py +1 -0
  122. data/tools/common/common/test/data/subdir_differ_dir/NOTHING +0 -0
  123. data/tools/common/common/test/data/subdir_differ_dir/README +1 -0
  124. data/tools/common/common/test/data/subdir_differ_dir/subdir/coin +1 -0
  125. data/tools/common/common/test/data/subdir_differ_dir/subdir/toto.txt +53 -0
  126. data/tools/common/common/test/data/test.ini +20 -0
  127. data/tools/common/common/test/data/test1.msg +30 -0
  128. data/tools/common/common/test/data/test2.msg +42 -0
  129. data/tools/common/common/test/data/write_protected_file.txt +0 -0
  130. data/tools/common/common/test/foomod.py +17 -0
  131. data/tools/common/common/test/unittest_cache.py +129 -0
  132. data/tools/common/common/test/unittest_changelog.py +37 -0
  133. data/tools/common/common/test/unittest_compat.py +239 -0
  134. data/tools/common/common/test/unittest_configuration.py +348 -0
  135. data/tools/common/common/test/unittest_date.py +154 -0
  136. data/tools/common/common/test/unittest_decorators.py +62 -0
  137. data/tools/common/common/test/unittest_deprecation.py +76 -0
  138. data/tools/common/common/test/unittest_fileutils.py +133 -0
  139. data/tools/common/common/test/unittest_graph.py +50 -0
  140. data/tools/common/common/test/unittest_html.py +76 -0
  141. data/tools/common/common/test/unittest_interface.py +87 -0
  142. data/tools/common/common/test/unittest_modutils.py +244 -0
  143. data/tools/common/common/test/unittest_pytest.py +50 -0
  144. data/tools/common/common/test/unittest_shellutils.py +248 -0
  145. data/tools/common/common/test/unittest_table.py +448 -0
  146. data/tools/common/common/test/unittest_taskqueue.py +71 -0
  147. data/tools/common/common/test/unittest_testlib.py +956 -0
  148. data/tools/common/common/test/unittest_textutils.py +247 -0
  149. data/tools/common/common/test/unittest_tree.py +248 -0
  150. data/tools/common/common/test/unittest_umessage.py +55 -0
  151. data/tools/common/common/test/unittest_ureports_html.py +64 -0
  152. data/tools/common/common/test/unittest_ureports_text.py +105 -0
  153. data/tools/common/common/test/unittest_xmlutils.py +75 -0
  154. data/tools/common/common/test/utils.py +87 -0
  155. data/tools/common/common/testlib.py +1927 -0
  156. data/tools/common/common/textutils.py +476 -0
  157. data/tools/common/common/tree.py +372 -0
  158. data/tools/common/common/umessage.py +161 -0
  159. data/tools/common/common/ureports/__init__.py +174 -0
  160. data/tools/common/common/ureports/docbook_writer.py +139 -0
  161. data/tools/common/common/ureports/html_writer.py +131 -0
  162. data/tools/common/common/ureports/nodes.py +201 -0
  163. data/tools/common/common/ureports/text_writer.py +140 -0
  164. data/tools/common/common/vcgutils.py +216 -0
  165. data/tools/common/common/visitor.py +107 -0
  166. data/tools/common/common/xmlrpcutils.py +136 -0
  167. data/tools/common/common/xmlutils.py +61 -0
  168. data/tools/compile/compile.py +16 -0
  169. data/tools/coverage/coverage.py +602 -0
  170. data/tools/epydoc/__init__.py +227 -0
  171. data/tools/epydoc/__init__.pyc +0 -0
  172. data/tools/epydoc/apidoc.py +2203 -0
  173. data/tools/epydoc/apidoc.pyc +0 -0
  174. data/tools/epydoc/checker.py +349 -0
  175. data/tools/epydoc/checker.pyc +0 -0
  176. data/tools/epydoc/cli.py +1470 -0
  177. data/tools/epydoc/cli.pyc +0 -0
  178. data/tools/epydoc/compat.py +250 -0
  179. data/tools/epydoc/compat.pyc +0 -0
  180. data/tools/epydoc/docbuilder.py +1358 -0
  181. data/tools/epydoc/docbuilder.pyc +0 -0
  182. data/tools/epydoc/docintrospecter.py +1056 -0
  183. data/tools/epydoc/docintrospecter.pyc +0 -0
  184. data/tools/epydoc/docparser.py +2113 -0
  185. data/tools/epydoc/docparser.pyc +0 -0
  186. data/tools/epydoc/docstringparser.py +1111 -0
  187. data/tools/epydoc/docstringparser.pyc +0 -0
  188. data/tools/epydoc/docwriter/__init__.py +12 -0
  189. data/tools/epydoc/docwriter/__init__.pyc +0 -0
  190. data/tools/epydoc/docwriter/dotgraph.py +1351 -0
  191. data/tools/epydoc/docwriter/dotgraph.pyc +0 -0
  192. data/tools/epydoc/docwriter/html.py +3491 -0
  193. data/tools/epydoc/docwriter/html.pyc +0 -0
  194. data/tools/epydoc/docwriter/html_colorize.py +909 -0
  195. data/tools/epydoc/docwriter/html_colorize.pyc +0 -0
  196. data/tools/epydoc/docwriter/html_css.py +550 -0
  197. data/tools/epydoc/docwriter/html_css.pyc +0 -0
  198. data/tools/epydoc/docwriter/html_help.py +190 -0
  199. data/tools/epydoc/docwriter/html_help.pyc +0 -0
  200. data/tools/epydoc/docwriter/latex.py +1187 -0
  201. data/tools/epydoc/docwriter/latex.pyc +0 -0
  202. data/tools/epydoc/docwriter/plaintext.py +276 -0
  203. data/tools/epydoc/docwriter/plaintext.pyc +0 -0
  204. data/tools/epydoc/docwriter/xlink.py +505 -0
  205. data/tools/epydoc/docwriter/xlink.pyc +0 -0
  206. data/tools/epydoc/gui.py +1148 -0
  207. data/tools/epydoc/gui.pyc +0 -0
  208. data/tools/epydoc/log.py +204 -0
  209. data/tools/epydoc/log.pyc +0 -0
  210. data/tools/epydoc/markup/__init__.py +623 -0
  211. data/tools/epydoc/markup/__init__.pyc +0 -0
  212. data/tools/epydoc/markup/doctest.py +311 -0
  213. data/tools/epydoc/markup/doctest.pyc +0 -0
  214. data/tools/epydoc/markup/epytext.py +2116 -0
  215. data/tools/epydoc/markup/epytext.pyc +0 -0
  216. data/tools/epydoc/markup/javadoc.py +250 -0
  217. data/tools/epydoc/markup/javadoc.pyc +0 -0
  218. data/tools/epydoc/markup/plaintext.py +78 -0
  219. data/tools/epydoc/markup/plaintext.pyc +0 -0
  220. data/tools/epydoc/markup/pyval_repr.py +532 -0
  221. data/tools/epydoc/markup/pyval_repr.pyc +0 -0
  222. data/tools/epydoc/markup/restructuredtext.py +906 -0
  223. data/tools/epydoc/markup/restructuredtext.pyc +0 -0
  224. data/tools/epydoc/test/__init__.py +97 -0
  225. data/tools/epydoc/test/__init__.pyc +0 -0
  226. data/tools/epydoc/test/util.py +226 -0
  227. data/tools/epydoc/test/util.pyc +0 -0
  228. data/tools/epydoc/util.py +289 -0
  229. data/tools/epydoc/util.pyc +0 -0
  230. data/tools/logilab/logilab/__init__.py +5 -0
  231. data/tools/logilab/logilab/astng/__init__.py +82 -0
  232. data/tools/logilab/logilab/astng/__pkginfo__.py +76 -0
  233. data/tools/logilab/logilab/astng/_exceptions.py +64 -0
  234. data/tools/logilab/logilab/astng/_nodes_ast.py +667 -0
  235. data/tools/logilab/logilab/astng/_nodes_compiler.py +758 -0
  236. data/tools/logilab/logilab/astng/bases.py +608 -0
  237. data/tools/logilab/logilab/astng/builder.py +239 -0
  238. data/tools/logilab/logilab/astng/inference.py +426 -0
  239. data/tools/logilab/logilab/astng/inspector.py +289 -0
  240. data/tools/logilab/logilab/astng/manager.py +421 -0
  241. data/tools/logilab/logilab/astng/mixins.py +165 -0
  242. data/tools/logilab/logilab/astng/node_classes.py +848 -0
  243. data/tools/logilab/logilab/astng/nodes.py +85 -0
  244. data/tools/logilab/logilab/astng/nodes_as_string.py +389 -0
  245. data/tools/logilab/logilab/astng/patchcomptransformer.py +159 -0
  246. data/tools/logilab/logilab/astng/protocols.py +333 -0
  247. data/tools/logilab/logilab/astng/raw_building.py +212 -0
  248. data/tools/logilab/logilab/astng/rebuilder.py +307 -0
  249. data/tools/logilab/logilab/astng/scoped_nodes.py +951 -0
  250. data/tools/logilab/logilab/astng/test/__init__.py +19 -0
  251. data/tools/logilab/logilab/astng/test/data/MyPyPa-0.1.0-py2.5.egg +0 -0
  252. data/tools/logilab/logilab/astng/test/data/MyPyPa-0.1.0-py2.5.zip +0 -0
  253. data/tools/logilab/logilab/astng/test/data/SSL1/Connection1.py +33 -0
  254. data/tools/logilab/logilab/astng/test/data/SSL1/__init__.py +20 -0
  255. data/tools/logilab/logilab/astng/test/data/__init__.py +20 -0
  256. data/tools/logilab/logilab/astng/test/data/all.py +29 -0
  257. data/tools/logilab/logilab/astng/test/data/appl/__init__.py +23 -0
  258. data/tools/logilab/logilab/astng/test/data/appl/myConnection.py +30 -0
  259. data/tools/logilab/logilab/astng/test/data/format.py +34 -0
  260. data/tools/logilab/logilab/astng/test/data/module.py +90 -0
  261. data/tools/logilab/logilab/astng/test/data/module2.py +112 -0
  262. data/tools/logilab/logilab/astng/test/data/noendingnewline.py +57 -0
  263. data/tools/logilab/logilab/astng/test/data/nonregr.py +76 -0
  264. data/tools/logilab/logilab/astng/test/data/notall.py +28 -0
  265. data/tools/logilab/logilab/astng/test/data2/__init__.py +20 -0
  266. data/tools/logilab/logilab/astng/test/data2/clientmodule_test.py +51 -0
  267. data/tools/logilab/logilab/astng/test/data2/suppliermodule_test.py +32 -0
  268. data/tools/logilab/logilab/astng/test/regrtest.py +135 -0
  269. data/tools/logilab/logilab/astng/test/regrtest_data/absimport.py +22 -0
  270. data/tools/logilab/logilab/astng/test/regrtest_data/descriptor_crash.py +31 -0
  271. data/tools/logilab/logilab/astng/test/regrtest_data/import_package_subpackage_module.py +68 -0
  272. data/tools/logilab/logilab/astng/test/regrtest_data/package/__init__.py +24 -0
  273. data/tools/logilab/logilab/astng/test/regrtest_data/package/subpackage/__init__.py +20 -0
  274. data/tools/logilab/logilab/astng/test/regrtest_data/package/subpackage/module.py +20 -0
  275. data/tools/logilab/logilab/astng/test/unittest_builder.py +684 -0
  276. data/tools/logilab/logilab/astng/test/unittest_inference.py +1112 -0
  277. data/tools/logilab/logilab/astng/test/unittest_inspector.py +105 -0
  278. data/tools/logilab/logilab/astng/test/unittest_lookup.py +302 -0
  279. data/tools/logilab/logilab/astng/test/unittest_manager.py +98 -0
  280. data/tools/logilab/logilab/astng/test/unittest_nodes.py +302 -0
  281. data/tools/logilab/logilab/astng/test/unittest_scoped_nodes.py +501 -0
  282. data/tools/logilab/logilab/astng/test/unittest_utils.py +104 -0
  283. data/tools/logilab/logilab/astng/utils.py +342 -0
  284. data/tools/logilab/logilab/common/__init__.py +140 -0
  285. data/tools/logilab/logilab/common/__pkginfo__.py +43 -0
  286. data/tools/logilab/logilab/common/adbh.py +35 -0
  287. data/tools/logilab/logilab/common/cache.py +114 -0
  288. data/tools/logilab/logilab/common/changelog.py +234 -0
  289. data/tools/logilab/logilab/common/clcommands.py +181 -0
  290. data/tools/logilab/logilab/common/cli.py +212 -0
  291. data/tools/logilab/logilab/common/compat.py +328 -0
  292. data/tools/logilab/logilab/common/configuration.py +1087 -0
  293. data/tools/logilab/logilab/common/contexts.py +58 -0
  294. data/tools/logilab/logilab/common/corbautils.py +117 -0
  295. data/tools/logilab/logilab/common/daemon.py +171 -0
  296. data/tools/logilab/logilab/common/date.py +279 -0
  297. data/tools/logilab/logilab/common/db.py +49 -0
  298. data/tools/logilab/logilab/common/dbf.py +229 -0
  299. data/tools/logilab/logilab/common/debugger.py +208 -0
  300. data/tools/logilab/logilab/common/decorators.py +190 -0
  301. data/tools/logilab/logilab/common/deprecation.py +118 -0
  302. data/tools/logilab/logilab/common/fileutils.py +409 -0
  303. data/tools/logilab/logilab/common/graph.py +259 -0
  304. data/tools/logilab/logilab/common/html.py +142 -0
  305. data/tools/logilab/logilab/common/interface.py +76 -0
  306. data/tools/logilab/logilab/common/logging_ext.py +166 -0
  307. data/tools/logilab/logilab/common/modutils.py +670 -0
  308. data/tools/logilab/logilab/common/optik_ext.py +383 -0
  309. data/tools/logilab/logilab/common/optparser.py +92 -0
  310. data/tools/logilab/logilab/common/pdf_ext.py +111 -0
  311. data/tools/logilab/logilab/common/proc.py +276 -0
  312. data/tools/logilab/logilab/common/pyro_ext.py +146 -0
  313. data/tools/logilab/logilab/common/pytest.py +754 -0
  314. data/tools/logilab/logilab/common/shellutils.py +383 -0
  315. data/tools/logilab/logilab/common/sphinx_ext.py +87 -0
  316. data/tools/logilab/logilab/common/sphinxutils.py +122 -0
  317. data/tools/logilab/logilab/common/sqlgen.py +31 -0
  318. data/tools/logilab/logilab/common/table.py +930 -0
  319. data/tools/logilab/logilab/common/tasksqueue.py +97 -0
  320. data/tools/logilab/logilab/common/test/__init__.py +1 -0
  321. data/tools/logilab/logilab/common/test/data/ChangeLog +184 -0
  322. data/tools/logilab/logilab/common/test/data/MyPyPa-0.1.0-py2.5.egg +0 -0
  323. data/tools/logilab/logilab/common/test/data/__init__.py +1 -0
  324. data/tools/logilab/logilab/common/test/data/content_differ_dir/NOTHING +0 -0
  325. data/tools/logilab/logilab/common/test/data/content_differ_dir/README +1 -0
  326. data/tools/logilab/logilab/common/test/data/content_differ_dir/subdir/coin +1 -0
  327. data/tools/logilab/logilab/common/test/data/content_differ_dir/subdir/toto.txt +53 -0
  328. data/tools/logilab/logilab/common/test/data/file_differ_dir/NOTHING +0 -0
  329. data/tools/logilab/logilab/common/test/data/file_differ_dir/README +1 -0
  330. data/tools/logilab/logilab/common/test/data/file_differ_dir/subdir/toto.txt +53 -0
  331. data/tools/logilab/logilab/common/test/data/file_differ_dir/subdirtwo/Hello +0 -0
  332. data/tools/logilab/logilab/common/test/data/find_test/__init__.py +0 -0
  333. data/tools/logilab/logilab/common/test/data/find_test/foo.txt +0 -0
  334. data/tools/logilab/logilab/common/test/data/find_test/module.py +0 -0
  335. data/tools/logilab/logilab/common/test/data/find_test/module2.py +0 -0
  336. data/tools/logilab/logilab/common/test/data/find_test/newlines.txt +0 -0
  337. data/tools/logilab/logilab/common/test/data/find_test/noendingnewline.py +0 -0
  338. data/tools/logilab/logilab/common/test/data/find_test/nonregr.py +0 -0
  339. data/tools/logilab/logilab/common/test/data/find_test/normal_file.txt +0 -0
  340. data/tools/logilab/logilab/common/test/data/find_test/spam.txt +0 -0
  341. data/tools/logilab/logilab/common/test/data/find_test/sub/doc.txt +0 -0
  342. data/tools/logilab/logilab/common/test/data/find_test/sub/momo.py +0 -0
  343. data/tools/logilab/logilab/common/test/data/find_test/test.ini +0 -0
  344. data/tools/logilab/logilab/common/test/data/find_test/test1.msg +0 -0
  345. data/tools/logilab/logilab/common/test/data/find_test/test2.msg +0 -0
  346. data/tools/logilab/logilab/common/test/data/find_test/write_protected_file.txt +0 -0
  347. data/tools/logilab/logilab/common/test/data/foo.txt +9 -0
  348. data/tools/logilab/logilab/common/test/data/module.py +88 -0
  349. data/tools/logilab/logilab/common/test/data/module2.py +77 -0
  350. data/tools/logilab/logilab/common/test/data/newlines.txt +3 -0
  351. data/tools/logilab/logilab/common/test/data/noendingnewline.py +36 -0
  352. data/tools/logilab/logilab/common/test/data/nonregr.py +14 -0
  353. data/tools/logilab/logilab/common/test/data/normal_file.txt +0 -0
  354. data/tools/logilab/logilab/common/test/data/reference_dir/NOTHING +0 -0
  355. data/tools/logilab/logilab/common/test/data/reference_dir/README +1 -0
  356. data/tools/logilab/logilab/common/test/data/reference_dir/subdir/coin +1 -0
  357. data/tools/logilab/logilab/common/test/data/reference_dir/subdir/toto.txt +53 -0
  358. data/tools/logilab/logilab/common/test/data/same_dir/NOTHING +0 -0
  359. data/tools/logilab/logilab/common/test/data/same_dir/README +1 -0
  360. data/tools/logilab/logilab/common/test/data/same_dir/subdir/coin +1 -0
  361. data/tools/logilab/logilab/common/test/data/same_dir/subdir/toto.txt +53 -0
  362. data/tools/logilab/logilab/common/test/data/spam.txt +9 -0
  363. data/tools/logilab/logilab/common/test/data/sub/doc.txt +1 -0
  364. data/tools/logilab/logilab/common/test/data/sub/momo.py +1 -0
  365. data/tools/logilab/logilab/common/test/data/subdir_differ_dir/NOTHING +0 -0
  366. data/tools/logilab/logilab/common/test/data/subdir_differ_dir/README +1 -0
  367. data/tools/logilab/logilab/common/test/data/subdir_differ_dir/subdir/coin +1 -0
  368. data/tools/logilab/logilab/common/test/data/subdir_differ_dir/subdir/toto.txt +53 -0
  369. data/tools/logilab/logilab/common/test/data/test.ini +20 -0
  370. data/tools/logilab/logilab/common/test/data/test1.msg +30 -0
  371. data/tools/logilab/logilab/common/test/data/test2.msg +42 -0
  372. data/tools/logilab/logilab/common/test/data/write_protected_file.txt +0 -0
  373. data/tools/logilab/logilab/common/test/foomod.py +17 -0
  374. data/tools/logilab/logilab/common/test/unittest_cache.py +129 -0
  375. data/tools/logilab/logilab/common/test/unittest_changelog.py +37 -0
  376. data/tools/logilab/logilab/common/test/unittest_compat.py +239 -0
  377. data/tools/logilab/logilab/common/test/unittest_configuration.py +348 -0
  378. data/tools/logilab/logilab/common/test/unittest_date.py +154 -0
  379. data/tools/logilab/logilab/common/test/unittest_decorators.py +62 -0
  380. data/tools/logilab/logilab/common/test/unittest_deprecation.py +76 -0
  381. data/tools/logilab/logilab/common/test/unittest_fileutils.py +133 -0
  382. data/tools/logilab/logilab/common/test/unittest_graph.py +50 -0
  383. data/tools/logilab/logilab/common/test/unittest_html.py +76 -0
  384. data/tools/logilab/logilab/common/test/unittest_interface.py +87 -0
  385. data/tools/logilab/logilab/common/test/unittest_modutils.py +244 -0
  386. data/tools/logilab/logilab/common/test/unittest_pytest.py +50 -0
  387. data/tools/logilab/logilab/common/test/unittest_shellutils.py +248 -0
  388. data/tools/logilab/logilab/common/test/unittest_table.py +448 -0
  389. data/tools/logilab/logilab/common/test/unittest_taskqueue.py +71 -0
  390. data/tools/logilab/logilab/common/test/unittest_testlib.py +956 -0
  391. data/tools/logilab/logilab/common/test/unittest_textutils.py +247 -0
  392. data/tools/logilab/logilab/common/test/unittest_tree.py +248 -0
  393. data/tools/logilab/logilab/common/test/unittest_umessage.py +55 -0
  394. data/tools/logilab/logilab/common/test/unittest_ureports_html.py +64 -0
  395. data/tools/logilab/logilab/common/test/unittest_ureports_text.py +105 -0
  396. data/tools/logilab/logilab/common/test/unittest_xmlutils.py +75 -0
  397. data/tools/logilab/logilab/common/test/utils.py +87 -0
  398. data/tools/logilab/logilab/common/testlib.py +1927 -0
  399. data/tools/logilab/logilab/common/textutils.py +476 -0
  400. data/tools/logilab/logilab/common/tree.py +372 -0
  401. data/tools/logilab/logilab/common/umessage.py +161 -0
  402. data/tools/logilab/logilab/common/ureports/__init__.py +174 -0
  403. data/tools/logilab/logilab/common/ureports/docbook_writer.py +139 -0
  404. data/tools/logilab/logilab/common/ureports/html_writer.py +131 -0
  405. data/tools/logilab/logilab/common/ureports/nodes.py +201 -0
  406. data/tools/logilab/logilab/common/ureports/text_writer.py +140 -0
  407. data/tools/logilab/logilab/common/vcgutils.py +216 -0
  408. data/tools/logilab/logilab/common/visitor.py +107 -0
  409. data/tools/logilab/logilab/common/xmlrpcutils.py +136 -0
  410. data/tools/logilab/logilab/common/xmlutils.py +61 -0
  411. data/tools/pychecker/COPYRIGHT +31 -0
  412. data/tools/pychecker/ChangeLog +349 -0
  413. data/tools/pychecker/CodeChecks.py +1969 -0
  414. data/tools/pychecker/CodeChecks.pyc +0 -0
  415. data/tools/pychecker/CodeChecks.pyo +0 -0
  416. data/tools/pychecker/Config.py +475 -0
  417. data/tools/pychecker/Config.pyc +0 -0
  418. data/tools/pychecker/Config.pyo +0 -0
  419. data/tools/pychecker/KNOWN_BUGS +100 -0
  420. data/tools/pychecker/MAINTAINERS +81 -0
  421. data/tools/pychecker/NEWS +406 -0
  422. data/tools/pychecker/OP.py +131 -0
  423. data/tools/pychecker/OP.pyc +0 -0
  424. data/tools/pychecker/OP.pyo +0 -0
  425. data/tools/pychecker/OptionTypes.py +117 -0
  426. data/tools/pychecker/OptionTypes.pyc +0 -0
  427. data/tools/pychecker/OptionTypes.pyo +0 -0
  428. data/tools/pychecker/README +152 -0
  429. data/tools/pychecker/Stack.py +115 -0
  430. data/tools/pychecker/Stack.pyc +0 -0
  431. data/tools/pychecker/Stack.pyo +0 -0
  432. data/tools/pychecker/TODO +101 -0
  433. data/tools/pychecker/VERSION +1 -0
  434. data/tools/pychecker/Warning.py +50 -0
  435. data/tools/pychecker/Warning.pyc +0 -0
  436. data/tools/pychecker/Warning.pyo +0 -0
  437. data/tools/pychecker/__init__.py +17 -0
  438. data/tools/pychecker/__init__.pyc +0 -0
  439. data/tools/pychecker/__init__.pyo +0 -0
  440. data/tools/pychecker/checker.py +961 -0
  441. data/tools/pychecker/checker.pyc +0 -0
  442. data/tools/pychecker/checker.pyo +0 -0
  443. data/tools/pychecker/function.py +159 -0
  444. data/tools/pychecker/function.pyc +0 -0
  445. data/tools/pychecker/function.pyo +0 -0
  446. data/tools/pychecker/msgs.py +175 -0
  447. data/tools/pychecker/msgs.pyc +0 -0
  448. data/tools/pychecker/msgs.pyo +0 -0
  449. data/tools/pychecker/options.py +275 -0
  450. data/tools/pychecker/options.pyc +0 -0
  451. data/tools/pychecker/options.pyo +0 -0
  452. data/tools/pychecker/pcmodules.py +19 -0
  453. data/tools/pychecker/pcmodules.pyc +0 -0
  454. data/tools/pychecker/pcmodules.pyo +0 -0
  455. data/tools/pychecker/printer.py +47 -0
  456. data/tools/pychecker/printer.pyc +0 -0
  457. data/tools/pychecker/printer.pyo +0 -0
  458. data/tools/pychecker/python.py +427 -0
  459. data/tools/pychecker/python.pyc +0 -0
  460. data/tools/pychecker/python.pyo +0 -0
  461. data/tools/pychecker/utils.py +102 -0
  462. data/tools/pychecker/utils.pyc +0 -0
  463. data/tools/pychecker/utils.pyo +0 -0
  464. data/tools/pychecker/warn.py +778 -0
  465. data/tools/pychecker/warn.pyc +0 -0
  466. data/tools/pychecker/warn.pyo +0 -0
  467. data/tools/pylint2/pylint/__init__.py +16 -0
  468. data/tools/pylint2/pylint/__pkginfo__.py +67 -0
  469. data/tools/pylint2/pylint/checkers/__init__.py +155 -0
  470. data/tools/pylint2/pylint/checkers/base.py +749 -0
  471. data/tools/pylint2/pylint/checkers/classes.py +527 -0
  472. data/tools/pylint2/pylint/checkers/design_analysis.py +344 -0
  473. data/tools/pylint2/pylint/checkers/exceptions.py +183 -0
  474. data/tools/pylint2/pylint/checkers/format.py +367 -0
  475. data/tools/pylint2/pylint/checkers/imports.py +379 -0
  476. data/tools/pylint2/pylint/checkers/logging.py +98 -0
  477. data/tools/pylint2/pylint/checkers/misc.py +128 -0
  478. data/tools/pylint2/pylint/checkers/newstyle.py +107 -0
  479. data/tools/pylint2/pylint/checkers/raw_metrics.py +125 -0
  480. data/tools/pylint2/pylint/checkers/similar.py +333 -0
  481. data/tools/pylint2/pylint/checkers/string_format.py +239 -0
  482. data/tools/pylint2/pylint/checkers/typecheck.py +364 -0
  483. data/tools/pylint2/pylint/checkers/utils.py +208 -0
  484. data/tools/pylint2/pylint/checkers/variables.py +498 -0
  485. data/tools/pylint2/pylint/config.py +149 -0
  486. data/tools/pylint2/pylint/epylint.py +149 -0
  487. data/tools/pylint2/pylint/gui.py +433 -0
  488. data/tools/pylint2/pylint/interfaces.py +98 -0
  489. data/tools/pylint2/pylint/lint.py +914 -0
  490. data/tools/pylint2/pylint/pyreverse/__init__.py +5 -0
  491. data/tools/pylint2/pylint/pyreverse/diadefslib.py +229 -0
  492. data/tools/pylint2/pylint/pyreverse/diagrams.py +247 -0
  493. data/tools/pylint2/pylint/pyreverse/main.py +123 -0
  494. data/tools/pylint2/pylint/pyreverse/utils.py +131 -0
  495. data/tools/pylint2/pylint/pyreverse/writer.py +196 -0
  496. data/tools/pylint2/pylint/reporters/__init__.py +67 -0
  497. data/tools/pylint2/pylint/reporters/guireporter.py +36 -0
  498. data/tools/pylint2/pylint/reporters/html.py +69 -0
  499. data/tools/pylint2/pylint/reporters/text.py +156 -0
  500. data/tools/pylint2/pylint/utils.py +518 -0
  501. data/tools/pylint2/pylint.py +16 -0
  502. data/tools/test/suite.py +35 -0
  503. metadata +566 -0
@@ -0,0 +1,527 @@
1
+ # Copyright (c) 2003-2010 LOGILAB S.A. (Paris, FRANCE).
2
+ # http://www.logilab.fr/ -- mailto:contact@logilab.fr
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify it under
5
+ # the terms of the GNU General Public License as published by the Free Software
6
+ # Foundation; either version 2 of the License, or (at your option) any later
7
+ # version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful, but WITHOUT
10
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License along with
14
+ # this program; if not, write to the Free Software Foundation, Inc.,
15
+ # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16
+ """classes checker for Python code
17
+ """
18
+ from __future__ import generators
19
+
20
+ from logilab import astng
21
+ from logilab.astng import YES, Instance, are_exclusive
22
+
23
+ from pylint.interfaces import IASTNGChecker
24
+ from pylint.checkers import BaseChecker
25
+ from pylint.checkers.utils import PYMETHODS, overrides_a_method
26
+
27
+ def class_is_abstract(node):
28
+ """return true if the given class node should be considered as an abstract
29
+ class
30
+ """
31
+ for method in node.methods():
32
+ if method.parent.frame() is node:
33
+ if method.is_abstract(pass_is_abstract=False):
34
+ return True
35
+ return False
36
+
37
+
38
+ MSGS = {
39
+ 'F0202': ('Unable to check methods signature (%s / %s)',
40
+ 'Used when PyLint has been unable to check methods signature \
41
+ compatibility for an unexpected reason. Please report this kind \
42
+ if you don\'t make sense of it.'),
43
+
44
+ 'E0202': ('An attribute inherited from %s hide this method',
45
+ 'Used when a class defines a method which is hidden by an \
46
+ instance attribute from an ancestor class.'),
47
+ 'E0203': ('Access to member %r before its definition line %s',
48
+ 'Used when an instance member is accessed before it\'s actually\
49
+ assigned.'),
50
+ 'W0201': ('Attribute %r defined outside __init__',
51
+ 'Used when an instance attribute is defined outside the __init__\
52
+ method.'),
53
+
54
+ 'W0212': ('Access to a protected member %s of a client class', # E0214
55
+ 'Used when a protected member (i.e. class member with a name \
56
+ beginning with an underscore) is access outside the class or a \
57
+ descendant of the class where it\'s defined.'),
58
+
59
+ 'E0211': ('Method has no argument',
60
+ 'Used when a method which should have the bound instance as \
61
+ first argument has no argument defined.'),
62
+ 'E0213': ('Method should have "self" as first argument',
63
+ 'Used when a method has an attribute different the "self" as\
64
+ first argument. This is considered as an error since this is\
65
+ a so common convention that you shouldn\'t break it!'),
66
+ 'C0202': ('Class method should have "cls" as first argument', # E0212
67
+ 'Used when a class method has an attribute different than "cls"\
68
+ as first argument, to easily differentiate them from regular \
69
+ instance methods.'),
70
+ 'C0203': ('Metaclass method should have "mcs" as first argument', # E0214
71
+ 'Used when a metaclass method has an attribute different the \
72
+ "mcs" as first argument.'),
73
+
74
+ 'W0211': ('Static method with %r as first argument',
75
+ 'Used when a static method has "self" or "cls" as first argument.'
76
+ ),
77
+ 'R0201': ('Method could be a function',
78
+ 'Used when a method doesn\'t use its bound instance, and so could\
79
+ be written as a function.'
80
+ ),
81
+
82
+ 'E0221': ('Interface resolved to %s is not a class',
83
+ 'Used when a class claims to implement an interface which is not \
84
+ a class.'),
85
+ 'E0222': ('Missing method %r from %s interface' ,
86
+ 'Used when a method declared in an interface is missing from a \
87
+ class implementing this interface'),
88
+ 'W0221': ('Arguments number differs from %s method',
89
+ 'Used when a method has a different number of arguments than in \
90
+ the implemented interface or in an overridden method.'),
91
+ 'W0222': ('Signature differs from %s method',
92
+ 'Used when a method signature is different than in the \
93
+ implemented interface or in an overridden method.'),
94
+ 'W0223': ('Method %r is abstract in class %r but is not overridden',
95
+ 'Used when an abstract method (i.e. raise NotImplementedError) is \
96
+ not overridden in concrete class.'
97
+ ),
98
+ 'F0220': ('failed to resolve interfaces implemented by %s (%s)', # W0224
99
+ 'Used when a PyLint as failed to find interfaces implemented by \
100
+ a class'),
101
+
102
+
103
+ 'W0231': ('__init__ method from base class %r is not called',
104
+ 'Used when an ancestor class method has an __init__ method \
105
+ which is not called by a derived class.'),
106
+ 'W0232': ('Class has no __init__ method',
107
+ 'Used when a class has no __init__ method, neither its parent \
108
+ classes.'),
109
+ 'W0233': ('__init__ method from a non direct base class %r is called',
110
+ 'Used when an __init__ method is called on a class which is not \
111
+ in the direct ancestors for the analysed class.'),
112
+
113
+ }
114
+
115
+
116
+ class ClassChecker(BaseChecker):
117
+ """checks for :
118
+ * methods without self as first argument
119
+ * overridden methods signature
120
+ * access only to existent members via self
121
+ * attributes not defined in the __init__ method
122
+ * supported interfaces implementation
123
+ * unreachable code
124
+ """
125
+
126
+ __implements__ = (IASTNGChecker,)
127
+
128
+ # configuration section name
129
+ name = 'classes'
130
+ # messages
131
+ msgs = MSGS
132
+ priority = -2
133
+ # configuration options
134
+ options = (('ignore-iface-methods',
135
+ {'default' : (#zope interface
136
+ 'isImplementedBy', 'deferred', 'extends', 'names',
137
+ 'namesAndDescriptions', 'queryDescriptionFor', 'getBases',
138
+ 'getDescriptionFor', 'getDoc', 'getName', 'getTaggedValue',
139
+ 'getTaggedValueTags', 'isEqualOrExtendedBy', 'setTaggedValue',
140
+ 'isImplementedByInstancesOf',
141
+ # twisted
142
+ 'adaptWith',
143
+ # logilab.common interface
144
+ 'is_implemented_by'),
145
+ 'type' : 'csv',
146
+ 'metavar' : '<method names>',
147
+ 'help' : 'List of interface methods to ignore, \
148
+ separated by a comma. This is used for instance to not check methods defines \
149
+ in Zope\'s Interface base class.'}
150
+ ),
151
+
152
+ ('defining-attr-methods',
153
+ {'default' : ('__init__', '__new__', 'setUp'),
154
+ 'type' : 'csv',
155
+ 'metavar' : '<method names>',
156
+ 'help' : 'List of method names used to declare (i.e. assign) \
157
+ instance attributes.'}
158
+ ),
159
+
160
+ )
161
+
162
+ def __init__(self, linter=None):
163
+ BaseChecker.__init__(self, linter)
164
+ self._accessed = []
165
+ self._first_attrs = []
166
+ self._meth_could_be_func = None
167
+
168
+ def visit_class(self, node):
169
+ """init visit variable _accessed and check interfaces
170
+ """
171
+ self._accessed.append({})
172
+ self._check_bases_classes(node)
173
+ self._check_interfaces(node)
174
+ # if not an interface, exception, metaclass
175
+ if node.type == 'class':
176
+ try:
177
+ node.local_attr('__init__')
178
+ except astng.NotFoundError:
179
+ self.add_message('W0232', args=node, node=node)
180
+
181
+ def leave_class(self, cnode):
182
+ """close a class node:
183
+ check that instance attributes are defined in __init__ and check
184
+ access to existent members
185
+ """
186
+ # checks attributes are defined in an allowed method such as __init__
187
+ defining_methods = self.config.defining_attr_methods
188
+ for attr, nodes in cnode.instance_attrs.items():
189
+ nodes = [n for n in nodes if not
190
+ isinstance(n.statement(), (astng.Delete, astng.AugAssign))]
191
+ if not nodes:
192
+ continue # error detected by typechecking
193
+ attr_defined = False
194
+ # check if any method attr is defined in is a defining method
195
+ for node in nodes:
196
+ if node.frame().name in defining_methods:
197
+ attr_defined = True
198
+ if not attr_defined:
199
+ # check attribute is defined in a parent's __init__
200
+ for parent in cnode.instance_attr_ancestors(attr):
201
+ attr_defined = False
202
+ # check if any parent method attr is defined in is a defining method
203
+ for node in parent.instance_attrs[attr]:
204
+ if node.frame().name in defining_methods:
205
+ attr_defined = True
206
+ if attr_defined:
207
+ # we're done :)
208
+ break
209
+ else:
210
+ # check attribute is defined as a class attribute
211
+ try:
212
+ cnode.local_attr(attr)
213
+ except astng.NotFoundError:
214
+ self.add_message('W0201', args=attr, node=node)
215
+ # check access to existent members on non metaclass classes
216
+ accessed = self._accessed.pop()
217
+ if cnode.type != 'metaclass':
218
+ self._check_accessed_members(cnode, accessed)
219
+
220
+ def visit_function(self, node):
221
+ """check method arguments, overriding"""
222
+ # ignore actual functions
223
+ if not node.is_method():
224
+ return
225
+ klass = node.parent.frame()
226
+ self._meth_could_be_func = True
227
+ # check first argument is self if this is actually a method
228
+ self._check_first_arg_for_type(node, klass.type == 'metaclass')
229
+ if node.name == '__init__':
230
+ self._check_init(node)
231
+ return
232
+ # check signature if the method overloads inherited method
233
+ for overridden in klass.local_attr_ancestors(node.name):
234
+ # get astng for the searched method
235
+ try:
236
+ meth_node = overridden[node.name]
237
+ except KeyError:
238
+ # we have found the method but it's not in the local
239
+ # dictionary.
240
+ # This may happen with astng build from living objects
241
+ continue
242
+ if not isinstance(meth_node, astng.Function):
243
+ continue
244
+ self._check_signature(node, meth_node, 'overridden')
245
+ break
246
+ # check if the method overload an attribute
247
+ try:
248
+ overridden = klass.instance_attr(node.name)[0] # XXX
249
+ # we may be unable to get owner class if this is a monkey
250
+ # patched method
251
+ while overridden.parent and not isinstance(overridden, astng.Class):
252
+ overridden = overridden.parent.frame()
253
+ self.add_message('E0202', args=overridden.name, node=node)
254
+ except astng.NotFoundError:
255
+ pass
256
+
257
+ def leave_function(self, node):
258
+ """on method node, check if this method couldn't be a function
259
+
260
+ ignore class, static and abstract methods, initializer,
261
+ methods overridden from a parent class and any
262
+ kind of method defined in an interface for this warning
263
+ """
264
+ if node.is_method():
265
+ if node.args.args is not None:
266
+ self._first_attrs.pop()
267
+ class_node = node.parent.frame()
268
+ if (self._meth_could_be_func and node.type == 'method'
269
+ and not node.name in PYMETHODS
270
+ and not (node.is_abstract() or
271
+ overrides_a_method(class_node, node.name))
272
+ and class_node.type != 'interface'):
273
+ self.add_message('R0201', node=node)
274
+
275
+ def visit_getattr(self, node):
276
+ """check if the getattr is an access to a class member
277
+ if so, register it. Also check for access to protected
278
+ class member from outside its class (but ignore __special__
279
+ methods)
280
+ """
281
+ attrname = node.attrname
282
+ if self._first_attrs and isinstance(node.expr, astng.Name) and \
283
+ node.expr.name == self._first_attrs[-1]:
284
+ self._accessed[-1].setdefault(attrname, []).append(node)
285
+ elif attrname[0] == '_' and not attrname == '_' and not (
286
+ attrname.startswith('__') and attrname.endswith('__')):
287
+ # XXX move this in a reusable function
288
+ klass = node.frame()
289
+ while klass is not None and not isinstance(klass, astng.Class):
290
+ if klass.parent is None:
291
+ klass = None
292
+ else:
293
+ klass = klass.parent.frame()
294
+ # XXX infer to be more safe and less dirty ??
295
+ # in classes, check we are not getting a parent method
296
+ # through the class object or through super
297
+ callee = node.expr.as_string()
298
+ if klass is None or not (callee == klass.name or
299
+ callee in klass.basenames
300
+ or (isinstance(node.expr, astng.CallFunc)
301
+ and isinstance(node.expr.func, astng.Name)
302
+ and node.expr.func.name == 'super')):
303
+ self.add_message('W0212', node=node, args=attrname)
304
+
305
+
306
+ def visit_name(self, node):
307
+ """check if the name handle an access to a class member
308
+ if so, register it
309
+ """
310
+ if self._first_attrs and (node.name == self._first_attrs[-1] or
311
+ not self._first_attrs[-1]):
312
+ self._meth_could_be_func = False
313
+
314
+ def _check_accessed_members(self, node, accessed):
315
+ """check that accessed members are defined"""
316
+ # XXX refactor, probably much simpler now that E0201 is in type checker
317
+ for attr, nodes in accessed.items():
318
+ # deactivate "except doesn't do anything", that's expected
319
+ # pylint: disable=W0704
320
+ # is it a class attribute ?
321
+ try:
322
+ node.local_attr(attr)
323
+ # yes, stop here
324
+ continue
325
+ except astng.NotFoundError:
326
+ pass
327
+ # is it an instance attribute of a parent class ?
328
+ try:
329
+ node.instance_attr_ancestors(attr).next()
330
+ # yes, stop here
331
+ continue
332
+ except StopIteration:
333
+ pass
334
+ # is it an instance attribute ?
335
+ try:
336
+ defstmts = node.instance_attr(attr)
337
+ except astng.NotFoundError:
338
+ pass
339
+ else:
340
+ if len(defstmts) == 1:
341
+ defstmt = defstmts[0]
342
+ # check that if the node is accessed in the same method as
343
+ # it's defined, it's accessed after the initial assignment
344
+ frame = defstmt.frame()
345
+ lno = defstmt.fromlineno
346
+ for _node in nodes:
347
+ if _node.frame() is frame and _node.fromlineno < lno \
348
+ and not are_exclusive(_node.statement(), defstmt, ('AttributeError', 'Exception', 'BaseException')):
349
+ self.add_message('E0203', node=_node,
350
+ args=(attr, lno))
351
+
352
+ def _check_first_arg_for_type(self, node, metaclass=0):
353
+ """check the name of first argument, expect:
354
+
355
+ * 'self' for a regular method
356
+ * 'cls' for a class method
357
+ * 'mcs' for a metaclass
358
+ * not one of the above for a static method
359
+ """
360
+ # don't care about functions with unknown argument (builtins)
361
+ if node.args.args is None:
362
+ return
363
+ first_arg = node.args.args and node.argnames()[0]
364
+ self._first_attrs.append(first_arg)
365
+ first = self._first_attrs[-1]
366
+ # static method
367
+ if node.type == 'staticmethod':
368
+ if first_arg in ('self', 'cls', 'mcs'):
369
+ self.add_message('W0211', args=first, node=node)
370
+ self._first_attrs[-1] = None
371
+ # class / regular method with no args
372
+ elif not node.args.args:
373
+ self.add_message('E0211', node=node)
374
+ # metaclass method
375
+ elif metaclass:
376
+ if first != 'mcs':
377
+ self.add_message('C0203', node=node)
378
+ # class method
379
+ elif node.type == 'classmethod':
380
+ if first != 'cls':
381
+ self.add_message('C0202', node=node)
382
+ # regular method without self as argument
383
+ elif first != 'self':
384
+ self.add_message('E0213', node=node)
385
+
386
+ def _check_bases_classes(self, node):
387
+ """check that the given class node implements abstract methods from
388
+ base classes
389
+ """
390
+ # check if this class abstract
391
+ if class_is_abstract(node):
392
+ return
393
+ for method in node.methods():
394
+ owner = method.parent.frame()
395
+ if owner is node:
396
+ continue
397
+ # owner is not this class, it must be a parent class
398
+ # check that the ancestor's method is not abstract
399
+ if method.is_abstract(pass_is_abstract=False):
400
+ self.add_message('W0223', node=node,
401
+ args=(method.name, owner.name))
402
+
403
+ def _check_interfaces(self, node):
404
+ """check that the given class node really implements declared
405
+ interfaces
406
+ """
407
+ e0221_hack = [False]
408
+ def iface_handler(obj):
409
+ """filter interface objects, it should be classes"""
410
+ if not isinstance(obj, astng.Class):
411
+ e0221_hack[0] = True
412
+ self.add_message('E0221', node=node,
413
+ args=(obj.as_string(),))
414
+ return False
415
+ return True
416
+ ignore_iface_methods = self.config.ignore_iface_methods
417
+ try:
418
+ for iface in node.interfaces(handler_func=iface_handler):
419
+ for imethod in iface.methods():
420
+ name = imethod.name
421
+ if name.startswith('_') or name in ignore_iface_methods:
422
+ # don't check method beginning with an underscore,
423
+ # usually belonging to the interface implementation
424
+ continue
425
+ # get class method astng
426
+ try:
427
+ method = node_method(node, name)
428
+ except astng.NotFoundError:
429
+ self.add_message('E0222', args=(name, iface.name),
430
+ node=node)
431
+ continue
432
+ # ignore inherited methods
433
+ if method.parent.frame() is not node:
434
+ continue
435
+ # check signature
436
+ self._check_signature(method, imethod,
437
+ '%s interface' % iface.name)
438
+ except astng.InferenceError:
439
+ if e0221_hack[0]:
440
+ return
441
+ implements = Instance(node).getattr('__implements__')[0]
442
+ assignment = implements.parent
443
+ assert isinstance(assignment, astng.Assign)
444
+ # assignment.expr can be a Name or a Tuple or whatever.
445
+ # Use as_string() for the message
446
+ # FIXME: in case of multiple interfaces, find which one could not
447
+ # be resolved
448
+ self.add_message('F0220', node=implements,
449
+ args=(node.name, assignment.value.as_string()))
450
+
451
+ def _check_init(self, node):
452
+ """check that the __init__ method call super or ancestors'__init__
453
+ method
454
+ """
455
+ klass_node = node.parent.frame()
456
+ to_call = _ancestors_to_call(klass_node)
457
+ not_called_yet = dict(to_call)
458
+ for stmt in node.nodes_of_class(astng.CallFunc):
459
+ expr = stmt.func
460
+ if not isinstance(expr, astng.Getattr) \
461
+ or expr.attrname != '__init__':
462
+ continue
463
+ # skip the test if using super
464
+ if isinstance(expr.expr, astng.CallFunc) and \
465
+ isinstance(expr.expr.func, astng.Name) and \
466
+ expr.expr.func.name == 'super':
467
+ return
468
+ try:
469
+ klass = expr.expr.infer().next()
470
+ if klass is YES:
471
+ continue
472
+ try:
473
+ del not_called_yet[klass]
474
+ except KeyError:
475
+ if klass not in to_call:
476
+ self.add_message('W0233', node=expr, args=klass.name)
477
+ except astng.InferenceError:
478
+ continue
479
+ for klass in not_called_yet.keys():
480
+ if klass.name == 'object':
481
+ continue
482
+ self.add_message('W0231', args=klass.name, node=node)
483
+
484
+ def _check_signature(self, method1, refmethod, class_type):
485
+ """check that the signature of the two given methods match
486
+
487
+ class_type is in 'class', 'interface'
488
+ """
489
+ if not (isinstance(method1, astng.Function)
490
+ and isinstance(refmethod, astng.Function)):
491
+ self.add_message('F0202', args=(method1, refmethod), node=method1)
492
+ return
493
+ # don't care about functions with unknown argument (builtins)
494
+ if method1.args.args is None or refmethod.args.args is None:
495
+ return
496
+ if len(method1.args.args) != len(refmethod.args.args):
497
+ self.add_message('W0221', args=class_type, node=method1)
498
+ elif len(method1.args.defaults) < len(refmethod.args.defaults):
499
+ self.add_message('W0222', args=class_type, node=method1)
500
+
501
+
502
+ def _ancestors_to_call(klass_node, method='__init__'):
503
+ """return a dictionary where keys are the list of base classes providing
504
+ the queried method, and so that should/may be called from the method node
505
+ """
506
+ to_call = {}
507
+ for base_node in klass_node.ancestors(recurs=False):
508
+ try:
509
+ base_node.local_attr(method)
510
+ to_call[base_node] = 1
511
+ except astng.NotFoundError:
512
+ continue
513
+ return to_call
514
+
515
+
516
+ def node_method(node, method_name):
517
+ """get astng for <method_name> on the given class node, ensuring it
518
+ is a Function node
519
+ """
520
+ for n in node.local_attr(method_name):
521
+ if isinstance(n, astng.Function):
522
+ return n
523
+ raise astng.NotFoundError(method_name)
524
+
525
+ def register(linter):
526
+ """required method to auto register this checker """
527
+ linter.register_checker(ClassChecker(linter))