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,3491 +0,0 @@
1
- #
2
- # epydoc -- HTML output generator
3
- # Edward Loper
4
- #
5
- # Created [01/30/01 05:18 PM]
6
- # $Id: html.py,v 1.1 2009/11/26 13:20:44 casa Exp $
7
- #
8
-
9
- """
10
- The HTML output generator for epydoc. The main interface provided by
11
- this module is the L{HTMLWriter} class.
12
-
13
- @todo: Add a cache to L{HTMLWriter.url()}?
14
- """
15
- __docformat__ = 'epytext en'
16
-
17
- import re, os, sys, codecs, sre_constants, pprint, base64
18
- import urllib
19
- import __builtin__
20
- from epydoc.apidoc import *
21
- import epydoc.docstringparser
22
- import time, epydoc, epydoc.markup, epydoc.markup.epytext
23
- from epydoc.docwriter.html_colorize import PythonSourceColorizer
24
- from epydoc.docwriter import html_colorize
25
- from epydoc.docwriter.html_css import STYLESHEETS
26
- from epydoc.docwriter.html_help import HTML_HELP
27
- from epydoc.docwriter.dotgraph import *
28
- from epydoc import log
29
- from epydoc.util import plaintext_to_html, is_src_filename
30
- from epydoc.compat import * # Backwards compatibility
31
-
32
- ######################################################################
33
- ## Template Compiler
34
- ######################################################################
35
- # The compile_template() method defined in this section is used to
36
- # define several of HTMLWriter's methods.
37
-
38
- def compile_template(docstring, template_string,
39
- output_function='out', debug=epydoc.DEBUG):
40
- """
41
- Given a template string containing inline python source code,
42
- return a python function that will fill in the template, and
43
- output the result. The signature for this function is taken from
44
- the first line of C{docstring}. Output is generated by making
45
- repeated calls to the output function with the given name (which
46
- is typically one of the function's parameters).
47
-
48
- The templating language used by this function passes through all
49
- text as-is, with three exceptions:
50
-
51
- - If every line in the template string is indented by at least
52
- M{x} spaces, then the first M{x} spaces are stripped from each
53
- line.
54
-
55
- - Any line that begins with '>>>' (with no indentation)
56
- should contain python code, and will be inserted as-is into
57
- the template-filling function. If the line begins a control
58
- block (such as 'if' or 'for'), then the control block will
59
- be closed by the first '>>>'-marked line whose indentation is
60
- less than or equal to the line's own indentation (including
61
- lines that only contain comments.)
62
-
63
- - In any other line, any expression between two '$' signs will
64
- be evaluated and inserted into the line (using C{str()} to
65
- convert the result to a string).
66
-
67
- Here is a simple example:
68
-
69
- >>> TEMPLATE = '''
70
- ... <book>
71
- ... <title>$book.title$</title>
72
- ... <pages>$book.count_pages()$</pages>
73
- ... >>> for chapter in book.chapters:
74
- ... <chaptername>$chapter.name$</chaptername>
75
- ... >>> #endfor
76
- ... </book>
77
- >>> write_book = compile_template('write_book(out, book)', TEMPLATE)
78
-
79
- @newfield acknowledgements: Acknowledgements
80
- @acknowledgements: The syntax used by C{compile_template} is
81
- loosely based on Cheetah.
82
- """
83
- # Extract signature from the docstring:
84
- signature = docstring.lstrip().split('\n',1)[0].strip()
85
- func_name = signature.split('(',1)[0].strip()
86
-
87
- # Regexp to search for inline substitutions:
88
- INLINE = re.compile(r'\$([^\$]+)\$')
89
- # Regexp to search for python statements in the template:
90
- COMMAND = re.compile(r'(^>>>.*)\n?', re.MULTILINE)
91
-
92
- # Strip indentation from the template.
93
- template_string = strip_indent(template_string)
94
-
95
- # If we're debugging, then we'll store the generated function,
96
- # so we can print it along with any tracebacks that depend on it.
97
- if debug:
98
- signature = re.sub(r'\)\s*$', ', __debug=__debug)', signature)
99
-
100
- # Funciton declaration line
101
- pysrc_lines = ['def %s:' % signature]
102
- indents = [-1]
103
-
104
- if debug:
105
- pysrc_lines.append(' try:')
106
- indents.append(-1)
107
-
108
- commands = COMMAND.split(template_string.strip()+'\n')
109
- for i, command in enumerate(commands):
110
- if command == '': continue
111
-
112
- # String literal segment:
113
- if i%2 == 0:
114
- pieces = INLINE.split(command)
115
- for j, piece in enumerate(pieces):
116
- if j%2 == 0:
117
- # String piece
118
- pysrc_lines.append(' '*len(indents)+
119
- '%s(%r)' % (output_function, piece))
120
- else:
121
- # Variable piece
122
- pysrc_lines.append(' '*len(indents)+
123
- '%s(unicode(%s))' % (output_function, piece))
124
-
125
- # Python command:
126
- else:
127
- srcline = command[3:].lstrip()
128
- # Update indentation
129
- indent = len(command)-len(srcline)
130
- while indent <= indents[-1]: indents.pop()
131
- # Add on the line.
132
- srcline = srcline.rstrip()
133
- pysrc_lines.append(' '*len(indents)+srcline)
134
- if srcline.endswith(':'):
135
- indents.append(indent)
136
-
137
- if debug:
138
- pysrc_lines.append(' except Exception,e:')
139
- pysrc_lines.append(' pysrc, func_name = __debug ')
140
- pysrc_lines.append(' lineno = sys.exc_info()[2].tb_lineno')
141
- pysrc_lines.append(' print ("Exception in template %s() on "')
142
- pysrc_lines.append(' "line %d:" % (func_name, lineno))')
143
- pysrc_lines.append(' print pysrc[lineno-1]')
144
- pysrc_lines.append(' raise')
145
-
146
- pysrc = '\n'.join(pysrc_lines)+'\n'
147
- #log.debug(pysrc)
148
- if debug: localdict = {'__debug': (pysrc_lines, func_name)}
149
- else: localdict = {}
150
- try: exec pysrc in globals(), localdict
151
- except SyntaxError:
152
- log.error('Error in script:\n' + pysrc + '\n')
153
- raise
154
- template_func = localdict[func_name]
155
- template_func.__doc__ = docstring
156
- return template_func
157
-
158
- def strip_indent(s):
159
- """
160
- Given a multiline string C{s}, find the minimum indentation for
161
- all non-blank lines, and return a new string formed by stripping
162
- that amount of indentation from all lines in C{s}.
163
- """
164
- # Strip indentation from the template.
165
- minindent = sys.maxint
166
- lines = s.split('\n')
167
- for line in lines:
168
- stripline = line.lstrip()
169
- if stripline:
170
- minindent = min(minindent, len(line)-len(stripline))
171
- return '\n'.join([l[minindent:] for l in lines])
172
-
173
- ######################################################################
174
- ## HTML Writer
175
- ######################################################################
176
-
177
- class HTMLWriter:
178
- #////////////////////////////////////////////////////////////
179
- # Table of Contents
180
- #////////////////////////////////////////////////////////////
181
- #
182
- # 1. Interface Methods
183
- #
184
- # 2. Page Generation -- write complete web page files
185
- # 2.1. Module Pages
186
- # 2.2. Class Pages
187
- # 2.3. Trees Page
188
- # 2.4. Indices Page
189
- # 2.5. Help Page
190
- # 2.6. Frames-based table of contents pages
191
- # 2.7. Homepage (index.html)
192
- # 2.8. CSS Stylesheet
193
- # 2.9. Javascript file
194
- # 2.10. Graphs
195
- # 2.11. Images
196
- #
197
- # 3. Page Element Generation -- write pieces of a web page file
198
- # 3.1. Page Header
199
- # 3.2. Page Footer
200
- # 3.3. Navigation Bar
201
- # 3.4. Breadcrumbs
202
- # 3.5. Summary Tables
203
- #
204
- # 4. Helper functions
205
-
206
- def __init__(self, docindex, **kwargs):
207
- """
208
- Construct a new HTML writer, using the given documentation
209
- index.
210
-
211
- @param docindex: The documentation index.
212
-
213
- @type prj_name: C{string}
214
- @keyword prj_name: The name of the project. Defaults to
215
- none.
216
- @type prj_url: C{string}
217
- @keyword prj_url: The target for the project hopeage link on
218
- the navigation bar. If C{prj_url} is not specified,
219
- then no hyperlink is created.
220
- @type prj_link: C{string}
221
- @keyword prj_link: The label for the project link on the
222
- navigation bar. This link can contain arbitrary HTML
223
- code (e.g. images). By default, a label is constructed
224
- from C{prj_name}.
225
- @type top_page: C{string}
226
- @keyword top_page: The top page for the documentation. This
227
- is the default page shown main frame, when frames are
228
- enabled. C{top} can be a URL, the name of a
229
- module, the name of a class, or one of the special
230
- strings C{"trees.html"}, C{"indices.html"}, or
231
- C{"help.html"}. By default, the top-level package or
232
- module is used, if there is one; otherwise, C{"trees"}
233
- is used.
234
- @type css: C{string}
235
- @keyword css: The CSS stylesheet file. If C{css} is a file
236
- name, then the specified file's conents will be used.
237
- Otherwise, if C{css} is the name of a CSS stylesheet in
238
- L{epydoc.docwriter.html_css}, then that stylesheet will
239
- be used. Otherwise, an error is reported. If no stylesheet
240
- is specified, then the default stylesheet is used.
241
- @type help_file: C{string}
242
- @keyword help_file: The name of the help file. If no help file is
243
- specified, then the default help file will be used.
244
- @type show_private: C{boolean}
245
- @keyword show_private: Whether to create documentation for
246
- private objects. By default, private objects are documented.
247
- @type show_frames: C{boolean})
248
- @keyword show_frames: Whether to create a frames-based table of
249
- contents. By default, it is produced.
250
- @type show_imports: C{boolean}
251
- @keyword show_imports: Whether or not to display lists of
252
- imported functions and classes. By default, they are
253
- not shown.
254
- @type variable_maxlines: C{int}
255
- @keyword variable_maxlines: The maximum number of lines that
256
- should be displayed for the value of a variable in the
257
- variable details section. By default, 8 lines are
258
- displayed.
259
- @type variable_linelength: C{int}
260
- @keyword variable_linelength: The maximum line length used for
261
- displaying the values of variables in the variable
262
- details sections. If a line is longer than this length,
263
- then it will be wrapped to the next line. The default
264
- line length is 70 characters.
265
- @type variable_summary_linelength: C{int}
266
- @keyword variable_summary_linelength: The maximum line length
267
- used for displaying the values of variables in the summary
268
- section. If a line is longer than this length, then it
269
- will be truncated. The default is 40 characters.
270
- @type variable_tooltip_linelength: C{int}
271
- @keyword variable_tooltip_linelength: The maximum line length
272
- used for tooltips for the values of variables. If a
273
- line is longer than this length, then it will be
274
- truncated. The default is 600 characters.
275
- @type property_function_linelength: C{int}
276
- @keyword property_function_linelength: The maximum line length
277
- used to dispaly property functions (C{fget}, C{fset}, and
278
- C{fdel}) that contain something other than a function
279
- object. The default length is 40 characters.
280
- @type inheritance: C{string}
281
- @keyword inheritance: How inherited objects should be displayed.
282
- If C{inheritance='grouped'}, then inherited objects are
283
- gathered into groups; if C{inheritance='listed'}, then
284
- inherited objects are listed in a short list at the
285
- end of their group; if C{inheritance='included'}, then
286
- inherited objects are mixed in with non-inherited
287
- objects. The default is 'grouped'.
288
- @type include_source_code: C{boolean}
289
- @keyword include_source_code: If true, then generate colorized
290
- source code files for each python module.
291
- @type include_log: C{boolean}
292
- @keyword include_log: If true, the the footer will include an
293
- href to the page 'epydoc-log.html'.
294
- @type src_code_tab_width: C{int}
295
- @keyword src_code_tab_width: Number of spaces to replace each tab
296
- with in source code listings.
297
- """
298
- self.docindex = docindex
299
-
300
- # Process keyword arguments.
301
- self._show_private = kwargs.get('show_private', 1)
302
- """Should private docs be included?"""
303
-
304
- self._prj_name = kwargs.get('prj_name', None)
305
- """The project's name (for the project link in the navbar)"""
306
-
307
- self._prj_url = kwargs.get('prj_url', None)
308
- """URL for the project link in the navbar"""
309
-
310
- self._prj_link = kwargs.get('prj_link', None)
311
- """HTML code for the project link in the navbar"""
312
-
313
- self._top_page = kwargs.get('top_page', None)
314
- """The 'main' page"""
315
-
316
- self._css = kwargs.get('css')
317
- """CSS stylesheet to use"""
318
-
319
- self._helpfile = kwargs.get('help_file', None)
320
- """Filename of file to extract help contents from"""
321
-
322
- self._frames_index = kwargs.get('show_frames', 1)
323
- """Should a frames index be created?"""
324
-
325
- self._show_imports = kwargs.get('show_imports', False)
326
- """Should imports be listed?"""
327
-
328
- self._propfunc_linelen = kwargs.get('property_function_linelength', 40)
329
- """[XXX] Not used!"""
330
-
331
- self._variable_maxlines = kwargs.get('variable_maxlines', 8)
332
- """Max lines for variable values"""
333
-
334
- self._variable_linelen = kwargs.get('variable_linelength', 70)
335
- """Max line length for variable values"""
336
-
337
- self._variable_summary_linelen = \
338
- kwargs.get('variable_summary_linelength', 65)
339
- """Max length for variable value summaries"""
340
-
341
- self._variable_tooltip_linelen = \
342
- kwargs.get('variable_tooltip_linelength', 600)
343
- """Max length for variable tooltips"""
344
-
345
- self._inheritance = kwargs.get('inheritance', 'listed')
346
- """How should inheritance be displayed? 'listed', 'included',
347
- or 'grouped'"""
348
-
349
- self._incl_sourcecode = kwargs.get('include_source_code', True)
350
- """Should pages be generated for source code of modules?"""
351
-
352
- self._mark_docstrings = kwargs.get('mark_docstrings', False)
353
- """Wrap <span class='docstring'>...</span> around docstrings?"""
354
-
355
- self._graph_types = kwargs.get('graphs', ()) or ()
356
- """Graphs that we should include in our output."""
357
-
358
- self._include_log = kwargs.get('include_log', False)
359
- """Are we generating an HTML log page?"""
360
-
361
- self._src_code_tab_width = kwargs.get('src_code_tab_width', 8)
362
- """Number of spaces to replace each tab with in source code
363
- listings."""
364
-
365
- self._callgraph_cache = {}
366
- """Map the callgraph L{uid<DotGraph.uid>} to their HTML
367
- representation."""
368
-
369
- self._redundant_details = kwargs.get('redundant_details', False)
370
- """If true, then include objects in the details list even if all
371
- info about them is already provided by the summary table."""
372
-
373
- # For use with select_variables():
374
- if self._show_private:
375
- self._public_filter = None
376
- else:
377
- self._public_filter = True
378
-
379
- # Make sure inheritance has a sane value.
380
- if self._inheritance not in ('listed', 'included', 'grouped'):
381
- raise ValueError, 'Bad value for inheritance'
382
-
383
- # Create the project homepage link, if it was not specified.
384
- if (self._prj_name or self._prj_url) and not self._prj_link:
385
- self._prj_link = plaintext_to_html(self._prj_name or
386
- 'Project Homepage')
387
-
388
- # Add a hyperlink to _prj_url, if _prj_link doesn't already
389
- # contain any hyperlinks.
390
- if (self._prj_link and self._prj_url and
391
- not re.search(r'<a[^>]*\shref', self._prj_link)):
392
- self._prj_link = ('<a class="navbar" target="_top" href="'+
393
- self._prj_url+'">'+self._prj_link+'</a>')
394
-
395
- # Precompute lists & sets of APIDoc objects that we're
396
- # interested in.
397
- self.valdocs = valdocs = sorted(docindex.reachable_valdocs(
398
- imports=False, packages=False, bases=False, submodules=False,
399
- subclasses=False, private=self._show_private))
400
- self.module_list = [d for d in valdocs if isinstance(d, ModuleDoc)]
401
- """The list of L{ModuleDoc}s for the documented modules."""
402
- self.module_set = set(self.module_list)
403
- """The set of L{ModuleDoc}s for the documented modules."""
404
- self.class_list = [d for d in valdocs if isinstance(d, ClassDoc)]
405
- """The list of L{ClassDoc}s for the documented classes."""
406
- self.class_set = set(self.class_list)
407
- """The set of L{ClassDoc}s for the documented classes."""
408
- self.routine_list = [d for d in valdocs if isinstance(d, RoutineDoc)]
409
- """The list of L{RoutineDoc}s for the documented routines."""
410
- self.indexed_docs = []
411
- """The list of L{APIDoc}s for variables and values that should
412
- be included in the index."""
413
-
414
- # URL for 'trees' page
415
- if self.module_list: self._trees_url = 'module-tree.html'
416
- else: self._trees_url = 'class-tree.html'
417
-
418
- # Construct the value for self.indexed_docs.
419
- self.indexed_docs += [d for d in valdocs
420
- if not isinstance(d, GenericValueDoc)]
421
- for doc in valdocs:
422
- if isinstance(doc, NamespaceDoc):
423
- # add any vars with generic values; but don't include
424
- # inherited vars.
425
- self.indexed_docs += [d for d in doc.variables.values() if
426
- isinstance(d.value, GenericValueDoc)
427
- and d.container == doc]
428
- self.indexed_docs.sort()
429
-
430
- # Figure out the url for the top page.
431
- self._top_page_url = self._find_top_page(self._top_page)
432
-
433
- # Decide whether or not to split the identifier index.
434
- self._split_ident_index = (len(self.indexed_docs) >=
435
- self.SPLIT_IDENT_INDEX_SIZE)
436
-
437
- # Figure out how many output files there will be (for progress
438
- # reporting).
439
- self.modules_with_sourcecode = set()
440
- for doc in self.module_list:
441
- if isinstance(doc, ModuleDoc) and is_src_filename(doc.filename):
442
- self.modules_with_sourcecode.add(doc)
443
- self._num_files = (len(self.class_list) + len(self.module_list) +
444
- 10 + len(self.METADATA_INDICES))
445
- if self._frames_index:
446
- self._num_files += len(self.module_list) + 3
447
-
448
- if self._incl_sourcecode:
449
- self._num_files += len(self.modules_with_sourcecode)
450
- if self._split_ident_index:
451
- self._num_files += len(self.LETTERS)
452
-
453
- def _find_top_page(self, pagename):
454
- """
455
- Find the top page for the API documentation. This page is
456
- used as the default page shown in the main frame, when frames
457
- are used. When frames are not used, this page is copied to
458
- C{index.html}.
459
-
460
- @param pagename: The name of the page, as specified by the
461
- keyword argument C{top} to the constructor.
462
- @type pagename: C{string}
463
- @return: The URL of the top page.
464
- @rtype: C{string}
465
- """
466
- # If a page name was specified, then we need to figure out
467
- # what it points to.
468
- if pagename:
469
- # If it's a URL, then use it directly.
470
- if pagename.lower().startswith('http:'):
471
- return pagename
472
-
473
- # If it's an object, then use that object's page.
474
- try:
475
- doc = self.docindex.get_valdoc(pagename)
476
- return self.url(doc)
477
- except:
478
- pass
479
-
480
- # Otherwise, give up.
481
- log.warning('Could not find top page %r; using %s '
482
- 'instead' % (pagename, self._trees_url))
483
- return self._trees_url
484
-
485
- # If no page name was specified, then try to choose one
486
- # automatically.
487
- else:
488
- root = [val_doc for val_doc in self.docindex.root
489
- if isinstance(val_doc, (ClassDoc, ModuleDoc))]
490
- if len(root) == 0:
491
- # No docs?? Try the trees page.
492
- return self._trees_url
493
- elif len(root) == 1:
494
- # One item in the root; use that.
495
- return self.url(root[0])
496
- else:
497
- # Multiple root items; if they're all in one package,
498
- # then use that. Otherwise, use self._trees_url
499
- root = sorted(root, key=lambda v:len(v.canonical_name))
500
- top = root[0]
501
- for doc in root[1:]:
502
- if not top.canonical_name.dominates(doc.canonical_name):
503
- return self._trees_url
504
- else:
505
- return self.url(top)
506
-
507
- #////////////////////////////////////////////////////////////
508
- #{ 1. Interface Methods
509
- #////////////////////////////////////////////////////////////
510
-
511
- def write(self, directory=None):
512
- """
513
- Write the documentation to the given directory.
514
-
515
- @type directory: C{string}
516
- @param directory: The directory to which output should be
517
- written. If no directory is specified, output will be
518
- written to the current directory. If the directory does
519
- not exist, it will be created.
520
- @rtype: C{None}
521
- @raise OSError: If C{directory} cannot be created.
522
- @raise OSError: If any file cannot be created or written to.
523
- """
524
- # For progress reporting:
525
- self._files_written = 0.
526
-
527
- # Set the default values for ValueDoc formatted representations.
528
- orig_valdoc_defaults = (ValueDoc.SUMMARY_REPR_LINELEN,
529
- ValueDoc.REPR_LINELEN,
530
- ValueDoc.REPR_MAXLINES)
531
- ValueDoc.SUMMARY_REPR_LINELEN = self._variable_summary_linelen
532
- ValueDoc.REPR_LINELEN = self._variable_linelen
533
- ValueDoc.REPR_MAXLINES = self._variable_maxlines
534
-
535
- # Use an image for the crarr symbol.
536
- from epydoc.markup.epytext import ParsedEpytextDocstring
537
- orig_crarr_html = ParsedEpytextDocstring.SYMBOL_TO_HTML['crarr']
538
- ParsedEpytextDocstring.SYMBOL_TO_HTML['crarr'] = (
539
- r'<span class="variable-linewrap">'
540
- r'<img src="crarr.png" alt="\" /></span>')
541
-
542
- # Keep track of failed xrefs, and report them at the end.
543
- self._failed_xrefs = {}
544
-
545
- # Create destination directories, if necessary
546
- if not directory: directory = os.curdir
547
- self._mkdir(directory)
548
- self._directory = directory
549
-
550
- # Write the CSS file.
551
- self._files_written += 1
552
- log.progress(self._files_written/self._num_files, 'epydoc.css')
553
- self.write_css(directory, self._css)
554
-
555
- # Write the Javascript file.
556
- self._files_written += 1
557
- log.progress(self._files_written/self._num_files, 'epydoc.js')
558
- self.write_javascript(directory)
559
-
560
- # Write images
561
- self.write_images(directory)
562
-
563
- # Build the indices.
564
- indices = {'ident': self.build_identifier_index(),
565
- 'term': self.build_term_index()}
566
- for (name, label, label2) in self.METADATA_INDICES:
567
- indices[name] = self.build_metadata_index(name)
568
-
569
- # Write the identifier index. If requested, split it into
570
- # separate pages for each letter.
571
- ident_by_letter = self._group_by_letter(indices['ident'])
572
- if not self._split_ident_index:
573
- self._write(self.write_link_index, directory,
574
- 'identifier-index.html', indices,
575
- 'Identifier Index', 'identifier-index.html',
576
- ident_by_letter)
577
- else:
578
- # Write a page for each section.
579
- for letter in self.LETTERS:
580
- filename = 'identifier-index-%s.html' % letter
581
- self._write(self.write_link_index, directory, filename,
582
- indices, 'Identifier Index', filename,
583
- ident_by_letter, [letter],
584
- 'identifier-index-%s.html')
585
- # Use the first non-empty section as the main index page.
586
- for letter in self.LETTERS:
587
- if letter in ident_by_letter:
588
- filename = 'identifier-index.html'
589
- self._write(self.write_link_index, directory, filename,
590
- indices, 'Identifier Index', filename,
591
- ident_by_letter, [letter],
592
- 'identifier-index-%s.html')
593
- break
594
-
595
- # Write the term index.
596
- if indices['term']:
597
- term_by_letter = self._group_by_letter(indices['term'])
598
- self._write(self.write_link_index, directory, 'term-index.html',
599
- indices, 'Term Definition Index',
600
- 'term-index.html', term_by_letter)
601
- else:
602
- self._files_written += 1 # (skipped)
603
-
604
- # Write the metadata indices.
605
- for (name, label, label2) in self.METADATA_INDICES:
606
- if indices[name]:
607
- self._write(self.write_metadata_index, directory,
608
- '%s-index.html' % name, indices, name,
609
- label, label2)
610
- else:
611
- self._files_written += 1 # (skipped)
612
-
613
- # Write the trees file (package & class hierarchies)
614
- if self.module_list:
615
- self._write(self.write_module_tree, directory, 'module-tree.html')
616
- else:
617
- self._files_written += 1 # (skipped)
618
- if self.class_list:
619
- self._write(self.write_class_tree, directory, 'class-tree.html')
620
- else:
621
- self._files_written += 1 # (skipped)
622
-
623
- # Write the help file.
624
- self._write(self.write_help, directory,'help.html')
625
-
626
- # Write the frames-based table of contents.
627
- if self._frames_index:
628
- self._write(self.write_frames_index, directory, 'frames.html')
629
- self._write(self.write_toc, directory, 'toc.html')
630
- self._write(self.write_project_toc, directory, 'toc-everything.html')
631
- for doc in self.module_list:
632
- filename = 'toc-%s' % urllib.unquote(self.url(doc))
633
- self._write(self.write_module_toc, directory, filename, doc)
634
-
635
- # Write the object documentation.
636
- for doc in self.module_list:
637
- filename = urllib.unquote(self.url(doc))
638
- self._write(self.write_module, directory, filename, doc)
639
- for doc in self.class_list:
640
- filename = urllib.unquote(self.url(doc))
641
- self._write(self.write_class, directory, filename, doc)
642
-
643
- # Write source code files.
644
- if self._incl_sourcecode:
645
- # Build a map from short names to APIDocs, used when
646
- # linking names in the source code.
647
- name_to_docs = {}
648
- for api_doc in self.indexed_docs:
649
- if (api_doc.canonical_name is not None and
650
- self.url(api_doc) is not None):
651
- name = api_doc.canonical_name[-1]
652
- name_to_docs.setdefault(name, []).append(api_doc)
653
- # Sort each entry of the name_to_docs list.
654
- for doc_list in name_to_docs.values():
655
- doc_list.sort()
656
- # Write the source code for each module.
657
- for doc in self.modules_with_sourcecode:
658
- filename = urllib.unquote(self.pysrc_url(doc))
659
- self._write(self.write_sourcecode, directory, filename, doc,
660
- name_to_docs)
661
-
662
- # Write the auto-redirect page.
663
- self._write(self.write_redirect_page, directory, 'redirect.html')
664
-
665
- # Write the mapping object name -> URL
666
- self._write(self.write_api_list, directory, 'api-objects.txt')
667
-
668
- # Write the index.html files.
669
- # (this must be done last, since it might copy another file)
670
- self._files_written += 1
671
- log.progress(self._files_written/self._num_files, 'index.html')
672
- self.write_homepage(directory)
673
-
674
- # Don't report references to builtins as missing
675
- for k in self._failed_xrefs.keys(): # have a copy of keys
676
- if hasattr(__builtin__, k):
677
- del self._failed_xrefs[k]
678
-
679
- # Report any failed crossreferences
680
- if self._failed_xrefs:
681
- estr = 'Failed identifier crossreference targets:\n'
682
- failed_identifiers = self._failed_xrefs.keys()
683
- failed_identifiers.sort()
684
- for identifier in failed_identifiers:
685
- names = self._failed_xrefs[identifier].keys()
686
- names.sort()
687
- estr += '- %s' % identifier
688
- estr += '\n'
689
- for name in names:
690
- estr += ' (from %s)\n' % name
691
- log.docstring_warning(estr)
692
-
693
- # [xx] testing:
694
- if self._num_files != int(self._files_written):
695
- log.debug("Expected to write %d files, but actually "
696
- "wrote %d files" %
697
- (self._num_files, int(self._files_written)))
698
-
699
- # Restore defaults that we changed.
700
- (ValueDoc.SUMMARY_REPR_LINELEN, ValueDoc.REPR_LINELEN,
701
- ValueDoc.REPR_MAXLINES) = orig_valdoc_defaults
702
- ParsedEpytextDocstring.SYMBOL_TO_HTML['crarr'] = orig_crarr_html
703
-
704
- def _write(self, write_func, directory, filename, *args):
705
- # Display our progress.
706
- self._files_written += 1
707
- log.progress(self._files_written/self._num_files, filename)
708
-
709
- path = os.path.join(directory, filename)
710
- f = codecs.open(path, 'w', 'ascii', errors='xmlcharrefreplace')
711
- write_func(f.write, *args)
712
- f.close()
713
-
714
- def _mkdir(self, directory):
715
- """
716
- If the given directory does not exist, then attempt to create it.
717
- @rtype: C{None}
718
- """
719
- if not os.path.isdir(directory):
720
- if os.path.exists(directory):
721
- raise OSError('%r is not a directory' % directory)
722
- os.mkdir(directory)
723
-
724
- #////////////////////////////////////////////////////////////
725
- #{ 2.1. Module Pages
726
- #////////////////////////////////////////////////////////////
727
-
728
- def write_module(self, out, doc):
729
- """
730
- Write an HTML page containing the API documentation for the
731
- given module to C{out}.
732
-
733
- @param doc: A L{ModuleDoc} containing the API documentation
734
- for the module that should be described.
735
- """
736
- longname = doc.canonical_name
737
- shortname = doc.canonical_name[-1]
738
-
739
- # Write the page header (incl. navigation bar & breadcrumbs)
740
- self.write_header(out, str(longname))
741
- self.write_navbar(out, doc)
742
- self.write_breadcrumbs(out, doc, self.url(doc))
743
-
744
- # Write the name of the module we're describing.
745
- if doc.is_package is True: typ = 'Package'
746
- else: typ = 'Module'
747
- if longname[0].startswith('script-'):
748
- shortname = str(longname)[7:]
749
- typ = 'Script'
750
- out('<!-- ==================== %s ' % typ.upper() +
751
- 'DESCRIPTION ==================== -->\n')
752
- out('<h1 class="epydoc">%s %s</h1>' % (typ, shortname))
753
- out('<p class="nomargin-top">%s</p>\n' % self.pysrc_link(doc))
754
-
755
- # If the module has a description, then list it.
756
- if doc.descr not in (None, UNKNOWN):
757
- out(self.descr(doc, 2)+'\n\n')
758
-
759
- # Write any standarad metadata (todo, author, etc.)
760
- if doc.metadata is not UNKNOWN and doc.metadata:
761
- out('<hr />\n')
762
- self.write_standard_fields(out, doc)
763
-
764
- # If it's a package, then list the modules it contains.
765
- if doc.is_package is True:
766
- self.write_module_list(out, doc)
767
-
768
- # Write summary tables describing the variables that the
769
- # module defines.
770
- self.write_summary_table(out, "Classes", doc, "class")
771
- self.write_summary_table(out, "Functions", doc, "function")
772
- self.write_summary_table(out, "Variables", doc, "other")
773
-
774
- # Write a list of all imported objects.
775
- if self._show_imports:
776
- self.write_imports(out, doc)
777
-
778
- # Write detailed descriptions of functions & variables defined
779
- # in this module.
780
- self.write_details_list(out, "Function Details", doc, "function")
781
- self.write_details_list(out, "Variables Details", doc, "other")
782
-
783
- # Write the page footer (including navigation bar)
784
- self.write_navbar(out, doc)
785
- self.write_footer(out)
786
-
787
- #////////////////////////////////////////////////////////////
788
- #{ 2.??. Source Code Pages
789
- #////////////////////////////////////////////////////////////
790
-
791
- def write_sourcecode(self, out, doc, name_to_docs):
792
- #t0 = time.time()
793
-
794
- filename = doc.filename
795
- name = str(doc.canonical_name)
796
-
797
- # Header
798
- self.write_header(out, name)
799
- self.write_navbar(out, doc)
800
- self.write_breadcrumbs(out, doc, self.pysrc_url(doc))
801
-
802
- # Source code listing
803
- out('<h1 class="epydoc">Source Code for %s</h1>\n' %
804
- self.href(doc, label='%s %s' % (self.doc_kind(doc), name)))
805
- out('<pre class="py-src">\n')
806
- out(PythonSourceColorizer(filename, name, self.docindex,
807
- self.url, name_to_docs,
808
- self._src_code_tab_width).colorize())
809
- out('</pre>\n<br />\n')
810
-
811
- # Footer
812
- self.write_navbar(out, doc)
813
- self.write_footer(out)
814
-
815
- #log.debug('[%6.2f sec] Wrote pysrc for %s' %
816
- # (time.time()-t0, name))
817
-
818
- #////////////////////////////////////////////////////////////
819
- #{ 2.2. Class Pages
820
- #////////////////////////////////////////////////////////////
821
-
822
- def write_class(self, out, doc):
823
- """
824
- Write an HTML page containing the API documentation for the
825
- given class to C{out}.
826
-
827
- @param doc: A L{ClassDoc} containing the API documentation
828
- for the class that should be described.
829
- """
830
- longname = doc.canonical_name
831
- shortname = doc.canonical_name[-1]
832
-
833
- # Write the page header (incl. navigation bar & breadcrumbs)
834
- self.write_header(out, str(longname))
835
- self.write_navbar(out, doc)
836
- self.write_breadcrumbs(out, doc, self.url(doc))
837
-
838
- # Write the name of the class we're describing.
839
- if doc.is_type(): typ = 'Type'
840
- elif doc.is_exception(): typ = 'Exception'
841
- else: typ = 'Class'
842
- out('<!-- ==================== %s ' % typ.upper() +
843
- 'DESCRIPTION ==================== -->\n')
844
- out('<h1 class="epydoc">%s %s</h1>' % (typ, shortname))
845
- out('<p class="nomargin-top">%s</p>\n' % self.pysrc_link(doc))
846
-
847
- if ((doc.bases not in (UNKNOWN, None) and len(doc.bases) > 0) or
848
- (doc.subclasses not in (UNKNOWN,None) and len(doc.subclasses)>0)):
849
- # Display bases graphically, if requested.
850
- if 'umlclasstree' in self._graph_types:
851
- self.write_class_tree_graph(out, doc, uml_class_tree_graph)
852
- elif 'classtree' in self._graph_types:
853
- self.write_class_tree_graph(out, doc, class_tree_graph)
854
-
855
- # Otherwise, use ascii-art.
856
- else:
857
- # Write the base class tree.
858
- if doc.bases not in (UNKNOWN, None) and len(doc.bases) > 0:
859
- out('<pre class="base-tree">\n%s</pre>\n\n' %
860
- self.base_tree(doc))
861
-
862
- # Write the known subclasses
863
- if (doc.subclasses not in (UNKNOWN, None) and
864
- len(doc.subclasses) > 0):
865
- out('<dl><dt>Known Subclasses:</dt>\n<dd>\n ')
866
- out(' <ul class="subclass-list">\n')
867
- for i, subclass in enumerate(doc.subclasses):
868
- href = self.href(subclass, context=doc)
869
- if self._val_is_public(subclass): css = ''
870
- else: css = ' class="private"'
871
- if i > 0: href = ', '+href
872
- out('<li%s>%s</li>' % (css, href))
873
- out(' </ul>\n')
874
- out('</dd></dl>\n\n')
875
-
876
- out('<hr />\n')
877
-
878
- # If the class has a description, then list it.
879
- if doc.descr not in (None, UNKNOWN):
880
- out(self.descr(doc, 2)+'\n\n')
881
-
882
- # Write any standarad metadata (todo, author, etc.)
883
- if doc.metadata is not UNKNOWN and doc.metadata:
884
- out('<hr />\n')
885
- self.write_standard_fields(out, doc)
886
-
887
- # Write summary tables describing the variables that the
888
- # class defines.
889
- self.write_summary_table(out, "Nested Classes", doc, "class")
890
- self.write_summary_table(out, "Instance Methods", doc,
891
- "instancemethod")
892
- self.write_summary_table(out, "Class Methods", doc, "classmethod")
893
- self.write_summary_table(out, "Static Methods", doc, "staticmethod")
894
- self.write_summary_table(out, "Class Variables", doc,
895
- "classvariable")
896
- self.write_summary_table(out, "Instance Variables", doc,
897
- "instancevariable")
898
- self.write_summary_table(out, "Properties", doc, "property")
899
-
900
- # Write a list of all imported objects.
901
- if self._show_imports:
902
- self.write_imports(out, doc)
903
-
904
- # Write detailed descriptions of functions & variables defined
905
- # in this class.
906
- # [xx] why group methods into one section but split vars into two?
907
- # seems like we should either group in both cases or split in both
908
- # cases.
909
- self.write_details_list(out, "Method Details", doc, "method")
910
- self.write_details_list(out, "Class Variable Details", doc,
911
- "classvariable")
912
- self.write_details_list(out, "Instance Variable Details", doc,
913
- "instancevariable")
914
- self.write_details_list(out, "Property Details", doc, "property")
915
-
916
- # Write the page footer (including navigation bar)
917
- self.write_navbar(out, doc)
918
- self.write_footer(out)
919
-
920
- def write_class_tree_graph(self, out, doc, graphmaker):
921
- """
922
- Write HTML code for a class tree graph of C{doc} (a classdoc),
923
- using C{graphmaker} to draw the actual graph. C{graphmaker}
924
- should be L{class_tree_graph()}, or L{uml_class_tree_graph()},
925
- or any other function with a compatible signature.
926
-
927
- If the given class has any private sublcasses (including
928
- recursive subclasses), then two graph images will be generated
929
- -- one to display when private values are shown, and the other
930
- to display when private values are hidden.
931
- """
932
- linker = _HTMLDocstringLinker(self, doc)
933
- private_subcls = self._private_subclasses(doc)
934
- if private_subcls:
935
- out('<center>\n'
936
- ' <div class="private">%s</div>\n'
937
- ' <div class="public" style="display:none">%s</div>\n'
938
- '</center>\n' %
939
- (self.render_graph(graphmaker(doc, linker, doc)),
940
- self.render_graph(graphmaker(doc, linker, doc,
941
- exclude=private_subcls))))
942
- else:
943
- out('<center>\n%s\n</center>\n' %
944
- self.render_graph(graphmaker(doc, linker, doc)))
945
-
946
- #////////////////////////////////////////////////////////////
947
- #{ 2.3. Trees pages
948
- #////////////////////////////////////////////////////////////
949
-
950
- def write_module_tree(self, out):
951
- # Header material
952
- self.write_treepage_header(out, 'Module Hierarchy', 'module-tree.html')
953
- out('<h1 class="epydoc">Module Hierarchy</h1>\n')
954
-
955
- # Write entries for all top-level modules/packages.
956
- out('<ul class="nomargin-top">\n')
957
- for doc in self.module_list:
958
- if (doc.package in (None, UNKNOWN) or
959
- doc.package not in self.module_set):
960
- self.write_module_tree_item(out, doc)
961
- out('</ul>\n')
962
-
963
- # Footer material
964
- self.write_navbar(out, 'trees')
965
- self.write_footer(out)
966
-
967
- def write_class_tree(self, out):
968
- """
969
- Write HTML code for a nested list showing the base/subclass
970
- relationships between all documented classes. Each element of
971
- the top-level list is a class with no (documented) bases; and
972
- under each class is listed all of its subclasses. Note that
973
- in the case of multiple inheritance, a class may appear
974
- multiple times.
975
-
976
- @todo: For multiple inheritance, don't repeat subclasses the
977
- second time a class is mentioned; instead, link to the
978
- first mention.
979
- """
980
- # [XX] backref for multiple inheritance?
981
- # Header material
982
- self.write_treepage_header(out, 'Class Hierarchy', 'class-tree.html')
983
- out('<h1 class="epydoc">Class Hierarchy</h1>\n')
984
-
985
- # Build a set containing all classes that we should list.
986
- # This includes everything in class_list, plus any of those
987
- # class' bases, but not undocumented subclasses.
988
- class_set = self.class_set.copy()
989
- for doc in self.class_list:
990
- if doc.bases != UNKNOWN:
991
- for base in doc.bases:
992
- if base not in class_set:
993
- if isinstance(base, ClassDoc):
994
- class_set.update(base.mro())
995
- else:
996
- # [XX] need to deal with this -- how?
997
- pass
998
- #class_set.add(base)
999
-
1000
- out('<ul class="nomargin-top">\n')
1001
- for doc in sorted(class_set, key=lambda c:c.canonical_name[-1]):
1002
- if doc.bases != UNKNOWN and len(doc.bases)==0:
1003
- self.write_class_tree_item(out, doc, class_set)
1004
- out('</ul>\n')
1005
-
1006
- # Footer material
1007
- self.write_navbar(out, 'trees')
1008
- self.write_footer(out)
1009
-
1010
- def write_treepage_header(self, out, title, url):
1011
- # Header material.
1012
- self.write_header(out, title)
1013
- self.write_navbar(out, 'trees')
1014
- self.write_breadcrumbs(out, 'trees', url)
1015
- if self.class_list and self.module_list:
1016
- out('<center><b>\n')
1017
- out(' [ <a href="module-tree.html">Module Hierarchy</a>\n')
1018
- out(' | <a href="class-tree.html">Class Hierarchy</a> ]\n')
1019
- out('</b></center><br />\n')
1020
-
1021
-
1022
- #////////////////////////////////////////////////////////////
1023
- #{ 2.4. Index pages
1024
- #////////////////////////////////////////////////////////////
1025
-
1026
- SPLIT_IDENT_INDEX_SIZE = 3000
1027
- """If the identifier index has more than this number of entries,
1028
- then it will be split into separate pages, one for each
1029
- alphabetical section."""
1030
-
1031
- LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'
1032
- """The alphabetical sections that are used for link index pages."""
1033
-
1034
- def write_link_index(self, out, indices, title, url, index_by_section,
1035
- sections=LETTERS, section_url='#%s'):
1036
-
1037
- # Header
1038
- self.write_indexpage_header(out, indices, title, url)
1039
-
1040
- # Index title & links to alphabetical sections.
1041
- out('<table border="0" width="100%">\n'
1042
- '<tr valign="bottom"><td>\n')
1043
- out('<h1 class="epydoc">%s</h1>\n</td><td>\n[\n' % title)
1044
- for sec in self.LETTERS:
1045
- if sec in index_by_section:
1046
- out(' <a href="%s">%s</a>\n' % (section_url % sec, sec))
1047
- else:
1048
- out(' %s\n' % sec)
1049
- out(']\n')
1050
- out('</td></table>\n')
1051
-
1052
- # Alphabetical sections.
1053
- sections = [s for s in sections if s in index_by_section]
1054
- if sections:
1055
- out('<table border="0" width="100%">\n')
1056
- for section in sorted(sections):
1057
- out('<tr valign="top"><td valign="top" width="1%">')
1058
- out('<h2 class="epydoc"><a name="%s">%s</a></h2></td>\n' %
1059
- (section, section))
1060
- out('<td valign="top">\n')
1061
- self.write_index_section(out, index_by_section[section], True)
1062
- out('</td></tr>\n')
1063
- out('</table>\n<br />')
1064
-
1065
- # Footer material.
1066
- out('<br />')
1067
- self.write_navbar(out, 'indices')
1068
- self.write_footer(out)
1069
-
1070
-
1071
- def write_metadata_index(self, out, indices, field, title, typ):
1072
- """
1073
- Write an HTML page containing a metadata index.
1074
- """
1075
- index = indices[field]
1076
-
1077
- # Header material.
1078
- self.write_indexpage_header(out, indices, title,
1079
- '%s-index.html' % field)
1080
-
1081
- # Page title.
1082
- out('<h1 class="epydoc"><a name="%s">%s</a></h1>\n<br />\n' %
1083
- (field, title))
1084
-
1085
- # Index (one section per arg)
1086
- for arg in sorted(index):
1087
- # Write a section title.
1088
- if arg is not None:
1089
- if len([1 for (doc, descrs) in index[arg] if
1090
- not self._doc_or_ancestor_is_private(doc)]) == 0:
1091
- out('<div class="private">')
1092
- else:
1093
- out('<div>')
1094
- self.write_table_header(out, 'metadata-index', arg)
1095
- out('</table>')
1096
- # List every descr for this arg.
1097
- for (doc, descrs) in index[arg]:
1098
- if self._doc_or_ancestor_is_private(doc):
1099
- out('<div class="private">\n')
1100
- else:
1101
- out('<div>\n')
1102
- out('<table width="100%" class="metadata-index" '
1103
- 'bgcolor="#e0e0e0"><tr><td class="metadata-index">')
1104
- out('<b>%s in %s</b>' %
1105
- (typ, self.href(doc, label=doc.canonical_name)))
1106
- out(' <ul class="nomargin">\n')
1107
- for descr in descrs:
1108
- out(' <li>%s</li>\n' %
1109
- self.docstring_to_html(descr,doc,4))
1110
- out(' </ul>\n')
1111
- out('</table></div>\n')
1112
-
1113
- # Footer material.
1114
- out('<br />')
1115
- self.write_navbar(out, 'indices')
1116
- self.write_footer(out)
1117
-
1118
- def write_indexpage_header(self, out, indices, title, url):
1119
- """
1120
- A helper for the index page generation functions, which
1121
- generates a header that can be used to navigate between the
1122
- different indices.
1123
- """
1124
- self.write_header(out, title)
1125
- self.write_navbar(out, 'indices')
1126
- self.write_breadcrumbs(out, 'indices', url)
1127
-
1128
- if (indices['term'] or
1129
- [1 for (name,l,l2) in self.METADATA_INDICES if indices[name]]):
1130
- out('<center><b>[\n')
1131
- out(' <a href="identifier-index.html">Identifiers</a>\n')
1132
- if indices['term']:
1133
- out('| <a href="term-index.html">Term Definitions</a>\n')
1134
- for (name, label, label2) in self.METADATA_INDICES:
1135
- if indices[name]:
1136
- out('| <a href="%s-index.html">%s</a>\n' %
1137
- (name, label2))
1138
- out(']</b></center><br />\n')
1139
-
1140
- def write_index_section(self, out, items, add_blankline=False):
1141
- out('<table class="link-index" width="100%" border="1">\n')
1142
- num_rows = (len(items)+2)/3
1143
- for row in range(num_rows):
1144
- out('<tr>\n')
1145
- for col in range(3):
1146
- out('<td width="33%" class="link-index">')
1147
- i = col*num_rows+row
1148
- if i < len(items):
1149
- name, url, container = items[col*num_rows+row]
1150
- out('<a href="%s">%s</a>' % (url, name))
1151
- if container is not None:
1152
- out('<br />\n')
1153
- if isinstance(container, ModuleDoc):
1154
- label = container.canonical_name
1155
- else:
1156
- label = container.canonical_name[-1]
1157
- out('<span class="index-where">(in&nbsp;%s)'
1158
- '</span>' % self.href(container, label))
1159
- else:
1160
- out('&nbsp;')
1161
- out('</td>\n')
1162
- out('</tr>\n')
1163
- if add_blankline and num_rows == 1:
1164
- blank_cell = '<td class="link-index">&nbsp;</td>'
1165
- out('<tr>'+3*blank_cell+'</tr>\n')
1166
- out('</table>\n')
1167
-
1168
- #////////////////////////////////////////////////////////////
1169
- #{ 2.5. Help Page
1170
- #////////////////////////////////////////////////////////////
1171
-
1172
- def write_help(self, out):
1173
- """
1174
- Write an HTML help file to the given stream. If
1175
- C{self._helpfile} contains a help file, then use it;
1176
- otherwise, use the default helpfile from
1177
- L{epydoc.docwriter.html_help}.
1178
- """
1179
- # todo: optionally parse .rst etc help files?
1180
-
1181
- # Get the contents of the help file.
1182
- if self._helpfile:
1183
- if os.path.exists(self._helpfile):
1184
- try: help = open(self._helpfile).read()
1185
- except: raise IOError("Can't open help file: %r" %
1186
- self._helpfile)
1187
- else:
1188
- raise IOError("Can't find help file: %r" % self._helpfile)
1189
- else:
1190
- if self._prj_name: thisprj = self._prj_name
1191
- else: thisprj = 'this project'
1192
- help = HTML_HELP % {'this_project':thisprj}
1193
-
1194
- # Insert the help contents into a webpage.
1195
- self.write_header(out, 'Help')
1196
- self.write_navbar(out, 'help')
1197
- self.write_breadcrumbs(out, 'help', 'help.html')
1198
- out(help)
1199
- self.write_navbar(out, 'help')
1200
- self.write_footer(out)
1201
-
1202
- #////////////////////////////////////////////////////////////
1203
- #{ 2.6. Frames-based Table of Contents
1204
- #////////////////////////////////////////////////////////////
1205
-
1206
- write_frames_index = compile_template(
1207
- """
1208
- write_frames_index(self, out)
1209
-
1210
- Write the frames index file for the frames-based table of
1211
- contents to the given streams.
1212
- """,
1213
- # /------------------------- Template -------------------------\
1214
- '''
1215
- <?xml version="1.0" encoding="iso-8859-1"?>
1216
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
1217
- "DTD/xhtml1-frameset.dtd">
1218
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
1219
- <head>
1220
- <title> $self._prj_name or "API Documentation"$ </title>
1221
- </head>
1222
- <frameset cols="20%,80%">
1223
- <frameset rows="30%,70%">
1224
- <frame src="toc.html" name="moduleListFrame"
1225
- id="moduleListFrame" />
1226
- <frame src="toc-everything.html" name="moduleFrame"
1227
- id="moduleFrame" />
1228
- </frameset>
1229
- <frame src="$self._top_page_url$" name="mainFrame" id="mainFrame" />
1230
- </frameset>
1231
- </html>
1232
- ''')
1233
- # \------------------------------------------------------------/
1234
-
1235
- write_toc = compile_template(
1236
- """
1237
- write_toc(self, out)
1238
- """,
1239
- # /------------------------- Template -------------------------\
1240
- '''
1241
- >>> self.write_header(out, "Table of Contents")
1242
- <h1 class="toc">Table&nbsp;of&nbsp;Contents</h1>
1243
- <hr />
1244
- <a target="moduleFrame" href="toc-everything.html">Everything</a>
1245
- <br />
1246
- >>> self.write_toc_section(out, "Modules", self.module_list)
1247
- <hr />
1248
- >>> if self._show_private:
1249
- $self.PRIVATE_LINK$
1250
- >>> #endif
1251
- >>> self.write_footer(out, short=True)
1252
- ''')
1253
- # \------------------------------------------------------------/
1254
-
1255
- def write_toc_section(self, out, name, docs, fullname=True):
1256
- if not docs: return
1257
-
1258
- # Assign names to each item, and sort by name.
1259
- if fullname:
1260
- docs = [(str(d.canonical_name), d) for d in docs]
1261
- else:
1262
- docs = [(str(d.canonical_name[-1]), d) for d in docs]
1263
- docs.sort()
1264
-
1265
- out(' <h2 class="toc">%s</h2>\n' % name)
1266
- for label, doc in docs:
1267
- doc_url = self.url(doc)
1268
- toc_url = 'toc-%s' % doc_url
1269
- is_private = self._doc_or_ancestor_is_private(doc)
1270
- if is_private:
1271
- if not self._show_private: continue
1272
- out(' <div class="private">\n')
1273
-
1274
- if isinstance(doc, ModuleDoc):
1275
- out(' <a target="moduleFrame" href="%s"\n'
1276
- ' onclick="setFrame(\'%s\',\'%s\');"'
1277
- ' >%s</a><br />' % (toc_url, toc_url, doc_url, label))
1278
- else:
1279
- out(' <a target="mainFrame" href="%s"\n'
1280
- ' >%s</a><br />' % (doc_url, label))
1281
- if is_private:
1282
- out(' </div>\n')
1283
-
1284
- def write_project_toc(self, out):
1285
- self.write_header(out, "Everything")
1286
- out('<h1 class="toc">Everything</h1>\n')
1287
- out('<hr />\n')
1288
-
1289
- # List the classes.
1290
- self.write_toc_section(out, "All Classes", self.class_list)
1291
-
1292
- # List the functions.
1293
- funcs = [d for d in self.routine_list
1294
- if not isinstance(self.docindex.container(d),
1295
- (ClassDoc, types.NoneType))]
1296
- self.write_toc_section(out, "All Functions", funcs)
1297
-
1298
- # List the variables.
1299
- vars = []
1300
- for doc in self.module_list:
1301
- vars += doc.select_variables(value_type='other',
1302
- imported=False,
1303
- public=self._public_filter)
1304
- self.write_toc_section(out, "All Variables", vars)
1305
-
1306
- # Footer material.
1307
- out('<hr />\n')
1308
- if self._show_private:
1309
- out(self.PRIVATE_LINK+'\n')
1310
- self.write_footer(out, short=True)
1311
-
1312
- def write_module_toc(self, out, doc):
1313
- """
1314
- Write an HTML page containing the table of contents page for
1315
- the given module to the given streams. This page lists the
1316
- modules, classes, exceptions, functions, and variables defined
1317
- by the module.
1318
- """
1319
- name = doc.canonical_name[-1]
1320
- self.write_header(out, name)
1321
- out('<h1 class="toc">Module %s</h1>\n' % name)
1322
- out('<hr />\n')
1323
-
1324
-
1325
- # List the classes.
1326
- classes = doc.select_variables(value_type='class', imported=False,
1327
- public=self._public_filter)
1328
- self.write_toc_section(out, "Classes", classes, fullname=False)
1329
-
1330
- # List the functions.
1331
- funcs = doc.select_variables(value_type='function', imported=False,
1332
- public=self._public_filter)
1333
- self.write_toc_section(out, "Functions", funcs, fullname=False)
1334
-
1335
- # List the variables.
1336
- variables = doc.select_variables(value_type='other', imported=False,
1337
- public=self._public_filter)
1338
- self.write_toc_section(out, "Variables", variables, fullname=False)
1339
-
1340
- # Footer material.
1341
- out('<hr />\n')
1342
- if self._show_private:
1343
- out(self.PRIVATE_LINK+'\n')
1344
- self.write_footer(out, short=True)
1345
-
1346
- #////////////////////////////////////////////////////////////
1347
- #{ 2.7. Project homepage (index.html)
1348
- #////////////////////////////////////////////////////////////
1349
-
1350
- def write_homepage(self, directory):
1351
- """
1352
- Write an C{index.html} file in the given directory. The
1353
- contents of this file are copied or linked from an existing
1354
- page, so this method must be called after all pages have been
1355
- written. The page used is determined by L{_frames_index} and
1356
- L{_top_page}:
1357
- - If L{_frames_index} is true, then C{frames.html} is
1358
- copied.
1359
- - Otherwise, the page specified by L{_top_page} is
1360
- copied.
1361
- """
1362
- filename = os.path.join(directory, 'index.html')
1363
- if self._frames_index: top = 'frames.html'
1364
- else: top = self._top_page_url
1365
-
1366
- # Copy the non-frames index file from top, if it's internal.
1367
- if top[:5] != 'http:' and '/' not in top:
1368
- try:
1369
- # Read top into `s`.
1370
- topfile = os.path.join(directory, top)
1371
- s = open(topfile, 'r').read()
1372
-
1373
- # Write the output file.
1374
- open(filename, 'w').write(s)
1375
- return
1376
- except:
1377
- log.error('Warning: error copying index; '
1378
- 'using a redirect page')
1379
-
1380
- # Use a redirect if top is external, or if we faild to copy.
1381
- name = self._prj_name or 'this project'
1382
- f = open(filename, 'w')
1383
- self.write_redirect_index(f.write, top, name)
1384
- f.close()
1385
-
1386
- write_redirect_index = compile_template(
1387
- """
1388
- write_redirect_index(self, out, top, name)
1389
- """,
1390
- # /------------------------- Template -------------------------\
1391
- '''
1392
- <?xml version="1.0" encoding="iso-8859-1"?>
1393
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
1394
- "DTD/xhtml1-strict.dtd">
1395
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
1396
- <head>
1397
- <title> Redirect </title>
1398
- <meta http-equiv="refresh" content="1;url=$top$" />
1399
- <link rel="stylesheet" href="epydoc.css" type="text/css"></link>
1400
- </head>
1401
- <body>
1402
- <p>Redirecting to the API documentation for
1403
- <a href="$top$">$self._prj_name or "this project"$</a>...</p>
1404
- </body>
1405
- </html>
1406
- ''')
1407
- # \------------------------------------------------------------/
1408
-
1409
- #////////////////////////////////////////////////////////////
1410
- #{ 2.8. Stylesheet (epydoc.css)
1411
- #////////////////////////////////////////////////////////////
1412
-
1413
- def write_css(self, directory, cssname):
1414
- """
1415
- Write the CSS stylesheet in the given directory. If
1416
- C{cssname} contains a stylesheet file or name (from
1417
- L{epydoc.docwriter.html_css}), then use that stylesheet;
1418
- otherwise, use the default stylesheet.
1419
-
1420
- @rtype: C{None}
1421
- """
1422
- filename = os.path.join(directory, 'epydoc.css')
1423
-
1424
- # Get the contents for the stylesheet file.
1425
- if cssname is None:
1426
- css = STYLESHEETS['default'][0]
1427
- else:
1428
- if os.path.exists(cssname):
1429
- try: css = open(cssname).read()
1430
- except: raise IOError("Can't open CSS file: %r" % cssname)
1431
- elif cssname in STYLESHEETS:
1432
- css = STYLESHEETS[cssname][0]
1433
- else:
1434
- raise IOError("Can't find CSS file: %r" % cssname)
1435
-
1436
- # Write the stylesheet.
1437
- cssfile = open(filename, 'w')
1438
- cssfile.write(css)
1439
- cssfile.close()
1440
-
1441
- #////////////////////////////////////////////////////////////
1442
- #{ 2.9. Javascript (epydoc.js)
1443
- #////////////////////////////////////////////////////////////
1444
-
1445
- def write_javascript(self, directory):
1446
- jsfile = open(os.path.join(directory, 'epydoc.js'), 'w')
1447
- print >> jsfile, self.TOGGLE_PRIVATE_JS
1448
- print >> jsfile, self.SHOW_PRIVATE_JS
1449
- print >> jsfile, self.GET_COOKIE_JS
1450
- print >> jsfile, self.SET_FRAME_JS
1451
- print >> jsfile, self.HIDE_PRIVATE_JS
1452
- print >> jsfile, self.TOGGLE_CALLGRAPH_JS
1453
- print >> jsfile, html_colorize.PYSRC_JAVASCRIPTS
1454
- print >> jsfile, self.GET_ANCHOR_JS
1455
- print >> jsfile, self.REDIRECT_URL_JS
1456
- jsfile.close()
1457
-
1458
- #: A javascript that is used to show or hide the API documentation
1459
- #: for private objects. In order for this to work correctly, all
1460
- #: documentation for private objects should be enclosed in
1461
- #: C{<div class="private">...</div>} elements.
1462
- TOGGLE_PRIVATE_JS = '''
1463
- function toggle_private() {
1464
- // Search for any private/public links on this page. Store
1465
- // their old text in "cmd," so we will know what action to
1466
- // take; and change their text to the opposite action.
1467
- var cmd = "?";
1468
- var elts = document.getElementsByTagName("a");
1469
- for(var i=0; i<elts.length; i++) {
1470
- if (elts[i].className == "privatelink") {
1471
- cmd = elts[i].innerHTML;
1472
- elts[i].innerHTML = ((cmd && cmd.substr(0,4)=="show")?
1473
- "hide&nbsp;private":"show&nbsp;private");
1474
- }
1475
- }
1476
- // Update all DIVs containing private objects.
1477
- var elts = document.getElementsByTagName("div");
1478
- for(var i=0; i<elts.length; i++) {
1479
- if (elts[i].className == "private") {
1480
- elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")?"none":"block");
1481
- }
1482
- else if (elts[i].className == "public") {
1483
- elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")?"block":"none");
1484
- }
1485
- }
1486
- // Update all table rows containing private objects. Note, we
1487
- // use "" instead of "block" becaue IE & firefox disagree on what
1488
- // this should be (block vs table-row), and "" just gives the
1489
- // default for both browsers.
1490
- var elts = document.getElementsByTagName("tr");
1491
- for(var i=0; i<elts.length; i++) {
1492
- if (elts[i].className == "private") {
1493
- elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")?"none":"");
1494
- }
1495
- }
1496
- // Update all list items containing private objects.
1497
- var elts = document.getElementsByTagName("li");
1498
- for(var i=0; i<elts.length; i++) {
1499
- if (elts[i].className == "private") {
1500
- elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")?
1501
- "none":"");
1502
- }
1503
- }
1504
- // Update all list items containing private objects.
1505
- var elts = document.getElementsByTagName("ul");
1506
- for(var i=0; i<elts.length; i++) {
1507
- if (elts[i].className == "private") {
1508
- elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")?"none":"block");
1509
- }
1510
- }
1511
- // Set a cookie to remember the current option.
1512
- document.cookie = "EpydocPrivate="+cmd;
1513
- }
1514
- '''.strip()
1515
-
1516
- #: A javascript that is used to read the value of a cookie. This
1517
- #: is used to remember whether private variables should be shown or
1518
- #: hidden.
1519
- GET_COOKIE_JS = '''
1520
- function getCookie(name) {
1521
- var dc = document.cookie;
1522
- var prefix = name + "=";
1523
- var begin = dc.indexOf("; " + prefix);
1524
- if (begin == -1) {
1525
- begin = dc.indexOf(prefix);
1526
- if (begin != 0) return null;
1527
- } else
1528
- { begin += 2; }
1529
- var end = document.cookie.indexOf(";", begin);
1530
- if (end == -1)
1531
- { end = dc.length; }
1532
- return unescape(dc.substring(begin + prefix.length, end));
1533
- }
1534
- '''.strip()
1535
-
1536
- #: A javascript that is used to set the contents of two frames at
1537
- #: once. This is used by the project table-of-contents frame to
1538
- #: set both the module table-of-contents frame and the main frame
1539
- #: when the user clicks on a module.
1540
- SET_FRAME_JS = '''
1541
- function setFrame(url1, url2) {
1542
- parent.frames[1].location.href = url1;
1543
- parent.frames[2].location.href = url2;
1544
- }
1545
- '''.strip()
1546
-
1547
- #: A javascript that is used to hide private variables, unless
1548
- #: either: (a) the cookie says not to; or (b) we appear to be
1549
- #: linking to a private variable.
1550
- HIDE_PRIVATE_JS = '''
1551
- function checkCookie() {
1552
- var cmd=getCookie("EpydocPrivate");
1553
- if (cmd && cmd.substr(0,4)!="show" && location.href.indexOf("#_") < 0)
1554
- toggle_private();
1555
- }
1556
- '''.strip()
1557
-
1558
- TOGGLE_CALLGRAPH_JS = '''
1559
- function toggleCallGraph(id) {
1560
- var elt = document.getElementById(id);
1561
- if (elt.style.display == "none")
1562
- elt.style.display = "block";
1563
- else
1564
- elt.style.display = "none";
1565
- }
1566
- '''.strip()
1567
-
1568
- SHOW_PRIVATE_JS = '''
1569
- function show_private() {
1570
- var elts = document.getElementsByTagName("a");
1571
- for(var i=0; i<elts.length; i++) {
1572
- if (elts[i].className == "privatelink") {
1573
- cmd = elts[i].innerHTML;
1574
- if (cmd && cmd.substr(0,4)=="show")
1575
- toggle_private();
1576
- }
1577
- }
1578
- }
1579
- '''.strip()
1580
-
1581
- GET_ANCHOR_JS = '''
1582
- function get_anchor() {
1583
- var href = location.href;
1584
- var start = href.indexOf("#")+1;
1585
- if ((start != 0) && (start != href.length))
1586
- return href.substring(start, href.length);
1587
- }
1588
- '''.strip()
1589
-
1590
- #: A javascript that is used to implement the auto-redirect page.
1591
- #: When the user visits <redirect.html#dotted.name>, they will
1592
- #: automatically get redirected to the page for the object with
1593
- #: the given fully-qualified dotted name. E.g., for epydoc,
1594
- #: <redirect.html#epydoc.apidoc.UNKNOWN> redirects the user to
1595
- #: <epydoc.apidoc-module.html#UNKNOWN>.
1596
- REDIRECT_URL_JS = '''
1597
- function redirect_url(dottedName) {
1598
- // Scan through each element of the "pages" list, and check
1599
- // if "name" matches with any of them.
1600
- for (var i=0; i<pages.length; i++) {
1601
-
1602
- // Each page has the form "<pagename>-m" or "<pagename>-c";
1603
- // extract the <pagename> portion & compare it to dottedName.
1604
- var pagename = pages[i].substring(0, pages[i].length-2);
1605
- if (pagename == dottedName.substring(0,pagename.length)) {
1606
-
1607
- // We\'ve found a page that matches `dottedName`;
1608
- // construct its URL, using leftover `dottedName`
1609
- // content to form an anchor.
1610
- var pagetype = pages[i].charAt(pages[i].length-1);
1611
- var url = pagename + ((pagetype=="m")?"-module.html":
1612
- "-class.html");
1613
- if (dottedName.length > pagename.length)
1614
- url += "#" + dottedName.substring(pagename.length+1,
1615
- dottedName.length);
1616
- return url;
1617
- }
1618
- }
1619
- }
1620
- '''.strip()
1621
-
1622
-
1623
- #////////////////////////////////////////////////////////////
1624
- #{ 2.10. Graphs
1625
- #////////////////////////////////////////////////////////////
1626
-
1627
- def render_graph(self, graph):
1628
- if graph is None: return ''
1629
- graph.caption = graph.title = None
1630
- image_url = '%s.gif' % graph.uid
1631
- image_file = os.path.join(self._directory, image_url)
1632
- return graph.to_html(image_file, image_url)
1633
-
1634
- RE_CALLGRAPH_ID = re.compile(r"""["'](.+-div)['"]""")
1635
-
1636
- def render_callgraph(self, callgraph, token=""):
1637
- """Render the HTML chunk of a callgraph.
1638
-
1639
- If C{callgraph} is a string, use the L{_callgraph_cache} to return
1640
- a pre-rendered HTML chunk. This mostly avoids to run C{dot} twice for
1641
- the same callgraph. Else, run the graph and store its HTML output in
1642
- the cache.
1643
-
1644
- @param callgraph: The graph to render or its L{uid<DotGraph.uid>}.
1645
- @type callgraph: L{DotGraph} or C{str}
1646
- @param token: A string that can be used to make the C{<div>} id
1647
- unambiguous, if the callgraph is used more than once in a page.
1648
- @type token: C{str}
1649
- @return: The HTML representation of the graph.
1650
- @rtype: C{str}
1651
- """
1652
- if callgraph is None: return ""
1653
-
1654
- if isinstance(callgraph, basestring):
1655
- uid = callgraph
1656
- rv = self._callgraph_cache.get(callgraph, "")
1657
-
1658
- else:
1659
- uid = callgraph.uid
1660
- graph_html = self.render_graph(callgraph)
1661
- if graph_html == '':
1662
- rv = ""
1663
- else:
1664
- rv = ('<div style="display:none" id="%%s-div"><center>\n'
1665
- '<table border="0" cellpadding="0" cellspacing="0">\n'
1666
- ' <tr><td>%s</td></tr>\n'
1667
- ' <tr><th>Call Graph</th></tr>\n'
1668
- '</table><br />\n</center></div>\n' % graph_html)
1669
-
1670
- # Store in the cache the complete HTML chunk without the
1671
- # div id, which may be made unambiguous by the token
1672
- self._callgraph_cache[uid] = rv
1673
-
1674
- # Mangle with the graph
1675
- if rv: rv = rv % (uid + token)
1676
- return rv
1677
-
1678
- def callgraph_link(self, callgraph, token=""):
1679
- """Render the HTML chunk of a callgraph link.
1680
-
1681
- The link can toggles the visibility of the callgraph rendered using
1682
- L{render_callgraph} with matching parameters.
1683
-
1684
- @param callgraph: The graph to render or its L{uid<DotGraph.uid>}.
1685
- @type callgraph: L{DotGraph} or C{str}
1686
- @param token: A string that can be used to make the C{<div>} id
1687
- unambiguous, if the callgraph is used more than once in a page.
1688
- @type token: C{str}
1689
- @return: The HTML representation of the graph link.
1690
- @rtype: C{str}
1691
- """
1692
- # Use class=codelink, to match style w/ the source code link.
1693
- if callgraph is None: return ''
1694
-
1695
- if isinstance(callgraph, basestring):
1696
- uid = callgraph
1697
- else:
1698
- uid = callgraph.uid
1699
-
1700
- return ('<br /><span class="codelink"><a href="javascript:void(0);" '
1701
- 'onclick="toggleCallGraph(\'%s-div\');return false;">'
1702
- 'call&nbsp;graph</a></span>&nbsp;' % (uid + token))
1703
-
1704
- #////////////////////////////////////////////////////////////
1705
- #{ 2.11. Images
1706
- #////////////////////////////////////////////////////////////
1707
-
1708
- IMAGES = {'crarr.png': # Carriage-return arrow, used for LINEWRAP.
1709
- 'iVBORw0KGgoAAAANSUhEUgAAABEAAAAKCAMAAABlokWQAAAALHRFWHRD'
1710
- 'cmVhdGlvbiBUaW1lAFR1\nZSAyMiBBdWcgMjAwNiAwMDo0MzoxMCAtMD'
1711
- 'UwMGAMEFgAAAAHdElNRQfWCBYFASkQ033WAAAACXBI\nWXMAAB7CAAAe'
1712
- 'wgFu0HU+AAAABGdBTUEAALGPC/xhBQAAAEVQTFRF////zcOw18/AgGY0'
1713
- 'c1cg4dvQ\ninJEYEAAYkME3NXI6eTcloFYe2Asr5+AbE4Uh29A9fPwqp'
1714
- 'l4ZEUI8O3onopk0Ma0lH5U1nfFdgAA\nAAF0Uk5TAEDm2GYAAABNSURB'
1715
- 'VHjaY2BAAbzsvDAmK5oIlxgfioiwCAe7KJKIgKAQOzsLLwTwA0VY\n+d'
1716
- 'iRAT8T0AxuIIMHqoaXCWIPGzsHJ6orGJiYWRjQASOcBQAocgMSPKMTIg'
1717
- 'AAAABJRU5ErkJggg==\n',
1718
- }
1719
-
1720
- def write_images(self, directory):
1721
- for (name, data) in self.IMAGES.items():
1722
- f = open(os.path.join(directory, name), 'wb')
1723
- f.write(base64.decodestring(data))
1724
- f.close()
1725
-
1726
- #////////////////////////////////////////////////////////////
1727
- #{ 3.1. Page Header
1728
- #////////////////////////////////////////////////////////////
1729
-
1730
- write_header = compile_template(
1731
- """
1732
- write_header(self, out, title)
1733
-
1734
- Generate HTML code for the standard page header, and write it
1735
- to C{out}. C{title} is a string containing the page title.
1736
- It should be appropriately escaped/encoded.
1737
- """,
1738
- # /------------------------- Template -------------------------\
1739
- '''
1740
- <?xml version="1.0" encoding="ascii"?>
1741
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
1742
- "DTD/xhtml1-transitional.dtd">
1743
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
1744
- <head>
1745
- <title>$title$</title>
1746
- <link rel="stylesheet" href="epydoc.css" type="text/css" />
1747
- <script type="text/javascript" src="epydoc.js"></script>
1748
- </head>
1749
-
1750
- <body bgcolor="white" text="black" link="blue" vlink="#204080"
1751
- alink="#204080">
1752
- ''')
1753
- # \------------------------------------------------------------/
1754
-
1755
- #////////////////////////////////////////////////////////////
1756
- #{ 3.2. Page Footer
1757
- #////////////////////////////////////////////////////////////
1758
-
1759
- write_footer = compile_template(
1760
- """
1761
- write_footer(self, out, short=False)
1762
-
1763
- Generate HTML code for the standard page footer, and write it
1764
- to C{out}.
1765
- """,
1766
- # /------------------------- Template -------------------------\
1767
- '''
1768
- >>> if not short:
1769
- <table border="0" cellpadding="0" cellspacing="0" width="100%%">
1770
- <tr>
1771
- <td align="left" class="footer">
1772
- >>> if self._include_log:
1773
- <a href="epydoc-log.html">Generated by Epydoc
1774
- $epydoc.__version__$ on $time.asctime()$</a>
1775
- >>> else:
1776
- Generated by Epydoc $epydoc.__version__$ on $time.asctime()$
1777
- >>> #endif
1778
- </td>
1779
- <td align="right" class="footer">
1780
- <a target="mainFrame" href="http://epydoc.sourceforge.net"
1781
- >http://epydoc.sourceforge.net</a>
1782
- </td>
1783
- </tr>
1784
- </table>
1785
- >>> #endif
1786
-
1787
- <script type="text/javascript">
1788
- <!--
1789
- // Private objects are initially displayed (because if
1790
- // javascript is turned off then we want them to be
1791
- // visible); but by default, we want to hide them. So hide
1792
- // them unless we have a cookie that says to show them.
1793
- checkCookie();
1794
- // -->
1795
- </script>
1796
- </body>
1797
- </html>
1798
- ''')
1799
- # \------------------------------------------------------------/
1800
-
1801
- #////////////////////////////////////////////////////////////
1802
- #{ 3.3. Navigation Bar
1803
- #////////////////////////////////////////////////////////////
1804
-
1805
- write_navbar = compile_template(
1806
- """
1807
- write_navbar(self, out, context)
1808
-
1809
- Generate HTML code for the navigation bar, and write it to
1810
- C{out}. The navigation bar typically looks like::
1811
-
1812
- [ Home Trees Index Help Project ]
1813
-
1814
- @param context: A value indicating what page we're generating
1815
- a navigation bar for. If we're generating an API
1816
- documentation page for an object, then C{context} is a
1817
- L{ValueDoc} containing the documentation for that object;
1818
- otherwise, C{context} is a string name for the page. The
1819
- following string names are recognized: C{'tree'}, C{'index'},
1820
- and C{'help'}.
1821
- """,
1822
- # /------------------------- Template -------------------------\
1823
- '''
1824
- <!-- ==================== NAVIGATION BAR ==================== -->
1825
- <table class="navbar" border="0" width="100%" cellpadding="0"
1826
- bgcolor="#a0c0ff" cellspacing="0">
1827
- <tr valign="middle">
1828
- >>> if self._top_page_url not in (self._trees_url, "identifier-index.html", "help.html"):
1829
- <!-- Home link -->
1830
- >>> if (isinstance(context, ValueDoc) and
1831
- >>> self._top_page_url == self.url(context.canonical_name)):
1832
- <th bgcolor="#70b0f0" class="navbar-select"
1833
- >&nbsp;&nbsp;&nbsp;Home&nbsp;&nbsp;&nbsp;</th>
1834
- >>> else:
1835
- <th>&nbsp;&nbsp;&nbsp;<a
1836
- href="$self._top_page_url$">Home</a>&nbsp;&nbsp;&nbsp;</th>
1837
- >>> #endif
1838
-
1839
- <!-- Tree link -->
1840
- >>> if context == "trees":
1841
- <th bgcolor="#70b0f0" class="navbar-select"
1842
- >&nbsp;&nbsp;&nbsp;Trees&nbsp;&nbsp;&nbsp;</th>
1843
- >>> else:
1844
- <th>&nbsp;&nbsp;&nbsp;<a
1845
- href="$self._trees_url$">Trees</a>&nbsp;&nbsp;&nbsp;</th>
1846
- >>> #endif
1847
-
1848
- <!-- Index link -->
1849
- >>> if context == "indices":
1850
- <th bgcolor="#70b0f0" class="navbar-select"
1851
- >&nbsp;&nbsp;&nbsp;Indices&nbsp;&nbsp;&nbsp;</th>
1852
- >>> else:
1853
- <th>&nbsp;&nbsp;&nbsp;<a
1854
- href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
1855
- >>> #endif
1856
-
1857
- <!-- Help link -->
1858
- >>> if context == "help":
1859
- <th bgcolor="#70b0f0" class="navbar-select"
1860
- >&nbsp;&nbsp;&nbsp;Help&nbsp;&nbsp;&nbsp;</th>
1861
- >>> else:
1862
- <th>&nbsp;&nbsp;&nbsp;<a
1863
- href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
1864
- >>> #endif
1865
-
1866
- >>> if self._prj_link:
1867
- <!-- Project homepage -->
1868
- <th class="navbar" align="right" width="100%">
1869
- <table border="0" cellpadding="0" cellspacing="0">
1870
- <tr><th class="navbar" align="center"
1871
- >$self._prj_link.strip()$</th>
1872
- </tr></table></th>
1873
- >>> else:
1874
- <th class="navbar" width="100%"></th>
1875
- >>> #endif
1876
- </tr>
1877
- </table>
1878
- ''')
1879
- # \------------------------------------------------------------/
1880
-
1881
- #////////////////////////////////////////////////////////////
1882
- #{ 3.4. Breadcrumbs
1883
- #////////////////////////////////////////////////////////////
1884
-
1885
- write_breadcrumbs = compile_template(
1886
- """
1887
- write_breadcrumbs(self, out, context, context_url)
1888
-
1889
- Generate HTML for the breadcrumbs line, and write it to
1890
- C{out}. The breadcrumbs line is an invisible table with a
1891
- list of pointers to the current object's ancestors on the
1892
- left; and the show/hide private selector and the
1893
- frames/noframes selector on the right.
1894
-
1895
- @param context: The API documentation for the object whose
1896
- breadcrumbs we should generate.
1897
- @type context: L{ValueDoc}
1898
- """,
1899
- # /------------------------- Template -------------------------\
1900
- '''
1901
- <table width="100%" cellpadding="0" cellspacing="0">
1902
- <tr valign="top">
1903
- >>> if isinstance(context, APIDoc):
1904
- <td width="100%">
1905
- <span class="breadcrumbs">
1906
- >>> crumbs = self.breadcrumbs(context)
1907
- >>> for crumb in crumbs[:-1]:
1908
- $crumb$ ::
1909
- >>> #endfor
1910
- $crumbs[-1]$
1911
- </span>
1912
- </td>
1913
- >>> else:
1914
- <td width="100%">&nbsp;</td>
1915
- >>> #endif
1916
- <td>
1917
- <table cellpadding="0" cellspacing="0">
1918
- <!-- hide/show private -->
1919
- >>> if self._show_private:
1920
- <tr><td align="right">$self.PRIVATE_LINK$</td></tr>
1921
- >>> #endif
1922
- >>> if self._frames_index:
1923
- <tr><td align="right"><span class="options"
1924
- >[<a href="frames.html" target="_top">frames</a
1925
- >]&nbsp;|&nbsp;<a href="$context_url$"
1926
- target="_top">no&nbsp;frames</a>]</span></td></tr>
1927
- >>> #endif
1928
- </table>
1929
- </td>
1930
- </tr>
1931
- </table>
1932
- ''')
1933
- # \------------------------------------------------------------/
1934
-
1935
- def breadcrumbs(self, doc):
1936
- crumbs = [self._crumb(doc)]
1937
-
1938
- # Generate the crumbs for uid's ancestors.
1939
- while True:
1940
- container = self.docindex.container(doc)
1941
- assert doc != container, 'object is its own container?'
1942
- if container is None:
1943
- if doc.canonical_name is UNKNOWN:
1944
- return ['??']+crumbs
1945
- elif isinstance(doc, ModuleDoc):
1946
- return ['Package&nbsp;%s' % ident
1947
- for ident in doc.canonical_name[:-1]]+crumbs
1948
- else:
1949
- return list(doc.canonical_name)+crumbs
1950
- else:
1951
- label = self._crumb(container)
1952
- name = container.canonical_name
1953
- crumbs.insert(0, self.href(container, label)) # [xx] code=0??
1954
- doc = container
1955
-
1956
- def _crumb(self, doc):
1957
- if (len(doc.canonical_name)==1 and
1958
- doc.canonical_name[0].startswith('script-')):
1959
- return 'Script&nbsp;%s' % doc.canonical_name[0][7:]
1960
- return '%s&nbsp;%s' % (self.doc_kind(doc), doc.canonical_name[-1])
1961
-
1962
- #////////////////////////////////////////////////////////////
1963
- #{ 3.5. Summary Tables
1964
- #////////////////////////////////////////////////////////////
1965
-
1966
- def write_summary_table(self, out, heading, doc, value_type):
1967
- """
1968
- Generate HTML code for a summary table, and write it to
1969
- C{out}. A summary table is a table that includes a one-row
1970
- description for each variable (of a given type) in a module
1971
- or class.
1972
-
1973
- @param heading: The heading for the summary table; typically,
1974
- this indicates what kind of value the table describes
1975
- (e.g., functions or classes).
1976
- @param doc: A L{ValueDoc} object containing the API
1977
- documentation for the module or class whose variables
1978
- we should summarize.
1979
- @param value_type: A string indicating what type of value
1980
- should be listed in this summary table. This value
1981
- is passed on to C{doc}'s C{select_variables()} method.
1982
- """
1983
- # inh_var_groups is a dictionary used to hold "inheritance
1984
- # pseudo-groups", which are created when inheritance is
1985
- # 'grouped'. It maps each base to a list of vars inherited
1986
- # from that base.
1987
- grouped_inh_vars = {}
1988
-
1989
- # Divide all public variables of the given type into groups.
1990
- groups = [(plaintext_to_html(group_name),
1991
- doc.select_variables(group=group_name, imported=False,
1992
- value_type=value_type,
1993
- public=self._public_filter))
1994
- for group_name in doc.group_names()]
1995
-
1996
- # Discard any empty groups; and return if they're all empty.
1997
- groups = [(g,vars) for (g,vars) in groups if vars]
1998
- if not groups: return
1999
-
2000
- # Write a header
2001
- self.write_table_header(out, "summary", heading)
2002
-
2003
- # Write a section for each group.
2004
- for name, var_docs in groups:
2005
- self.write_summary_group(out, doc, name,
2006
- var_docs, grouped_inh_vars)
2007
-
2008
- # Write a section for each inheritance pseudo-group (used if
2009
- # inheritance=='grouped')
2010
- if grouped_inh_vars:
2011
- for base in doc.mro():
2012
- if base in grouped_inh_vars:
2013
- hdr = 'Inherited from %s' % self.href(base, context=doc)
2014
- tr_class = ''
2015
- if len([v for v in grouped_inh_vars[base]
2016
- if v.is_public]) == 0:
2017
- tr_class = ' class="private"'
2018
- self.write_group_header(out, hdr, tr_class)
2019
- for var_doc in grouped_inh_vars[base]:
2020
- self.write_summary_line(out, var_doc, doc)
2021
-
2022
- # Write a footer for the table.
2023
- out(self.TABLE_FOOTER)
2024
-
2025
- def write_summary_group(self, out, doc, name, var_docs, grouped_inh_vars):
2026
- # Split up the var_docs list, according to the way each var
2027
- # should be displayed:
2028
- # - listed_inh_vars -- for listed inherited variables.
2029
- # - grouped_inh_vars -- for grouped inherited variables.
2030
- # - normal_vars -- for all other variables.
2031
- listed_inh_vars = {}
2032
- normal_vars = []
2033
- for var_doc in var_docs:
2034
- if var_doc.container != doc:
2035
- base = var_doc.container
2036
- if not isinstance(base, ClassDoc):
2037
- # This *should* never happen:
2038
- log.warning("%s's container is not a class!" % var_doc)
2039
- normal_vars.append(var_doc)
2040
- elif (base not in self.class_set or
2041
- self._inheritance == 'listed'):
2042
- listed_inh_vars.setdefault(base,[]).append(var_doc)
2043
- elif self._inheritance == 'grouped':
2044
- grouped_inh_vars.setdefault(base,[]).append(var_doc)
2045
- else:
2046
- normal_vars.append(var_doc)
2047
- else:
2048
- normal_vars.append(var_doc)
2049
-
2050
- # Write a header for the group.
2051
- if name != '':
2052
- tr_class = ''
2053
- if len([v for v in var_docs if v.is_public]) == 0:
2054
- tr_class = ' class="private"'
2055
- self.write_group_header(out, name, tr_class)
2056
-
2057
- # Write a line for each normal var:
2058
- for var_doc in normal_vars:
2059
- self.write_summary_line(out, var_doc, doc)
2060
- # Write a subsection for inherited vars:
2061
- if listed_inh_vars:
2062
- self.write_inheritance_list(out, doc, listed_inh_vars)
2063
-
2064
- def write_inheritance_list(self, out, doc, listed_inh_vars):
2065
- out(' <tr>\n <td colspan="2" class="summary">\n')
2066
- for base in doc.mro():
2067
- if base not in listed_inh_vars: continue
2068
- public_vars = [v for v in listed_inh_vars[base]
2069
- if v.is_public]
2070
- private_vars = [v for v in listed_inh_vars[base]
2071
- if not v.is_public]
2072
- if public_vars:
2073
- out(' <p class="indent-wrapped-lines">'
2074
- '<b>Inherited from <code>%s</code></b>:\n' %
2075
- self.href(base, context=doc))
2076
- self.write_var_list(out, public_vars)
2077
- out(' </p>\n')
2078
- if private_vars and self._show_private:
2079
- out(' <div class="private">')
2080
- out(' <p class="indent-wrapped-lines">'
2081
- '<b>Inherited from <code>%s</code></b> (private):\n' %
2082
- self.href(base, context=doc))
2083
- self.write_var_list(out, private_vars)
2084
- out(' </p></div>\n')
2085
- out(' </td>\n </tr>\n')
2086
-
2087
- def write_var_list(self, out, vardocs):
2088
- out(' ')
2089
- out(',\n '.join(['<code>%s</code>' % self.href(v,v.name)
2090
- for v in vardocs])+'\n')
2091
-
2092
- def write_summary_line(self, out, var_doc, container):
2093
- """
2094
- Generate HTML code for a single line of a summary table, and
2095
- write it to C{out}. See L{write_summary_table} for more
2096
- information.
2097
-
2098
- @param var_doc: The API documentation for the variable that
2099
- should be described by this line of the summary table.
2100
- @param container: The API documentation for the class or
2101
- module whose summary table we're writing.
2102
- """
2103
- pysrc_link = None
2104
- callgraph = None
2105
-
2106
- # If it's a private variable, then mark its <tr>.
2107
- if var_doc.is_public: tr_class = ''
2108
- else: tr_class = ' class="private"'
2109
-
2110
- # Decide an anchor or a link is to be generated.
2111
- link_name = self._redundant_details or var_doc.is_detailed()
2112
- anchor = not link_name
2113
-
2114
- # Construct the HTML code for the type (cell 1) & description
2115
- # (cell 2).
2116
- if isinstance(var_doc.value, RoutineDoc):
2117
- typ = self.return_type(var_doc, indent=6)
2118
- description = self.function_signature(var_doc, is_summary=True,
2119
- link_name=link_name, anchor=anchor)
2120
- pysrc_link = self.pysrc_link(var_doc.value)
2121
-
2122
- # Perpare the call-graph, if requested
2123
- if 'callgraph' in self._graph_types:
2124
- linker = _HTMLDocstringLinker(self, var_doc.value)
2125
- callgraph = call_graph([var_doc.value], self.docindex,
2126
- linker, var_doc, add_callers=True,
2127
- add_callees=True)
2128
- if callgraph and callgraph.nodes:
2129
- var_doc.value.callgraph_uid = callgraph.uid
2130
- else:
2131
- callgraph = None
2132
- else:
2133
- typ = self.type_descr(var_doc, indent=6)
2134
- description = self.summary_name(var_doc,
2135
- link_name=link_name, anchor=anchor)
2136
- if isinstance(var_doc.value, GenericValueDoc):
2137
- # The summary max length has been chosen setting
2138
- # L{ValueDoc.SUMMARY_REPR_LINELEN} in the constructor
2139
- max_len=self._variable_summary_linelen-3-len(var_doc.name)
2140
- val_repr = var_doc.value.summary_pyval_repr(max_len)
2141
- tooltip = self.variable_tooltip(var_doc)
2142
- description += (' = <code%s>%s</code>' %
2143
- (tooltip, val_repr.to_html(None)))
2144
-
2145
- # Add the summary to the description (if there is one).
2146
- summary = self.summary(var_doc, indent=6)
2147
- if summary: description += '<br />\n %s' % summary
2148
-
2149
- # If it's inherited, then add a note to the description.
2150
- if var_doc.container != container and self._inheritance=="included":
2151
- description += ("\n <em>(Inherited from " +
2152
- self.href(var_doc.container) + ")</em>")
2153
-
2154
- # Write the summary line.
2155
- self._write_summary_line(out, typ, description, tr_class, pysrc_link,
2156
- callgraph)
2157
-
2158
- _write_summary_line = compile_template(
2159
- "_write_summary_line(self, out, typ, description, tr_class, "
2160
- "pysrc_link, callgraph)",
2161
- # /------------------------- Template -------------------------\
2162
- '''
2163
- <tr$tr_class$>
2164
- <td width="15%" align="right" valign="top" class="summary">
2165
- <span class="summary-type">$typ or "&nbsp;"$</span>
2166
- </td><td class="summary">
2167
- >>> if pysrc_link is not None or callgraph is not None:
2168
- <table width="100%" cellpadding="0" cellspacing="0" border="0">
2169
- <tr>
2170
- <td>$description$</td>
2171
- <td align="right" valign="top">
2172
- $pysrc_link$
2173
- $self.callgraph_link(callgraph, token='-summary')$
2174
- </td>
2175
- </tr>
2176
- </table>
2177
- $self.render_callgraph(callgraph, token='-summary')$
2178
- >>> #endif
2179
- >>> if pysrc_link is None and callgraph is None:
2180
- $description$
2181
- >>> #endif
2182
- </td>
2183
- </tr>
2184
- ''')
2185
- # \------------------------------------------------------------/
2186
-
2187
- #////////////////////////////////////////////////////////////
2188
- #{ 3.6. Details Lists
2189
- #////////////////////////////////////////////////////////////
2190
-
2191
- def write_details_list(self, out, heading, doc, value_type):
2192
- # Get a list of the VarDocs we should describe.
2193
- if self._redundant_details:
2194
- detailed = None
2195
- else:
2196
- detailed = True
2197
- if isinstance(doc, ClassDoc):
2198
- var_docs = doc.select_variables(value_type=value_type,
2199
- imported=False, inherited=False,
2200
- public=self._public_filter,
2201
- detailed=detailed)
2202
- else:
2203
- var_docs = doc.select_variables(value_type=value_type,
2204
- imported=False,
2205
- public=self._public_filter,
2206
- detailed=detailed)
2207
- if not var_docs: return
2208
-
2209
- # Write a header
2210
- self.write_table_header(out, "details", heading)
2211
- out(self.TABLE_FOOTER)
2212
-
2213
- for var_doc in var_docs:
2214
- self.write_details_entry(out, var_doc)
2215
-
2216
- out('<br />\n')
2217
-
2218
- def write_details_entry(self, out, var_doc):
2219
- descr = self.descr(var_doc, indent=2) or ''
2220
- if var_doc.is_public: div_class = ''
2221
- else: div_class = ' class="private"'
2222
-
2223
- # Functions
2224
- if isinstance(var_doc.value, RoutineDoc):
2225
- rtype = self.return_type(var_doc, indent=10)
2226
- rdescr = self.return_descr(var_doc, indent=10)
2227
- arg_descrs = []
2228
- args = set()
2229
- # Find the description for each arg. (Leave them in the
2230
- # same order that they're listed in the docstring.)
2231
- for (arg_names, arg_descr) in var_doc.value.arg_descrs:
2232
- args.update(arg_names)
2233
- lhs = ', '.join([self.arg_name_to_html(var_doc.value, n)
2234
- for n in arg_names])
2235
- rhs = self.docstring_to_html(arg_descr, var_doc.value, 10)
2236
- arg_descrs.append( (lhs, rhs) )
2237
- # Check for arguments for which we have @type but not @param;
2238
- # and add them to the arg_descrs list.
2239
- for arg in var_doc.value.arg_types:
2240
- if arg not in args:
2241
- argname = self.arg_name_to_html(var_doc.value, arg)
2242
- arg_descrs.append( (argname,'') )
2243
-
2244
- self.write_function_details_entry(out, var_doc, descr,
2245
- var_doc.value.callgraph_uid,
2246
- rtype, rdescr, arg_descrs,
2247
- div_class)
2248
-
2249
- # Properties
2250
- elif isinstance(var_doc.value, PropertyDoc):
2251
- prop_doc = var_doc.value
2252
- accessors = [ (name,
2253
- self.property_accessor_to_html(val_doc, prop_doc),
2254
- self.summary(val_doc))
2255
- for (name, val_doc) in
2256
- [('Get', prop_doc.fget), ('Set', prop_doc.fset),
2257
- ('Delete', prop_doc.fdel)]
2258
- if val_doc not in (None, UNKNOWN)
2259
- and val_doc.pyval is not None ]
2260
-
2261
- self.write_property_details_entry(out, var_doc, descr,
2262
- accessors, div_class)
2263
-
2264
- # Variables
2265
- else:
2266
- self.write_variable_details_entry(out, var_doc, descr, div_class)
2267
-
2268
- def labelled_list_item(self, lhs, rhs):
2269
- # If the RHS starts with a paragraph, then move the
2270
- # paragraph-start tag to the beginning of the lhs instead (so
2271
- # there won't be a line break after the '-').
2272
- m = re.match(r'^<p( [^>]+)?>', rhs)
2273
- if m:
2274
- lhs = m.group() + lhs
2275
- rhs = rhs[m.end():]
2276
-
2277
- if rhs:
2278
- return '<li>%s - %s</li>' % (lhs, rhs)
2279
- else:
2280
- return '<li>%s</li>' % (lhs,)
2281
-
2282
- def property_accessor_to_html(self, val_doc, context=None):
2283
- if val_doc not in (None, UNKNOWN):
2284
- if isinstance(val_doc, RoutineDoc):
2285
- return self.function_signature(val_doc, is_summary=True,
2286
- link_name=True, context=context)
2287
- elif isinstance(val_doc, GenericValueDoc):
2288
- return self.pprint_value(val_doc)
2289
- else:
2290
- return self.href(val_doc, context=context)
2291
- else:
2292
- return '??'
2293
-
2294
- def arg_name_to_html(self, func_doc, arg_name):
2295
- """
2296
- A helper function used to format an argument name, for use in
2297
- the argument description list under a routine's details entry.
2298
- This just wraps strong & code tags around the arg name; and if
2299
- the arg name is associated with a type, then adds it
2300
- parenthetically after the name.
2301
- """
2302
- s = '<strong class="pname"><code>%s</code></strong>' % arg_name
2303
- if arg_name in func_doc.arg_types:
2304
- typ = func_doc.arg_types[arg_name]
2305
- typ_html = self.docstring_to_html(typ, func_doc, 10)
2306
- s += " (%s)" % typ_html
2307
- return s
2308
-
2309
- write_function_details_entry = compile_template(
2310
- '''
2311
- write_function_details_entry(self, out, var_doc, descr, callgraph, \
2312
- rtype, rdescr, arg_descrs, div_class)
2313
- ''',
2314
- # /------------------------- Template -------------------------\
2315
- '''
2316
- >>> func_doc = var_doc.value
2317
- <a name="$var_doc.name$"></a>
2318
- <div$div_class$>
2319
- >>> self.write_table_header(out, "details")
2320
- <tr><td>
2321
- <table width="100%" cellpadding="0" cellspacing="0" border="0">
2322
- <tr valign="top"><td>
2323
- <h3 class="epydoc">$self.function_signature(var_doc)$
2324
- >>> if var_doc.name in self.SPECIAL_METHODS:
2325
- <br /><em class="fname">($self.SPECIAL_METHODS[var_doc.name]$)</em>
2326
- >>> #endif
2327
- >>> if isinstance(func_doc, ClassMethodDoc):
2328
- <br /><em class="fname">Class Method</em>
2329
- >>> #endif
2330
- >>> if isinstance(func_doc, StaticMethodDoc):
2331
- <br /><em class="fname">Static Method</em>
2332
- >>> #endif
2333
- </h3>
2334
- </td><td align="right" valign="top"
2335
- >$self.pysrc_link(func_doc)$&nbsp;
2336
- $self.callgraph_link(callgraph)$</td>
2337
- </tr></table>
2338
- $self.render_callgraph(callgraph)$
2339
- $descr$
2340
- <dl class="fields">
2341
- >>> # === parameters ===
2342
- >>> if arg_descrs:
2343
- <dt>Parameters:</dt>
2344
- <dd><ul class="nomargin-top">
2345
- >>> for lhs, rhs in arg_descrs:
2346
- $self.labelled_list_item(lhs, rhs)$
2347
- >>> #endfor
2348
- </ul></dd>
2349
- >>> #endif
2350
- >>> # === return type ===
2351
- >>> if rdescr and rtype:
2352
- <dt>Returns: $rtype$</dt>
2353
- <dd>$rdescr$</dd>
2354
- >>> elif rdescr:
2355
- <dt>Returns:</dt>
2356
- <dd>$rdescr$</dd>
2357
- >>> elif rtype:
2358
- <dt>Returns: $rtype$</dt>
2359
- >>> #endif
2360
- >>> # === decorators ===
2361
- >>> if func_doc.decorators not in (None, UNKNOWN):
2362
- >>> # (staticmethod & classmethod are already shown, above)
2363
- >>> decos = filter(lambda deco:
2364
- >>> not ((deco=="staticmethod" and
2365
- >>> isinstance(func_doc, StaticMethodDoc)) or
2366
- >>> (deco=="classmethod" and
2367
- >>> isinstance(func_doc, ClassMethodDoc))),
2368
- >>> func_doc.decorators)
2369
- >>> else:
2370
- >>> decos = None
2371
- >>> #endif
2372
- >>> if decos:
2373
- <dt>Decorators:</dt>
2374
- <dd><ul class="nomargin-top">
2375
- >>> for deco in decos:
2376
- <li><code>@$deco$</code></li>
2377
- >>> #endfor
2378
- </ul></dd>
2379
- >>> #endif
2380
- >>> # === exceptions ===
2381
- >>> if func_doc.exception_descrs not in (None, UNKNOWN, (), []):
2382
- <dt>Raises:</dt>
2383
- <dd><ul class="nomargin-top">
2384
- >>> for name, descr in func_doc.exception_descrs:
2385
- >>> exc_name = self.docindex.find(name, func_doc)
2386
- >>> if exc_name is not None:
2387
- >>> name = self.href(exc_name, label=str(name))
2388
- >>> #endif
2389
- $self.labelled_list_item(
2390
- "<code><strong class=\'fraise\'>" +
2391
- str(name) + "</strong></code>",
2392
- self.docstring_to_html(descr, func_doc, 8))$
2393
- >>> #endfor
2394
- </ul></dd>
2395
- >>> #endif
2396
- >>> # === overrides ===
2397
- >>> if var_doc.overrides not in (None, UNKNOWN):
2398
- <dt>Overrides:
2399
- >>> # Avoid passing GenericValueDoc to href()
2400
- >>> if isinstance(var_doc.overrides.value, RoutineDoc):
2401
- $self.href(var_doc.overrides.value, context=var_doc)$
2402
- >>> else:
2403
- >>> # In this case, a less interesting label is generated.
2404
- $self.href(var_doc.overrides, context=var_doc)$
2405
- >>> #endif
2406
- >>> if (func_doc.docstring in (None, UNKNOWN) and
2407
- >>> var_doc.overrides.value.docstring not in (None, UNKNOWN)):
2408
- <dd><em class="note">(inherited documentation)</em></dd>
2409
- >>> #endif
2410
- </dt>
2411
- >>> #endif
2412
- </dl>
2413
- >>> # === metadata ===
2414
- >>> self.write_standard_fields(out, func_doc)
2415
- </td></tr></table>
2416
- </div>
2417
- ''')
2418
- # \------------------------------------------------------------/
2419
-
2420
- # Names for the __special__ methods.
2421
- SPECIAL_METHODS ={
2422
- '__init__': 'Constructor',
2423
- '__del__': 'Destructor',
2424
- '__add__': 'Addition operator',
2425
- '__sub__': 'Subtraction operator',
2426
- '__and__': 'And operator',
2427
- '__or__': 'Or operator',
2428
- '__xor__': 'Exclusive-Or operator',
2429
- '__repr__': 'Representation operator',
2430
- '__call__': 'Call operator',
2431
- '__getattr__': 'Qualification operator',
2432
- '__getitem__': 'Indexing operator',
2433
- '__setitem__': 'Index assignment operator',
2434
- '__delitem__': 'Index deletion operator',
2435
- '__delslice__': 'Slice deletion operator',
2436
- '__setslice__': 'Slice assignment operator',
2437
- '__getslice__': 'Slicling operator',
2438
- '__len__': 'Length operator',
2439
- '__cmp__': 'Comparison operator',
2440
- '__eq__': 'Equality operator',
2441
- '__in__': 'Containership operator',
2442
- '__gt__': 'Greater-than operator',
2443
- '__lt__': 'Less-than operator',
2444
- '__ge__': 'Greater-than-or-equals operator',
2445
- '__le__': 'Less-than-or-equals operator',
2446
- '__radd__': 'Right-side addition operator',
2447
- '__hash__': 'Hashing function',
2448
- '__contains__': 'In operator',
2449
- '__nonzero__': 'Boolean test operator',
2450
- '__str__': 'Informal representation operator',
2451
- }
2452
-
2453
- write_property_details_entry = compile_template(
2454
- '''
2455
- write_property_details_entry(self, out, var_doc, descr, \
2456
- accessors, div_class)
2457
- ''',
2458
- # /------------------------- Template -------------------------\
2459
- '''
2460
- >>> prop_doc = var_doc.value
2461
- <a name="$var_doc.name$"></a>
2462
- <div$div_class$>
2463
- >>> self.write_table_header(out, "details")
2464
- <tr><td>
2465
- <h3 class="epydoc">$var_doc.name$</h3>
2466
- $descr$
2467
- <dl class="fields">
2468
- >>> for (name, val, summary) in accessors:
2469
- <dt>$name$ Method:</dt>
2470
- <dd class="value">$val$
2471
- >>> if summary:
2472
- - $summary$
2473
- >>> #endif
2474
- </dd>
2475
- >>> #endfor
2476
- >>> if prop_doc.type_descr not in (None, UNKNOWN):
2477
- <dt>Type:</dt>
2478
- <dd>$self.type_descr(var_doc, indent=6)$</dd>
2479
- >>> #endif
2480
- </dl>
2481
- >>> self.write_standard_fields(out, prop_doc)
2482
- </td></tr></table>
2483
- </div>
2484
- ''')
2485
- # \------------------------------------------------------------/
2486
-
2487
- write_variable_details_entry = compile_template(
2488
- '''
2489
- write_variable_details_entry(self, out, var_doc, descr, div_class)
2490
- ''',
2491
- # /------------------------- Template -------------------------\
2492
- '''
2493
- <a name="$var_doc.name$"></a>
2494
- <div$div_class$>
2495
- >>> self.write_table_header(out, "details")
2496
- <tr><td>
2497
- <h3 class="epydoc">$var_doc.name$</h3>
2498
- $descr$
2499
- <dl class="fields">
2500
- >>> if var_doc.type_descr not in (None, UNKNOWN):
2501
- <dt>Type:</dt>
2502
- <dd>$self.type_descr(var_doc, indent=6)$</dd>
2503
- >>> #endif
2504
- </dl>
2505
- >>> self.write_standard_fields(out, var_doc)
2506
- >>> if var_doc.value is not UNKNOWN:
2507
- <dl class="fields">
2508
- <dt>Value:</dt>
2509
- <dd>$self.pprint_value(var_doc.value)$</dd>
2510
- </dl>
2511
- >>> #endif
2512
- </td></tr></table>
2513
- </div>
2514
- ''')
2515
- # \------------------------------------------------------------/
2516
-
2517
- def variable_tooltip(self, var_doc):
2518
- if var_doc.value in (None, UNKNOWN):
2519
- return ''
2520
- s = var_doc.value.pyval_repr().to_plaintext(None)
2521
- if len(s) > self._variable_tooltip_linelen:
2522
- s = s[:self._variable_tooltip_linelen-3]+'...'
2523
- return ' title="%s"' % plaintext_to_html(s)
2524
-
2525
- def pprint_value(self, val_doc):
2526
- if val_doc is UNKNOWN:
2527
- return '??'
2528
- elif isinstance(val_doc, GenericValueDoc):
2529
- return ('<table><tr><td><pre class="variable">\n' +
2530
- val_doc.pyval_repr().to_html(None) +
2531
- '\n</pre></td></tr></table>\n')
2532
- else:
2533
- return self.href(val_doc)
2534
-
2535
- #////////////////////////////////////////////////////////////
2536
- #{ Base Tree
2537
- #////////////////////////////////////////////////////////////
2538
-
2539
- def base_tree(self, doc, width=None, postfix='', context=None):
2540
- """
2541
- @return: The HTML code for a class's base tree. The tree is
2542
- drawn 'upside-down' and right justified, to allow for
2543
- multiple inheritance.
2544
- @rtype: C{string}
2545
- """
2546
- if context is None:
2547
- context = doc.defining_module
2548
- if width == None: width = self.find_tree_width(doc, context)
2549
- if isinstance(doc, ClassDoc) and doc.bases != UNKNOWN:
2550
- bases = doc.bases
2551
- else:
2552
- bases = []
2553
-
2554
- if postfix == '':
2555
- # [XX] use var name instead of canonical name?
2556
- s = (' '*(width-2) + '<strong class="uidshort">'+
2557
- self.contextual_label(doc, context)+'</strong>\n')
2558
- else: s = ''
2559
- for i in range(len(bases)-1, -1, -1):
2560
- base = bases[i]
2561
- label = self.contextual_label(base, context)
2562
- s = (' '*(width-4-len(label)) + self.href(base, label)
2563
- +' --+'+postfix+'\n' +
2564
- ' '*(width-4) +
2565
- ' |'+postfix+'\n' +
2566
- s)
2567
- if i != 0:
2568
- s = (self.base_tree(base, width-4, ' |'+postfix, context)+s)
2569
- else:
2570
- s = (self.base_tree(base, width-4, ' '+postfix, context)+s)
2571
- return s
2572
-
2573
- def find_tree_width(self, doc, context):
2574
- """
2575
- Helper function for L{base_tree}.
2576
- @return: The width of a base tree, when drawn
2577
- right-justified. This is used by L{base_tree} to
2578
- determine how far to indent lines of the base tree.
2579
- @rtype: C{int}
2580
- """
2581
- if not isinstance(doc, ClassDoc): return 2
2582
- if doc.bases == UNKNOWN: return 2
2583
- width = 2
2584
- for base in doc.bases:
2585
- width = max(width, len(self.contextual_label(base, context))+4,
2586
- self.find_tree_width(base, context)+4)
2587
- return width
2588
-
2589
- def contextual_label(self, doc, context):
2590
- """
2591
- Return the label for C{doc} to be shown in C{context}.
2592
- """
2593
- if doc.canonical_name is None:
2594
- if doc.parse_repr is not None:
2595
- return doc.parse_repr
2596
- else:
2597
- return '??'
2598
- else:
2599
- if context is UNKNOWN:
2600
- return str(doc.canonical_name)
2601
- else:
2602
- context_name = context.canonical_name
2603
- return str(doc.canonical_name.contextualize(context_name))
2604
-
2605
- #////////////////////////////////////////////////////////////
2606
- #{ Function Signatures
2607
- #////////////////////////////////////////////////////////////
2608
-
2609
- def function_signature(self, api_doc, is_summary=False,
2610
- link_name=False, anchor=False, context=None):
2611
- """Render a function signature in HTML.
2612
-
2613
- @param api_doc: The object whose name is to be rendered. If a
2614
- C{VariableDoc}, its C{value} should be a C{RoutineDoc}
2615
- @type api_doc: L{VariableDoc} or L{RoutineDoc}
2616
- @param is_summary: True if the fuction is to be rendered in the summary.
2617
- type css_class: C{bool}
2618
- @param link_name: If True, the name is a link to the object anchor.
2619
- @type link_name: C{bool}
2620
- @param anchor: If True, the name is the object anchor.
2621
- @type anchor: C{bool}
2622
- @param context: If set, represent the function name from this context.
2623
- Only useful when C{api_doc} is a L{RoutineDoc}.
2624
- @type context: L{DottedName}
2625
-
2626
- @return: The HTML code for the object.
2627
- @rtype: C{str}
2628
- """
2629
- if is_summary: css_class = 'summary-sig'
2630
- else: css_class = 'sig'
2631
-
2632
- # [XX] clean this up!
2633
- if isinstance(api_doc, VariableDoc):
2634
- func_doc = api_doc.value
2635
- # This should never happen, but just in case:
2636
- if api_doc.value in (None, UNKNOWN):
2637
- return (('<span class="%s"><span class="%s-name">%s'+
2638
- '</span>(...)</span>') %
2639
- (css_class, css_class, api_doc.name))
2640
- # Get the function's name.
2641
- name = self.summary_name(api_doc, css_class=css_class+'-name',
2642
- link_name=link_name, anchor=anchor)
2643
- else:
2644
- func_doc = api_doc
2645
- name = self.href(api_doc, css_class=css_class+'-name',
2646
- context=context)
2647
-
2648
- if func_doc.posargs == UNKNOWN:
2649
- args = ['...']
2650
- else:
2651
- args = [self.func_arg(n, d, css_class) for (n, d)
2652
- in zip(func_doc.posargs, func_doc.posarg_defaults)]
2653
- if func_doc.vararg not in (None, UNKNOWN):
2654
- if func_doc.vararg == '...':
2655
- args.append('<span class="%s-arg">...</span>' % css_class)
2656
- else:
2657
- args.append('<span class="%s-arg">*%s</span>' %
2658
- (css_class, func_doc.vararg))
2659
- if func_doc.kwarg not in (None, UNKNOWN):
2660
- args.append('<span class="%s-arg">**%s</span>' %
2661
- (css_class, func_doc.kwarg))
2662
-
2663
- return ('<span class="%s">%s(%s)</span>' %
2664
- (css_class, name, ',\n '.join(args)))
2665
-
2666
- def summary_name(self, api_doc, css_class='summary-name',
2667
- link_name=False, anchor=False):
2668
- """Render an object name in HTML.
2669
-
2670
- @param api_doc: The object whose name is to be rendered
2671
- @type api_doc: L{APIDoc}
2672
- @param css_class: The CSS class to assign to the rendered name
2673
- type css_class: C{str}
2674
- @param link_name: If True, the name is a link to the object anchor.
2675
- @type link_name: C{bool}
2676
- @param anchor: If True, the name is the object anchor.
2677
- @type anchor: C{bool}
2678
-
2679
- @return: The HTML code for the object.
2680
- @rtype: C{str}
2681
- """
2682
- if anchor:
2683
- rv = '<a name="%s"></a>' % api_doc.name
2684
- else:
2685
- rv = ''
2686
-
2687
- if link_name:
2688
- rv += self.href(api_doc, css_class=css_class)
2689
- else:
2690
- rv += '<span class="%s">%s</span>' % (css_class, api_doc.name)
2691
-
2692
- return rv
2693
-
2694
- # [xx] tuple args???
2695
- def func_arg(self, name, default, css_class):
2696
- name = self._arg_name(name)
2697
- s = '<span class="%s-arg">%s</span>' % (css_class, name)
2698
- if default is not None:
2699
- s += ('=<span class="%s-default">%s</span>' %
2700
- (css_class, default.summary_pyval_repr().to_html(None)))
2701
- return s
2702
-
2703
- def _arg_name(self, arg):
2704
- if isinstance(arg, basestring):
2705
- return arg
2706
- elif len(arg) == 1:
2707
- return '(%s,)' % self._arg_name(arg[0])
2708
- else:
2709
- return '(%s)' % (', '.join([self._arg_name(a) for a in arg]))
2710
-
2711
-
2712
-
2713
-
2714
- #////////////////////////////////////////////////////////////
2715
- #{ Import Lists
2716
- #////////////////////////////////////////////////////////////
2717
-
2718
- def write_imports(self, out, doc):
2719
- assert isinstance(doc, NamespaceDoc)
2720
- imports = doc.select_variables(imported=True,
2721
- public=self._public_filter)
2722
- if not imports: return
2723
-
2724
- out('<p class="indent-wrapped-lines">')
2725
- out('<b>Imports:</b>\n ')
2726
- out(',\n '.join([self._import(v, doc) for v in imports]))
2727
- out('\n</p><br />\n')
2728
-
2729
- def _import(self, var_doc, context):
2730
- if var_doc.imported_from not in (None, UNKNOWN):
2731
- return self.href(var_doc.imported_from,
2732
- var_doc.name, context=context,
2733
- tooltip='%s' % var_doc.imported_from)
2734
- elif (var_doc.value not in (None, UNKNOWN) and not
2735
- isinstance(var_doc.value, GenericValueDoc)):
2736
- return self.href(var_doc.value,
2737
- var_doc.name, context=context,
2738
- tooltip='%s' % var_doc.value.canonical_name)
2739
- else:
2740
- return plaintext_to_html(var_doc.name)
2741
-
2742
- #////////////////////////////////////////////////////////////
2743
- #{ Function Attributes
2744
- #////////////////////////////////////////////////////////////
2745
-
2746
- #////////////////////////////////////////////////////////////
2747
- #{ Module Trees
2748
- #////////////////////////////////////////////////////////////
2749
-
2750
- def write_module_list(self, out, doc):
2751
- if len(doc.submodules) == 0: return
2752
- self.write_table_header(out, "summary", "Submodules")
2753
-
2754
- for group_name in doc.group_names():
2755
- if not doc.submodule_groups[group_name]: continue
2756
- if group_name:
2757
- self.write_group_header(out, group_name)
2758
- out(' <tr><td class="summary">\n'
2759
- ' <ul class="nomargin">\n')
2760
- for submodule in doc.submodule_groups[group_name]:
2761
- self.write_module_tree_item(out, submodule, package=doc)
2762
- out(' </ul></td></tr>\n')
2763
-
2764
- out(self.TABLE_FOOTER+'\n<br />\n')
2765
-
2766
- def write_module_tree_item(self, out, doc, package=None):
2767
- # If it's a private variable, then mark its <li>.
2768
- var = package and package.variables.get(doc.canonical_name[-1])
2769
- priv = ((var is not None and var.is_public is False) or
2770
- (var is None and doc.canonical_name[-1].startswith('_')))
2771
- out(' <li%s> <strong class="uidlink">%s</strong>'
2772
- % (priv and ' class="private"' or '', self.href(doc)))
2773
- if doc.summary not in (None, UNKNOWN):
2774
- out(': <em class="summary">'+
2775
- self.description(doc.summary, doc, 8)+'</em>')
2776
- if doc.submodules != UNKNOWN and doc.submodules:
2777
- if priv: out('\n <ul class="private">\n')
2778
- else: out('\n <ul>\n')
2779
- for submodule in doc.submodules:
2780
- self.write_module_tree_item(out, submodule, package=doc)
2781
- out(' </ul>\n')
2782
- out(' </li>\n')
2783
-
2784
- #////////////////////////////////////////////////////////////
2785
- #{ Class trees
2786
- #////////////////////////////////////////////////////////////
2787
-
2788
- write_class_tree_item = compile_template(
2789
- '''
2790
- write_class_tree_item(self, out, doc, class_set)
2791
- ''',
2792
- # /------------------------- Template -------------------------\
2793
- '''
2794
- >>> if doc.summary in (None, UNKNOWN):
2795
- <li> <strong class="uidlink">$self.href(doc)$</strong>
2796
- >>> else:
2797
- <li> <strong class="uidlink">$self.href(doc)$</strong>:
2798
- <em class="summary">$self.description(doc.summary, doc, 8)$</em>
2799
- >>> # endif
2800
- >>> if doc.subclasses:
2801
- <ul>
2802
- >>> for subclass in sorted(set(doc.subclasses), key=lambda c:c.canonical_name[-1]):
2803
- >>> if subclass in class_set:
2804
- >>> self.write_class_tree_item(out, subclass, class_set)
2805
- >>> #endif
2806
- >>> #endfor
2807
- </ul>
2808
- >>> #endif
2809
- </li>
2810
- ''')
2811
- # \------------------------------------------------------------/
2812
-
2813
- #////////////////////////////////////////////////////////////
2814
- #{ Standard Fields
2815
- #////////////////////////////////////////////////////////////
2816
-
2817
- def write_standard_fields(self, out, doc):
2818
- """
2819
- Write HTML code containing descriptions of any standard markup
2820
- fields that are defined by the given L{APIDoc} object (such as
2821
- C{@author} and C{@todo} fields).
2822
-
2823
- @param doc: The L{APIDoc} object containing the API documentation
2824
- for the object whose standard markup fields should be
2825
- described.
2826
- """
2827
- fields = []
2828
- field_values = {}
2829
-
2830
- for (field, arg, descr) in doc.metadata:
2831
- if field not in field_values:
2832
- fields.append(field)
2833
- if field.takes_arg:
2834
- subfields = field_values.setdefault(field,{})
2835
- subfields.setdefault(arg,[]).append(descr)
2836
- else:
2837
- field_values.setdefault(field,[]).append(descr)
2838
-
2839
- if not fields: return
2840
-
2841
- out('<div class="fields">')
2842
- for field in fields:
2843
- if field.takes_arg:
2844
- for arg, descrs in field_values[field].items():
2845
- self.write_standard_field(out, doc, field, descrs, arg)
2846
-
2847
- else:
2848
- self.write_standard_field(out, doc, field, field_values[field])
2849
-
2850
- out('</div>')
2851
-
2852
- write_standard_field = compile_template(
2853
- """
2854
- write_standard_field(self, out, doc, field, descrs, arg='')
2855
-
2856
- """,
2857
- # /------------------------- Template -------------------------\
2858
- '''
2859
- >>> if arg: arglabel = " (%s)" % arg
2860
- >>> else: arglabel = ""
2861
- >>> if len(descrs) == 1:
2862
- <p><strong>$field.singular+arglabel$:</strong>
2863
- $self.description(descrs[0], doc, 8)$
2864
- </p>
2865
- >>> elif field.short:
2866
- <dl><dt>$field.plural+arglabel$:</dt>
2867
- <dd>
2868
- >>> for descr in descrs[:-1]:
2869
- $self.description(descr, doc, 10)$,
2870
- >>> # end for
2871
- $self.description(descrs[-1], doc, 10)$
2872
- </dd>
2873
- </dl>
2874
- >>> else:
2875
- <strong>$field.plural+arglabel$:</strong>
2876
- <ul class="nomargin-top">
2877
- >>> for descr in descrs:
2878
- <li>
2879
- $self.description(descr, doc, 8)$
2880
- </li>
2881
- >>> # end for
2882
- </ul>
2883
- >>> # end else
2884
- >>> # end for
2885
- ''')
2886
- # \------------------------------------------------------------/
2887
-
2888
- #////////////////////////////////////////////////////////////
2889
- #{ Index generation
2890
- #////////////////////////////////////////////////////////////
2891
-
2892
- #: A list of metadata indices that should be generated. Each
2893
- #: entry in this list is a tuple C{(tag, label, short_label)},
2894
- #: where C{tag} is the cannonical tag of a metadata field;
2895
- #: C{label} is a label for the index page; and C{short_label}
2896
- #: is a shorter label, used in the index selector.
2897
- METADATA_INDICES = [('bug', 'Bug List', 'Bugs'),
2898
- ('todo', 'To Do List', 'To Do'),
2899
- ('change', 'Change Log', 'Changes'),
2900
- ('deprecated', 'Deprecation List', 'Deprecations'),
2901
- ('since', 'Introductions List', 'Introductions'),
2902
- ]
2903
-
2904
- def build_identifier_index(self):
2905
- items = []
2906
- for doc in self.indexed_docs:
2907
- name = plaintext_to_html(doc.canonical_name[-1])
2908
- if isinstance(doc, RoutineDoc): name += '()'
2909
- url = self.url(doc)
2910
- if not url: continue
2911
- container = self.docindex.container(doc)
2912
- items.append( (name, url, container) )
2913
- return sorted(items, key=lambda v:v[0].lower())
2914
-
2915
- def _group_by_letter(self, items):
2916
- """Preserves sort order of the input."""
2917
- index = {}
2918
- for item in items:
2919
- first_letter = item[0][0].upper()
2920
- if not ("A" <= first_letter <= "Z"):
2921
- first_letter = '_'
2922
- index.setdefault(first_letter, []).append(item)
2923
- return index
2924
-
2925
- def build_term_index(self):
2926
- items = []
2927
- for doc in self.indexed_docs:
2928
- url = self.url(doc)
2929
- items += self._terms_from_docstring(url, doc, doc.descr)
2930
- for (field, arg, descr) in doc.metadata:
2931
- items += self._terms_from_docstring(url, doc, descr)
2932
- if hasattr(doc, 'type_descr'):
2933
- items += self._terms_from_docstring(url, doc,
2934
- doc.type_descr)
2935
- if hasattr(doc, 'return_descr'):
2936
- items += self._terms_from_docstring(url, doc,
2937
- doc.return_descr)
2938
- if hasattr(doc, 'return_type'):
2939
- items += self._terms_from_docstring(url, doc,
2940
- doc.return_type)
2941
- return sorted(items, key=lambda v:v[0].lower())
2942
-
2943
- def _terms_from_docstring(self, base_url, container, parsed_docstring):
2944
- if parsed_docstring in (None, UNKNOWN): return []
2945
- terms = []
2946
- # Strip any existing anchor off:
2947
- base_url = re.sub('#.*', '', '%s' % (base_url,))
2948
- for term in parsed_docstring.index_terms():
2949
- anchor = self._term_index_to_anchor(term)
2950
- url = '%s#%s' % (base_url, anchor)
2951
- terms.append( (term.to_plaintext(None), url, container) )
2952
- return terms
2953
-
2954
- def build_metadata_index(self, field_name):
2955
- # Build the index.
2956
- index = {}
2957
- for doc in self.indexed_docs:
2958
- if (not self._show_private and
2959
- self._doc_or_ancestor_is_private(doc)):
2960
- continue
2961
- descrs = {}
2962
- if doc.metadata is not UNKNOWN:
2963
- for (field, arg, descr) in doc.metadata:
2964
- if field.tags[0] == field_name:
2965
- descrs.setdefault(arg, []).append(descr)
2966
- for (arg, descr_list) in descrs.iteritems():
2967
- index.setdefault(arg, []).append( (doc, descr_list) )
2968
- return index
2969
-
2970
- def _term_index_to_anchor(self, term):
2971
- """
2972
- Given the name of an inline index item, construct a URI anchor.
2973
- These anchors are used to create links from the index page to each
2974
- index item.
2975
- """
2976
- # Include "-" so we don't accidentally collide with the name
2977
- # of a python identifier.
2978
- s = re.sub(r'\s\s+', '-', term.to_plaintext(None))
2979
- return "index-"+re.sub("[^a-zA-Z0-9]", "_", s)
2980
-
2981
- #////////////////////////////////////////////////////////////
2982
- #{ Redirect page
2983
- #////////////////////////////////////////////////////////////
2984
-
2985
- def write_redirect_page(self, out):
2986
- """
2987
- Build the auto-redirect page, which translates dotted names to
2988
- URLs using javascript. When the user visits
2989
- <redirect.html#dotted.name>, they will automatically get
2990
- redirected to the page for the object with the given
2991
- fully-qualified dotted name. E.g., for epydoc,
2992
- <redirect.html#epydoc.apidoc.UNKNOWN> redirects the user to
2993
- <epydoc.apidoc-module.html#UNKNOWN>.
2994
- """
2995
- # Construct a list of all the module & class pages that we're
2996
- # documenting. The redirect_url javascript will scan through
2997
- # this list, looking for a page name that matches the
2998
- # requested dotted name.
2999
- pages = (['%s-m' % val_doc.canonical_name
3000
- for val_doc in self.module_list] +
3001
- ['%s-c' % val_doc.canonical_name
3002
- for val_doc in self.class_list])
3003
- # Sort the pages from longest to shortest. This ensures that
3004
- # we find e.g. "x.y.z" in the list before "x.y".
3005
- pages = sorted(pages, key=lambda p:-len(p))
3006
-
3007
- # Write the redirect page.
3008
- self._write_redirect_page(out, pages)
3009
-
3010
- _write_redirect_page = compile_template(
3011
- '''
3012
- _write_redirect_page(self, out, pages)
3013
- ''',
3014
- # /------------------------- Template -------------------------\
3015
- '''
3016
- <html><head><title>Epydoc Redirect Page</title>
3017
- <meta http-equiv="cache-control" content="no-cache" />
3018
- <meta http-equiv="expires" content="0" />
3019
- <meta http-equiv="pragma" content="no-cache" />
3020
- <script type="text/javascript" src="epydoc.js"></script>
3021
- </head>
3022
- <body>
3023
- <script type="text/javascript">
3024
- <!--
3025
- var pages = $"[%s]" % ", ".join(['"%s"' % v for v in pages])$;
3026
- var dottedName = get_anchor();
3027
- if (dottedName) {
3028
- var target = redirect_url(dottedName);
3029
- if (target) window.location.replace(target);
3030
- }
3031
- // -->
3032
- </script>
3033
-
3034
- <h3>Epydoc Auto-redirect page</h3>
3035
-
3036
- <p>When javascript is enabled, this page will redirect URLs of
3037
- the form <tt>redirect.html#<i>dotted.name</i></tt> to the
3038
- documentation for the object with the given fully-qualified
3039
- dotted name.</p>
3040
- <p><a id="message"> &nbsp; </a></p>
3041
-
3042
- <script type="text/javascript">
3043
- <!--
3044
- if (dottedName) {
3045
- var msg = document.getElementById("message");
3046
- msg.innerHTML = "No documentation found for <tt>"+
3047
- dottedName+"</tt>";
3048
- }
3049
- // -->
3050
- </script>
3051
-
3052
- </body>
3053
- </html>
3054
- ''')
3055
- # \------------------------------------------------------------/
3056
-
3057
- #////////////////////////////////////////////////////////////
3058
- #{ URLs list
3059
- #////////////////////////////////////////////////////////////
3060
-
3061
- def write_api_list(self, out):
3062
- """
3063
- Write a list of mapping name->url for all the documented objects.
3064
- """
3065
- # Construct a list of all the module & class pages that we're
3066
- # documenting. The redirect_url javascript will scan through
3067
- # this list, looking for a page name that matches the
3068
- # requested dotted name.
3069
- skip = (ModuleDoc, ClassDoc, type(UNKNOWN))
3070
- for val_doc in self.module_list:
3071
- self.write_url_record(out, val_doc)
3072
- for var in val_doc.variables.itervalues():
3073
- if not isinstance(var.value, skip):
3074
- self.write_url_record(out, var)
3075
-
3076
- for val_doc in self.class_list:
3077
- self.write_url_record(out, val_doc)
3078
- for var in val_doc.variables.itervalues():
3079
- self.write_url_record(out, var)
3080
-
3081
- def write_url_record(self, out, obj):
3082
- url = self.url(obj)
3083
- if url is not None:
3084
- out("%s\t%s\n" % (obj.canonical_name, url))
3085
-
3086
- #////////////////////////////////////////////////////////////
3087
- #{ Helper functions
3088
- #////////////////////////////////////////////////////////////
3089
-
3090
- def _val_is_public(self, valdoc):
3091
- """Make a best-guess as to whether the given class is public."""
3092
- container = self.docindex.container(valdoc)
3093
- if isinstance(container, NamespaceDoc):
3094
- for vardoc in container.variables.values():
3095
- if vardoc in (UNKNOWN, None): continue
3096
- if vardoc.value is valdoc:
3097
- return vardoc.is_public
3098
- return True
3099
-
3100
- # [XX] Is it worth-while to pull the anchor tricks that I do here?
3101
- # Or should I just live with the fact that show/hide private moves
3102
- # stuff around?
3103
- write_table_header = compile_template(
3104
- '''
3105
- write_table_header(self, out, css_class, heading=None, \
3106
- private_link=True, colspan=2)
3107
- ''',
3108
- # /------------------------- Template -------------------------\
3109
- '''
3110
- >>> if heading is not None:
3111
- >>> anchor = "section-%s" % re.sub("\W", "", heading)
3112
- <!-- ==================== $heading.upper()$ ==================== -->
3113
- <a name="$anchor$"></a>
3114
- >>> #endif
3115
- <table class="$css_class$" border="1" cellpadding="3"
3116
- cellspacing="0" width="100%" bgcolor="white">
3117
- >>> if heading is not None:
3118
- <tr bgcolor="#70b0f0" class="table-header">
3119
- >>> if private_link and self._show_private:
3120
- <td colspan="$colspan$" class="table-header">
3121
- <table border="0" cellpadding="0" cellspacing="0" width="100%">
3122
- <tr valign="top">
3123
- <td align="left"><span class="table-header">$heading$</span></td>
3124
- <td align="right" valign="top"
3125
- ><span class="options">[<a href="#$anchor$"
3126
- class="privatelink" onclick="toggle_private();"
3127
- >hide private</a>]</span></td>
3128
- </tr>
3129
- </table>
3130
- </td>
3131
- >>> else:
3132
- <td align="left" colspan="2" class="table-header">
3133
- <span class="table-header">$heading$</span></td>
3134
- >>> #endif
3135
- </tr>
3136
- >>> #endif
3137
- ''')
3138
- # \------------------------------------------------------------/
3139
-
3140
- TABLE_FOOTER = '</table>\n'
3141
-
3142
- PRIVATE_LINK = '''
3143
- <span class="options">[<a href="javascript:void(0);" class="privatelink"
3144
- onclick="toggle_private();">hide&nbsp;private</a>]</span>
3145
- '''.strip()
3146
-
3147
- write_group_header = compile_template(
3148
- '''
3149
- write_group_header(self, out, group, tr_class='')
3150
- ''',
3151
- # /------------------------- Template -------------------------\
3152
- '''
3153
- <tr bgcolor="#e8f0f8" $tr_class$>
3154
- <th colspan="2" class="group-header"
3155
- >&nbsp;&nbsp;&nbsp;&nbsp;$group$</th></tr>
3156
- ''')
3157
- # \------------------------------------------------------------/
3158
-
3159
- _url_cache = {}
3160
- def url(self, obj):
3161
- """
3162
- Return the URL for the given object, which can be a
3163
- C{VariableDoc}, a C{ValueDoc}, or a C{DottedName}.
3164
- """
3165
- cached_url = self._url_cache.get(id(obj))
3166
- if cached_url is not None:
3167
- return cached_url
3168
- else:
3169
- url = self._url_cache[id(obj)] = self._url(obj)
3170
- return url
3171
-
3172
- def _url(self, obj):
3173
- """
3174
- Internal helper for L{url}.
3175
- """
3176
- # Module: <canonical_name>-module.html
3177
- if isinstance(obj, ModuleDoc):
3178
- if obj not in self.module_set: return None
3179
- return urllib.quote('%s'%obj.canonical_name) + '-module.html'
3180
- # Class: <canonical_name>-class.html
3181
- elif isinstance(obj, ClassDoc):
3182
- if obj not in self.class_set: return None
3183
- return urllib.quote('%s'%obj.canonical_name) + '-class.html'
3184
- # Variable
3185
- elif isinstance(obj, VariableDoc):
3186
- val_doc = obj.value
3187
- if isinstance(val_doc, (ModuleDoc, ClassDoc)):
3188
- return self.url(val_doc)
3189
- elif obj.container in (None, UNKNOWN):
3190
- if val_doc in (None, UNKNOWN): return None
3191
- return self.url(val_doc)
3192
- elif obj.is_imported == True:
3193
- if obj.imported_from is not UNKNOWN:
3194
- return self.url(obj.imported_from)
3195
- else:
3196
- return None
3197
- else:
3198
- container_url = self.url(obj.container)
3199
- if container_url is None: return None
3200
- return '%s#%s' % (container_url, urllib.quote('%s'%obj.name))
3201
- # Value (other than module or class)
3202
- elif isinstance(obj, ValueDoc):
3203
- container = self.docindex.container(obj)
3204
- if container is None:
3205
- return None # We couldn't find it!
3206
- else:
3207
- container_url = self.url(container)
3208
- if container_url is None: return None
3209
- anchor = urllib.quote('%s'%obj.canonical_name[-1])
3210
- return '%s#%s' % (container_url, anchor)
3211
- # Dotted name: look up the corresponding APIDoc
3212
- elif isinstance(obj, DottedName):
3213
- val_doc = self.docindex.get_valdoc(obj)
3214
- if val_doc is None: return None
3215
- return self.url(val_doc)
3216
- # Special pages:
3217
- elif obj == 'indices':
3218
- return 'identifier-index.html'
3219
- elif obj == 'help':
3220
- return 'help.html'
3221
- elif obj == 'trees':
3222
- return self._trees_url
3223
- else:
3224
- raise ValueError, "Don't know what to do with %r" % obj
3225
-
3226
- def pysrc_link(self, api_doc):
3227
- if not self._incl_sourcecode:
3228
- return ''
3229
- url = self.pysrc_url(api_doc)
3230
- if url is not None:
3231
- return ('<span class="codelink"><a href="%s">source&nbsp;'
3232
- 'code</a></span>' % url)
3233
- else:
3234
- return ''
3235
-
3236
- def pysrc_url(self, api_doc):
3237
- if isinstance(api_doc, VariableDoc):
3238
- if api_doc.value not in (None, UNKNOWN):
3239
- return pysrc_url(api_doc.value)
3240
- else:
3241
- return None
3242
- elif isinstance(api_doc, ModuleDoc):
3243
- if api_doc in self.modules_with_sourcecode:
3244
- return ('%s-pysrc.html' %
3245
- urllib.quote('%s' % api_doc.canonical_name))
3246
- else:
3247
- return None
3248
- else:
3249
- module = api_doc.defining_module
3250
- if module == UNKNOWN: return None
3251
- module_pysrc_url = self.pysrc_url(module)
3252
- if module_pysrc_url is None: return None
3253
- module_name = module.canonical_name
3254
- if not module_name.dominates(api_doc.canonical_name, True):
3255
- log.debug('%r is in %r but name does not dominate' %
3256
- (api_doc, module))
3257
- return module_pysrc_url
3258
- mname_len = len(module.canonical_name)
3259
- anchor = '%s' % api_doc.canonical_name[mname_len:]
3260
- return '%s#%s' % (module_pysrc_url, urllib.quote(anchor))
3261
-
3262
- # We didn't find it:
3263
- return None
3264
-
3265
- # [xx] add code to automatically do <code> wrapping or the like?
3266
- def href(self, target, label=None, css_class=None, context=None,
3267
- tooltip=None):
3268
- """
3269
- Return the HTML code for an HREF link to the given target
3270
- (which can be a C{VariableDoc}, a C{ValueDoc}, or a
3271
- C{DottedName}.
3272
- If a C{NamespaceDoc} C{context} is specified, the target label is
3273
- contextualized to it.
3274
- """
3275
- assert isinstance(target, (APIDoc, DottedName))
3276
-
3277
- # Pick a label, if none was given.
3278
- if label is None:
3279
- if isinstance(target, VariableDoc):
3280
- label = target.name
3281
- elif (isinstance(target, ValueDoc) and
3282
- target.canonical_name is not UNKNOWN):
3283
- label = target.canonical_name
3284
- elif isinstance(target, DottedName):
3285
- label = target
3286
- elif isinstance(target, GenericValueDoc):
3287
- raise ValueError("href() should not be called with "
3288
- "GenericValueDoc objects (perhaps you "
3289
- "meant to use the containing variable?)")
3290
- else:
3291
- raise ValueError("Unable to find a label for %r" % target)
3292
-
3293
- if context is not None and isinstance(label, DottedName):
3294
- label = label.contextualize(context.canonical_name.container())
3295
-
3296
- label = plaintext_to_html(str(label))
3297
-
3298
- # Munge names for scripts & unreachable values
3299
- if label.startswith('script-'):
3300
- label = label[7:] + ' (script)'
3301
- if label.startswith('??'):
3302
- label = '<i>unreachable</i>' + label[2:]
3303
- label = re.sub(r'-\d+$', '', label)
3304
-
3305
- # Get the url for the target.
3306
- url = self.url(target)
3307
- if url is None:
3308
- if tooltip: return '<span title="%s">%s</span>' % (tooltip, label)
3309
- else: return label
3310
-
3311
- # Construct a string for the class attribute.
3312
- if css_class is None:
3313
- css = ''
3314
- else:
3315
- css = ' class="%s"' % css_class
3316
-
3317
- onclick = ''
3318
- if ((isinstance(target, VariableDoc) and not target.is_public) or
3319
- (isinstance(target, ValueDoc) and
3320
- not isinstance(target, GenericValueDoc) and
3321
- not self._val_is_public(target))):
3322
- onclick = ' onclick="show_private();"'
3323
-
3324
- if tooltip:
3325
- tooltip = ' title="%s"' % tooltip
3326
- else:
3327
- tooltip = ''
3328
-
3329
- return '<a href="%s"%s%s%s>%s</a>' % (url, css, onclick, tooltip, label)
3330
-
3331
- def _attr_to_html(self, attr, api_doc, indent):
3332
- if api_doc in (None, UNKNOWN):
3333
- return ''
3334
- pds = getattr(api_doc, attr, None) # pds = ParsedDocstring.
3335
- if pds not in (None, UNKNOWN):
3336
- return self.docstring_to_html(pds, api_doc, indent)
3337
- elif isinstance(api_doc, VariableDoc):
3338
- return self._attr_to_html(attr, api_doc.value, indent)
3339
-
3340
- def summary(self, api_doc, indent=0):
3341
- return self._attr_to_html('summary', api_doc, indent)
3342
-
3343
- def descr(self, api_doc, indent=0):
3344
- return self._attr_to_html('descr', api_doc, indent)
3345
-
3346
- def type_descr(self, api_doc, indent=0):
3347
- return self._attr_to_html('type_descr', api_doc, indent)
3348
-
3349
- def return_type(self, api_doc, indent=0):
3350
- return self._attr_to_html('return_type', api_doc, indent)
3351
-
3352
- def return_descr(self, api_doc, indent=0):
3353
- return self._attr_to_html('return_descr', api_doc, indent)
3354
-
3355
- def docstring_to_html(self, parsed_docstring, where=None, indent=0):
3356
- if parsed_docstring in (None, UNKNOWN): return ''
3357
- linker = _HTMLDocstringLinker(self, where)
3358
- s = parsed_docstring.to_html(linker, indent=indent,
3359
- directory=self._directory,
3360
- docindex=self.docindex,
3361
- context=where).strip()
3362
- if self._mark_docstrings:
3363
- s = '<span class="docstring">%s</span><!--end docstring-->' % s
3364
- return s
3365
-
3366
- def description(self, parsed_docstring, where=None, indent=0):
3367
- assert isinstance(where, (APIDoc, type(None)))
3368
- if parsed_docstring in (None, UNKNOWN): return ''
3369
- linker = _HTMLDocstringLinker(self, where)
3370
- descr = parsed_docstring.to_html(linker, indent=indent,
3371
- directory=self._directory,
3372
- docindex=self.docindex,
3373
- context=where).strip()
3374
- if descr == '': return '&nbsp;'
3375
- return descr
3376
-
3377
- # [xx] Should this be defined by the APIDoc classes themselves??
3378
- def doc_kind(self, doc):
3379
- if isinstance(doc, ModuleDoc) and doc.is_package == True:
3380
- return 'Package'
3381
- elif (isinstance(doc, ModuleDoc) and
3382
- doc.canonical_name[0].startswith('script')):
3383
- return 'Script'
3384
- elif isinstance(doc, ModuleDoc):
3385
- return 'Module'
3386
- elif isinstance(doc, ClassDoc):
3387
- return 'Class'
3388
- elif isinstance(doc, ClassMethodDoc):
3389
- return 'Class Method'
3390
- elif isinstance(doc, StaticMethodDoc):
3391
- return 'Static Method'
3392
- elif isinstance(doc, RoutineDoc):
3393
- if isinstance(self.docindex.container(doc), ClassDoc):
3394
- return 'Method'
3395
- else:
3396
- return 'Function'
3397
- else:
3398
- return 'Variable'
3399
-
3400
- def _doc_or_ancestor_is_private(self, api_doc):
3401
- name = api_doc.canonical_name
3402
- for i in range(len(name), 0, -1):
3403
- # Is it (or an ancestor) a private var?
3404
- var_doc = self.docindex.get_vardoc(name[:i])
3405
- if var_doc is not None and var_doc.is_public == False:
3406
- return True
3407
- # Is it (or an ancestor) a private module?
3408
- val_doc = self.docindex.get_valdoc(name[:i])
3409
- if (val_doc is not None and isinstance(val_doc, ModuleDoc) and
3410
- val_doc.canonical_name[-1].startswith('_')):
3411
- return True
3412
- return False
3413
-
3414
- def _private_subclasses(self, class_doc):
3415
- """Return a list of all subclasses of the given class that are
3416
- private, as determined by L{_val_is_private}. Recursive
3417
- subclasses are included in this list."""
3418
- queue = [class_doc]
3419
- private = set()
3420
- for cls in queue:
3421
- if (isinstance(cls, ClassDoc) and
3422
- cls.subclasses not in (None, UNKNOWN)):
3423
- queue.extend(cls.subclasses)
3424
- private.update([c for c in cls.subclasses if
3425
- not self._val_is_public(c)])
3426
- return private
3427
-
3428
- class _HTMLDocstringLinker(epydoc.markup.DocstringLinker):
3429
- def __init__(self, htmlwriter, container):
3430
- self.htmlwriter = htmlwriter
3431
- self.docindex = htmlwriter.docindex
3432
- self.container = container
3433
-
3434
- def translate_indexterm(self, indexterm):
3435
- key = self.htmlwriter._term_index_to_anchor(indexterm)
3436
- return ('<a name="%s"></a><i class="indexterm">%s</i>' %
3437
- (key, indexterm.to_html(self)))
3438
-
3439
- def translate_identifier_xref(self, identifier, label=None):
3440
- # Pick a label for this xref.
3441
- if label is None: label = plaintext_to_html(identifier)
3442
-
3443
- # Find the APIDoc for it (if it's available).
3444
- doc = self.docindex.find(identifier, self.container)
3445
-
3446
- # If we didn't find a target, then try checking in the contexts
3447
- # of the ancestor classes.
3448
- if doc is None and isinstance(self.container, RoutineDoc):
3449
- container = self.docindex.get_vardoc(
3450
- self.container.canonical_name)
3451
- while (doc is None and container not in (None, UNKNOWN)
3452
- and container.overrides not in (None, UNKNOWN)):
3453
- container = container.overrides
3454
- doc = self.docindex.find(identifier, container)
3455
-
3456
- # Translate it into HTML.
3457
- if doc is None:
3458
- self._failed_xref(identifier)
3459
- return '<code class="link">%s</code>' % label
3460
- else:
3461
- return self.htmlwriter.href(doc, label, 'link')
3462
-
3463
- # [xx] Should this be added to the DocstringLinker interface???
3464
- # Currently, this is *only* used by dotgraph.
3465
- def url_for(self, identifier):
3466
- if isinstance(identifier, (basestring, DottedName)):
3467
- doc = self.docindex.find(identifier, self.container)
3468
- if doc:
3469
- return self.htmlwriter.url(doc)
3470
- else:
3471
- return None
3472
-
3473
- elif isinstance(identifier, APIDoc):
3474
- return self.htmlwriter.url(identifier)
3475
- doc = identifier
3476
-
3477
- else:
3478
- raise TypeError('Expected string or APIDoc')
3479
-
3480
- def _failed_xref(self, identifier):
3481
- """Add an identifier to the htmlwriter's failed crossreference
3482
- list."""
3483
- # Don't count it as a failed xref if it's a parameter of the
3484
- # current function.
3485
- if (isinstance(self.container, RoutineDoc) and
3486
- identifier in self.container.all_args()):
3487
- return
3488
-
3489
- failed_xrefs = self.htmlwriter._failed_xrefs
3490
- context = self.container.canonical_name
3491
- failed_xrefs.setdefault(identifier,{})[context] = 1