bee_python 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,1969 @@
1
+ #!/usr/bin/env python
2
+
3
+ # Copyright (c) 2001-2006, MetaSlash Inc. All rights reserved.
4
+ # Portions Copyright (c) 2005, Google, Inc. All rights reserved.
5
+
6
+ """
7
+ Find warnings in byte code from Python source files.
8
+ """
9
+
10
+ import string
11
+ import types
12
+
13
+ from pychecker import msgs
14
+ from pychecker import utils
15
+ from pychecker import Warning
16
+ from pychecker import OP
17
+ from pychecker import Stack
18
+ from pychecker import python
19
+
20
+ __pychecker__ = 'no-argsused'
21
+
22
+
23
+ def cfg() :
24
+ return utils.cfg()
25
+
26
+ def getFunctionArgErr(func_name, argCount, minArgs, maxArgs):
27
+ err = None
28
+ if maxArgs == None:
29
+ if argCount < minArgs :
30
+ err = msgs.INVALID_ARG_COUNT2 % (func_name, argCount, minArgs)
31
+ elif argCount < minArgs or argCount > maxArgs:
32
+ if minArgs == maxArgs:
33
+ err = msgs.INVALID_ARG_COUNT1 % (func_name, argCount, minArgs)
34
+ else:
35
+ err = msgs.INVALID_ARG_COUNT3 % (func_name, argCount, minArgs, maxArgs)
36
+ return err
37
+
38
+ def _checkFunctionArgCount(code, func_name, argCount, minArgs, maxArgs,
39
+ objectReference = 0) :
40
+ # there is an implied argument for object creation and self.xxx()
41
+ if objectReference :
42
+ minArgs = minArgs - 1
43
+ if maxArgs is not None :
44
+ maxArgs = maxArgs - 1
45
+
46
+ err = getFunctionArgErr(func_name, argCount, minArgs, maxArgs)
47
+ if err :
48
+ code.addWarning(err)
49
+
50
+ def _checkFunctionArgs(code, func, objectReference, argCount, kwArgs,
51
+ check_arg_count = 1) :
52
+ func_name = func.function.func_code.co_name
53
+ if kwArgs :
54
+ args_len = func.function.func_code.co_argcount
55
+ arg_names = func.function.func_code.co_varnames[argCount:args_len]
56
+ if argCount < args_len and kwArgs[0] in arg_names:
57
+ if cfg().namedArgs :
58
+ code.addWarning(msgs.FUNC_USES_NAMED_ARGS % func_name)
59
+
60
+ # convert the named args into regular params, and really check
61
+ while argCount < args_len and kwArgs and kwArgs[0] in arg_names:
62
+ argCount = argCount + 1
63
+ kwArgs = kwArgs[1:]
64
+ _checkFunctionArgs(code, func, objectReference, argCount, kwArgs,
65
+ check_arg_count)
66
+ return
67
+
68
+ if not func.supportsKW :
69
+ code.addWarning(msgs.FUNC_DOESNT_SUPPORT_KW % func_name)
70
+
71
+ if check_arg_count :
72
+ _checkFunctionArgCount(code, func_name, argCount,
73
+ func.minArgs, func.maxArgs, objectReference)
74
+
75
+ def _getReferenceFromModule(module, identifier) :
76
+ func = module.functions.get(identifier, None)
77
+ if func is not None :
78
+ return func, None, 0
79
+
80
+ create = 0
81
+ c = module.classes.get(identifier, None)
82
+ if c is not None :
83
+ func = c.methods.get(utils.INIT, None)
84
+ create = 1
85
+ return func, c, create
86
+
87
+ def _getFunction(module, stackValue) :
88
+ 'Return (function, class) from the stack value'
89
+
90
+ identifier = stackValue.data
91
+ if type(identifier) == types.StringType :
92
+ return _getReferenceFromModule(module, identifier)
93
+
94
+ # find the module this references
95
+ i, maxLen = 0, len(identifier)
96
+ while i < maxLen :
97
+ id = utils.safestr(identifier[i])
98
+ if module.classes.has_key(id) or module.functions.has_key(id) :
99
+ break
100
+ refModule = module.modules.get(id, None)
101
+ if refModule is not None :
102
+ module = refModule
103
+ else :
104
+ return None, None, 0
105
+ i = i + 1
106
+
107
+ # if we got to the end, there is only modules, nothing we can do
108
+ # we also can't handle if there is more than 2 items left
109
+ if i >= maxLen or (i+2) < maxLen :
110
+ return None, None, 0
111
+
112
+ if (i+1) == maxLen :
113
+ return _getReferenceFromModule(module, identifier[-1])
114
+
115
+ # we can't handle self.x.y
116
+ if (i+2) == maxLen and identifier[0] == cfg().methodArgName:
117
+ return None, None, 0
118
+
119
+ c = module.classes.get(identifier[-2], None)
120
+ if c is None :
121
+ return None, None, 0
122
+ return c.methods.get(identifier[-1], None), c, 0
123
+
124
+ def _validateKwArgs(code, info, func_name, kwArgs):
125
+ if len(info) < 4:
126
+ code.addWarning(msgs.FUNC_DOESNT_SUPPORT_KW % func_name)
127
+ elif not info[3]:
128
+ return
129
+
130
+ try:
131
+ # info could be from a builtin method which means that
132
+ # info[3] is not a list.
133
+ dummy = info[3][0]
134
+ except IndexError:
135
+ return
136
+
137
+ for arg in kwArgs:
138
+ if arg not in info[3]:
139
+ code.addWarning(msgs.FUNC_DOESNT_SUPPORT_KW_ARG % (func_name, arg))
140
+
141
+ def _checkBuiltin(code, loadValue, argCount, kwArgs, check_arg_count = 1) :
142
+ returnValue = Stack.makeFuncReturnValue(loadValue, argCount)
143
+ func_name = loadValue.data
144
+ if loadValue.type == Stack.TYPE_GLOBAL :
145
+ info = python.GLOBAL_FUNC_INFO.get(func_name, None)
146
+ if info is not None :
147
+ if func_name == 'input' and cfg().usesInput:
148
+ code.addWarning(msgs.USES_INPUT)
149
+ if cfg().constAttr and \
150
+ ((func_name == 'setattr' and argCount >= 2) or
151
+ (func_name == 'getattr' and argCount == 2)):
152
+ arg2 = code.stack[-argCount + 1]
153
+ if arg2.const:
154
+ # lambda with setattr and const is a common way of setting
155
+ # attributes, so allow it
156
+ if code.func.function.func_name != '<lambda>':
157
+ code.addWarning(msgs.USES_CONST_ATTR % func_name)
158
+
159
+ if kwArgs:
160
+ _validateKwArgs(code, info, func_name, kwArgs)
161
+ elif check_arg_count :
162
+ _checkFunctionArgCount(code, func_name, argCount,
163
+ info[1], info[2])
164
+ returnValue = Stack.Item(returnValue.data, info[0])
165
+ returnValue.setStringType(info[0])
166
+ elif type(func_name) == types.TupleType and len(func_name) <= 2 :
167
+ objType = code.typeMap.get(utils.safestr(func_name[0]), [])
168
+ if types.ListType in objType :
169
+ try :
170
+ if func_name[1] == 'append' and argCount > 1 :
171
+ code.addWarning(msgs.LIST_APPEND_ARGS % func_name[0])
172
+ check_arg_count = 0
173
+ except AttributeError :
174
+ # FIXME: why do we need to catch AttributeError???
175
+ pass
176
+ if len(objType) == 1 :
177
+ # if it's a builtin, check method
178
+ builtinType = python.BUILTIN_METHODS.get(objType[0])
179
+ if builtinType is not None :
180
+ methodInfo = builtinType.get(func_name[1])
181
+ # set func properly
182
+ if kwArgs :
183
+ _validateKwArgs(code, methodInfo, func_name[1], kwArgs)
184
+ elif methodInfo :
185
+ returnValue = Stack.Item(func_name[1], methodInfo[0])
186
+ returnValue.setStringType(methodInfo[0])
187
+ if check_arg_count and methodInfo is not None :
188
+ _checkFunctionArgCount(code, func_name[1], argCount,
189
+ methodInfo[1], methodInfo[2])
190
+
191
+ return returnValue
192
+
193
+ _IMMUTABLE_LIST_METHODS = ('count', 'index',)
194
+ _IMMUTABLE_DICT_METHODS = ('copy', 'get', 'has_key',
195
+ 'items', 'keys', 'values',
196
+ 'iteritems', 'iterkeys', 'itervalues')
197
+
198
+ def _checkModifyDefaultArg(code, objectName, methodName=None) :
199
+ try :
200
+ value = code.func.defaultValue(objectName)
201
+ objectType = type(value)
202
+ if objectType in python.MUTABLE_TYPES :
203
+ if objectType == types.DictType and \
204
+ methodName in _IMMUTABLE_DICT_METHODS :
205
+ return
206
+ if objectType == types.ListType and \
207
+ methodName in _IMMUTABLE_LIST_METHODS :
208
+ return
209
+ code.addWarning(msgs.MODIFYING_DEFAULT_ARG % objectName)
210
+ except ValueError :
211
+ pass
212
+
213
+ def _isexception(object) :
214
+ # FIXME: i have no idea why this function is necessary
215
+ # it seems that the issubclass() should work, but it doesn't always
216
+
217
+ if hasattr(object, 'type'):
218
+ if object.type == types.TupleType:
219
+ # if we have a tuple, we can't check the contents (not enough info)
220
+ ## for item in object.value:
221
+ ## if not _isexception(item):
222
+ ## return 0
223
+ return 1
224
+
225
+ try:
226
+ # try/except is necessary for globals like NotImplemented
227
+ if issubclass(object, Exception) :
228
+ return 1
229
+ # Python 2.5 added a BaseException to the hierarchy. That's
230
+ # really what we need to check if it exists.
231
+ if utils.pythonVersion() >= utils.PYTHON_2_5:
232
+ if issubclass(object, BaseException):
233
+ return 1
234
+ except TypeError:
235
+ return 0
236
+
237
+ for c in object.__bases__ :
238
+ if utils.startswith(utils.safestr(c), 'exceptions.') :
239
+ return 1
240
+ if len(c.__bases__) > 0 and _isexception(c) :
241
+ return 1
242
+ return 0
243
+
244
+ def _checkStringFind(code, loadValue):
245
+ if len(loadValue.data) == 2 and loadValue.data[1] == 'find':
246
+ try:
247
+ if types.StringType in code.typeMap.get(loadValue.data[0], []):
248
+ op = code.nextOpInfo()[0]
249
+ if OP.IS_CONDITIONAL_JUMP(op) or OP.IS_NOT(op):
250
+ code.addWarning(msgs.BAD_STRING_FIND)
251
+ except TypeError:
252
+ # we don't care if loadValue.data[0] is not hashable
253
+ pass
254
+
255
+ def _checkAbstract(refClass, code, name):
256
+ name_list = refClass.isAbstract()
257
+ if name_list:
258
+ name_list.sort()
259
+ names = string.join(name_list, ", ")
260
+ code.addWarning(msgs.METHODS_NEED_OVERRIDE % (names, name))
261
+
262
+ _SEQUENCE_TYPES = (types.TupleType, types.ListType, types.StringType)
263
+ try: _SEQUENCE_TYPES = _SEQUENCE_TYPES + (types.UnicodeType,)
264
+ except AttributeError: pass
265
+
266
+ # FIXME: this is not complete. errors will be caught only sometimes,
267
+ # depending on the order the functions/methods are processed
268
+ # in the dict. Need to be able to run through all functions
269
+ # twice, but because the code sucks, this is not possible.
270
+ def _checkReturnValueUse(code, func):
271
+ if func.returnValues is None:
272
+ return
273
+
274
+ err = None
275
+ opInfo = code.nextOpInfo()
276
+ if func.returnsNoValue():
277
+ # make sure we really know how to check for all the return types
278
+ for rv in func.returnValues:
279
+ if rv[1].type in _UNCHECKABLE_STACK_TYPES:
280
+ return
281
+
282
+ if not OP.POP_TOP(opInfo[0]):
283
+ err = msgs.USING_NONE_RETURN_VALUE % utils.safestr(func)
284
+ elif OP.UNPACK_SEQUENCE(opInfo[0]):
285
+ # verify unpacking into proper # of vars
286
+ varCount = opInfo[1]
287
+ stackRV = func.returnValues[0][1]
288
+ returnType = stackRV.getType({})
289
+ funcCount = stackRV.length
290
+ if returnType in _SEQUENCE_TYPES:
291
+ if varCount != funcCount and funcCount > 0:
292
+ err = msgs.WRONG_UNPACK_FUNCTION % (utils.safestr(func), funcCount, varCount)
293
+ elif returnType not in _UNCHECKABLE_STACK_TYPES:
294
+ err = msgs.UNPACK_NON_SEQUENCE % (utils.safestr(func), _getTypeStr(returnType))
295
+ if err:
296
+ code.addWarning(err)
297
+
298
+ def _handleFunctionCall(codeSource, code, argCount, indexOffset = 0,
299
+ check_arg_count = 1) :
300
+ 'Checks for warnings, returns function called (may be None)'
301
+
302
+ if not code.stack :
303
+ return
304
+
305
+ kwArgCount = argCount >> utils.VAR_ARGS_BITS
306
+ argCount = argCount & utils.MAX_ARGS_MASK
307
+
308
+ # function call on stack is before the args, and keyword args
309
+ funcIndex = argCount + 2 * kwArgCount + 1 + indexOffset
310
+ if funcIndex > len(code.stack) :
311
+ funcIndex = 0
312
+ # to find on stack, we have to look backwards from top of stack (end)
313
+ funcIndex = -funcIndex
314
+
315
+ # store the keyword names/keys to check if using named arguments
316
+ kwArgs = []
317
+ if kwArgCount > 0 :
318
+ # loop backwards by 2 (keyword, value) in stack to find keyword args
319
+ for i in range(-2 - indexOffset, (-2 * kwArgCount - 1), -2) :
320
+ kwArgs.append(code.stack[i].data)
321
+ kwArgs.reverse()
322
+
323
+ loadValue = code.stack[funcIndex]
324
+ funcName = loadValue.getName()
325
+ returnValue = Stack.makeFuncReturnValue(loadValue, argCount)
326
+
327
+ if loadValue.isMethodCall(codeSource.classObject, cfg().methodArgName):
328
+ methodName = loadValue.data[1]
329
+ try :
330
+ m = codeSource.classObject.methods[methodName]
331
+ if m != None :
332
+ objRef = not m.isStaticMethod()
333
+ _checkFunctionArgs(code, m, objRef, argCount, kwArgs,
334
+ check_arg_count)
335
+ except KeyError :
336
+ sattr = codeSource.classObject.statics.get(methodName)
337
+ if sattr is not None :
338
+ funcName = sattr.getName()
339
+
340
+ if sattr is None and cfg().callingAttribute :
341
+ code.addWarning(msgs.INVALID_METHOD % methodName)
342
+
343
+ elif loadValue.type in (Stack.TYPE_ATTRIBUTE, Stack.TYPE_GLOBAL) and \
344
+ type(loadValue.data) in (types.StringType, types.TupleType) :
345
+ # apply(func, (args)), can't check # of args, so just return func
346
+ if loadValue.data == 'apply' :
347
+ loadValue = code.stack[funcIndex+1]
348
+ funcName = loadValue.getName()
349
+ else :
350
+ if cfg().modifyDefaultValue and \
351
+ type(loadValue.data) == types.TupleType :
352
+ _checkModifyDefaultArg(code, loadValue.data[0],
353
+ loadValue.data[1])
354
+
355
+ func, refClass, method = _getFunction(codeSource.module, loadValue)
356
+ if func == None and type(loadValue.data) == types.TupleType and \
357
+ len(loadValue.data) == 2 :
358
+ # looks like we are making a method call
359
+ data = loadValue.data
360
+ if type(data[0]) == types.StringType :
361
+ # do we know the type of the local variable?
362
+ varType = code.typeMap.get(data[0])
363
+ if varType is not None and len(varType) == 1 :
364
+ if hasattr(varType[0], 'methods') :
365
+ # it's a class & we know the type, get the method
366
+ func = varType[0].methods.get(data[1])
367
+ if func is not None :
368
+ method = 1
369
+
370
+ if cfg().abstractClasses and refClass and method:
371
+ _checkAbstract(refClass, code, funcName)
372
+
373
+ if cfg().stringFind:
374
+ _checkStringFind(code, loadValue)
375
+
376
+ if func != None :
377
+ if refClass and func.isClassMethod():
378
+ argCount = argCount + 1
379
+ _checkFunctionArgs(code, func, method, argCount, kwArgs,
380
+ check_arg_count)
381
+ # if this isn't a c'tor, we should check
382
+ if not (refClass and method) and cfg().checkReturnValues:
383
+ _checkReturnValueUse(code, func)
384
+
385
+ if refClass :
386
+ if method :
387
+ # c'tor, return the class as the type
388
+ returnValue = Stack.Item(loadValue, refClass)
389
+ elif func.isClassMethod():
390
+ # FIXME: do anything here?
391
+ pass
392
+ elif argCount > 0 and cfg().methodArgName and \
393
+ not func.isStaticMethod() and \
394
+ code.stack[funcIndex].type == Stack.TYPE_ATTRIBUTE and \
395
+ code.stack[funcIndex+1].data != cfg().methodArgName:
396
+ e = msgs.SELF_NOT_FIRST_ARG % (cfg().methodArgName, '')
397
+ code.addWarning(e)
398
+ elif refClass and method :
399
+ returnValue = Stack.Item(loadValue, refClass)
400
+ if (argCount > 0 or len(kwArgs) > 0) and \
401
+ not refClass.ignoreAttrs and \
402
+ not refClass.methods.has_key(utils.INIT) and \
403
+ not _isexception(refClass.classObject) :
404
+ code.addWarning(msgs.NO_CTOR_ARGS)
405
+ else :
406
+ returnValue = _checkBuiltin(code, loadValue, argCount, kwArgs,
407
+ check_arg_count)
408
+ if returnValue.type is types.NoneType and \
409
+ not OP.POP_TOP(code.nextOpInfo()[0]) :
410
+ name = utils.safestr(loadValue.data)
411
+ if type(loadValue.data) == types.TupleType :
412
+ name = string.join(loadValue.data, '.')
413
+ # lambda with setattr is a common way of setting
414
+ # attributes, so allow it
415
+ if name != 'setattr' \
416
+ or code.func.function.func_name != '<lambda>':
417
+ code.addWarning(msgs.USING_NONE_RETURN_VALUE % name)
418
+
419
+ code.stack = code.stack[:funcIndex] + [ returnValue ]
420
+ code.functionsCalled[funcName] = loadValue
421
+
422
+
423
+ def _classHasAttribute(c, attr) :
424
+ return (c.methods.has_key(attr) or c.members.has_key(attr) or
425
+ hasattr(c.classObject, attr))
426
+
427
+ def _checkClassAttribute(attr, c, code) :
428
+ if _classHasAttribute(c, attr) :
429
+ try :
430
+ del c.memberRefs[attr]
431
+ except KeyError :
432
+ pass
433
+ elif cfg().classAttrExists :
434
+ if attr not in cfg().missingAttrs:
435
+ code.addWarning(msgs.INVALID_CLASS_ATTR % attr)
436
+
437
+ def _checkModuleAttribute(attr, module, code, ref) :
438
+ try:
439
+ if attr not in module.modules[ref].attributes and \
440
+ not utils.endswith(ref, '.' + attr) :
441
+ code.addWarning(msgs.INVALID_MODULE_ATTR % attr)
442
+ except (KeyError, TypeError):
443
+ # if ref isn't found, or ref isn't even hashable, we don't care
444
+ # we may not know, or ref could be something funky [e for e].method()
445
+ pass
446
+
447
+ try:
448
+ _checkClassAttribute(attr, module.classes[ref], code)
449
+ except (KeyError, TypeError):
450
+ # if ref isn't found, or ref isn't even hashable, we don't care
451
+ # we may not know, or ref could be something funky [e for e].method()
452
+ pass
453
+
454
+
455
+ def _getGlobalName(name, func) :
456
+ # get the right name of global refs (for from XXX import YYY)
457
+ opModule = func.function.func_globals.get(name)
458
+ try :
459
+ if opModule and isinstance(opModule, types.ModuleType) :
460
+ name = opModule.__name__
461
+ except :
462
+ # we have to do this in case the class raises an access exception
463
+ # due to overriding __special__() methods
464
+ pass
465
+
466
+ return name
467
+
468
+
469
+ def _checkNoEffect(code, ignoreStmtWithNoEffect=0):
470
+ if (not ignoreStmtWithNoEffect and
471
+ OP.POP_TOP(code.nextOpInfo()[0]) and cfg().noEffect):
472
+ code.addWarning(msgs.POSSIBLE_STMT_WITH_NO_EFFECT)
473
+
474
+ def _makeConstant(code, index, factoryFunction) :
475
+ "Build a constant on the stack ((), [], or {})"
476
+ if index > 0 :
477
+ code.stack[-index:] = [ factoryFunction(code.stack[-index:]) ]
478
+ _checkNoEffect(code)
479
+ else :
480
+ code.pushStack(factoryFunction())
481
+
482
+
483
+ def _hasGlobal(operand, module, func, main) :
484
+ return (func.function.func_globals.has_key(operand) or
485
+ main or module.moduleLineNums.has_key(operand) or
486
+ __builtins__.has_key(operand))
487
+
488
+ def _checkGlobal(operand, module, func, code, err, main = 0) :
489
+ if not _hasGlobal(operand, module, func, main) :
490
+ code.addWarning(err % operand)
491
+ if not cfg().reportAllGlobals :
492
+ func.function.func_globals[operand] = operand
493
+
494
+
495
+ def _handleComparison(stack, operand) :
496
+ num_ops = 2
497
+ if operand == 'exception match':
498
+ num_ops = 1
499
+
500
+ si = min(len(stack), num_ops)
501
+ compareValues = stack[-si:]
502
+ for _ in range(si, 2) :
503
+ compareValues.append(Stack.Item(None, None))
504
+ stack[-si:] = [ Stack.makeComparison(compareValues, operand) ]
505
+ return compareValues
506
+
507
+ def _handleImport(code, operand, module, main, fromName) :
508
+ # FIXME: this function should be refactored/cleaned up
509
+ key = operand
510
+ tmpOperand = tmpFromName = operand
511
+ if fromName is not None :
512
+ tmpOperand = tmpFromName = fromName
513
+ key = (fromName, operand)
514
+
515
+ if cfg().deprecated:
516
+ try:
517
+ undeprecated = python.DEPRECATED_MODULES[tmpFromName]
518
+ except KeyError:
519
+ pass
520
+ else:
521
+ msg = msgs.USING_DEPRECATED_MODULE % tmpFromName
522
+ if undeprecated:
523
+ msg.data = msg.data + msgs.USE_INSTEAD % undeprecated
524
+ code.addWarning(msg)
525
+
526
+ if cfg().reimportSelf and tmpOperand == module.module.__name__ :
527
+ code.addWarning(msgs.IMPORT_SELF % tmpOperand)
528
+
529
+ modline1 = module.moduleLineNums.get(tmpOperand, None)
530
+ modline2 = module.moduleLineNums.get((tmpFromName, '*'), None)
531
+ key2 = (tmpFromName,)
532
+ if fromName is not None and operand != '*' :
533
+ key2 = (tmpFromName, operand)
534
+ modline3 = module.moduleLineNums.get(key2, None)
535
+
536
+ if modline1 is not None or modline2 is not None or modline3 is not None :
537
+ err = None
538
+
539
+ if fromName is None :
540
+ if modline1 is not None :
541
+ err = msgs.MODULE_IMPORTED_AGAIN % operand
542
+ elif cfg().mixImport :
543
+ err = msgs.MIX_IMPORT_AND_FROM_IMPORT % tmpFromName
544
+ else :
545
+ if modline3 is not None and operand != '*' :
546
+ err = 'from %s import %s' % (tmpFromName, operand)
547
+ err = msgs.MODULE_MEMBER_IMPORTED_AGAIN % err
548
+ elif modline1 is not None :
549
+ if cfg().mixImport and code.getLineNum() != modline1[1] :
550
+ err = msgs.MIX_IMPORT_AND_FROM_IMPORT % tmpFromName
551
+ else :
552
+ err = msgs.MODULE_MEMBER_ALSO_STAR_IMPORTED % fromName
553
+
554
+ # filter out warnings when files are different (ie, from X import ...)
555
+ if err is not None and cfg().moduleImportErrors :
556
+ bytes = module.main_code
557
+ if bytes is None or \
558
+ bytes.function.func_code.co_filename == code.func_code.co_filename :
559
+ code.addWarning(err)
560
+
561
+ if main :
562
+ fileline = (code.func_code.co_filename, code.getLineNum())
563
+ module.moduleLineNums[key] = fileline
564
+ if fromName is not None :
565
+ module.moduleLineNums[(fromName,)] = fileline
566
+
567
+
568
+ def _handleImportFrom(code, operand, module, main) :
569
+ fromName = code.stack[-1].data
570
+ if utils.pythonVersion() < utils.PYTHON_2_0 and \
571
+ OP.POP_TOP(code.nextOpInfo()[0]):
572
+ code.popNextOp()
573
+ code.pushStack(Stack.Item(operand, types.ModuleType))
574
+ _handleImport(code, operand, module, main, fromName)
575
+
576
+
577
+ # http://www.python.org/doc/current/lib/typesseq-strings.html
578
+ _FORMAT_CONVERTERS = 'diouxXeEfFgGcrs'
579
+ # NOTE: lLh are legal in the flags, but are ignored by python, we warn
580
+ _FORMAT_FLAGS = '*#- +.' + string.digits
581
+
582
+ def _getFormatInfo(format, code) :
583
+ vars = []
584
+
585
+ # first get rid of all the instances of %% in the string, they don't count
586
+ format = string.replace(format, "%%", "")
587
+ sections = string.split(format, '%')
588
+ percentFormatCount = formatCount = string.count(format, '%')
589
+ mappingFormatCount = 0
590
+
591
+ # skip the first item in the list, it's always empty
592
+ for section in sections[1:] :
593
+ orig_section = section
594
+ if not section:
595
+ w = msgs.INVALID_FORMAT % orig_section
596
+ w.data = w.data + ' (end of format string)'
597
+ code.addWarning(w)
598
+ continue
599
+
600
+ # handle dictionary formats
601
+ if section[0] == '(' :
602
+ mappingFormatCount = mappingFormatCount + 1
603
+ varname = string.split(section, ')')
604
+ if varname[1] == '' :
605
+ code.addWarning(msgs.INVALID_FORMAT % section)
606
+ vars.append(varname[0][1:])
607
+ section = varname[1]
608
+
609
+ if not section :
610
+ # no format data to check
611
+ continue
612
+
613
+ # FIXME: we ought to just define a regular expression to check
614
+ # formatRE = '[ #+-]*([0-9]*|*)(|.(|*|[0-9]*)[diouxXeEfFgGcrs].*'
615
+ stars = 0
616
+ for i in range(0, len(section)) :
617
+ if section[i] in _FORMAT_CONVERTERS :
618
+ break
619
+ if section[i] in _FORMAT_FLAGS :
620
+ if section[i] == '*' :
621
+ stars = stars + 1
622
+ if mappingFormatCount > 0 :
623
+ code.addWarning(msgs.USING_STAR_IN_FORMAT_MAPPING % section)
624
+
625
+ if stars > 2 :
626
+ code.addWarning(msgs.TOO_MANY_STARS_IN_FORMAT)
627
+
628
+ formatCount = formatCount + stars
629
+ if section[i] not in _FORMAT_CONVERTERS :
630
+ code.addWarning(msgs.INVALID_FORMAT % orig_section)
631
+
632
+ if mappingFormatCount > 0 and mappingFormatCount != percentFormatCount :
633
+ code.addWarning(msgs.CANT_MIX_MAPPING_IN_FORMATS)
634
+
635
+ return formatCount, vars
636
+
637
+ def _getConstant(code, module, data) :
638
+ data = utils.safestr(data.data)
639
+ format = code.constants.get(data)
640
+ if format is not None :
641
+ return format
642
+
643
+ format = module.variables.get(data)
644
+ if format is not None and format.value is not None :
645
+ return format.value
646
+ return None
647
+
648
+ _UNCHECKABLE_FORMAT_STACK_TYPES = \
649
+ (Stack.TYPE_UNKNOWN, Stack.TYPE_FUNC_RETURN, Stack.TYPE_ATTRIBUTE,
650
+ Stack.TYPE_GLOBAL, Stack.TYPE_EXCEPT)
651
+ _UNCHECKABLE_STACK_TYPES = _UNCHECKABLE_FORMAT_STACK_TYPES + (types.NoneType,)
652
+
653
+ def _getFormatString(code, codeSource) :
654
+ if len(code.stack) <= 1 :
655
+ return ''
656
+
657
+ format = code.stack[-2]
658
+ if format.type != types.StringType or not format.const :
659
+ format = _getConstant(code, codeSource.module, format)
660
+ if format is None or type(format) != types.StringType :
661
+ return ''
662
+ return format
663
+ return format.data
664
+
665
+
666
+ def _getFormatWarnings(code, codeSource) :
667
+ format = _getFormatString(code, codeSource)
668
+ if not format :
669
+ return
670
+
671
+ args = 0
672
+ count, vars = _getFormatInfo(format, code)
673
+ topOfStack = code.stack[-1]
674
+ if topOfStack.isLocals() :
675
+ for varname in vars :
676
+ if not code.unusedLocals.has_key(varname) :
677
+ code.addWarning(msgs.NO_LOCAL_VAR % varname)
678
+ else :
679
+ code.unusedLocals[varname] = None
680
+ else :
681
+ stackItemType = topOfStack.getType(code.typeMap)
682
+ if ((stackItemType == types.DictType and len(vars) > 0) or
683
+ codeSource.func.isParam(topOfStack.data) or
684
+ stackItemType in _UNCHECKABLE_FORMAT_STACK_TYPES) :
685
+ return
686
+
687
+ if topOfStack.type == types.TupleType :
688
+ args = topOfStack.length
689
+ elif stackItemType == types.TupleType :
690
+ args = len(code.constants.get(topOfStack.data, (0,)))
691
+ else :
692
+ args = 1
693
+
694
+ if args and count != args :
695
+ code.addWarning(msgs.INVALID_FORMAT_COUNT % (count, args))
696
+
697
+ def _checkAttributeType(code, stackValue, attr) :
698
+ if not cfg().checkObjectAttrs :
699
+ return
700
+
701
+ varTypes = code.typeMap.get(utils.safestr(stackValue.data), None)
702
+ if not varTypes :
703
+ return
704
+
705
+ # the value may have been converted on stack (`v`)
706
+ other_types = []
707
+ if stackValue.type not in varTypes :
708
+ other_types = [stackValue.type]
709
+
710
+ for varType in varTypes + other_types :
711
+ # ignore built-in types that have no attributes
712
+ if python.METHODLESS_OBJECTS.has_key(varType) :
713
+ continue
714
+
715
+ attrs = python.BUILTIN_ATTRS.get(varType, None)
716
+ if attrs is not None :
717
+ if attr in attrs :
718
+ return
719
+ continue
720
+
721
+ if hasattr(varType, 'ignoreAttrs') :
722
+ if varType.ignoreAttrs or _classHasAttribute(varType, attr) :
723
+ return
724
+ elif not hasattr(varType, 'attributes') or attr in varType.attributes :
725
+ return
726
+
727
+ code.addWarning(msgs.OBJECT_HAS_NO_ATTR % (stackValue.data, attr))
728
+
729
+
730
+ def _getTypeStr(t):
731
+ returnStr = utils.safestr(t)
732
+ strs = string.split(returnStr, "'")
733
+ try:
734
+ if len(strs) == 3:
735
+ returnStr = strs[-2]
736
+ except IndexError:
737
+ pass
738
+ return returnStr
739
+
740
+
741
+ def _getLineNum(co, instr_index):
742
+ co_lnotab = co.co_lnotab
743
+ lineno = co.co_firstlineno
744
+ addr = 0
745
+ for lnotab_index in range(0, len(co_lnotab), 2):
746
+ addr = addr + ord(co_lnotab[lnotab_index])
747
+ if addr > instr_index:
748
+ return lineno
749
+ lineno = lineno + ord(co_lnotab[lnotab_index+1])
750
+ return lineno
751
+
752
+
753
+ class Code :
754
+ 'Hold all the code state information necessary to find warnings'
755
+
756
+ def __init__(self) :
757
+ self.bytes = None
758
+ self.func = None
759
+ self.func_code = None
760
+ self.index = 0
761
+ self.indexList = []
762
+ self.extended_arg = 0
763
+ self.lastLineNum = 0
764
+ self.maxCode = 0
765
+ self.has_except = 0
766
+ self.try_finally_first = 0
767
+ self.starts_and_ends_with_finally = 0
768
+
769
+ self.returnValues = []
770
+ self.raiseValues = []
771
+ self.stack = []
772
+
773
+ self.unpackCount = 0
774
+ self.loops = 0
775
+ self.branches = {}
776
+
777
+ self.warnings = []
778
+
779
+ self.globalRefs = {}
780
+ self.unusedLocals = {}
781
+ self.deletedLocals = {}
782
+ self.functionsCalled = {}
783
+ self.typeMap = {}
784
+ self.constants = {}
785
+ self.codeObjects = {}
786
+
787
+ def init(self, func) :
788
+ self.func = func
789
+ self.func_code, self.bytes, self.index, self.maxCode, self.extended_arg = \
790
+ OP.initFuncCode(func.function)
791
+ self.lastLineNum = self.func_code.co_firstlineno
792
+ self.returnValues = []
793
+
794
+ # initialize the arguments to unused
795
+ for arg in func.arguments() :
796
+ self.unusedLocals[arg] = 0
797
+ self.typeMap[arg] = [ Stack.TYPE_UNKNOWN ]
798
+
799
+ def getLineNum(self):
800
+ line = self.lastLineNum
801
+ # if we don't have linenum info, calc it from co_lntab & index
802
+ if line == self.func_code.co_firstlineno:
803
+ # FIXME: this could be optimized, if we kept last line info
804
+ line = _getLineNum(self.func_code, self.index - 1)
805
+ return line
806
+
807
+ def getWarning(self, err, line = None) :
808
+ if line is None :
809
+ line = self.getLineNum()
810
+ return Warning.Warning(self.func_code, line, err)
811
+
812
+ def addWarning(self, err, line = None) :
813
+ w = err
814
+ if not isinstance(w, Warning.Warning):
815
+ w = self.getWarning(err, line)
816
+ self.warnings.append(w)
817
+
818
+ def popNextOp(self) :
819
+ self.indexList.append(self.index)
820
+ info = OP.getInfo(self.bytes, self.index, self.extended_arg)
821
+ op, oparg, self.index, self.extended_arg = info
822
+ if op < OP.HAVE_ARGUMENT :
823
+ utils.debug(" %d %s" % (self.indexList[-1], OP.name[op]))
824
+ operand = None
825
+ else :
826
+ operand = OP.getOperand(op, self.func_code, oparg)
827
+ self.label = label = OP.getLabel(op, oparg, self.index)
828
+ utils.debug(" %d %s" % (self.indexList[-1], OP.name[op]), oparg, operand)
829
+ if label != None :
830
+ self.addBranch(label)
831
+
832
+ return op, oparg, operand
833
+
834
+ def nextOpInfo(self, offset = 0) :
835
+ try :
836
+ return OP.getInfo(self.bytes, self.index + offset, 0)[0:3]
837
+ except IndexError :
838
+ return -1, 0, -1
839
+
840
+ def getFirstOp(self) :
841
+ # find the first real op, maybe we should not check if params are used
842
+ i = extended_arg = 0
843
+ while i < self.maxCode :
844
+ op, oparg, i, extended_arg = OP.getInfo(self.bytes, i, extended_arg)
845
+ if not OP.LINE_NUM(op) :
846
+ if not (OP.LOAD_CONST(op) or OP.LOAD_GLOBAL(op)) :
847
+ return op
848
+ raise RuntimeError('Could not find first opcode in function')
849
+
850
+ def pushStack(self, item, ignoreStmtWithNoEffect=0):
851
+ self.stack.append(item)
852
+ _checkNoEffect(self, ignoreStmtWithNoEffect)
853
+
854
+ def popStack(self) :
855
+ if self.stack :
856
+ del self.stack[-1]
857
+
858
+ def popStackItems(self, count) :
859
+ stackLen = len(self.stack)
860
+ if stackLen > 0 :
861
+ count = min(count, stackLen)
862
+ del self.stack[-count:]
863
+
864
+ def unpack(self) :
865
+ if self.unpackCount :
866
+ self.unpackCount = self.unpackCount - 1
867
+ else :
868
+ self.popStack()
869
+
870
+ def __getStringStackType(self, data) :
871
+ try :
872
+ return data.getType({})
873
+ except AttributeError :
874
+ return Stack.TYPE_UNKNOWN
875
+
876
+ def __getStackType(self) :
877
+ if not self.stack :
878
+ return Stack.TYPE_UNKNOWN
879
+
880
+ if not self.unpackCount :
881
+ return self.__getStringStackType(self.stack[-1])
882
+
883
+ data = self.stack[-1].data
884
+ if type(data) == types.TupleType :
885
+ try :
886
+ return self.__getStringStackType(data[len(data)-self.unpackCount])
887
+ except IndexError :
888
+ # happens when unpacking a var for which we don't know the size
889
+ pass
890
+
891
+ return Stack.TYPE_UNKNOWN
892
+
893
+ def setType(self, name) :
894
+ valueList = self.typeMap.get(name, [])
895
+ newType = self.__getStackType()
896
+ # longs are being merged with ints, assume they are the same
897
+ # comparisons are really ints anyways
898
+ if newType in (types.LongType, Stack.TYPE_COMPARISON):
899
+ newType = types.IntType
900
+ if newType not in valueList :
901
+ valueList.append(newType)
902
+
903
+ # need to ignore various types (Unknown, Func return values, etc)
904
+ # also ignore None, don't care if they use it and a real type
905
+ if valueList and newType not in _UNCHECKABLE_STACK_TYPES and \
906
+ cfg().inconsistentTypes:
907
+ oldTypes = []
908
+ # only add types to the value list that are "interesting"
909
+ for typeToAdd in valueList:
910
+ if typeToAdd not in _UNCHECKABLE_STACK_TYPES and \
911
+ typeToAdd != newType:
912
+ oldTypes.append(_getTypeStr(typeToAdd))
913
+ # do we have any "interesting" old types? if so, warn
914
+ if oldTypes:
915
+ self.addWarning(msgs.INCONSISTENT_TYPE % \
916
+ (name, oldTypes, _getTypeStr(newType)))
917
+ self.typeMap[name] = valueList
918
+
919
+ def addReturn(self) :
920
+ if len(self.stack) > 0 :
921
+ value = (self.getLineNum(), self.stack[-1], self.nextOpInfo()[2])
922
+ self.returnValues.append(value)
923
+ self.popStack()
924
+
925
+ def addRaise(self) :
926
+ self.raiseValues.append((self.getLineNum(), None, self.nextOpInfo()[2]))
927
+
928
+ def addBranch(self, label) :
929
+ if label is not None :
930
+ self.branches[label] = self.branches.get(label, 0) + 1
931
+
932
+ def removeBranch(self, label) :
933
+ branch = self.branches.get(label, None)
934
+ if branch is not None :
935
+ if branch == 1 :
936
+ del self.branches[label]
937
+ else :
938
+ self.branches[label] = branch - 1
939
+
940
+ def remove_unreachable_code(self, label) :
941
+ if len(self.indexList) >= 2 :
942
+ index = self.indexList[-2]
943
+ if index >= 0 and OP.POP_BLOCK(ord(self.bytes[index])) :
944
+ index = self.indexList[-3]
945
+ if index >= 0 :
946
+ op = ord(self.bytes[index])
947
+ if OP.RETURN_VALUE(op) or OP.RAISE_VARARGS(op) or \
948
+ OP.END_FINALLY(ord(self.bytes[label-1])) :
949
+ self.removeBranch(label)
950
+
951
+ def updateCheckerArgs(self, operand) :
952
+ rc = utils.shouldUpdateArgs(operand)
953
+ if rc :
954
+ utils.updateCheckerArgs(self.stack[-1].data, self.func_code,
955
+ self.getLineNum(), self.warnings)
956
+ return rc
957
+
958
+ def updateModuleLineNums(self, module, operand) :
959
+ filelist = (self.func_code.co_filename, self.getLineNum())
960
+ module.moduleLineNums[operand] = filelist
961
+
962
+
963
+ class CodeSource :
964
+ 'Holds source information about a code block (module, class, func, etc)'
965
+ def __init__(self, module, func, c, main, in_class, code) :
966
+ self.module = module
967
+ self.func = func
968
+ self.classObject = c
969
+ self.main = main
970
+ self.in_class = in_class
971
+ self.code = code
972
+ self.calling_code = []
973
+
974
+ def _checkException(code, name) :
975
+ if code.stack and code.stack[-1].type == Stack.TYPE_EXCEPT :
976
+ if __builtins__.has_key(name) :
977
+ code.addWarning(msgs.SET_EXCEPT_TO_BUILTIN % name)
978
+
979
+ def _checkAssign(code, name):
980
+ if name in _BAD_ASSIGN_NAMES:
981
+ code.addWarning(msgs.SHOULDNT_ASSIGN_BUILTIN % name)
982
+ else:
983
+ cap = string.capitalize(name)
984
+ if cap in _BAD_ASSIGN_NAMES:
985
+ code.addWarning(msgs.SHOULDNT_ASSIGN_NAME % (name, cap))
986
+
987
+ def _checkVariableOperationOnItself(code, lname, msg):
988
+ if code.stack and code.stack[-1].getName() == lname:
989
+ code.addWarning(msg % lname)
990
+
991
+ def _checkFutureKeywords(code, varname) :
992
+ kw = python.FUTURE_KEYWORDS.get(varname)
993
+ if kw is not None :
994
+ code.addWarning(msgs.USING_KEYWORD % (varname, kw))
995
+
996
+ def _STORE_NAME(oparg, operand, codeSource, code) :
997
+ if not code.updateCheckerArgs(operand) :
998
+ _checkFutureKeywords(code, operand)
999
+ module = codeSource.module
1000
+ if not codeSource.in_class :
1001
+ _checkShadowBuiltin(code, operand)
1002
+ if not codeSource.calling_code :
1003
+ _checkGlobal(operand, module, codeSource.func, code,
1004
+ msgs.GLOBAL_DEFINED_NOT_DECLARED, codeSource.main)
1005
+ else :
1006
+ if code.stack :
1007
+ codeSource.classObject.statics[operand] = code.stack[-1]
1008
+ codeSource.classObject.lineNums[operand] = code.getLineNum()
1009
+
1010
+ var = module.variables.get(operand)
1011
+ if var is not None and code.stack and code.stack[-1].const :
1012
+ var.value = code.stack[-1].data
1013
+
1014
+ if code.unpackCount :
1015
+ code.unpackCount = code.unpackCount - 1
1016
+ else:
1017
+ _checkAssign(code, operand)
1018
+ _checkException(code, operand)
1019
+ code.popStack()
1020
+ if not module.moduleLineNums.has_key(operand) and codeSource.main :
1021
+ code.updateModuleLineNums(module, operand)
1022
+
1023
+ _STORE_GLOBAL = _STORE_NAME
1024
+
1025
+ def _checkLoadGlobal(codeSource, code, varname) :
1026
+ _checkFutureKeywords(code, varname)
1027
+ should_check = 1
1028
+ if code.func_code.co_name == utils.LAMBDA :
1029
+ # this could really be a local reference, check first
1030
+ if not codeSource.main and codeSource.calling_code:
1031
+ func = getattr(codeSource.calling_code[-1], 'function', None)
1032
+ if func is not None and varname in func.func_code.co_varnames :
1033
+ _handleLoadLocal(code, codeSource, varname)
1034
+ should_check = 0
1035
+
1036
+ if should_check :
1037
+ # if a global var starts w/__ and the global is referenced in a class
1038
+ # we have to strip off the _class-name, to get the original name
1039
+ if codeSource.classObject and \
1040
+ utils.startswith(varname, '_' + codeSource.classObject.name + '__'):
1041
+ varname = varname[len(codeSource.classObject.name)+1:]
1042
+
1043
+ # make sure we remember each global ref to check for unused
1044
+ code.globalRefs[_getGlobalName(varname, codeSource.func)] = varname
1045
+ if not codeSource.in_class :
1046
+ _checkGlobal(varname, codeSource.module, codeSource.func,
1047
+ code, msgs.INVALID_GLOBAL)
1048
+
1049
+ def _LOAD_NAME(oparg, operand, codeSource, code) :
1050
+ _checkLoadGlobal(codeSource, code, operand)
1051
+
1052
+ # if there was from XXX import *, _* names aren't imported
1053
+ if codeSource.module.modules.has_key(operand) and \
1054
+ hasattr(codeSource.module.module, operand) :
1055
+ operand = getattr(codeSource.module.module, operand).__name__
1056
+
1057
+ opType, const = Stack.TYPE_GLOBAL, 0
1058
+ if operand == 'None' :
1059
+ opType, const = types.NoneType, 0
1060
+ elif operand == 'Ellipsis' :
1061
+ opType, const = types.EllipsisType, 1
1062
+ code.pushStack(Stack.Item(operand, opType, const))
1063
+
1064
+ _LOAD_GLOBAL = _LOAD_NAME
1065
+
1066
+ def _LOAD_DEREF(oparg, operand, codeSource, code) :
1067
+ if type(oparg) == types.IntType :
1068
+ func_code = code.func_code
1069
+ try:
1070
+ argname = func_code.co_cellvars[oparg]
1071
+ except IndexError:
1072
+ argname = func_code.co_freevars[oparg - len(func_code.co_cellvars)]
1073
+ code.pushStack(Stack.Item(argname, types.StringType))
1074
+ if code.func_code.co_name != utils.LAMBDA :
1075
+ code.unusedLocals[argname] = None
1076
+ else :
1077
+ _LOAD_GLOBAL(oparg, operand, codeSource, code)
1078
+
1079
+ _LOAD_CLOSURE = _LOAD_DEREF
1080
+
1081
+ def _DELETE_NAME(oparg, operand, codeSource, code) :
1082
+ _checkLoadGlobal(codeSource, code, operand)
1083
+ # FIXME: handle deleting global multiple times
1084
+ _DELETE_GLOBAL = _DELETE_NAME
1085
+
1086
+ def _make_const(value):
1087
+ if type(value) == types.TupleType:
1088
+ return Stack.makeTuple(map(_make_const, value))
1089
+ return Stack.Item(value, type(value), 1)
1090
+
1091
+ def _LOAD_CONST(oparg, operand, codeSource, code) :
1092
+ code.pushStack(_make_const(operand))
1093
+ if type(operand) == types.CodeType :
1094
+ name = operand.co_name
1095
+ obj = code.codeObjects.get(name, None)
1096
+ if name == utils.LAMBDA :
1097
+ # use a unique key, so we can have multiple lambdas
1098
+ code.codeObjects[code.index] = operand
1099
+ elif obj is None :
1100
+ code.codeObjects[name] = operand
1101
+ elif cfg().redefiningFunction :
1102
+ code.addWarning(msgs.REDEFINING_ATTR % (name, obj.co_firstlineno))
1103
+
1104
+
1105
+ def _checkLocalShadow(code, module, varname) :
1106
+ if module.variables.has_key(varname) and cfg().shadows :
1107
+ line = module.moduleLineNums.get(varname, ('<unknown>', 0))
1108
+ w = code.getWarning(msgs.LOCAL_SHADOWS_GLOBAL % (varname, line[1]))
1109
+ if line[0] != w.file:
1110
+ w.err = '%s in file %s' % (w.err, line[0])
1111
+ code.addWarning(w)
1112
+
1113
+ def _checkShadowBuiltin(code, varname) :
1114
+ if __builtins__.has_key(varname) and varname[0] != '_' and \
1115
+ cfg().shadowBuiltins:
1116
+ code.addWarning(msgs.VARIABLE_SHADOWS_BUILTIN % varname)
1117
+
1118
+ def _checkLoadLocal(code, codeSource, varname, deletedWarn, usedBeforeSetWarn) :
1119
+ _checkFutureKeywords(code, varname)
1120
+ deletedLine = code.deletedLocals.get(varname)
1121
+ if deletedLine :
1122
+ code.addWarning(deletedWarn % (varname, deletedLine))
1123
+ elif not code.unusedLocals.has_key(varname) and \
1124
+ not codeSource.func.isParam(varname) :
1125
+ code.addWarning(usedBeforeSetWarn % varname)
1126
+ code.unusedLocals[varname] = None
1127
+ _checkLocalShadow(code, codeSource.module, varname)
1128
+
1129
+ def _handleLoadLocal(code, codeSource, varname) :
1130
+ _checkLoadLocal(code, codeSource, varname,
1131
+ msgs.LOCAL_DELETED, msgs.VAR_USED_BEFORE_SET)
1132
+
1133
+ def _LOAD_FAST(oparg, operand, codeSource, code) :
1134
+ code.pushStack(Stack.Item(operand, type(operand)))
1135
+ _handleLoadLocal(code, codeSource, operand)
1136
+
1137
+ def _STORE_FAST(oparg, operand, codeSource, code) :
1138
+ if not code.updateCheckerArgs(operand) :
1139
+ _checkFutureKeywords(code, operand)
1140
+ if code.stack and code.stack[-1].type == types.StringType and \
1141
+ not code.stack[-1].const:
1142
+ _checkVariableOperationOnItself(code, operand,
1143
+ msgs.SET_VAR_TO_ITSELF)
1144
+ code.setType(operand)
1145
+ if not code.unpackCount and code.stack and \
1146
+ (code.stack[-1].const or code.stack[-1].type == types.TupleType) :
1147
+ if code.constants.has_key(operand) :
1148
+ del code.constants[operand]
1149
+ else :
1150
+ code.constants[operand] = code.stack[-1].data
1151
+
1152
+ _checkLocalShadow(code, codeSource.module, operand)
1153
+ _checkShadowBuiltin(code, operand)
1154
+ _checkAssign(code, operand)
1155
+ _checkException(code, operand)
1156
+ if code.deletedLocals.has_key(operand) :
1157
+ del code.deletedLocals[operand]
1158
+ if not code.unusedLocals.has_key(operand) :
1159
+ errLine = code.getLineNum()
1160
+ if code.unpackCount and not cfg().unusedLocalTuple :
1161
+ errLine = -errLine
1162
+ code.unusedLocals[operand] = errLine
1163
+ code.unpack()
1164
+
1165
+ def _DELETE_FAST(oparg, operand, codeSource, code) :
1166
+ _checkLoadLocal(code, codeSource, operand,
1167
+ msgs.LOCAL_ALREADY_DELETED, msgs.VAR_DELETED_BEFORE_SET)
1168
+ code.deletedLocals[operand] = code.getLineNum()
1169
+
1170
+ def _checkAttribute(top, operand, codeSource, code) :
1171
+ if top.data == cfg().methodArgName and codeSource.classObject != None :
1172
+ _checkClassAttribute(operand, codeSource.classObject, code)
1173
+ elif type(top.type) == types.StringType or top.type == types.ModuleType :
1174
+ _checkModuleAttribute(operand, codeSource.module, code, top.data)
1175
+ else :
1176
+ _checkAttributeType(code, top, operand)
1177
+
1178
+ def _checkExcessiveReferences(code, top, extraAttr = None) :
1179
+ if cfg().maxReferences <= 0 :
1180
+ return
1181
+
1182
+ try :
1183
+ data = top.data
1184
+ if extraAttr is not None :
1185
+ data = data + (extraAttr,)
1186
+
1187
+ maxReferences = cfg().maxReferences
1188
+ if data[0] == cfg().methodArgName:
1189
+ maxReferences = maxReferences + 1
1190
+ if len(data) > maxReferences :
1191
+ name = string.join(top.data, '.')
1192
+ code.addWarning(msgs.TOO_MANY_REFERENCES % (maxReferences, name))
1193
+ except TypeError :
1194
+ pass
1195
+
1196
+ def _checkDeprecated(code, identifierTuple):
1197
+ # check deprecated module.function
1198
+ try:
1199
+ name = string.join(identifierTuple, '.')
1200
+ undeprecated = python.DEPRECATED_ATTRS[name]
1201
+ except (KeyError, TypeError):
1202
+ pass
1203
+ else:
1204
+ msg = msgs.USING_DEPRECATED_ATTR % name
1205
+ if undeprecated:
1206
+ msg.data = msg.data + msgs.USE_INSTEAD % undeprecated
1207
+ code.addWarning(msg)
1208
+
1209
+ def _LOAD_ATTR(oparg, operand, codeSource, code) :
1210
+ if len(code.stack) > 0 :
1211
+ top = code.stack[-1]
1212
+ _checkAttribute(top, operand, codeSource, code)
1213
+ top.addAttribute(operand)
1214
+
1215
+ if len(top.data) == 2:
1216
+ if cfg().deprecated:
1217
+ _checkDeprecated(code, top.data)
1218
+
1219
+ try:
1220
+ insecure = python.SECURITY_FUNCS.get(top.data[0])
1221
+ except TypeError:
1222
+ pass
1223
+ else:
1224
+ if insecure and insecure.has_key(operand):
1225
+ func = string.join(top.data, '.')
1226
+ code.addWarning(msgs.USING_INSECURE_FUNC % func)
1227
+
1228
+ nextOp = code.nextOpInfo()[0]
1229
+ if not OP.LOAD_ATTR(nextOp) :
1230
+ if OP.POP_TOP(nextOp) and cfg().noEffect:
1231
+ code.addWarning(msgs.POSSIBLE_STMT_WITH_NO_EFFECT)
1232
+ else :
1233
+ _checkExcessiveReferences(code, top)
1234
+
1235
+ def _ok_to_set_attr(classObject, basename, attr) :
1236
+ return (cfg().onlyCheckInitForMembers and classObject != None and
1237
+ basename == cfg().methodArgName and
1238
+ not _classHasAttribute(classObject, attr))
1239
+
1240
+ def _STORE_ATTR(oparg, operand, codeSource, code) :
1241
+ if code.stack :
1242
+ top = code.stack.pop()
1243
+ top_name = '%s.%s' % (top.getName(), operand)
1244
+ try:
1245
+ # FIXME: this is a hack to handle code like:
1246
+ # a.a = [x for x in range(2) if x > 1]
1247
+ previous = code.stack[-1]
1248
+ except IndexError:
1249
+ previous = None
1250
+ if top.type in (types.StringType, Stack.TYPE_ATTRIBUTE) and \
1251
+ previous and previous.type == Stack.TYPE_ATTRIBUTE:
1252
+ _checkVariableOperationOnItself(code, top_name,
1253
+ msgs.SET_VAR_TO_ITSELF)
1254
+ _checkExcessiveReferences(code, top, operand)
1255
+ if _ok_to_set_attr(codeSource.classObject, top.data, operand) :
1256
+ code.addWarning(msgs.INVALID_SET_CLASS_ATTR % operand)
1257
+ code.unpack()
1258
+
1259
+ def _DELETE_ATTR(oparg, operand, codeSource, code) :
1260
+ if len(code.stack) > 0 :
1261
+ _checkAttribute(code.stack[-1], operand, codeSource, code)
1262
+
1263
+ def _getExceptionInfo(codeSource, item):
1264
+ # FIXME: probably ought to try to handle raise module.Error
1265
+ if item.type is types.StringType and item.const == 1:
1266
+ return item.data, 1
1267
+
1268
+ e = None
1269
+ if item.type is Stack.TYPE_GLOBAL:
1270
+ try:
1271
+ e = eval(item.data)
1272
+ except NameError:
1273
+ pass
1274
+
1275
+ if not e:
1276
+ try:
1277
+ c = codeSource.module.classes.get(item.data)
1278
+ except TypeError: # item.data may not be hashable (e.g., list)
1279
+ return e, 0
1280
+
1281
+ if c is not None:
1282
+ e = c.classObject
1283
+ else:
1284
+ v = codeSource.module.variables.get(item.data)
1285
+ if v is not None:
1286
+ return v, (v.type == types.StringType)
1287
+ return e, 0
1288
+
1289
+ _UNCHECKABLE_CATCH_TYPES = (Stack.TYPE_UNKNOWN, Stack.TYPE_ATTRIBUTE)
1290
+ def _checkCatchException(codeSource, code, item):
1291
+ if not cfg().badExceptions:
1292
+ return
1293
+
1294
+ if item.data is None or item.type in _UNCHECKABLE_CATCH_TYPES:
1295
+ return
1296
+
1297
+ e, is_str = _getExceptionInfo(codeSource, item)
1298
+ if is_str:
1299
+ code.addWarning(msgs.CATCH_STR_EXCEPTION % item.data)
1300
+ elif e is not None and not _isexception(e):
1301
+ code.addWarning(msgs.CATCH_BAD_EXCEPTION % item.data)
1302
+
1303
+ def _handleExceptionChecks(codeSource, code, checks):
1304
+ for item in checks:
1305
+ if item is not None:
1306
+ if item.type is not types.TupleType:
1307
+ _checkCatchException(codeSource, code, item)
1308
+ else:
1309
+ for ti in item.data:
1310
+ if isinstance(ti, Stack.Item):
1311
+ _checkCatchException(codeSource, code, ti)
1312
+
1313
+ _BOOL_NAMES = ('True', 'False')
1314
+ _BAD_ASSIGN_NAMES = _BOOL_NAMES + ('None',)
1315
+
1316
+ def _checkBoolean(code, checks):
1317
+ for item in checks:
1318
+ try:
1319
+ data = string.capitalize(item.data)
1320
+ if item.type is Stack.TYPE_GLOBAL and data in _BOOL_NAMES:
1321
+ code.addWarning(msgs.BOOL_COMPARE % item.data)
1322
+ except (AttributeError, TypeError):
1323
+ # TypeError is necessary for Python 1.5.2
1324
+ pass # ignore items that are not a StackItem or a string
1325
+
1326
+ def _COMPARE_OP(oparg, operand, codeSource, code) :
1327
+ compareValues = _handleComparison(code.stack, operand)
1328
+ if oparg == OP.EXCEPT_COMPARISON:
1329
+ _handleExceptionChecks(codeSource, code, compareValues)
1330
+ elif oparg < OP.IN_COMPARISON: # '<', '<=', '==', '!=', '>', '>='
1331
+ _checkBoolean(code, compareValues)
1332
+ elif oparg < OP.IS_COMPARISON: # 'in', 'not in'
1333
+ # TODO: any checks that should be done here?
1334
+ pass
1335
+ elif cfg().isLiteral:
1336
+ # X is Y or X is not Y comparison
1337
+ second_arg = code.stack[-1].data[2]
1338
+ # FIXME: how should booleans be handled, need to think about it
1339
+ ## if second_arg.const or (second_arg.type == Stack.TYPE_GLOBAL and
1340
+ ## second_arg.data in ['True', 'False']):
1341
+ if second_arg.const and second_arg.data is not None:
1342
+ data = second_arg.data
1343
+ if second_arg.type is types.DictType:
1344
+ data = {}
1345
+ not_str = ''
1346
+ if oparg != OP.IS_COMPARISON:
1347
+ not_str = ' not'
1348
+ code.addWarning(msgs.IS_LITERAL % (not_str, data))
1349
+
1350
+ _checkNoEffect(code)
1351
+
1352
+ def _IMPORT_NAME(oparg, operand, codeSource, code) :
1353
+ code.pushStack(Stack.Item(operand, types.ModuleType))
1354
+ nextOp = code.nextOpInfo()[0]
1355
+ if not OP.IMPORT_FROM(nextOp) and not OP.IMPORT_STAR(nextOp) :
1356
+ _handleImport(code, operand, codeSource.module, codeSource.main, None)
1357
+
1358
+ def _IMPORT_FROM(oparg, operand, codeSource, code) :
1359
+ _handleImportFrom(code, operand, codeSource.module, codeSource.main)
1360
+ # this is necessary for python 1.5 (see STORE_GLOBAL/NAME)
1361
+ if utils.pythonVersion() < utils.PYTHON_2_0 :
1362
+ code.popStack()
1363
+ if not codeSource.main :
1364
+ code.unusedLocals[operand] = None
1365
+ elif not codeSource.module.moduleLineNums.has_key(operand) :
1366
+ code.updateModuleLineNums(codeSource.module, operand)
1367
+
1368
+ def _IMPORT_STAR(oparg, operand, codeSource, code) :
1369
+ _handleImportFrom(code, '*', codeSource.module, codeSource.main)
1370
+
1371
+ # Python 2.3 introduced some optimizations that create problems
1372
+ # this is a utility for ignoring these cases
1373
+ def _shouldIgnoreCodeOptimizations(code, bytecodes, offset, length=None):
1374
+ if utils.pythonVersion() < utils.PYTHON_2_3:
1375
+ return 0
1376
+
1377
+ if length is None:
1378
+ length = offset - 1
1379
+ try:
1380
+ start = code.index - offset
1381
+ return bytecodes == code.bytes[start:start+length]
1382
+ except IndexError:
1383
+ return 0
1384
+
1385
+ # In Python 2.3, a, b = 1,2 generates this code:
1386
+ # ...
1387
+ # ROT_TWO
1388
+ # JUMP_FORWARD 2
1389
+ # DUP_TOP
1390
+ # POP_TOP
1391
+ #
1392
+ # which generates a Possible stmt w/no effect
1393
+
1394
+ # ROT_TWO = 2; JUMP_FORWARD = 110; 2, 0 is the offset (2)
1395
+ _IGNORE_SEQ = '%c%c%c%c' % (2, 110, 2, 0)
1396
+ def _shouldIgnoreNoEffectWarning(code):
1397
+ return _shouldIgnoreCodeOptimizations(code, _IGNORE_SEQ, 5)
1398
+
1399
+ def _DUP_TOP(oparg, operand, codeSource, code) :
1400
+ if len(code.stack) > 0 :
1401
+ code.pushStack(code.stack[-1], _shouldIgnoreNoEffectWarning(code))
1402
+
1403
+ def _popn(code, n) :
1404
+ if len(code.stack) >= 2 :
1405
+ loadValue = code.stack[-2]
1406
+ if cfg().modifyDefaultValue and loadValue.type == types.StringType :
1407
+ _checkModifyDefaultArg(code, loadValue.data)
1408
+
1409
+ code.popStackItems(n)
1410
+
1411
+ def _DELETE_SUBSCR(oparg, operand, codeSource, code) :
1412
+ _popn(code, 2)
1413
+
1414
+ def _STORE_SUBSCR(oparg, operand, codeSource, code) :
1415
+ _popn(code, 3)
1416
+
1417
+ def _CALL_FUNCTION(oparg, operand, codeSource, code) :
1418
+ _handleFunctionCall(codeSource, code, oparg)
1419
+
1420
+ def _CALL_FUNCTION_VAR(oparg, operand, codeSource, code) :
1421
+ _handleFunctionCall(codeSource, code, oparg, 1, 0)
1422
+
1423
+ def _CALL_FUNCTION_KW(oparg, operand, codeSource, code) :
1424
+ _handleFunctionCall(codeSource, code, oparg, 1)
1425
+
1426
+ def _CALL_FUNCTION_VAR_KW(oparg, operand, codeSource, code) :
1427
+ _handleFunctionCall(codeSource, code, oparg, 2, 0)
1428
+
1429
+ def _MAKE_FUNCTION(oparg, operand, codeSource, code) :
1430
+ newValue = Stack.makeFuncReturnValue(code.stack[-1], oparg)
1431
+ code.popStackItems(oparg+1)
1432
+ code.pushStack(newValue)
1433
+
1434
+ def _MAKE_CLOSURE(oparg, operand, codeSource, code) :
1435
+ _MAKE_FUNCTION(max(0, oparg - 1), operand, codeSource, code)
1436
+
1437
+ def _BUILD_MAP(oparg, operand, codeSource, code) :
1438
+ _makeConstant(code, oparg, Stack.makeDict)
1439
+ def _BUILD_TUPLE(oparg, operand, codeSource, code) :
1440
+ _makeConstant(code, oparg, Stack.makeTuple)
1441
+ def _BUILD_LIST(oparg, operand, codeSource, code) :
1442
+ _makeConstant(code, oparg, Stack.makeList)
1443
+
1444
+ def _BUILD_CLASS(oparg, operand, codeSource, code) :
1445
+ newValue = Stack.makeFuncReturnValue(code.stack[-1], types.ClassType)
1446
+ code.popStackItems(3)
1447
+ code.pushStack(newValue)
1448
+
1449
+ def _LIST_APPEND(oparg, operand, codeSource, code):
1450
+ code.popStackItems(2)
1451
+
1452
+ def _modifyStackName(code, suffix):
1453
+ if code.stack:
1454
+ tos = code.stack[-1]
1455
+ tos_type = type(tos.data)
1456
+ if tos_type == types.StringType:
1457
+ tos.data = tos.data + suffix
1458
+ elif tos_type == types.TupleType and \
1459
+ type(tos.data[-1]) == types.StringType:
1460
+ tos.data = tos.data[:-1] + (tos.data[-1] + suffix,)
1461
+
1462
+ def _UNARY_CONVERT(oparg, operand, codeSource, code) :
1463
+ if code.stack:
1464
+ stackValue = code.stack[-1]
1465
+ if stackValue.data == cfg().methodArgName and \
1466
+ stackValue.const == 0 and codeSource.classObject is not None and \
1467
+ codeSource.func.function.func_name == '__repr__' :
1468
+ code.addWarning(msgs.USING_SELF_IN_REPR)
1469
+ stackValue.data = utils.safestr(stackValue.data)
1470
+ stackValue.type = types.StringType
1471
+ _modifyStackName(code, '-repr')
1472
+
1473
+ def _UNARY_POSITIVE(oparg, operand, codeSource, code) :
1474
+ if OP.UNARY_POSITIVE(code.nextOpInfo()[0]) :
1475
+ code.addWarning(msgs.STMT_WITH_NO_EFFECT % '++')
1476
+ code.popNextOp()
1477
+ elif cfg().unaryPositive and code.stack and not code.stack[-1].const :
1478
+ code.addWarning(msgs.UNARY_POSITIVE_HAS_NO_EFFECT)
1479
+ _modifyStackName(code, '-pos')
1480
+
1481
+ def _UNARY_NEGATIVE(oparg, operand, codeSource, code) :
1482
+ if OP.UNARY_NEGATIVE(code.nextOpInfo()[0]) :
1483
+ code.addWarning(msgs.STMT_WITH_NO_EFFECT % '--')
1484
+ _modifyStackName(code, '-neg')
1485
+
1486
+ def _UNARY_NOT(oparg, operand, codeSource, code) :
1487
+ _modifyStackName(code, '-not')
1488
+
1489
+ def _UNARY_INVERT(oparg, operand, codeSource, code) :
1490
+ if OP.UNARY_INVERT(code.nextOpInfo()[0]) :
1491
+ code.addWarning(msgs.STMT_WITH_NO_EFFECT % '~~')
1492
+ _modifyStackName(code, '-invert')
1493
+
1494
+
1495
+ def _popStackRef(code, operand, count = 2) :
1496
+ code.popStackItems(count)
1497
+ code.pushStack(Stack.Item(operand, Stack.TYPE_UNKNOWN))
1498
+
1499
+ def _popModifiedStack(code, suffix=' '):
1500
+ code.popStack()
1501
+ _modifyStackName(code, suffix)
1502
+
1503
+ def _pop(oparg, operand, codeSource, code) :
1504
+ code.popStack()
1505
+ _POP_TOP = _PRINT_ITEM = _pop
1506
+
1507
+ def _popModified(oparg, operand, codeSource, code):
1508
+ _popModifiedStack(code)
1509
+
1510
+ def _BINARY_RSHIFT(oparg, operand, codeSource, code):
1511
+ _coerce_type(code)
1512
+ _popModified(oparg, operand, codeSource, code)
1513
+ _BINARY_LSHIFT = _BINARY_RSHIFT
1514
+
1515
+ def _checkModifyNoOp(code, op, msg=msgs.MODIFY_VAR_NOOP, modifyStack=1):
1516
+ stack = code.stack
1517
+ if len(stack) >= 2:
1518
+ if (stack[-1].type != Stack.TYPE_UNKNOWN and
1519
+ stack[-2].type != Stack.TYPE_UNKNOWN):
1520
+ name = stack[-1].getName()
1521
+ if name != Stack.TYPE_UNKNOWN and name == stack[-2].getName():
1522
+ code.addWarning(msg % (name, op, name))
1523
+
1524
+ if modifyStack:
1525
+ code.popStack()
1526
+ stack[-1].const = 0
1527
+ _modifyStackName(code, op)
1528
+
1529
+ def _BINARY_AND(oparg, operand, codeSource, code):
1530
+ # Don't modify the stack, since _coerce_type() will do it.
1531
+ _checkModifyNoOp(code, '&', modifyStack=0)
1532
+ _coerce_type(code)
1533
+
1534
+ def _BINARY_OR(oparg, operand, codeSource, code):
1535
+ # Don't modify the stack, since _coerce_type() will do it.
1536
+ _checkModifyNoOp(code, '|', modifyStack=0)
1537
+ _coerce_type(code)
1538
+
1539
+ def _BINARY_XOR(oparg, operand, codeSource, code):
1540
+ # Don't modify the stack, since _coerce_type() will do it.
1541
+ _checkModifyNoOp(code, '^', msgs.XOR_VAR_WITH_ITSELF, modifyStack=0)
1542
+ _coerce_type(code)
1543
+
1544
+ def _PRINT_ITEM_TO(oparg, operand, codeSource, code) :
1545
+ code.popStackItems(2)
1546
+
1547
+ try:
1548
+ ComplexType = types.ComplexType
1549
+ except NameError:
1550
+ ComplexType = types.FloatType # need some numeric type here
1551
+
1552
+ _NUMERIC_TYPES = (types.IntType, types.FloatType, ComplexType)
1553
+
1554
+ # FIXME: This is pathetically weak, need to handle more types
1555
+ def _coerce_type(code) :
1556
+ _checkNoEffect(code)
1557
+ newItem = Stack.Item('<stack>', Stack.TYPE_UNKNOWN)
1558
+ if len(code.stack) >= 2 :
1559
+ s1, s2 = code.stack[-2:]
1560
+ s1type = s1.getType(code.typeMap)
1561
+ s2type = s2.getType(code.typeMap)
1562
+ if s1type != s2type :
1563
+ if s1type in _NUMERIC_TYPES and s2type in _NUMERIC_TYPES :
1564
+ newType = types.FloatType
1565
+ if s1type == ComplexType or s2type == ComplexType:
1566
+ newType = ComplexType
1567
+ newItem.type = newType
1568
+
1569
+ code.popStackItems(2)
1570
+ code.pushStack(newItem)
1571
+
1572
+ def _BINARY_ADD(oparg, operand, codeSource, code) :
1573
+ stack = code.stack
1574
+ if len(stack) >= 2 and (stack[-1].const and stack[-2].const and
1575
+ stack[-1].type == stack[-2].type) :
1576
+ value = stack[-2].data + stack[-1].data
1577
+ code.popStackItems(2)
1578
+ code.pushStack(Stack.Item(value, type(value), 1))
1579
+ else :
1580
+ _coerce_type(code)
1581
+
1582
+ def _BINARY_SUBTRACT(oparg, operand, codeSource, code) :
1583
+ _coerce_type(code)
1584
+ _BINARY_POWER = _BINARY_SUBTRACT
1585
+
1586
+ def _BINARY_SUBSCR(oparg, operand, codeSource, code) :
1587
+ _checkNoEffect(code)
1588
+ if len(code.stack) >= 2 :
1589
+ stack = code.stack
1590
+ varType = code.typeMap.get(utils.safestr(stack[-2].data), [])
1591
+ if types.ListType in varType and stack[-1].type == types.TupleType :
1592
+ code.addWarning(msgs.USING_TUPLE_ACCESS_TO_LIST % stack[-2].data)
1593
+ _popStackRef(code, operand)
1594
+
1595
+ def _isint(stackItem, code) :
1596
+ if type(stackItem.data) == types.IntType :
1597
+ return 1
1598
+ stackTypes = code.typeMap.get(stackItem.data, [])
1599
+ if len(stackTypes) != 1 :
1600
+ return 0
1601
+ return types.IntType in stackTypes
1602
+
1603
+ def _BINARY_DIVIDE(oparg, operand, codeSource, code) :
1604
+ _checkNoEffect(code)
1605
+ _checkModifyNoOp(code, '/', msgs.DIVIDE_VAR_BY_ITSELF, 0)
1606
+ if cfg().intDivide and len(code.stack) >= 2 :
1607
+ if _isint(code.stack[-1], code) and _isint(code.stack[-2], code) :
1608
+ # don't warn if we are going to convert the result to an int
1609
+ if not (len(code.stack) >= 3 and
1610
+ code.stack[-3].data == 'int' and
1611
+ OP.CALL_FUNCTION(code.nextOpInfo()[0])):
1612
+ code.addWarning(msgs.INTEGER_DIVISION % tuple(code.stack[-2:]))
1613
+
1614
+ _popModifiedStack(code, '/')
1615
+
1616
+ def _BINARY_TRUE_DIVIDE(oparg, operand, codeSource, code) :
1617
+ _checkNoEffect(code)
1618
+ _checkVariableOperationOnItself(code, operand, msgs.DIVIDE_VAR_BY_ITSELF)
1619
+ _popModifiedStack(code, '/')
1620
+ _BINARY_FLOOR_DIVIDE = _BINARY_TRUE_DIVIDE
1621
+
1622
+ def _BINARY_MULTIPLY(oparg, operand, codeSource, code) :
1623
+ if len(code.stack) >= 2 :
1624
+ format = _getFormatString(code, codeSource)
1625
+ if format and type(code.stack[-1].data) == types.IntType :
1626
+ code.stack[-2].data = format * code.stack[-1].data
1627
+ code.popStack()
1628
+ else:
1629
+ _coerce_type(code)
1630
+ else:
1631
+ _popModifiedStack(code, '*')
1632
+
1633
+ def _BINARY_MODULO(oparg, operand, codeSource, code) :
1634
+ _checkNoEffect(code)
1635
+ if cfg().modulo1 and code.stack and code.stack[-1].data == 1:
1636
+ if len(code.stack) < 2 or \
1637
+ code.stack[-2].getType(code.typeMap) != types.FloatType:
1638
+ code.addWarning(msgs.MODULO_1)
1639
+ _getFormatWarnings(code, codeSource)
1640
+ _popModifiedStack(code, '%')
1641
+ if code.stack:
1642
+ code.stack[-1].const = 0
1643
+
1644
+ def _ROT_TWO(oparg, operand, codeSource, code) :
1645
+ if len(code.stack) >= 2 :
1646
+ tmp = code.stack[-2]
1647
+ code.stack[-2] = code.stack[-1]
1648
+ code.stack[-1] = tmp
1649
+
1650
+ def _ROT_THREE(oparg, operand, codeSource, code) :
1651
+ """Lifts second and third stack item one position up,
1652
+ moves top down to position three."""
1653
+ if len(code.stack) >= 3 :
1654
+ second = code.stack[-2]
1655
+ third = code.stack[-3]
1656
+ code.stack[-3] = code.stack[-1]
1657
+ code.stack[-2] = third
1658
+ code.stack[-1] = second
1659
+
1660
+ def _ROT_FOUR(oparg, operand, codeSource, code) :
1661
+ """Lifts second, third and forth stack item one position up,
1662
+ moves top down to position four."""
1663
+ if len(code.stack) >= 4 :
1664
+ second = code.stack[-2]
1665
+ third = code.stack[-3]
1666
+ fourth = code.stack[-4]
1667
+ code.stack[-4] = code.stack[-1]
1668
+ code.stack[-3] = fourth
1669
+ code.stack[-2] = third
1670
+ code.stack[-1] = second
1671
+
1672
+ def _SETUP_EXCEPT(oparg, operand, codeSource, code) :
1673
+ code.has_except = 1
1674
+ code.pushStack(Stack.Item(None, Stack.TYPE_EXCEPT))
1675
+ code.pushStack(Stack.Item(None, Stack.TYPE_EXCEPT))
1676
+
1677
+ def _SETUP_FINALLY(oparg, operand, codeSource, code) :
1678
+ if not code.has_except :
1679
+ code.try_finally_first = 1
1680
+
1681
+ def _END_FINALLY(oparg, operand, codeSource, code) :
1682
+ if code.try_finally_first and code.index == (len(code.bytes) - 4) :
1683
+ code.starts_and_ends_with_finally = 1
1684
+
1685
+ def _LINE_NUM(oparg, operand, codeSource, code) :
1686
+ code.lastLineNum = oparg
1687
+
1688
+ def _UNPACK_SEQUENCE(oparg, operand, codeSource, code) :
1689
+ code.unpackCount = oparg
1690
+ if code.stack:
1691
+ top = code.stack[-1]
1692
+ # if we know we have a tuple, make sure we unpack it into the
1693
+ # right # of variables
1694
+ topType = top.getType(code.typeMap)
1695
+ if topType in _SEQUENCE_TYPES:
1696
+ length = top.length
1697
+ # we don't know the length, maybe it's constant and we can find out
1698
+ if length == 0:
1699
+ value = code.constants.get(utils.safestr(top.data))
1700
+ if type(value) in _SEQUENCE_TYPES:
1701
+ length = len(value)
1702
+ if length > 0 and length != oparg:
1703
+ if cfg().unpackLength:
1704
+ code.addWarning(msgs.WRONG_UNPACK_SIZE % (length, oparg))
1705
+ elif topType not in _UNCHECKABLE_STACK_TYPES:
1706
+ if cfg().unpackNonSequence:
1707
+ code.addWarning(msgs.UNPACK_NON_SEQUENCE %
1708
+ (top.data, _getTypeStr(topType)))
1709
+ _modifyStackName(code, '-unpack')
1710
+
1711
+ def _SLICE_1_ARG(oparg, operand, codeSource, code) :
1712
+ _popStackRef(code, operand)
1713
+
1714
+ _SLICE1 = _SLICE2 = _SLICE_1_ARG
1715
+
1716
+ def _SLICE3(oparg, operand, codeSource, code) :
1717
+ _popStackRef(code, operand, 3)
1718
+
1719
+ def _check_string_iteration(code, index):
1720
+ try:
1721
+ item = code.stack[index]
1722
+ except IndexError:
1723
+ return
1724
+ if item.getType(code.typeMap) == types.StringType and \
1725
+ cfg().stringIteration:
1726
+ code.addWarning(msgs.STRING_ITERATION % item.data)
1727
+
1728
+ def _FOR_LOOP(oparg, operand, codeSource, code) :
1729
+ code.loops = code.loops + 1
1730
+ _check_string_iteration(code, -2)
1731
+ _popStackRef(code, '<for_loop>', 2)
1732
+
1733
+ def _GET_ITER(oparg, operand, codeSource, code) :
1734
+ _check_string_iteration(code, -1)
1735
+
1736
+ def _FOR_ITER(oparg, operand, codeSource, code) :
1737
+ code.loops = code.loops + 1
1738
+ _popStackRef(code, '<for_iter>', 1)
1739
+
1740
+ def _jump(oparg, operand, codeSource, code) :
1741
+ if len(code.stack) > 0 :
1742
+ topOfStack = code.stack[-1]
1743
+ if topOfStack.isMethodCall(codeSource.classObject, cfg().methodArgName):
1744
+ name = topOfStack.data[-1]
1745
+ if codeSource.classObject.methods.has_key(name) :
1746
+ code.addWarning(msgs.USING_METHOD_AS_ATTR % name)
1747
+ _JUMP_ABSOLUTE = _jump
1748
+
1749
+ def _skip_loops(bytes, i, lastLineNum, max) :
1750
+ extended_arg = 0
1751
+ blockCount = 1
1752
+ while i < max :
1753
+ op, oparg, i, extended_arg = OP.getInfo(bytes, i, extended_arg)
1754
+ if OP.LINE_NUM(op) :
1755
+ lastLineNum = oparg
1756
+ elif OP.FOR_LOOP(op) or OP.FOR_ITER(op) or OP.SETUP_LOOP(op) :
1757
+ blockCount = blockCount + 1
1758
+ elif OP.POP_BLOCK(op) :
1759
+ blockCount = blockCount - 1
1760
+ if blockCount <= 0 :
1761
+ break
1762
+
1763
+ return lastLineNum, i
1764
+
1765
+ def _is_unreachable(code, topOfStack, branch, if_false) :
1766
+ # Are we are checking exceptions, but we not catching all exceptions?
1767
+ if (topOfStack.type == Stack.TYPE_COMPARISON and
1768
+ topOfStack.data[1] == 'exception match' and
1769
+ topOfStack.data[2] is not Exception) :
1770
+ return 1
1771
+
1772
+ # do we possibly have while 1: ?
1773
+ if not (topOfStack.const and topOfStack.data == 1 and if_false) :
1774
+ return 0
1775
+
1776
+ # get the op just before the branch (ie, -3)
1777
+ op, oparg, i, extended_arg = OP.getInfo(code.bytes, branch - 3, 0)
1778
+ # are we are jumping to before the while 1: (LOAD_CONST, JUMP_IF_FALSE)
1779
+ if not (OP.JUMP_ABSOLUTE(op) and oparg == (code.index - 3*3)) :
1780
+ return 0
1781
+
1782
+ # check if we break out of the loop
1783
+ i = code.index
1784
+ lastLineNum = code.getLineNum()
1785
+ while i < branch :
1786
+ op, oparg, i, extended_arg = OP.getInfo(code.bytes, i, extended_arg)
1787
+ if OP.LINE_NUM(op) :
1788
+ lastLineNum = oparg
1789
+ elif OP.BREAK_LOOP(op) :
1790
+ return 0
1791
+ elif OP.FOR_LOOP(op) or OP.FOR_ITER(op) or OP.SETUP_LOOP(op) :
1792
+ lastLineNum, i = _skip_loops(code.bytes, i, lastLineNum, branch)
1793
+
1794
+ i = code.index - 3*4
1795
+ op, oparg, i, extended_arg = OP.getInfo(code.bytes, i, 0)
1796
+ if OP.SETUP_LOOP(op) :
1797
+ # a little lie to pretend we have a raise after a while 1:
1798
+ code.removeBranch(i + oparg)
1799
+ code.raiseValues.append((lastLineNum, None, i + oparg))
1800
+ return 1
1801
+
1802
+ # In Python 2.3, while/if 1: gets optimized to
1803
+ # ...
1804
+ # JUMP_FORWARD 4
1805
+ # JUMP_IF_FALSE ?
1806
+ # POP_TOP
1807
+ #
1808
+ # which generates a Using a conditional statement with a constant value
1809
+
1810
+ # JUMP_FORWARD = 110; 4, 0 is the offset (4)
1811
+ _IGNORE_BOGUS_JUMP = '%c%c%c' % (110, 4, 0)
1812
+ def _shouldIgnoreBogusJumps(code):
1813
+ return _shouldIgnoreCodeOptimizations(code, _IGNORE_BOGUS_JUMP, 6, 3)
1814
+
1815
+ def _checkConstantCondition(code, topOfStack, if_false):
1816
+ # don't warn when doing (test and 'true' or 'false')
1817
+ # still warn when doing (test and None or 'false')
1818
+ if if_false or not OP.LOAD_CONST(code.nextOpInfo(1)[0]) or \
1819
+ not topOfStack.data or topOfStack.type is types.NoneType:
1820
+ if not _shouldIgnoreBogusJumps(code):
1821
+ code.addWarning(msgs.CONSTANT_CONDITION % utils.safestr(topOfStack))
1822
+
1823
+ def _jump_conditional(oparg, operand, codeSource, code, if_false) :
1824
+ # FIXME: this doesn't work in 2.3+ since constant conditions
1825
+ # are optimized away by the compiler.
1826
+ if code.stack :
1827
+ topOfStack = code.stack[-1]
1828
+ if (topOfStack.const or topOfStack.type is types.NoneType) and \
1829
+ cfg().constantConditions and \
1830
+ (topOfStack.data != 1 or cfg().constant1):
1831
+ _checkConstantCondition(code, topOfStack, if_false)
1832
+
1833
+ if _is_unreachable(code, topOfStack, code.label, if_false) :
1834
+ code.removeBranch(code.label)
1835
+
1836
+ _jump(oparg, operand, codeSource, code)
1837
+
1838
+ def _JUMP_IF_FALSE(oparg, operand, codeSource, code) :
1839
+ _jump_conditional(oparg, operand, codeSource, code, 1)
1840
+
1841
+ def _JUMP_IF_TRUE(oparg, operand, codeSource, code) :
1842
+ _jump_conditional(oparg, operand, codeSource, code, 0)
1843
+
1844
+ def _JUMP_FORWARD(oparg, operand, codeSource, code) :
1845
+ _jump(oparg, operand, codeSource, code)
1846
+ code.remove_unreachable_code(code.label)
1847
+
1848
+ def _RETURN_VALUE(oparg, operand, codeSource, code) :
1849
+ if not codeSource.calling_code :
1850
+ code.addReturn()
1851
+
1852
+ def _EXEC_STMT(oparg, operand, codeSource, code) :
1853
+ if cfg().usesExec :
1854
+ if code.stack and code.stack[-1].isNone() :
1855
+ code.addWarning(msgs.USES_GLOBAL_EXEC)
1856
+ else :
1857
+ code.addWarning(msgs.USES_EXEC)
1858
+
1859
+ def _checkStrException(code, varType, item):
1860
+ if varType is types.StringType:
1861
+ code.addWarning(msgs.RAISE_STR_EXCEPTION % item.data)
1862
+
1863
+ def _RAISE_VARARGS(oparg, operand, codeSource, code) :
1864
+ code.addRaise()
1865
+ if not cfg().badExceptions:
1866
+ return
1867
+
1868
+ if oparg > 0 and len(code.stack) >= oparg:
1869
+ item = code.stack[-oparg]
1870
+ if item.type not in (Stack.TYPE_FUNC_RETURN, Stack.TYPE_UNKNOWN):
1871
+ if item.type is Stack.TYPE_GLOBAL:
1872
+ e, is_str = _getExceptionInfo(codeSource, item)
1873
+ if is_str:
1874
+ _checkStrException(code, e.type, item)
1875
+ elif e is not None and not _isexception(e):
1876
+ code.addWarning(msgs.RAISE_BAD_EXCEPTION % item.data)
1877
+ else:
1878
+ _checkStrException(code, item.getType(code.typeMap), item)
1879
+
1880
+
1881
+ DISPATCH = [ None ] * 256
1882
+ DISPATCH[ 1] = _POP_TOP
1883
+ DISPATCH[ 2] = _ROT_TWO
1884
+ DISPATCH[ 3] = _ROT_THREE
1885
+ DISPATCH[ 4] = _DUP_TOP
1886
+ DISPATCH[ 5] = _ROT_FOUR
1887
+ DISPATCH[ 10] = _UNARY_POSITIVE
1888
+ DISPATCH[ 11] = _UNARY_NEGATIVE
1889
+ DISPATCH[ 12] = _UNARY_NOT
1890
+ DISPATCH[ 13] = _UNARY_CONVERT
1891
+ DISPATCH[ 15] = _UNARY_INVERT
1892
+ DISPATCH[ 18] = _LIST_APPEND
1893
+ DISPATCH[ 19] = _BINARY_POWER
1894
+ DISPATCH[ 20] = _BINARY_MULTIPLY
1895
+ DISPATCH[ 21] = _BINARY_DIVIDE
1896
+ DISPATCH[ 22] = _BINARY_MODULO
1897
+ DISPATCH[ 23] = _BINARY_ADD
1898
+ DISPATCH[ 24] = _BINARY_SUBTRACT
1899
+ DISPATCH[ 25] = _BINARY_SUBSCR
1900
+ DISPATCH[ 26] = _BINARY_FLOOR_DIVIDE
1901
+ DISPATCH[ 27] = _BINARY_TRUE_DIVIDE
1902
+ # FIXME: add INPLACE FLOOR/TRUE DIVIDE: 28/29
1903
+ DISPATCH[ 31] = _SLICE1
1904
+ DISPATCH[ 32] = _SLICE2
1905
+ DISPATCH[ 33] = _SLICE3
1906
+ DISPATCH[ 55] = _BINARY_ADD # INPLACE
1907
+ DISPATCH[ 56] = _BINARY_SUBTRACT # INPLACE
1908
+ DISPATCH[ 57] = _BINARY_MULTIPLY # INPLACE
1909
+ DISPATCH[ 58] = _BINARY_DIVIDE # INPLACE
1910
+ DISPATCH[ 59] = _BINARY_MODULO # INPLACE
1911
+ DISPATCH[ 60] = _STORE_SUBSCR
1912
+ DISPATCH[ 61] = _DELETE_SUBSCR
1913
+ DISPATCH[ 62] = _BINARY_LSHIFT
1914
+ DISPATCH[ 63] = _BINARY_RSHIFT
1915
+ DISPATCH[ 64] = _BINARY_AND
1916
+ DISPATCH[ 65] = _BINARY_XOR
1917
+ DISPATCH[ 66] = _BINARY_OR
1918
+ DISPATCH[ 67] = _BINARY_POWER # INPLACE
1919
+ DISPATCH[ 68] = _GET_ITER
1920
+ DISPATCH[ 71] = _PRINT_ITEM
1921
+ DISPATCH[ 73] = _PRINT_ITEM_TO
1922
+ DISPATCH[ 75] = _BINARY_LSHIFT # INPLACE
1923
+ DISPATCH[ 76] = _BINARY_RSHIFT # INPLACE
1924
+ DISPATCH[ 77] = _BINARY_AND # INPLACE
1925
+ DISPATCH[ 78] = _BINARY_XOR # INPLACE
1926
+ DISPATCH[ 79] = _BINARY_OR # INPLACE
1927
+ DISPATCH[ 83] = _RETURN_VALUE
1928
+ DISPATCH[ 84] = _IMPORT_STAR
1929
+ DISPATCH[ 85] = _EXEC_STMT
1930
+ DISPATCH[ 88] = _END_FINALLY
1931
+ DISPATCH[ 89] = _BUILD_CLASS
1932
+ DISPATCH[ 90] = _STORE_NAME
1933
+ DISPATCH[ 91] = _DELETE_NAME
1934
+ DISPATCH[ 92] = _UNPACK_SEQUENCE
1935
+ DISPATCH[ 93] = _FOR_ITER
1936
+ DISPATCH[ 95] = _STORE_ATTR
1937
+ DISPATCH[ 96] = _DELETE_ATTR
1938
+ DISPATCH[ 97] = _STORE_GLOBAL
1939
+ DISPATCH[ 98] = _DELETE_GLOBAL
1940
+ DISPATCH[100] = _LOAD_CONST
1941
+ DISPATCH[101] = _LOAD_NAME
1942
+ DISPATCH[102] = _BUILD_TUPLE
1943
+ DISPATCH[103] = _BUILD_LIST
1944
+ DISPATCH[104] = _BUILD_MAP
1945
+ DISPATCH[105] = _LOAD_ATTR
1946
+ DISPATCH[106] = _COMPARE_OP
1947
+ DISPATCH[107] = _IMPORT_NAME
1948
+ DISPATCH[108] = _IMPORT_FROM
1949
+ DISPATCH[110] = _JUMP_FORWARD
1950
+ DISPATCH[111] = _JUMP_IF_FALSE
1951
+ DISPATCH[112] = _JUMP_IF_TRUE
1952
+ DISPATCH[113] = _JUMP_ABSOLUTE
1953
+ DISPATCH[114] = _FOR_LOOP
1954
+ DISPATCH[116] = _LOAD_GLOBAL
1955
+ DISPATCH[121] = _SETUP_EXCEPT
1956
+ DISPATCH[122] = _SETUP_FINALLY
1957
+ DISPATCH[124] = _LOAD_FAST
1958
+ DISPATCH[125] = _STORE_FAST
1959
+ DISPATCH[126] = _DELETE_FAST
1960
+ DISPATCH[127] = _LINE_NUM
1961
+ DISPATCH[130] = _RAISE_VARARGS
1962
+ DISPATCH[131] = _CALL_FUNCTION
1963
+ DISPATCH[132] = _MAKE_FUNCTION
1964
+ DISPATCH[134] = _MAKE_CLOSURE
1965
+ DISPATCH[135] = _LOAD_CLOSURE
1966
+ DISPATCH[136] = _LOAD_DEREF
1967
+ DISPATCH[140] = _CALL_FUNCTION_VAR
1968
+ DISPATCH[141] = _CALL_FUNCTION_KW
1969
+ DISPATCH[142] = _CALL_FUNCTION_VAR_KW