bee_python 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (488) hide show
  1. data/{build/README → README} +1 -1
  2. data/egg/egg/build.yml +11 -49
  3. data/egg/egg.yml +19 -27
  4. data/egg/http/build.erb +32 -36
  5. data/egg/http/libhttp.py +102 -0
  6. data/egg/http/pylint.cfg +236 -0
  7. data/egg/http/server.py +7 -0
  8. data/egg/http/test.erb +32 -0
  9. data/egg/http.yml +33 -29
  10. data/egg/mysql/mysql.py +8 -9
  11. data/egg/project/build.erb +21 -53
  12. data/egg/project/pylint.cfg +236 -0
  13. data/egg/project/test.py +2 -2
  14. data/egg/project.yml +23 -31
  15. data/egg/script/build.erb +18 -23
  16. data/egg/script/pylint.cfg +236 -0
  17. data/egg/script.yml +22 -18
  18. data/egg/source/source.py +6 -6
  19. data/egg/test/test.py +1 -1
  20. data/lib/bee_task_python.rb +3 -34
  21. data/python.yml +123 -0
  22. metadata +61 -503
  23. data/test/build.yml +0 -16
  24. data/test/tc_bee_task_python.rb +0 -27
  25. data/test/test_build.rb +0 -26
  26. data/test/test_build_listener.rb +0 -110
  27. data/test/ts_bee_python.rb +0 -26
  28. data/tools/common/__init__.py +0 -5
  29. data/tools/common/common/__init__.py +0 -140
  30. data/tools/common/common/__pkginfo__.py +0 -43
  31. data/tools/common/common/adbh.py +0 -35
  32. data/tools/common/common/cache.py +0 -114
  33. data/tools/common/common/changelog.py +0 -234
  34. data/tools/common/common/clcommands.py +0 -181
  35. data/tools/common/common/cli.py +0 -212
  36. data/tools/common/common/compat.py +0 -328
  37. data/tools/common/common/configuration.py +0 -1087
  38. data/tools/common/common/contexts.py +0 -58
  39. data/tools/common/common/corbautils.py +0 -117
  40. data/tools/common/common/daemon.py +0 -171
  41. data/tools/common/common/date.py +0 -279
  42. data/tools/common/common/db.py +0 -49
  43. data/tools/common/common/dbf.py +0 -229
  44. data/tools/common/common/debugger.py +0 -208
  45. data/tools/common/common/decorators.py +0 -190
  46. data/tools/common/common/deprecation.py +0 -118
  47. data/tools/common/common/fileutils.py +0 -409
  48. data/tools/common/common/graph.py +0 -259
  49. data/tools/common/common/html.py +0 -142
  50. data/tools/common/common/interface.py +0 -76
  51. data/tools/common/common/logging_ext.py +0 -166
  52. data/tools/common/common/modutils.py +0 -670
  53. data/tools/common/common/optik_ext.py +0 -383
  54. data/tools/common/common/optparser.py +0 -92
  55. data/tools/common/common/pdf_ext.py +0 -111
  56. data/tools/common/common/proc.py +0 -276
  57. data/tools/common/common/pyro_ext.py +0 -146
  58. data/tools/common/common/pytest.py +0 -754
  59. data/tools/common/common/shellutils.py +0 -383
  60. data/tools/common/common/sphinx_ext.py +0 -87
  61. data/tools/common/common/sphinxutils.py +0 -122
  62. data/tools/common/common/sqlgen.py +0 -31
  63. data/tools/common/common/table.py +0 -930
  64. data/tools/common/common/tasksqueue.py +0 -97
  65. data/tools/common/common/test/__init__.py +0 -1
  66. data/tools/common/common/test/data/ChangeLog +0 -184
  67. data/tools/common/common/test/data/MyPyPa-0.1.0-py2.5.egg +0 -0
  68. data/tools/common/common/test/data/__init__.py +0 -1
  69. data/tools/common/common/test/data/content_differ_dir/NOTHING +0 -0
  70. data/tools/common/common/test/data/content_differ_dir/README +0 -1
  71. data/tools/common/common/test/data/content_differ_dir/subdir/coin +0 -1
  72. data/tools/common/common/test/data/content_differ_dir/subdir/toto.txt +0 -53
  73. data/tools/common/common/test/data/file_differ_dir/NOTHING +0 -0
  74. data/tools/common/common/test/data/file_differ_dir/README +0 -1
  75. data/tools/common/common/test/data/file_differ_dir/subdir/toto.txt +0 -53
  76. data/tools/common/common/test/data/file_differ_dir/subdirtwo/Hello +0 -0
  77. data/tools/common/common/test/data/find_test/__init__.py +0 -0
  78. data/tools/common/common/test/data/find_test/foo.txt +0 -0
  79. data/tools/common/common/test/data/find_test/module.py +0 -0
  80. data/tools/common/common/test/data/find_test/module2.py +0 -0
  81. data/tools/common/common/test/data/find_test/newlines.txt +0 -0
  82. data/tools/common/common/test/data/find_test/noendingnewline.py +0 -0
  83. data/tools/common/common/test/data/find_test/nonregr.py +0 -0
  84. data/tools/common/common/test/data/find_test/normal_file.txt +0 -0
  85. data/tools/common/common/test/data/find_test/spam.txt +0 -0
  86. data/tools/common/common/test/data/find_test/sub/doc.txt +0 -0
  87. data/tools/common/common/test/data/find_test/sub/momo.py +0 -0
  88. data/tools/common/common/test/data/find_test/test.ini +0 -0
  89. data/tools/common/common/test/data/find_test/test1.msg +0 -0
  90. data/tools/common/common/test/data/find_test/test2.msg +0 -0
  91. data/tools/common/common/test/data/find_test/write_protected_file.txt +0 -0
  92. data/tools/common/common/test/data/foo.txt +0 -9
  93. data/tools/common/common/test/data/module.py +0 -88
  94. data/tools/common/common/test/data/module2.py +0 -77
  95. data/tools/common/common/test/data/newlines.txt +0 -3
  96. data/tools/common/common/test/data/noendingnewline.py +0 -36
  97. data/tools/common/common/test/data/nonregr.py +0 -14
  98. data/tools/common/common/test/data/normal_file.txt +0 -0
  99. data/tools/common/common/test/data/reference_dir/NOTHING +0 -0
  100. data/tools/common/common/test/data/reference_dir/README +0 -1
  101. data/tools/common/common/test/data/reference_dir/subdir/coin +0 -1
  102. data/tools/common/common/test/data/reference_dir/subdir/toto.txt +0 -53
  103. data/tools/common/common/test/data/same_dir/NOTHING +0 -0
  104. data/tools/common/common/test/data/same_dir/README +0 -1
  105. data/tools/common/common/test/data/same_dir/subdir/coin +0 -1
  106. data/tools/common/common/test/data/same_dir/subdir/toto.txt +0 -53
  107. data/tools/common/common/test/data/spam.txt +0 -9
  108. data/tools/common/common/test/data/sub/doc.txt +0 -1
  109. data/tools/common/common/test/data/sub/momo.py +0 -1
  110. data/tools/common/common/test/data/subdir_differ_dir/NOTHING +0 -0
  111. data/tools/common/common/test/data/subdir_differ_dir/README +0 -1
  112. data/tools/common/common/test/data/subdir_differ_dir/subdir/coin +0 -1
  113. data/tools/common/common/test/data/subdir_differ_dir/subdir/toto.txt +0 -53
  114. data/tools/common/common/test/data/test.ini +0 -20
  115. data/tools/common/common/test/data/test1.msg +0 -30
  116. data/tools/common/common/test/data/test2.msg +0 -42
  117. data/tools/common/common/test/data/write_protected_file.txt +0 -0
  118. data/tools/common/common/test/foomod.py +0 -17
  119. data/tools/common/common/test/unittest_cache.py +0 -129
  120. data/tools/common/common/test/unittest_changelog.py +0 -37
  121. data/tools/common/common/test/unittest_compat.py +0 -239
  122. data/tools/common/common/test/unittest_configuration.py +0 -348
  123. data/tools/common/common/test/unittest_date.py +0 -154
  124. data/tools/common/common/test/unittest_decorators.py +0 -62
  125. data/tools/common/common/test/unittest_deprecation.py +0 -76
  126. data/tools/common/common/test/unittest_fileutils.py +0 -133
  127. data/tools/common/common/test/unittest_graph.py +0 -50
  128. data/tools/common/common/test/unittest_html.py +0 -76
  129. data/tools/common/common/test/unittest_interface.py +0 -87
  130. data/tools/common/common/test/unittest_modutils.py +0 -244
  131. data/tools/common/common/test/unittest_pytest.py +0 -50
  132. data/tools/common/common/test/unittest_shellutils.py +0 -248
  133. data/tools/common/common/test/unittest_table.py +0 -448
  134. data/tools/common/common/test/unittest_taskqueue.py +0 -71
  135. data/tools/common/common/test/unittest_testlib.py +0 -956
  136. data/tools/common/common/test/unittest_textutils.py +0 -247
  137. data/tools/common/common/test/unittest_tree.py +0 -248
  138. data/tools/common/common/test/unittest_umessage.py +0 -55
  139. data/tools/common/common/test/unittest_ureports_html.py +0 -64
  140. data/tools/common/common/test/unittest_ureports_text.py +0 -105
  141. data/tools/common/common/test/unittest_xmlutils.py +0 -75
  142. data/tools/common/common/test/utils.py +0 -87
  143. data/tools/common/common/testlib.py +0 -1927
  144. data/tools/common/common/textutils.py +0 -476
  145. data/tools/common/common/tree.py +0 -372
  146. data/tools/common/common/umessage.py +0 -161
  147. data/tools/common/common/ureports/__init__.py +0 -174
  148. data/tools/common/common/ureports/docbook_writer.py +0 -139
  149. data/tools/common/common/ureports/html_writer.py +0 -131
  150. data/tools/common/common/ureports/nodes.py +0 -201
  151. data/tools/common/common/ureports/text_writer.py +0 -140
  152. data/tools/common/common/vcgutils.py +0 -216
  153. data/tools/common/common/visitor.py +0 -107
  154. data/tools/common/common/xmlrpcutils.py +0 -136
  155. data/tools/common/common/xmlutils.py +0 -61
  156. data/tools/coverage/coverage.py +0 -602
  157. data/tools/epydoc/__init__.py +0 -227
  158. data/tools/epydoc/__init__.pyc +0 -0
  159. data/tools/epydoc/apidoc.py +0 -2203
  160. data/tools/epydoc/apidoc.pyc +0 -0
  161. data/tools/epydoc/checker.py +0 -349
  162. data/tools/epydoc/checker.pyc +0 -0
  163. data/tools/epydoc/cli.py +0 -1470
  164. data/tools/epydoc/cli.pyc +0 -0
  165. data/tools/epydoc/compat.py +0 -250
  166. data/tools/epydoc/compat.pyc +0 -0
  167. data/tools/epydoc/docbuilder.py +0 -1358
  168. data/tools/epydoc/docbuilder.pyc +0 -0
  169. data/tools/epydoc/docintrospecter.py +0 -1056
  170. data/tools/epydoc/docintrospecter.pyc +0 -0
  171. data/tools/epydoc/docparser.py +0 -2113
  172. data/tools/epydoc/docparser.pyc +0 -0
  173. data/tools/epydoc/docstringparser.py +0 -1111
  174. data/tools/epydoc/docstringparser.pyc +0 -0
  175. data/tools/epydoc/docwriter/__init__.py +0 -12
  176. data/tools/epydoc/docwriter/__init__.pyc +0 -0
  177. data/tools/epydoc/docwriter/dotgraph.py +0 -1351
  178. data/tools/epydoc/docwriter/dotgraph.pyc +0 -0
  179. data/tools/epydoc/docwriter/html.py +0 -3491
  180. data/tools/epydoc/docwriter/html.pyc +0 -0
  181. data/tools/epydoc/docwriter/html_colorize.py +0 -909
  182. data/tools/epydoc/docwriter/html_colorize.pyc +0 -0
  183. data/tools/epydoc/docwriter/html_css.py +0 -550
  184. data/tools/epydoc/docwriter/html_css.pyc +0 -0
  185. data/tools/epydoc/docwriter/html_help.py +0 -190
  186. data/tools/epydoc/docwriter/html_help.pyc +0 -0
  187. data/tools/epydoc/docwriter/latex.py +0 -1187
  188. data/tools/epydoc/docwriter/latex.pyc +0 -0
  189. data/tools/epydoc/docwriter/plaintext.py +0 -276
  190. data/tools/epydoc/docwriter/plaintext.pyc +0 -0
  191. data/tools/epydoc/docwriter/xlink.py +0 -505
  192. data/tools/epydoc/docwriter/xlink.pyc +0 -0
  193. data/tools/epydoc/gui.py +0 -1148
  194. data/tools/epydoc/gui.pyc +0 -0
  195. data/tools/epydoc/log.py +0 -204
  196. data/tools/epydoc/log.pyc +0 -0
  197. data/tools/epydoc/markup/__init__.py +0 -623
  198. data/tools/epydoc/markup/__init__.pyc +0 -0
  199. data/tools/epydoc/markup/doctest.py +0 -311
  200. data/tools/epydoc/markup/doctest.pyc +0 -0
  201. data/tools/epydoc/markup/epytext.py +0 -2116
  202. data/tools/epydoc/markup/epytext.pyc +0 -0
  203. data/tools/epydoc/markup/javadoc.py +0 -250
  204. data/tools/epydoc/markup/javadoc.pyc +0 -0
  205. data/tools/epydoc/markup/plaintext.py +0 -78
  206. data/tools/epydoc/markup/plaintext.pyc +0 -0
  207. data/tools/epydoc/markup/pyval_repr.py +0 -532
  208. data/tools/epydoc/markup/pyval_repr.pyc +0 -0
  209. data/tools/epydoc/markup/restructuredtext.py +0 -906
  210. data/tools/epydoc/markup/restructuredtext.pyc +0 -0
  211. data/tools/epydoc/test/__init__.py +0 -97
  212. data/tools/epydoc/test/__init__.pyc +0 -0
  213. data/tools/epydoc/test/util.py +0 -226
  214. data/tools/epydoc/test/util.pyc +0 -0
  215. data/tools/epydoc/util.py +0 -289
  216. data/tools/epydoc/util.pyc +0 -0
  217. data/tools/logilab/logilab/__init__.py +0 -5
  218. data/tools/logilab/logilab/astng/__init__.py +0 -82
  219. data/tools/logilab/logilab/astng/__pkginfo__.py +0 -76
  220. data/tools/logilab/logilab/astng/_exceptions.py +0 -64
  221. data/tools/logilab/logilab/astng/_nodes_ast.py +0 -667
  222. data/tools/logilab/logilab/astng/_nodes_compiler.py +0 -758
  223. data/tools/logilab/logilab/astng/bases.py +0 -608
  224. data/tools/logilab/logilab/astng/builder.py +0 -239
  225. data/tools/logilab/logilab/astng/inference.py +0 -426
  226. data/tools/logilab/logilab/astng/inspector.py +0 -289
  227. data/tools/logilab/logilab/astng/manager.py +0 -421
  228. data/tools/logilab/logilab/astng/mixins.py +0 -165
  229. data/tools/logilab/logilab/astng/node_classes.py +0 -848
  230. data/tools/logilab/logilab/astng/nodes.py +0 -85
  231. data/tools/logilab/logilab/astng/nodes_as_string.py +0 -389
  232. data/tools/logilab/logilab/astng/patchcomptransformer.py +0 -159
  233. data/tools/logilab/logilab/astng/protocols.py +0 -333
  234. data/tools/logilab/logilab/astng/raw_building.py +0 -212
  235. data/tools/logilab/logilab/astng/rebuilder.py +0 -307
  236. data/tools/logilab/logilab/astng/scoped_nodes.py +0 -951
  237. data/tools/logilab/logilab/astng/test/__init__.py +0 -19
  238. data/tools/logilab/logilab/astng/test/data/MyPyPa-0.1.0-py2.5.egg +0 -0
  239. data/tools/logilab/logilab/astng/test/data/MyPyPa-0.1.0-py2.5.zip +0 -0
  240. data/tools/logilab/logilab/astng/test/data/SSL1/Connection1.py +0 -33
  241. data/tools/logilab/logilab/astng/test/data/SSL1/__init__.py +0 -20
  242. data/tools/logilab/logilab/astng/test/data/__init__.py +0 -20
  243. data/tools/logilab/logilab/astng/test/data/all.py +0 -29
  244. data/tools/logilab/logilab/astng/test/data/appl/__init__.py +0 -23
  245. data/tools/logilab/logilab/astng/test/data/appl/myConnection.py +0 -30
  246. data/tools/logilab/logilab/astng/test/data/format.py +0 -34
  247. data/tools/logilab/logilab/astng/test/data/module.py +0 -90
  248. data/tools/logilab/logilab/astng/test/data/module2.py +0 -112
  249. data/tools/logilab/logilab/astng/test/data/noendingnewline.py +0 -57
  250. data/tools/logilab/logilab/astng/test/data/nonregr.py +0 -76
  251. data/tools/logilab/logilab/astng/test/data/notall.py +0 -28
  252. data/tools/logilab/logilab/astng/test/data2/__init__.py +0 -20
  253. data/tools/logilab/logilab/astng/test/data2/clientmodule_test.py +0 -51
  254. data/tools/logilab/logilab/astng/test/data2/suppliermodule_test.py +0 -32
  255. data/tools/logilab/logilab/astng/test/regrtest.py +0 -135
  256. data/tools/logilab/logilab/astng/test/regrtest_data/absimport.py +0 -22
  257. data/tools/logilab/logilab/astng/test/regrtest_data/descriptor_crash.py +0 -31
  258. data/tools/logilab/logilab/astng/test/regrtest_data/import_package_subpackage_module.py +0 -68
  259. data/tools/logilab/logilab/astng/test/regrtest_data/package/__init__.py +0 -24
  260. data/tools/logilab/logilab/astng/test/regrtest_data/package/subpackage/__init__.py +0 -20
  261. data/tools/logilab/logilab/astng/test/regrtest_data/package/subpackage/module.py +0 -20
  262. data/tools/logilab/logilab/astng/test/unittest_builder.py +0 -684
  263. data/tools/logilab/logilab/astng/test/unittest_inference.py +0 -1112
  264. data/tools/logilab/logilab/astng/test/unittest_inspector.py +0 -105
  265. data/tools/logilab/logilab/astng/test/unittest_lookup.py +0 -302
  266. data/tools/logilab/logilab/astng/test/unittest_manager.py +0 -98
  267. data/tools/logilab/logilab/astng/test/unittest_nodes.py +0 -302
  268. data/tools/logilab/logilab/astng/test/unittest_scoped_nodes.py +0 -501
  269. data/tools/logilab/logilab/astng/test/unittest_utils.py +0 -104
  270. data/tools/logilab/logilab/astng/utils.py +0 -342
  271. data/tools/logilab/logilab/common/__init__.py +0 -140
  272. data/tools/logilab/logilab/common/__pkginfo__.py +0 -43
  273. data/tools/logilab/logilab/common/adbh.py +0 -35
  274. data/tools/logilab/logilab/common/cache.py +0 -114
  275. data/tools/logilab/logilab/common/changelog.py +0 -234
  276. data/tools/logilab/logilab/common/clcommands.py +0 -181
  277. data/tools/logilab/logilab/common/cli.py +0 -212
  278. data/tools/logilab/logilab/common/compat.py +0 -328
  279. data/tools/logilab/logilab/common/configuration.py +0 -1087
  280. data/tools/logilab/logilab/common/contexts.py +0 -58
  281. data/tools/logilab/logilab/common/corbautils.py +0 -117
  282. data/tools/logilab/logilab/common/daemon.py +0 -171
  283. data/tools/logilab/logilab/common/date.py +0 -279
  284. data/tools/logilab/logilab/common/db.py +0 -49
  285. data/tools/logilab/logilab/common/dbf.py +0 -229
  286. data/tools/logilab/logilab/common/debugger.py +0 -208
  287. data/tools/logilab/logilab/common/decorators.py +0 -190
  288. data/tools/logilab/logilab/common/deprecation.py +0 -118
  289. data/tools/logilab/logilab/common/fileutils.py +0 -409
  290. data/tools/logilab/logilab/common/graph.py +0 -259
  291. data/tools/logilab/logilab/common/html.py +0 -142
  292. data/tools/logilab/logilab/common/interface.py +0 -76
  293. data/tools/logilab/logilab/common/logging_ext.py +0 -166
  294. data/tools/logilab/logilab/common/modutils.py +0 -670
  295. data/tools/logilab/logilab/common/optik_ext.py +0 -383
  296. data/tools/logilab/logilab/common/optparser.py +0 -92
  297. data/tools/logilab/logilab/common/pdf_ext.py +0 -111
  298. data/tools/logilab/logilab/common/proc.py +0 -276
  299. data/tools/logilab/logilab/common/pyro_ext.py +0 -146
  300. data/tools/logilab/logilab/common/pytest.py +0 -754
  301. data/tools/logilab/logilab/common/shellutils.py +0 -383
  302. data/tools/logilab/logilab/common/sphinx_ext.py +0 -87
  303. data/tools/logilab/logilab/common/sphinxutils.py +0 -122
  304. data/tools/logilab/logilab/common/sqlgen.py +0 -31
  305. data/tools/logilab/logilab/common/table.py +0 -930
  306. data/tools/logilab/logilab/common/tasksqueue.py +0 -97
  307. data/tools/logilab/logilab/common/test/__init__.py +0 -1
  308. data/tools/logilab/logilab/common/test/data/ChangeLog +0 -184
  309. data/tools/logilab/logilab/common/test/data/MyPyPa-0.1.0-py2.5.egg +0 -0
  310. data/tools/logilab/logilab/common/test/data/__init__.py +0 -1
  311. data/tools/logilab/logilab/common/test/data/content_differ_dir/NOTHING +0 -0
  312. data/tools/logilab/logilab/common/test/data/content_differ_dir/README +0 -1
  313. data/tools/logilab/logilab/common/test/data/content_differ_dir/subdir/coin +0 -1
  314. data/tools/logilab/logilab/common/test/data/content_differ_dir/subdir/toto.txt +0 -53
  315. data/tools/logilab/logilab/common/test/data/file_differ_dir/NOTHING +0 -0
  316. data/tools/logilab/logilab/common/test/data/file_differ_dir/README +0 -1
  317. data/tools/logilab/logilab/common/test/data/file_differ_dir/subdir/toto.txt +0 -53
  318. data/tools/logilab/logilab/common/test/data/file_differ_dir/subdirtwo/Hello +0 -0
  319. data/tools/logilab/logilab/common/test/data/find_test/__init__.py +0 -0
  320. data/tools/logilab/logilab/common/test/data/find_test/foo.txt +0 -0
  321. data/tools/logilab/logilab/common/test/data/find_test/module.py +0 -0
  322. data/tools/logilab/logilab/common/test/data/find_test/module2.py +0 -0
  323. data/tools/logilab/logilab/common/test/data/find_test/newlines.txt +0 -0
  324. data/tools/logilab/logilab/common/test/data/find_test/noendingnewline.py +0 -0
  325. data/tools/logilab/logilab/common/test/data/find_test/nonregr.py +0 -0
  326. data/tools/logilab/logilab/common/test/data/find_test/normal_file.txt +0 -0
  327. data/tools/logilab/logilab/common/test/data/find_test/spam.txt +0 -0
  328. data/tools/logilab/logilab/common/test/data/find_test/sub/doc.txt +0 -0
  329. data/tools/logilab/logilab/common/test/data/find_test/sub/momo.py +0 -0
  330. data/tools/logilab/logilab/common/test/data/find_test/test.ini +0 -0
  331. data/tools/logilab/logilab/common/test/data/find_test/test1.msg +0 -0
  332. data/tools/logilab/logilab/common/test/data/find_test/test2.msg +0 -0
  333. data/tools/logilab/logilab/common/test/data/find_test/write_protected_file.txt +0 -0
  334. data/tools/logilab/logilab/common/test/data/foo.txt +0 -9
  335. data/tools/logilab/logilab/common/test/data/module.py +0 -88
  336. data/tools/logilab/logilab/common/test/data/module2.py +0 -77
  337. data/tools/logilab/logilab/common/test/data/newlines.txt +0 -3
  338. data/tools/logilab/logilab/common/test/data/noendingnewline.py +0 -36
  339. data/tools/logilab/logilab/common/test/data/nonregr.py +0 -14
  340. data/tools/logilab/logilab/common/test/data/normal_file.txt +0 -0
  341. data/tools/logilab/logilab/common/test/data/reference_dir/NOTHING +0 -0
  342. data/tools/logilab/logilab/common/test/data/reference_dir/README +0 -1
  343. data/tools/logilab/logilab/common/test/data/reference_dir/subdir/coin +0 -1
  344. data/tools/logilab/logilab/common/test/data/reference_dir/subdir/toto.txt +0 -53
  345. data/tools/logilab/logilab/common/test/data/same_dir/NOTHING +0 -0
  346. data/tools/logilab/logilab/common/test/data/same_dir/README +0 -1
  347. data/tools/logilab/logilab/common/test/data/same_dir/subdir/coin +0 -1
  348. data/tools/logilab/logilab/common/test/data/same_dir/subdir/toto.txt +0 -53
  349. data/tools/logilab/logilab/common/test/data/spam.txt +0 -9
  350. data/tools/logilab/logilab/common/test/data/sub/doc.txt +0 -1
  351. data/tools/logilab/logilab/common/test/data/sub/momo.py +0 -1
  352. data/tools/logilab/logilab/common/test/data/subdir_differ_dir/NOTHING +0 -0
  353. data/tools/logilab/logilab/common/test/data/subdir_differ_dir/README +0 -1
  354. data/tools/logilab/logilab/common/test/data/subdir_differ_dir/subdir/coin +0 -1
  355. data/tools/logilab/logilab/common/test/data/subdir_differ_dir/subdir/toto.txt +0 -53
  356. data/tools/logilab/logilab/common/test/data/test.ini +0 -20
  357. data/tools/logilab/logilab/common/test/data/test1.msg +0 -30
  358. data/tools/logilab/logilab/common/test/data/test2.msg +0 -42
  359. data/tools/logilab/logilab/common/test/data/write_protected_file.txt +0 -0
  360. data/tools/logilab/logilab/common/test/foomod.py +0 -17
  361. data/tools/logilab/logilab/common/test/unittest_cache.py +0 -129
  362. data/tools/logilab/logilab/common/test/unittest_changelog.py +0 -37
  363. data/tools/logilab/logilab/common/test/unittest_compat.py +0 -239
  364. data/tools/logilab/logilab/common/test/unittest_configuration.py +0 -348
  365. data/tools/logilab/logilab/common/test/unittest_date.py +0 -154
  366. data/tools/logilab/logilab/common/test/unittest_decorators.py +0 -62
  367. data/tools/logilab/logilab/common/test/unittest_deprecation.py +0 -76
  368. data/tools/logilab/logilab/common/test/unittest_fileutils.py +0 -133
  369. data/tools/logilab/logilab/common/test/unittest_graph.py +0 -50
  370. data/tools/logilab/logilab/common/test/unittest_html.py +0 -76
  371. data/tools/logilab/logilab/common/test/unittest_interface.py +0 -87
  372. data/tools/logilab/logilab/common/test/unittest_modutils.py +0 -244
  373. data/tools/logilab/logilab/common/test/unittest_pytest.py +0 -50
  374. data/tools/logilab/logilab/common/test/unittest_shellutils.py +0 -248
  375. data/tools/logilab/logilab/common/test/unittest_table.py +0 -448
  376. data/tools/logilab/logilab/common/test/unittest_taskqueue.py +0 -71
  377. data/tools/logilab/logilab/common/test/unittest_testlib.py +0 -956
  378. data/tools/logilab/logilab/common/test/unittest_textutils.py +0 -247
  379. data/tools/logilab/logilab/common/test/unittest_tree.py +0 -248
  380. data/tools/logilab/logilab/common/test/unittest_umessage.py +0 -55
  381. data/tools/logilab/logilab/common/test/unittest_ureports_html.py +0 -64
  382. data/tools/logilab/logilab/common/test/unittest_ureports_text.py +0 -105
  383. data/tools/logilab/logilab/common/test/unittest_xmlutils.py +0 -75
  384. data/tools/logilab/logilab/common/test/utils.py +0 -87
  385. data/tools/logilab/logilab/common/testlib.py +0 -1927
  386. data/tools/logilab/logilab/common/textutils.py +0 -476
  387. data/tools/logilab/logilab/common/tree.py +0 -372
  388. data/tools/logilab/logilab/common/umessage.py +0 -161
  389. data/tools/logilab/logilab/common/ureports/__init__.py +0 -174
  390. data/tools/logilab/logilab/common/ureports/docbook_writer.py +0 -139
  391. data/tools/logilab/logilab/common/ureports/html_writer.py +0 -131
  392. data/tools/logilab/logilab/common/ureports/nodes.py +0 -201
  393. data/tools/logilab/logilab/common/ureports/text_writer.py +0 -140
  394. data/tools/logilab/logilab/common/vcgutils.py +0 -216
  395. data/tools/logilab/logilab/common/visitor.py +0 -107
  396. data/tools/logilab/logilab/common/xmlrpcutils.py +0 -136
  397. data/tools/logilab/logilab/common/xmlutils.py +0 -61
  398. data/tools/pychecker/COPYRIGHT +0 -31
  399. data/tools/pychecker/ChangeLog +0 -349
  400. data/tools/pychecker/CodeChecks.py +0 -1969
  401. data/tools/pychecker/CodeChecks.pyc +0 -0
  402. data/tools/pychecker/CodeChecks.pyo +0 -0
  403. data/tools/pychecker/Config.py +0 -475
  404. data/tools/pychecker/Config.pyc +0 -0
  405. data/tools/pychecker/Config.pyo +0 -0
  406. data/tools/pychecker/KNOWN_BUGS +0 -100
  407. data/tools/pychecker/MAINTAINERS +0 -81
  408. data/tools/pychecker/NEWS +0 -406
  409. data/tools/pychecker/OP.py +0 -131
  410. data/tools/pychecker/OP.pyc +0 -0
  411. data/tools/pychecker/OP.pyo +0 -0
  412. data/tools/pychecker/OptionTypes.py +0 -117
  413. data/tools/pychecker/OptionTypes.pyc +0 -0
  414. data/tools/pychecker/OptionTypes.pyo +0 -0
  415. data/tools/pychecker/README +0 -152
  416. data/tools/pychecker/Stack.py +0 -115
  417. data/tools/pychecker/Stack.pyc +0 -0
  418. data/tools/pychecker/Stack.pyo +0 -0
  419. data/tools/pychecker/TODO +0 -101
  420. data/tools/pychecker/VERSION +0 -1
  421. data/tools/pychecker/Warning.py +0 -50
  422. data/tools/pychecker/Warning.pyc +0 -0
  423. data/tools/pychecker/Warning.pyo +0 -0
  424. data/tools/pychecker/__init__.py +0 -17
  425. data/tools/pychecker/__init__.pyc +0 -0
  426. data/tools/pychecker/__init__.pyo +0 -0
  427. data/tools/pychecker/checker.py +0 -961
  428. data/tools/pychecker/checker.pyc +0 -0
  429. data/tools/pychecker/checker.pyo +0 -0
  430. data/tools/pychecker/function.py +0 -159
  431. data/tools/pychecker/function.pyc +0 -0
  432. data/tools/pychecker/function.pyo +0 -0
  433. data/tools/pychecker/msgs.py +0 -175
  434. data/tools/pychecker/msgs.pyc +0 -0
  435. data/tools/pychecker/msgs.pyo +0 -0
  436. data/tools/pychecker/options.py +0 -275
  437. data/tools/pychecker/options.pyc +0 -0
  438. data/tools/pychecker/options.pyo +0 -0
  439. data/tools/pychecker/pcmodules.py +0 -19
  440. data/tools/pychecker/pcmodules.pyc +0 -0
  441. data/tools/pychecker/pcmodules.pyo +0 -0
  442. data/tools/pychecker/printer.py +0 -47
  443. data/tools/pychecker/printer.pyc +0 -0
  444. data/tools/pychecker/printer.pyo +0 -0
  445. data/tools/pychecker/python.py +0 -427
  446. data/tools/pychecker/python.pyc +0 -0
  447. data/tools/pychecker/python.pyo +0 -0
  448. data/tools/pychecker/utils.py +0 -102
  449. data/tools/pychecker/utils.pyc +0 -0
  450. data/tools/pychecker/utils.pyo +0 -0
  451. data/tools/pychecker/warn.py +0 -778
  452. data/tools/pychecker/warn.pyc +0 -0
  453. data/tools/pychecker/warn.pyo +0 -0
  454. data/tools/pylint2/pylint/__init__.py +0 -16
  455. data/tools/pylint2/pylint/__pkginfo__.py +0 -67
  456. data/tools/pylint2/pylint/checkers/__init__.py +0 -155
  457. data/tools/pylint2/pylint/checkers/base.py +0 -749
  458. data/tools/pylint2/pylint/checkers/classes.py +0 -527
  459. data/tools/pylint2/pylint/checkers/design_analysis.py +0 -344
  460. data/tools/pylint2/pylint/checkers/exceptions.py +0 -183
  461. data/tools/pylint2/pylint/checkers/format.py +0 -367
  462. data/tools/pylint2/pylint/checkers/imports.py +0 -379
  463. data/tools/pylint2/pylint/checkers/logging.py +0 -98
  464. data/tools/pylint2/pylint/checkers/misc.py +0 -128
  465. data/tools/pylint2/pylint/checkers/newstyle.py +0 -107
  466. data/tools/pylint2/pylint/checkers/raw_metrics.py +0 -125
  467. data/tools/pylint2/pylint/checkers/similar.py +0 -333
  468. data/tools/pylint2/pylint/checkers/string_format.py +0 -239
  469. data/tools/pylint2/pylint/checkers/typecheck.py +0 -364
  470. data/tools/pylint2/pylint/checkers/utils.py +0 -208
  471. data/tools/pylint2/pylint/checkers/variables.py +0 -498
  472. data/tools/pylint2/pylint/config.py +0 -149
  473. data/tools/pylint2/pylint/epylint.py +0 -149
  474. data/tools/pylint2/pylint/gui.py +0 -433
  475. data/tools/pylint2/pylint/interfaces.py +0 -98
  476. data/tools/pylint2/pylint/lint.py +0 -914
  477. data/tools/pylint2/pylint/pyreverse/__init__.py +0 -5
  478. data/tools/pylint2/pylint/pyreverse/diadefslib.py +0 -229
  479. data/tools/pylint2/pylint/pyreverse/diagrams.py +0 -247
  480. data/tools/pylint2/pylint/pyreverse/main.py +0 -123
  481. data/tools/pylint2/pylint/pyreverse/utils.py +0 -131
  482. data/tools/pylint2/pylint/pyreverse/writer.py +0 -196
  483. data/tools/pylint2/pylint/reporters/__init__.py +0 -67
  484. data/tools/pylint2/pylint/reporters/guireporter.py +0 -36
  485. data/tools/pylint2/pylint/reporters/html.py +0 -69
  486. data/tools/pylint2/pylint/reporters/text.py +0 -156
  487. data/tools/pylint2/pylint/utils.py +0 -518
  488. data/tools/pylint2/pylint.py +0 -16
@@ -1,1351 +0,0 @@
1
- # epydoc -- Graph generation
2
- #
3
- # Copyright (C) 2005 Edward Loper
4
- # Author: Edward Loper <edloper@loper.org>
5
- # URL: <http://epydoc.sf.net>
6
- #
7
- # $Id: dotgraph.py,v 1.1 2009/11/26 13:20:43 casa Exp $
8
-
9
- """
10
- Render Graphviz directed graphs as images. Below are some examples.
11
-
12
- .. importgraph::
13
-
14
- .. classtree:: epydoc.apidoc.APIDoc
15
-
16
- .. packagetree:: epydoc
17
-
18
- :see: `The Graphviz Homepage
19
- <http://www.research.att.com/sw/tools/graphviz/>`__
20
- """
21
- __docformat__ = 'restructuredtext'
22
-
23
- import re
24
- import sys
25
- from epydoc import log
26
- from epydoc.apidoc import *
27
- from epydoc.util import *
28
- from epydoc.compat import * # Backwards compatibility
29
-
30
- # colors for graphs of APIDocs
31
- MODULE_BG = '#d8e8ff'
32
- CLASS_BG = '#d8ffe8'
33
- SELECTED_BG = '#ffd0d0'
34
- BASECLASS_BG = '#e0b0a0'
35
- SUBCLASS_BG = '#e0b0a0'
36
- ROUTINE_BG = '#e8d0b0' # maybe?
37
- INH_LINK_COLOR = '#800000'
38
-
39
- ######################################################################
40
- #{ Dot Graphs
41
- ######################################################################
42
-
43
- DOT_COMMAND = 'dot'
44
- """The command that should be used to spawn dot"""
45
-
46
- class DotGraph:
47
- """
48
- A ``dot`` directed graph. The contents of the graph are
49
- constructed from the following instance variables:
50
-
51
- - `nodes`: A list of `DotGraphNode`\\s, encoding the nodes
52
- that are present in the graph. Each node is characterized
53
- a set of attributes, including an optional label.
54
- - `edges`: A list of `DotGraphEdge`\\s, encoding the edges
55
- that are present in the graph. Each edge is characterized
56
- by a set of attributes, including an optional label.
57
- - `node_defaults`: Default attributes for nodes.
58
- - `edge_defaults`: Default attributes for edges.
59
- - `body`: A string that is appended as-is in the body of
60
- the graph. This can be used to build more complex dot
61
- graphs.
62
-
63
- The `link()` method can be used to resolve crossreference links
64
- within the graph. In particular, if the 'href' attribute of any
65
- node or edge is assigned a value of the form ``<name>``, then it
66
- will be replaced by the URL of the object with that name. This
67
- applies to the `body` as well as the `nodes` and `edges`.
68
-
69
- To render the graph, use the methods `write()` and `render()`.
70
- Usually, you should call `link()` before you render the graph.
71
- """
72
- _uids = set()
73
- """A set of all uids that that have been generated, used to ensure
74
- that each new graph has a unique uid."""
75
-
76
- DEFAULT_NODE_DEFAULTS={'fontsize':10, 'fontname': 'Helvetica'}
77
- DEFAULT_EDGE_DEFAULTS={'fontsize':10, 'fontname': 'Helvetica'}
78
-
79
- def __init__(self, title, body='', node_defaults=None,
80
- edge_defaults=None, caption=None):
81
- """
82
- Create a new `DotGraph`.
83
- """
84
- self.title = title
85
- """The title of the graph."""
86
-
87
- self.caption = caption
88
- """A caption for the graph."""
89
-
90
- self.nodes = []
91
- """A list of the nodes that are present in the graph.
92
-
93
- :type: ``list`` of `DotGraphNode`"""
94
-
95
- self.edges = []
96
- """A list of the edges that are present in the graph.
97
-
98
- :type: ``list`` of `DotGraphEdge`"""
99
-
100
- self.body = body
101
- """A string that should be included as-is in the body of the
102
- graph.
103
-
104
- :type: ``str``"""
105
-
106
- self.node_defaults = node_defaults or self.DEFAULT_NODE_DEFAULTS
107
- """Default attribute values for nodes."""
108
-
109
- self.edge_defaults = edge_defaults or self.DEFAULT_EDGE_DEFAULTS
110
- """Default attribute values for edges."""
111
-
112
- self.uid = re.sub(r'\W', '_', title).lower()
113
- """A unique identifier for this graph. This can be used as a
114
- filename when rendering the graph. No two `DotGraph`\s will
115
- have the same uid."""
116
-
117
- # Encode the title, if necessary.
118
- if isinstance(self.title, unicode):
119
- self.title = self.title.encode('ascii', 'xmlcharrefreplace')
120
-
121
- # Make sure the UID isn't too long.
122
- self.uid = self.uid[:30]
123
-
124
- # Make sure the UID is unique
125
- if self.uid in self._uids:
126
- n = 2
127
- while ('%s_%s' % (self.uid, n)) in self._uids: n += 1
128
- self.uid = '%s_%s' % (self.uid, n)
129
- self._uids.add(self.uid)
130
-
131
- def to_html(self, image_file, image_url, center=True):
132
- """
133
- Return the HTML code that should be uesd to display this graph
134
- (including a client-side image map).
135
-
136
- :param image_url: The URL of the image file for this graph;
137
- this should be generated separately with the `write()` method.
138
- """
139
- # If dotversion >1.8.10, then we can generate the image and
140
- # the cmapx with a single call to dot. Otherwise, we need to
141
- # run dot twice.
142
- if get_dot_version() > [1,8,10]:
143
- cmapx = self._run_dot('-Tgif', '-o%s' % image_file, '-Tcmapx')
144
- if cmapx is None: return '' # failed to render
145
- else:
146
- if not self.write(image_file):
147
- return '' # failed to render
148
- cmapx = self.render('cmapx') or ''
149
-
150
- # Decode the cmapx (dot uses utf-8)
151
- try:
152
- cmapx = cmapx.decode('utf-8')
153
- except UnicodeDecodeError:
154
- log.debug('%s: unable to decode cmapx from dot; graph will '
155
- 'not have clickable regions' % image_file)
156
- cmapx = ''
157
-
158
- title = plaintext_to_html(self.title or '')
159
- caption = plaintext_to_html(self.caption or '')
160
- if title or caption:
161
- css_class = 'graph-with-title'
162
- else:
163
- css_class = 'graph-without-title'
164
- if len(title)+len(caption) > 80:
165
- title_align = 'left'
166
- table_width = ' width="600"'
167
- else:
168
- title_align = 'center'
169
- table_width = ''
170
-
171
- if center: s = '<center>'
172
- if title or caption:
173
- s += ('<table border="0" cellpadding="0" cellspacing="0" '
174
- 'class="graph"%s>\n <tr><td align="center">\n' %
175
- table_width)
176
- s += (' %s\n <img src="%s" alt=%r usemap="#%s" '
177
- 'ismap="ismap" class="%s" />\n' %
178
- (cmapx.strip(), image_url, title, self.uid, css_class))
179
- if title or caption:
180
- s += ' </td></tr>\n <tr><td align=%r>\n' % title_align
181
- if title:
182
- s += '<span class="graph-title">%s</span>' % title
183
- if title and caption:
184
- s += ' -- '
185
- if caption:
186
- s += '<span class="graph-caption">%s</span>' % caption
187
- s += '\n </td></tr>\n</table><br />'
188
- if center: s += '</center>'
189
- return s
190
-
191
- def link(self, docstring_linker):
192
- """
193
- Replace any href attributes whose value is ``<name>`` with
194
- the url of the object whose name is ``<name>``.
195
- """
196
- # Link xrefs in nodes
197
- self._link_href(self.node_defaults, docstring_linker)
198
- for node in self.nodes:
199
- self._link_href(node.attribs, docstring_linker)
200
-
201
- # Link xrefs in edges
202
- self._link_href(self.edge_defaults, docstring_linker)
203
- for edge in self.nodes:
204
- self._link_href(edge.attribs, docstring_linker)
205
-
206
- # Link xrefs in body
207
- def subfunc(m):
208
- url = docstring_linker.url_for(m.group(1))
209
- if url: return 'href="%s"%s' % (url, m.group(2))
210
- else: return ''
211
- self.body = re.sub("href\s*=\s*['\"]?<([\w\.]+)>['\"]?\s*(,?)",
212
- subfunc, self.body)
213
-
214
- def _link_href(self, attribs, docstring_linker):
215
- """Helper for `link()`"""
216
- if 'href' in attribs:
217
- m = re.match(r'^<([\w\.]+)>$', attribs['href'])
218
- if m:
219
- url = docstring_linker.url_for(m.group(1))
220
- if url: attribs['href'] = url
221
- else: del attribs['href']
222
-
223
- def write(self, filename, language='gif'):
224
- """
225
- Render the graph using the output format `language`, and write
226
- the result to `filename`.
227
-
228
- :return: True if rendering was successful.
229
- """
230
- result = self._run_dot('-T%s' % language,
231
- '-o%s' % filename)
232
- # Decode into unicode, if necessary.
233
- if language == 'cmapx' and result is not None:
234
- result = result.decode('utf-8')
235
- return (result is not None)
236
-
237
- def render(self, language='gif'):
238
- """
239
- Use the ``dot`` command to render this graph, using the output
240
- format `language`. Return the result as a string, or ``None``
241
- if the rendering failed.
242
- """
243
- return self._run_dot('-T%s' % language)
244
-
245
- def _run_dot(self, *options):
246
- try:
247
- result, err = run_subprocess((DOT_COMMAND,)+options,
248
- self.to_dotfile())
249
- if err: log.warning("Graphviz dot warning(s):\n%s" % err)
250
- except OSError, e:
251
- log.warning("Unable to render Graphviz dot graph:\n%s" % e)
252
- #log.debug(self.to_dotfile())
253
- return None
254
-
255
- return result
256
-
257
- def to_dotfile(self):
258
- """
259
- Return the string contents of the dot file that should be used
260
- to render this graph.
261
- """
262
- lines = ['digraph %s {' % self.uid,
263
- 'node [%s]' % ','.join(['%s="%s"' % (k,v) for (k,v)
264
- in self.node_defaults.items()]),
265
- 'edge [%s]' % ','.join(['%s="%s"' % (k,v) for (k,v)
266
- in self.edge_defaults.items()])]
267
- if self.body:
268
- lines.append(self.body)
269
- lines.append('/* Nodes */')
270
- for node in self.nodes:
271
- lines.append(node.to_dotfile())
272
- lines.append('/* Edges */')
273
- for edge in self.edges:
274
- lines.append(edge.to_dotfile())
275
- lines.append('}')
276
-
277
- # Default dot input encoding is UTF-8
278
- return u'\n'.join(lines).encode('utf-8')
279
-
280
- class DotGraphNode:
281
- _next_id = 0
282
- def __init__(self, label=None, html_label=None, **attribs):
283
- if label is not None and html_label is not None:
284
- raise ValueError('Use label or html_label, not both.')
285
- if label is not None: attribs['label'] = label
286
- self._html_label = html_label
287
- self._attribs = attribs
288
- self.id = self.__class__._next_id
289
- self.__class__._next_id += 1
290
- self.port = None
291
-
292
- def __getitem__(self, attr):
293
- return self._attribs[attr]
294
-
295
- def __setitem__(self, attr, val):
296
- if attr == 'html_label':
297
- self._attribs.pop('label')
298
- self._html_label = val
299
- else:
300
- if attr == 'label': self._html_label = None
301
- self._attribs[attr] = val
302
-
303
- def to_dotfile(self):
304
- """
305
- Return the dot commands that should be used to render this node.
306
- """
307
- attribs = ['%s="%s"' % (k,v) for (k,v) in self._attribs.items()
308
- if v is not None]
309
- if self._html_label:
310
- attribs.insert(0, 'label=<%s>' % (self._html_label,))
311
- if attribs: attribs = ' [%s]' % (','.join(attribs))
312
- return 'node%d%s' % (self.id, attribs)
313
-
314
- class DotGraphEdge:
315
- def __init__(self, start, end, label=None, **attribs):
316
- """
317
- :type start: `DotGraphNode`
318
- :type end: `DotGraphNode`
319
- """
320
- assert isinstance(start, DotGraphNode)
321
- assert isinstance(end, DotGraphNode)
322
- if label is not None: attribs['label'] = label
323
- self.start = start #: :type: `DotGraphNode`
324
- self.end = end #: :type: `DotGraphNode`
325
- self._attribs = attribs
326
-
327
- def __getitem__(self, attr):
328
- return self._attribs[attr]
329
-
330
- def __setitem__(self, attr, val):
331
- self._attribs[attr] = val
332
-
333
- def to_dotfile(self):
334
- """
335
- Return the dot commands that should be used to render this edge.
336
- """
337
- # Set head & tail ports, if the nodes have preferred ports.
338
- attribs = self._attribs.copy()
339
- if (self.start.port is not None and 'headport' not in attribs):
340
- attribs['headport'] = self.start.port
341
- if (self.end.port is not None and 'tailport' not in attribs):
342
- attribs['tailport'] = self.end.port
343
- # Convert attribs to a string
344
- attribs = ','.join(['%s="%s"' % (k,v) for (k,v) in attribs.items()
345
- if v is not None])
346
- if attribs: attribs = ' [%s]' % attribs
347
- # Return the dotfile edge.
348
- return 'node%d -> node%d%s' % (self.start.id, self.end.id, attribs)
349
-
350
- ######################################################################
351
- #{ Specialized Nodes for UML Graphs
352
- ######################################################################
353
-
354
- class DotGraphUmlClassNode(DotGraphNode):
355
- """
356
- A specialized dot graph node used to display `ClassDoc`\s using
357
- UML notation. The node is rendered as a table with three cells:
358
- the top cell contains the class name; the middle cell contains a
359
- list of attributes; and the bottom cell contains a list of
360
- operations::
361
-
362
- +-------------+
363
- | ClassName |
364
- +-------------+
365
- | x: int |
366
- | ... |
367
- +-------------+
368
- | f(self, x) |
369
- | ... |
370
- +-------------+
371
-
372
- `DotGraphUmlClassNode`\s may be *collapsed*, in which case they are
373
- drawn as a simple box containing the class name::
374
-
375
- +-------------+
376
- | ClassName |
377
- +-------------+
378
-
379
- Attributes with types corresponding to documented classes can
380
- optionally be converted into edges, using `link_attributes()`.
381
-
382
- :todo: Add more options?
383
- - show/hide operation signature
384
- - show/hide operation signature types
385
- - show/hide operation signature return type
386
- - show/hide attribute types
387
- - use qualifiers
388
- """
389
-
390
- def __init__(self, class_doc, linker, context, collapsed=False,
391
- bgcolor=CLASS_BG, **options):
392
- """
393
- Create a new `DotGraphUmlClassNode` based on the class
394
- `class_doc`.
395
-
396
- :Parameters:
397
- `linker` : `markup.DocstringLinker`
398
- Used to look up URLs for classes.
399
- `context` : `APIDoc`
400
- The context in which this node will be drawn; dotted
401
- names will be contextualized to this context.
402
- `collapsed` : ``bool``
403
- If true, then display this node as a simple box.
404
- `bgcolor` : ```str```
405
- The background color for this node.
406
- `options` : ``dict``
407
- A set of options used to control how the node should
408
- be displayed.
409
-
410
- :Keywords:
411
- - `show_private_vars`: If false, then private variables
412
- are filtered out of the attributes & operations lists.
413
- (Default: *False*)
414
- - `show_magic_vars`: If false, then magic variables
415
- (such as ``__init__`` and ``__add__``) are filtered out of
416
- the attributes & operations lists. (Default: *True*)
417
- - `show_inherited_vars`: If false, then inherited variables
418
- are filtered out of the attributes & operations lists.
419
- (Default: *False*)
420
- - `max_attributes`: The maximum number of attributes that
421
- should be listed in the attribute box. If the class has
422
- more than this number of attributes, some will be
423
- ellided. Ellipsis is marked with ``'...'``.
424
- - `max_operations`: The maximum number of operations that
425
- should be listed in the operation box.
426
- - `add_nodes_for_linked_attributes`: If true, then
427
- `link_attributes()` will create new a collapsed node for
428
- the types of a linked attributes if no node yet exists for
429
- that type.
430
- """
431
- if not isinstance(class_doc, ClassDoc):
432
- raise TypeError('Expected a ClassDoc as 1st argument')
433
-
434
- self.class_doc = class_doc
435
- """The class represented by this node."""
436
-
437
- self.linker = linker
438
- """Used to look up URLs for classes."""
439
-
440
- self.context = context
441
- """The context in which the node will be drawn."""
442
-
443
- self.bgcolor = bgcolor
444
- """The background color of the node."""
445
-
446
- self.options = options
447
- """Options used to control how the node is displayed."""
448
-
449
- self.collapsed = collapsed
450
- """If true, then draw this node as a simple box."""
451
-
452
- self.attributes = []
453
- """The list of VariableDocs for attributes"""
454
-
455
- self.operations = []
456
- """The list of VariableDocs for operations"""
457
-
458
- self.qualifiers = []
459
- """List of (key_label, port) tuples."""
460
-
461
- self.edges = []
462
- """List of edges used to represent this node's attributes.
463
- These should not be added to the `DotGraph`; this node will
464
- generate their dotfile code directly."""
465
-
466
- # Initialize operations & attributes lists.
467
- show_private = options.get('show_private_vars', False)
468
- show_magic = options.get('show_magic_vars', True)
469
- show_inherited = options.get('show_inherited_vars', False)
470
- for var in class_doc.sorted_variables:
471
- name = var.canonical_name[-1]
472
- if ((not show_private and var.is_public == False) or
473
- (not show_magic and re.match('__\w+__$', name)) or
474
- (not show_inherited and var.container != class_doc)):
475
- pass
476
- elif isinstance(var.value, RoutineDoc):
477
- self.operations.append(var)
478
- else:
479
- self.attributes.append(var)
480
-
481
- # Initialize our dot node settings.
482
- tooltip = self._summary(class_doc)
483
- if tooltip:
484
- # dot chokes on a \n in the attribute...
485
- tooltip = " ".join(tooltip.split())
486
- else:
487
- tooltip = class_doc.canonical_name
488
- DotGraphNode.__init__(self, tooltip=tooltip,
489
- width=0, height=0, shape='plaintext',
490
- href=linker.url_for(class_doc) or NOOP_URL)
491
-
492
- #/////////////////////////////////////////////////////////////////
493
- #{ Attribute Linking
494
- #/////////////////////////////////////////////////////////////////
495
-
496
- SIMPLE_TYPE_RE = re.compile(
497
- r'^([\w\.]+)$')
498
- """A regular expression that matches descriptions of simple types."""
499
-
500
- COLLECTION_TYPE_RE = re.compile(
501
- r'^(list|set|sequence|tuple|collection) of ([\w\.]+)$')
502
- """A regular expression that matches descriptions of collection types."""
503
-
504
- MAPPING_TYPE_RE = re.compile(
505
- r'^(dict|dictionary|map|mapping) from ([\w\.]+) to ([\w\.]+)$')
506
- """A regular expression that matches descriptions of mapping types."""
507
-
508
- MAPPING_TO_COLLECTION_TYPE_RE = re.compile(
509
- r'^(dict|dictionary|map|mapping) from ([\w\.]+) to '
510
- r'(list|set|sequence|tuple|collection) of ([\w\.]+)$')
511
- """A regular expression that matches descriptions of mapping types
512
- whose value type is a collection."""
513
-
514
- OPTIONAL_TYPE_RE = re.compile(
515
- r'^(None or|optional) ([\w\.]+)$|^([\w\.]+) or None$')
516
- """A regular expression that matches descriptions of optional types."""
517
-
518
- def link_attributes(self, nodes):
519
- """
520
- Convert any attributes with type descriptions corresponding to
521
- documented classes to edges. The following type descriptions
522
- are currently handled:
523
-
524
- - Dotted names: Create an attribute edge to the named type,
525
- labelled with the variable name.
526
- - Collections: Create an attribute edge to the named type,
527
- labelled with the variable name, and marked with '*' at the
528
- type end of the edge.
529
- - Mappings: Create an attribute edge to the named type,
530
- labelled with the variable name, connected to the class by
531
- a qualifier box that contains the key type description.
532
- - Optional: Create an attribute edge to the named type,
533
- labelled with the variable name, and marked with '0..1' at
534
- the type end of the edge.
535
-
536
- The edges created by `link_attributes()` are handled internally
537
- by `DotGraphUmlClassNode`; they should *not* be added directly
538
- to the `DotGraph`.
539
-
540
- :param nodes: A dictionary mapping from `ClassDoc`\s to
541
- `DotGraphUmlClassNode`\s, used to look up the nodes for
542
- attribute types. If the ``add_nodes_for_linked_attributes``
543
- option is used, then new nodes will be added to this
544
- dictionary for any types that are not already listed.
545
- These added nodes must be added to the `DotGraph`.
546
- """
547
- # Try to convert each attribute var into a graph edge. If
548
- # _link_attribute returns true, then it succeeded, so remove
549
- # that var from our attribute list; otherwise, leave that var
550
- # in our attribute list.
551
- self.attributes = [var for var in self.attributes
552
- if not self._link_attribute(var, nodes)]
553
-
554
- def _link_attribute(self, var, nodes):
555
- """
556
- Helper for `link_attributes()`: try to convert the attribute
557
- variable `var` into an edge, and add that edge to
558
- `self.edges`. Return ``True`` iff the variable was
559
- successfully converted to an edge (in which case, it should be
560
- removed from the attributes list).
561
- """
562
- type_descr = self._type_descr(var) or self._type_descr(var.value)
563
-
564
- # Simple type.
565
- m = self.SIMPLE_TYPE_RE.match(type_descr)
566
- if m and self._add_attribute_edge(var, nodes, m.group(1)):
567
- return True
568
-
569
- # Collection type.
570
- m = self.COLLECTION_TYPE_RE.match(type_descr)
571
- if m and self._add_attribute_edge(var, nodes, m.group(2),
572
- headlabel='*'):
573
- return True
574
-
575
- # Optional type.
576
- m = self.OPTIONAL_TYPE_RE.match(type_descr)
577
- if m and self._add_attribute_edge(var, nodes, m.group(2) or m.group(3),
578
- headlabel='0..1'):
579
- return True
580
-
581
- # Mapping type.
582
- m = self.MAPPING_TYPE_RE.match(type_descr)
583
- if m:
584
- port = 'qualifier_%s' % var.name
585
- if self._add_attribute_edge(var, nodes, m.group(3),
586
- tailport='%s:e' % port):
587
- self.qualifiers.append( (m.group(2), port) )
588
- return True
589
-
590
- # Mapping to collection type.
591
- m = self.MAPPING_TO_COLLECTION_TYPE_RE.match(type_descr)
592
- if m:
593
- port = 'qualifier_%s' % var.name
594
- if self._add_attribute_edge(var, nodes, m.group(4), headlabel='*',
595
- tailport='%s:e' % port):
596
- self.qualifiers.append( (m.group(2), port) )
597
- return True
598
-
599
- # We were unable to link this attribute.
600
- return False
601
-
602
- def _add_attribute_edge(self, var, nodes, type_str, **attribs):
603
- """
604
- Helper for `link_attributes()`: try to add an edge for the
605
- given attribute variable `var`. Return ``True`` if
606
- successful.
607
- """
608
- # Use the type string to look up a corresponding ValueDoc.
609
- type_doc = self.linker.docindex.find(type_str, var)
610
- if not type_doc: return False
611
-
612
- # Make sure the type is a class.
613
- if not isinstance(type_doc, ClassDoc): return False
614
-
615
- # Get the type ValueDoc's node. If it doesn't have one (and
616
- # add_nodes_for_linked_attributes=True), then create it.
617
- type_node = nodes.get(type_doc)
618
- if not type_node:
619
- if self.options.get('add_nodes_for_linked_attributes', True):
620
- type_node = DotGraphUmlClassNode(type_doc, self.linker,
621
- self.context, collapsed=True)
622
- nodes[type_doc] = type_node
623
- else:
624
- return False
625
-
626
- # Add an edge from self to the target type node.
627
- # [xx] should I set constraint=false here?
628
- attribs.setdefault('headport', 'body')
629
- attribs.setdefault('tailport', 'body')
630
- url = self.linker.url_for(var) or NOOP_URL
631
- self.edges.append(DotGraphEdge(self, type_node, label=var.name,
632
- arrowhead='open', href=url,
633
- tooltip=var.canonical_name, labeldistance=1.5,
634
- **attribs))
635
- return True
636
-
637
- #/////////////////////////////////////////////////////////////////
638
- #{ Helper Methods
639
- #/////////////////////////////////////////////////////////////////
640
- def _summary(self, api_doc):
641
- """Return a plaintext summary for `api_doc`"""
642
- if not isinstance(api_doc, APIDoc): return ''
643
- if api_doc.summary in (None, UNKNOWN): return ''
644
- summary = api_doc.summary.to_plaintext(None).strip()
645
- return plaintext_to_html(summary)
646
-
647
- _summary = classmethod(_summary)
648
-
649
- def _type_descr(self, api_doc):
650
- """Return a plaintext type description for `api_doc`"""
651
- if not hasattr(api_doc, 'type_descr'): return ''
652
- if api_doc.type_descr in (None, UNKNOWN): return ''
653
- type_descr = api_doc.type_descr.to_plaintext(self.linker).strip()
654
- return plaintext_to_html(type_descr)
655
-
656
- def _tooltip(self, var_doc):
657
- """Return a tooltip for `var_doc`."""
658
- return (self._summary(var_doc) or
659
- self._summary(var_doc.value) or
660
- var_doc.canonical_name)
661
-
662
- #/////////////////////////////////////////////////////////////////
663
- #{ Rendering
664
- #/////////////////////////////////////////////////////////////////
665
-
666
- def _attribute_cell(self, var_doc):
667
- # Construct the label
668
- label = var_doc.name
669
- type_descr = (self._type_descr(var_doc) or
670
- self._type_descr(var_doc.value))
671
- if type_descr: label += ': %s' % type_descr
672
- # Get the URL
673
- url = self.linker.url_for(var_doc) or NOOP_URL
674
- # Construct & return the pseudo-html code
675
- return self._ATTRIBUTE_CELL % (url, self._tooltip(var_doc), label)
676
-
677
- def _operation_cell(self, var_doc):
678
- """
679
- :todo: do 'word wrapping' on the signature, by starting a new
680
- row in the table, if necessary. How to indent the new
681
- line? Maybe use align=right? I don't think dot has a
682
- &nbsp;.
683
- :todo: Optionally add return type info?
684
- """
685
- # Construct the label (aka function signature)
686
- func_doc = var_doc.value
687
- args = [self._operation_arg(n, d, func_doc) for (n, d)
688
- in zip(func_doc.posargs, func_doc.posarg_defaults)]
689
- args = [plaintext_to_html(arg) for arg in args]
690
- if func_doc.vararg: args.append('*'+func_doc.vararg)
691
- if func_doc.kwarg: args.append('**'+func_doc.kwarg)
692
- label = '%s(%s)' % (var_doc.name, ', '.join(args))
693
- # Get the URL
694
- url = self.linker.url_for(var_doc) or NOOP_URL
695
- # Construct & return the pseudo-html code
696
- return self._OPERATION_CELL % (url, self._tooltip(var_doc), label)
697
-
698
- def _operation_arg(self, name, default, func_doc):
699
- """
700
- :todo: Handle tuple args better
701
- :todo: Optionally add type info?
702
- """
703
- if default is None:
704
- return '%s' % name
705
- else:
706
- pyval_repr = default.summary_pyval_repr().to_plaintext(None)
707
- return '%s=%s' % (name, pyval_repr)
708
-
709
- def _qualifier_cell(self, key_label, port):
710
- return self._QUALIFIER_CELL % (port, self.bgcolor, key_label)
711
-
712
- #: args: (url, tooltip, label)
713
- _ATTRIBUTE_CELL = '''
714
- <TR><TD ALIGN="LEFT" HREF="%s" TOOLTIP="%s">%s</TD></TR>
715
- '''
716
-
717
- #: args: (url, tooltip, label)
718
- _OPERATION_CELL = '''
719
- <TR><TD ALIGN="LEFT" HREF="%s" TOOLTIP="%s">%s</TD></TR>
720
- '''
721
-
722
- #: args: (port, bgcolor, label)
723
- _QUALIFIER_CELL = '''
724
- <TR><TD VALIGN="BOTTOM" PORT="%s" BGCOLOR="%s" BORDER="1">%s</TD></TR>
725
- '''
726
-
727
- _QUALIFIER_DIV = '''
728
- <TR><TD VALIGN="BOTTOM" HEIGHT="10" WIDTH="10" FIXEDSIZE="TRUE"></TD></TR>
729
- '''
730
-
731
- #: Args: (rowspan, bgcolor, classname, attributes, operations, qualifiers)
732
- _LABEL = '''
733
- <TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" CELLPADDING="0">
734
- <TR><TD ROWSPAN="%s">
735
- <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"
736
- CELLPADDING="0" PORT="body" BGCOLOR="%s">
737
- <TR><TD>%s</TD></TR>
738
- <TR><TD><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0">
739
- %s</TABLE></TD></TR>
740
- <TR><TD><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0">
741
- %s</TABLE></TD></TR>
742
- </TABLE>
743
- </TD></TR>
744
- %s
745
- </TABLE>'''
746
-
747
- _COLLAPSED_LABEL = '''
748
- <TABLE CELLBORDER="0" BGCOLOR="%s" PORT="body">
749
- <TR><TD>%s</TD></TR>
750
- </TABLE>'''
751
-
752
- def _get_html_label(self):
753
- # Get the class name & contextualize it.
754
- classname = self.class_doc.canonical_name
755
- classname = classname.contextualize(self.context.canonical_name)
756
-
757
- # If we're collapsed, display the node as a single box.
758
- if self.collapsed:
759
- return self._COLLAPSED_LABEL % (self.bgcolor, classname)
760
-
761
- # Construct the attribute list. (If it's too long, truncate)
762
- attrib_cells = [self._attribute_cell(a) for a in self.attributes]
763
- max_attributes = self.options.get('max_attributes', 15)
764
- if len(attrib_cells) == 0:
765
- attrib_cells = ['<TR><TD></TD></TR>']
766
- elif len(attrib_cells) > max_attributes:
767
- attrib_cells[max_attributes-2:-1] = ['<TR><TD>...</TD></TR>']
768
- attributes = ''.join(attrib_cells)
769
-
770
- # Construct the operation list. (If it's too long, truncate)
771
- oper_cells = [self._operation_cell(a) for a in self.operations]
772
- max_operations = self.options.get('max_operations', 15)
773
- if len(oper_cells) == 0:
774
- oper_cells = ['<TR><TD></TD></TR>']
775
- elif len(oper_cells) > max_operations:
776
- oper_cells[max_operations-2:-1] = ['<TR><TD>...</TD></TR>']
777
- operations = ''.join(oper_cells)
778
-
779
- # Construct the qualifier list & determine the rowspan.
780
- if self.qualifiers:
781
- rowspan = len(self.qualifiers)*2+2
782
- div = self._QUALIFIER_DIV
783
- qualifiers = div+div.join([self._qualifier_cell(l,p) for
784
- (l,p) in self.qualifiers])+div
785
- else:
786
- rowspan = 1
787
- qualifiers = ''
788
-
789
- # Put it all together.
790
- return self._LABEL % (rowspan, self.bgcolor, classname,
791
- attributes, operations, qualifiers)
792
-
793
- def to_dotfile(self):
794
- attribs = ['%s="%s"' % (k,v) for (k,v) in self._attribs.items()]
795
- attribs.append('label=<%s>' % self._get_html_label())
796
- s = 'node%d%s' % (self.id, ' [%s]' % (','.join(attribs)))
797
- if not self.collapsed:
798
- for edge in self.edges:
799
- s += '\n' + edge.to_dotfile()
800
- return s
801
-
802
- class DotGraphUmlModuleNode(DotGraphNode):
803
- """
804
- A specialized dot grah node used to display `ModuleDoc`\s using
805
- UML notation. Simple module nodes look like::
806
-
807
- .----.
808
- +------------+
809
- | modulename |
810
- +------------+
811
-
812
- Packages nodes are drawn with their modules & subpackages nested
813
- inside::
814
-
815
- .----.
816
- +----------------------------------------+
817
- | packagename |
818
- | |
819
- | .----. .----. .----. |
820
- | +---------+ +---------+ +---------+ |
821
- | | module1 | | module2 | | module3 | |
822
- | +---------+ +---------+ +---------+ |
823
- | |
824
- +----------------------------------------+
825
-
826
- """
827
- def __init__(self, module_doc, linker, context, collapsed=False,
828
- excluded_submodules=(), **options):
829
- self.module_doc = module_doc
830
- self.linker = linker
831
- self.context = context
832
- self.collapsed = collapsed
833
- self.options = options
834
- self.excluded_submodules = excluded_submodules
835
- DotGraphNode.__init__(self, shape='plaintext',
836
- href=linker.url_for(module_doc) or NOOP_URL,
837
- tooltip=module_doc.canonical_name)
838
-
839
- #: Expects: (color, color, url, tooltip, body)
840
- _MODULE_LABEL = '''
841
- <TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" ALIGN="LEFT">
842
- <TR><TD ALIGN="LEFT" VALIGN="BOTTOM" HEIGHT="8" WIDTH="16"
843
- FIXEDSIZE="true" BGCOLOR="%s" BORDER="1" PORT="tab"></TD></TR>
844
- <TR><TD ALIGN="LEFT" VALIGN="TOP" BGCOLOR="%s" BORDER="1" WIDTH="20"
845
- PORT="body" HREF="%s" TOOLTIP="%s">%s</TD></TR>
846
- </TABLE>'''
847
-
848
- #: Expects: (name, body_rows)
849
- _NESTED_BODY = '''
850
- <TABLE BORDER="0" CELLBORDER="0" CELLPADDING="0" CELLSPACING="0">
851
- <TR><TD ALIGN="LEFT">%s</TD></TR>
852
- %s
853
- </TABLE>'''
854
-
855
- #: Expects: (cells,)
856
- _NESTED_BODY_ROW = '''
857
- <TR><TD>
858
- <TABLE BORDER="0" CELLBORDER="0"><TR>%s</TR></TABLE>
859
- </TD></TR>'''
860
-
861
- def _get_html_label(self, package):
862
- """
863
- :Return: (label, depth, width) where:
864
-
865
- - ``label`` is the HTML label
866
- - ``depth`` is the depth of the package tree (for coloring)
867
- - ``width`` is the max width of the HTML label, roughly in
868
- units of characters.
869
- """
870
- MAX_ROW_WIDTH = 80 # unit is roughly characters.
871
- pkg_name = package.canonical_name
872
- pkg_url = self.linker.url_for(package) or NOOP_URL
873
-
874
- if (not package.is_package or len(package.submodules) == 0 or
875
- self.collapsed):
876
- pkg_color = self._color(package, 1)
877
- label = self._MODULE_LABEL % (pkg_color, pkg_color,
878
- pkg_url, pkg_name, pkg_name[-1])
879
- return (label, 1, len(pkg_name[-1])+3)
880
-
881
- # Get the label for each submodule, and divide them into rows.
882
- row_list = ['']
883
- row_width = 0
884
- max_depth = 0
885
- max_row_width = len(pkg_name[-1])+3
886
- for submodule in package.submodules:
887
- if submodule in self.excluded_submodules: continue
888
- # Get the submodule's label.
889
- label, depth, width = self._get_html_label(submodule)
890
- # Check if we should start a new row.
891
- if row_width > 0 and width+row_width > MAX_ROW_WIDTH:
892
- row_list.append('')
893
- row_width = 0
894
- # Add the submodule's label to the row.
895
- row_width += width
896
- row_list[-1] += '<TD ALIGN="LEFT">%s</TD>' % label
897
- # Update our max's.
898
- max_depth = max(depth, max_depth)
899
- max_row_width = max(row_width, max_row_width)
900
-
901
- # Figure out which color to use.
902
- pkg_color = self._color(package, depth+1)
903
-
904
- # Assemble & return the label.
905
- rows = ''.join([self._NESTED_BODY_ROW % r for r in row_list])
906
- body = self._NESTED_BODY % (pkg_name, rows)
907
- label = self._MODULE_LABEL % (pkg_color, pkg_color,
908
- pkg_url, pkg_name, body)
909
- return label, max_depth+1, max_row_width
910
-
911
- _COLOR_DIFF = 24
912
- def _color(self, package, depth):
913
- if package == self.context: return SELECTED_BG
914
- else:
915
- # Parse the base color.
916
- if re.match(MODULE_BG, 'r#[0-9a-fA-F]{6}$'):
917
- base = int(MODULE_BG[1:], 16)
918
- else:
919
- base = int('d8e8ff', 16)
920
- red = (base & 0xff0000) >> 16
921
- green = (base & 0x00ff00) >> 8
922
- blue = (base & 0x0000ff)
923
- # Make it darker with each level of depth. (but not *too*
924
- # dark -- package name needs to be readable)
925
- red = max(64, red-(depth-1)*self._COLOR_DIFF)
926
- green = max(64, green-(depth-1)*self._COLOR_DIFF)
927
- blue = max(64, blue-(depth-1)*self._COLOR_DIFF)
928
- # Convert it back to a color string
929
- return '#%06x' % ((red<<16)+(green<<8)+blue)
930
-
931
- def to_dotfile(self):
932
- attribs = ['%s="%s"' % (k,v) for (k,v) in self._attribs.items()]
933
- label, depth, width = self._get_html_label(self.module_doc)
934
- attribs.append('label=<%s>' % label)
935
- return 'node%d%s' % (self.id, ' [%s]' % (','.join(attribs)))
936
-
937
-
938
-
939
- ######################################################################
940
- #{ Graph Generation Functions
941
- ######################################################################
942
-
943
- def package_tree_graph(packages, linker, context=None, **options):
944
- """
945
- Return a `DotGraph` that graphically displays the package
946
- hierarchies for the given packages.
947
- """
948
- if options.get('style', 'uml') == 'uml': # default to uml style?
949
- if get_dot_version() >= [2]:
950
- return uml_package_tree_graph(packages, linker, context,
951
- **options)
952
- elif 'style' in options:
953
- log.warning('UML style package trees require dot version 2.0+')
954
-
955
- graph = DotGraph('Package Tree for %s' % name_list(packages, context),
956
- body='ranksep=.3\n;nodesep=.1\n',
957
- edge_defaults={'dir':'none'})
958
-
959
- # Options
960
- if options.get('dir', 'TB') != 'TB': # default: top-to-bottom
961
- graph.body += 'rankdir=%s\n' % options.get('dir', 'TB')
962
-
963
- # Get a list of all modules in the package.
964
- queue = list(packages)
965
- modules = set(packages)
966
- for module in queue:
967
- queue.extend(module.submodules)
968
- modules.update(module.submodules)
969
-
970
- # Add a node for each module.
971
- nodes = add_valdoc_nodes(graph, modules, linker, context)
972
-
973
- # Add an edge for each package/submodule relationship.
974
- for module in modules:
975
- for submodule in module.submodules:
976
- graph.edges.append(DotGraphEdge(nodes[module], nodes[submodule],
977
- headport='tab'))
978
-
979
- return graph
980
-
981
- def uml_package_tree_graph(packages, linker, context=None, **options):
982
- """
983
- Return a `DotGraph` that graphically displays the package
984
- hierarchies for the given packages as a nested set of UML
985
- symbols.
986
- """
987
- graph = DotGraph('Package Tree for %s' % name_list(packages, context))
988
- # Remove any packages whose containers are also in the list.
989
- root_packages = []
990
- for package1 in packages:
991
- for package2 in packages:
992
- if (package1 is not package2 and
993
- package2.canonical_name.dominates(package1.canonical_name)):
994
- break
995
- else:
996
- root_packages.append(package1)
997
- # If the context is a variable, then get its value.
998
- if isinstance(context, VariableDoc) and context.value is not UNKNOWN:
999
- context = context.value
1000
- # Return a graph with one node for each root package.
1001
- for package in root_packages:
1002
- graph.nodes.append(DotGraphUmlModuleNode(package, linker, context))
1003
- return graph
1004
-
1005
- ######################################################################
1006
- def class_tree_graph(bases, linker, context=None, **options):
1007
- """
1008
- Return a `DotGraph` that graphically displays the class
1009
- hierarchy for the given classes. Options:
1010
-
1011
- - exclude
1012
- - dir: LR|RL|BT requests a left-to-right, right-to-left, or
1013
- bottom-to- top, drawing. (corresponds to the dot option
1014
- 'rankdir'
1015
- """
1016
- if isinstance(bases, ClassDoc): bases = [bases]
1017
- graph = DotGraph('Class Hierarchy for %s' % name_list(bases, context),
1018
- body='ranksep=0.3\n',
1019
- edge_defaults={'sametail':True, 'dir':'none'})
1020
-
1021
- # Options
1022
- if options.get('dir', 'TB') != 'TB': # default: top-down
1023
- graph.body += 'rankdir=%s\n' % options.get('dir', 'TB')
1024
- exclude = options.get('exclude', ())
1025
-
1026
- # Find all superclasses & subclasses of the given classes.
1027
- classes = set(bases)
1028
- queue = list(bases)
1029
- for cls in queue:
1030
- if isinstance(cls, ClassDoc):
1031
- if cls.subclasses not in (None, UNKNOWN):
1032
- subclasses = cls.subclasses
1033
- if exclude:
1034
- subclasses = [d for d in subclasses if d not in exclude]
1035
- queue.extend(subclasses)
1036
- classes.update(subclasses)
1037
- queue = list(bases)
1038
- for cls in queue:
1039
- if isinstance(cls, ClassDoc):
1040
- if cls.bases not in (None, UNKNOWN):
1041
- bases = cls.bases
1042
- if exclude:
1043
- bases = [d for d in bases if d not in exclude]
1044
- queue.extend(bases)
1045
- classes.update(bases)
1046
-
1047
- # Add a node for each cls.
1048
- classes = [d for d in classes if isinstance(d, ClassDoc)
1049
- if d.pyval is not object]
1050
- nodes = add_valdoc_nodes(graph, classes, linker, context)
1051
-
1052
- # Add an edge for each package/subclass relationship.
1053
- edges = set()
1054
- for cls in classes:
1055
- for subcls in cls.subclasses:
1056
- if cls in nodes and subcls in nodes:
1057
- edges.add((nodes[cls], nodes[subcls]))
1058
- graph.edges = [DotGraphEdge(src,dst) for (src,dst) in edges]
1059
-
1060
- return graph
1061
-
1062
- ######################################################################
1063
- def uml_class_tree_graph(class_doc, linker, context=None, **options):
1064
- """
1065
- Return a `DotGraph` that graphically displays the class hierarchy
1066
- for the given class, using UML notation. Options:
1067
-
1068
- - max_attributes
1069
- - max_operations
1070
- - show_private_vars
1071
- - show_magic_vars
1072
- - link_attributes
1073
- """
1074
- nodes = {} # ClassDoc -> DotGraphUmlClassNode
1075
- exclude = options.get('exclude', ())
1076
-
1077
- # Create nodes for class_doc and all its bases.
1078
- for cls in class_doc.mro():
1079
- if cls.pyval is object: continue # don't include `object`.
1080
- if cls in exclude: break # stop if we get to an excluded class.
1081
- if cls == class_doc: color = SELECTED_BG
1082
- else: color = BASECLASS_BG
1083
- nodes[cls] = DotGraphUmlClassNode(cls, linker, context,
1084
- show_inherited_vars=False,
1085
- collapsed=False, bgcolor=color)
1086
-
1087
- # Create nodes for all class_doc's subclasses.
1088
- queue = [class_doc]
1089
- for cls in queue:
1090
- if (isinstance(cls, ClassDoc) and
1091
- cls.subclasses not in (None, UNKNOWN)):
1092
- for subcls in cls.subclasses:
1093
- subcls_name = subcls.canonical_name[-1]
1094
- if subcls not in nodes and subcls not in exclude:
1095
- queue.append(subcls)
1096
- nodes[subcls] = DotGraphUmlClassNode(
1097
- subcls, linker, context, collapsed=True,
1098
- bgcolor=SUBCLASS_BG)
1099
-
1100
- # Only show variables in the class where they're defined for
1101
- # *class_doc*.
1102
- mro = class_doc.mro()
1103
- for name, var in class_doc.variables.items():
1104
- i = mro.index(var.container)
1105
- for base in mro[i+1:]:
1106
- if base.pyval is object: continue # don't include `object`.
1107
- overridden_var = base.variables.get(name)
1108
- if overridden_var and overridden_var.container == base:
1109
- try:
1110
- if isinstance(overridden_var.value, RoutineDoc):
1111
- nodes[base].operations.remove(overridden_var)
1112
- else:
1113
- nodes[base].attributes.remove(overridden_var)
1114
- except ValueError:
1115
- pass # var is filtered (eg private or magic)
1116
-
1117
- # Keep track of which nodes are part of the inheritance graph
1118
- # (since link_attributes might add new nodes)
1119
- inheritance_nodes = set(nodes.values())
1120
-
1121
- # Turn attributes into links.
1122
- if options.get('link_attributes', True):
1123
- for node in nodes.values():
1124
- node.link_attributes(nodes)
1125
- # Make sure that none of the new attribute edges break the
1126
- # rank ordering assigned by inheritance.
1127
- for edge in node.edges:
1128
- if edge.end in inheritance_nodes:
1129
- edge['constraint'] = 'False'
1130
-
1131
- # Construct the graph.
1132
- graph = DotGraph('UML class diagram for %s' % class_doc.canonical_name,
1133
- body='ranksep=.2\n;nodesep=.3\n')
1134
- graph.nodes = nodes.values()
1135
-
1136
- # Add inheritance edges.
1137
- for node in inheritance_nodes:
1138
- for base in node.class_doc.bases:
1139
- if base in nodes:
1140
- graph.edges.append(DotGraphEdge(nodes[base], node,
1141
- dir='back', arrowtail='empty',
1142
- headport='body', tailport='body',
1143
- color=INH_LINK_COLOR, weight=100,
1144
- style='bold'))
1145
-
1146
- # And we're done!
1147
- return graph
1148
-
1149
- ######################################################################
1150
- def import_graph(modules, docindex, linker, context=None, **options):
1151
- graph = DotGraph('Import Graph', body='ranksep=.3\n;nodesep=.3\n')
1152
-
1153
- # Options
1154
- if options.get('dir', 'RL') != 'TB': # default: right-to-left.
1155
- graph.body += 'rankdir=%s\n' % options.get('dir', 'RL')
1156
-
1157
- # Add a node for each module.
1158
- nodes = add_valdoc_nodes(graph, modules, linker, context)
1159
-
1160
- # Edges.
1161
- edges = set()
1162
- for dst in modules:
1163
- if dst.imports in (None, UNKNOWN): continue
1164
- for var_name in dst.imports:
1165
- for i in range(len(var_name), 0, -1):
1166
- val_doc = docindex.find(var_name[:i], context)
1167
- if isinstance(val_doc, ModuleDoc):
1168
- if val_doc in nodes and dst in nodes:
1169
- edges.add((nodes[val_doc], nodes[dst]))
1170
- break
1171
- graph.edges = [DotGraphEdge(src,dst) for (src,dst) in edges]
1172
-
1173
- return graph
1174
-
1175
- ######################################################################
1176
- def call_graph(api_docs, docindex, linker, context=None, **options):
1177
- """
1178
- :param options:
1179
- - ``dir``: rankdir for the graph. (default=LR)
1180
- - ``add_callers``: also include callers for any of the
1181
- routines in ``api_docs``. (default=False)
1182
- - ``add_callees``: also include callees for any of the
1183
- routines in ``api_docs``. (default=False)
1184
- :todo: Add an ``exclude`` option?
1185
- """
1186
- if docindex.callers is None:
1187
- log.warning("No profiling information for call graph!")
1188
- return DotGraph('Call Graph') # return None instead?
1189
-
1190
- if isinstance(context, VariableDoc):
1191
- context = context.value
1192
-
1193
- # Get the set of requested functions.
1194
- functions = []
1195
- for api_doc in api_docs:
1196
- # If it's a variable, get its value.
1197
- if isinstance(api_doc, VariableDoc):
1198
- api_doc = api_doc.value
1199
- # Add the value to the functions list.
1200
- if isinstance(api_doc, RoutineDoc):
1201
- functions.append(api_doc)
1202
- elif isinstance(api_doc, NamespaceDoc):
1203
- for vardoc in api_doc.variables.values():
1204
- if isinstance(vardoc.value, RoutineDoc):
1205
- functions.append(vardoc.value)
1206
-
1207
- # Filter out functions with no callers/callees?
1208
- # [xx] this isnt' quite right, esp if add_callers or add_callees
1209
- # options are fales.
1210
- functions = [f for f in functions if
1211
- (f in docindex.callers) or (f in docindex.callees)]
1212
-
1213
- # Add any callers/callees of the selected functions
1214
- func_set = set(functions)
1215
- if options.get('add_callers', False) or options.get('add_callees', False):
1216
- for func_doc in functions:
1217
- if options.get('add_callers', False):
1218
- func_set.update(docindex.callers.get(func_doc, ()))
1219
- if options.get('add_callees', False):
1220
- func_set.update(docindex.callees.get(func_doc, ()))
1221
-
1222
- graph = DotGraph('Call Graph for %s' % name_list(api_docs, context),
1223
- node_defaults={'shape':'box', 'width': 0, 'height': 0})
1224
-
1225
- # Options
1226
- if options.get('dir', 'LR') != 'TB': # default: left-to-right
1227
- graph.body += 'rankdir=%s\n' % options.get('dir', 'LR')
1228
-
1229
- nodes = add_valdoc_nodes(graph, func_set, linker, context)
1230
-
1231
- # Find the edges.
1232
- edges = set()
1233
- for func_doc in functions:
1234
- for caller in docindex.callers.get(func_doc, ()):
1235
- if caller in nodes:
1236
- edges.add( (nodes[caller], nodes[func_doc]) )
1237
- for callee in docindex.callees.get(func_doc, ()):
1238
- if callee in nodes:
1239
- edges.add( (nodes[func_doc], nodes[callee]) )
1240
- graph.edges = [DotGraphEdge(src,dst) for (src,dst) in edges]
1241
-
1242
- return graph
1243
-
1244
- ######################################################################
1245
- #{ Dot Version
1246
- ######################################################################
1247
-
1248
- _dot_version = None
1249
- _DOT_VERSION_RE = re.compile(r'dot version ([\d\.]+)')
1250
- def get_dot_version():
1251
- global _dot_version
1252
- if _dot_version is None:
1253
- try:
1254
- out, err = run_subprocess([DOT_COMMAND, '-V'])
1255
- version_info = err or out
1256
- m = _DOT_VERSION_RE.match(version_info)
1257
- if m:
1258
- _dot_version = [int(x) for x in m.group(1).split('.')]
1259
- else:
1260
- _dot_version = (0,)
1261
- except OSError, e:
1262
- _dot_version = (0,)
1263
- log.info('Detected dot version %s' % _dot_version)
1264
- return _dot_version
1265
-
1266
- ######################################################################
1267
- #{ Helper Functions
1268
- ######################################################################
1269
-
1270
- def add_valdoc_nodes(graph, val_docs, linker, context):
1271
- """
1272
- :todo: Use different node styles for different subclasses of APIDoc
1273
- """
1274
- nodes = {}
1275
- val_docs = sorted(val_docs, key=lambda d:d.canonical_name)
1276
- for i, val_doc in enumerate(val_docs):
1277
- label = val_doc.canonical_name.contextualize(context.canonical_name)
1278
- node = nodes[val_doc] = DotGraphNode(label)
1279
- graph.nodes.append(node)
1280
- specialize_valdoc_node(node, val_doc, context, linker.url_for(val_doc))
1281
- return nodes
1282
-
1283
- NOOP_URL = 'javascript:void(0);'
1284
- MODULE_NODE_HTML = '''
1285
- <TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0"
1286
- CELLPADDING="0" PORT="table" ALIGN="LEFT">
1287
- <TR><TD ALIGN="LEFT" VALIGN="BOTTOM" HEIGHT="8" WIDTH="16" FIXEDSIZE="true"
1288
- BGCOLOR="%s" BORDER="1" PORT="tab"></TD></TR>
1289
- <TR><TD ALIGN="LEFT" VALIGN="TOP" BGCOLOR="%s" BORDER="1"
1290
- PORT="body" HREF="%s" TOOLTIP="%s">%s</TD></TR>
1291
- </TABLE>'''.strip()
1292
-
1293
- def specialize_valdoc_node(node, val_doc, context, url):
1294
- """
1295
- Update the style attributes of `node` to reflext its type
1296
- and context.
1297
- """
1298
- # We can only use html-style nodes if dot_version>2.
1299
- dot_version = get_dot_version()
1300
-
1301
- # If val_doc or context is a variable, get its value.
1302
- if isinstance(val_doc, VariableDoc) and val_doc.value is not UNKNOWN:
1303
- val_doc = val_doc.value
1304
- if isinstance(context, VariableDoc) and context.value is not UNKNOWN:
1305
- context = context.value
1306
-
1307
- # Set the URL. (Do this even if it points to the page we're
1308
- # currently on; otherwise, the tooltip is ignored.)
1309
- node['href'] = url or NOOP_URL
1310
-
1311
- if isinstance(val_doc, ModuleDoc) and dot_version >= [2]:
1312
- node['shape'] = 'plaintext'
1313
- if val_doc == context: color = SELECTED_BG
1314
- else: color = MODULE_BG
1315
- node['tooltip'] = node['label']
1316
- node['html_label'] = MODULE_NODE_HTML % (color, color, url,
1317
- val_doc.canonical_name,
1318
- node['label'])
1319
- node['width'] = node['height'] = 0
1320
- node.port = 'body'
1321
-
1322
- elif isinstance(val_doc, RoutineDoc):
1323
- node['shape'] = 'box'
1324
- node['style'] = 'rounded'
1325
- node['width'] = 0
1326
- node['height'] = 0
1327
- node['label'] = '%s()' % node['label']
1328
- node['tooltip'] = node['label']
1329
- if val_doc == context:
1330
- node['fillcolor'] = SELECTED_BG
1331
- node['style'] = 'filled,rounded,bold'
1332
-
1333
- else:
1334
- node['shape'] = 'box'
1335
- node['width'] = 0
1336
- node['height'] = 0
1337
- node['tooltip'] = node['label']
1338
- if val_doc == context:
1339
- node['fillcolor'] = SELECTED_BG
1340
- node['style'] = 'filled,bold'
1341
-
1342
- def name_list(api_docs, context=None):
1343
- if context is not None:
1344
- context = context.canonical_name
1345
- names = [str(d.canonical_name.contextualize(context)) for d in api_docs]
1346
- if len(names) == 0: return ''
1347
- if len(names) == 1: return '%s' % names[0]
1348
- elif len(names) == 2: return '%s and %s' % (names[0], names[1])
1349
- else:
1350
- return '%s, and %s' % (', '.join(names[:-1]), names[-1])
1351
-