bee_python 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (503) hide show
  1. data/LICENSE +202 -0
  2. data/build/README +23 -0
  3. data/egg/egg/build.yml +70 -0
  4. data/egg/egg/ez_setup.py +280 -0
  5. data/egg/egg/script.py +12 -0
  6. data/egg/egg/setup.erb +11 -0
  7. data/egg/egg/suite.py +37 -0
  8. data/egg/egg/test.py +31 -0
  9. data/egg/egg.yml +69 -0
  10. data/egg/http/build.erb +53 -0
  11. data/egg/http/server.py +34 -0
  12. data/egg/http.yml +50 -0
  13. data/egg/mysql/mysql.py +43 -0
  14. data/egg/mysql.yml +44 -0
  15. data/egg/project/build.erb +77 -0
  16. data/egg/project/script.py +42 -0
  17. data/egg/project/test.py +31 -0
  18. data/egg/project.yml +59 -0
  19. data/egg/script/build.erb +35 -0
  20. data/egg/script/script.py +42 -0
  21. data/egg/script.yml +50 -0
  22. data/egg/soap/build.erb +52 -0
  23. data/egg/soap/client.py +18 -0
  24. data/egg/soap/server.py +30 -0
  25. data/egg/soap.yml +58 -0
  26. data/egg/source/source.py +42 -0
  27. data/egg/source.yml +47 -0
  28. data/egg/test/test.py +28 -0
  29. data/egg/test.yml +44 -0
  30. data/egg/xmlrpc/build.erb +52 -0
  31. data/egg/xmlrpc/client.py +22 -0
  32. data/egg/xmlrpc/server.py +24 -0
  33. data/egg/xmlrpc.yml +51 -0
  34. data/lib/bee_task_python.rb +390 -0
  35. data/test/build.yml +16 -0
  36. data/test/tc_bee_task_python.rb +27 -0
  37. data/test/test_build.rb +26 -0
  38. data/test/test_build_listener.rb +62 -0
  39. data/test/ts_bee_python.rb +26 -0
  40. data/tools/common/__init__.py +5 -0
  41. data/tools/common/common/__init__.py +140 -0
  42. data/tools/common/common/__pkginfo__.py +43 -0
  43. data/tools/common/common/adbh.py +35 -0
  44. data/tools/common/common/cache.py +114 -0
  45. data/tools/common/common/changelog.py +234 -0
  46. data/tools/common/common/clcommands.py +181 -0
  47. data/tools/common/common/cli.py +212 -0
  48. data/tools/common/common/compat.py +328 -0
  49. data/tools/common/common/configuration.py +1087 -0
  50. data/tools/common/common/contexts.py +58 -0
  51. data/tools/common/common/corbautils.py +117 -0
  52. data/tools/common/common/daemon.py +171 -0
  53. data/tools/common/common/date.py +279 -0
  54. data/tools/common/common/db.py +49 -0
  55. data/tools/common/common/dbf.py +229 -0
  56. data/tools/common/common/debugger.py +208 -0
  57. data/tools/common/common/decorators.py +190 -0
  58. data/tools/common/common/deprecation.py +118 -0
  59. data/tools/common/common/fileutils.py +409 -0
  60. data/tools/common/common/graph.py +259 -0
  61. data/tools/common/common/html.py +142 -0
  62. data/tools/common/common/interface.py +76 -0
  63. data/tools/common/common/logging_ext.py +166 -0
  64. data/tools/common/common/modutils.py +670 -0
  65. data/tools/common/common/optik_ext.py +383 -0
  66. data/tools/common/common/optparser.py +92 -0
  67. data/tools/common/common/pdf_ext.py +111 -0
  68. data/tools/common/common/proc.py +276 -0
  69. data/tools/common/common/pyro_ext.py +146 -0
  70. data/tools/common/common/pytest.py +754 -0
  71. data/tools/common/common/shellutils.py +383 -0
  72. data/tools/common/common/sphinx_ext.py +87 -0
  73. data/tools/common/common/sphinxutils.py +122 -0
  74. data/tools/common/common/sqlgen.py +31 -0
  75. data/tools/common/common/table.py +930 -0
  76. data/tools/common/common/tasksqueue.py +97 -0
  77. data/tools/common/common/test/__init__.py +1 -0
  78. data/tools/common/common/test/data/ChangeLog +184 -0
  79. data/tools/common/common/test/data/MyPyPa-0.1.0-py2.5.egg +0 -0
  80. data/tools/common/common/test/data/__init__.py +1 -0
  81. data/tools/common/common/test/data/content_differ_dir/NOTHING +0 -0
  82. data/tools/common/common/test/data/content_differ_dir/README +1 -0
  83. data/tools/common/common/test/data/content_differ_dir/subdir/coin +1 -0
  84. data/tools/common/common/test/data/content_differ_dir/subdir/toto.txt +53 -0
  85. data/tools/common/common/test/data/file_differ_dir/NOTHING +0 -0
  86. data/tools/common/common/test/data/file_differ_dir/README +1 -0
  87. data/tools/common/common/test/data/file_differ_dir/subdir/toto.txt +53 -0
  88. data/tools/common/common/test/data/file_differ_dir/subdirtwo/Hello +0 -0
  89. data/tools/common/common/test/data/find_test/__init__.py +0 -0
  90. data/tools/common/common/test/data/find_test/foo.txt +0 -0
  91. data/tools/common/common/test/data/find_test/module.py +0 -0
  92. data/tools/common/common/test/data/find_test/module2.py +0 -0
  93. data/tools/common/common/test/data/find_test/newlines.txt +0 -0
  94. data/tools/common/common/test/data/find_test/noendingnewline.py +0 -0
  95. data/tools/common/common/test/data/find_test/nonregr.py +0 -0
  96. data/tools/common/common/test/data/find_test/normal_file.txt +0 -0
  97. data/tools/common/common/test/data/find_test/spam.txt +0 -0
  98. data/tools/common/common/test/data/find_test/sub/doc.txt +0 -0
  99. data/tools/common/common/test/data/find_test/sub/momo.py +0 -0
  100. data/tools/common/common/test/data/find_test/test.ini +0 -0
  101. data/tools/common/common/test/data/find_test/test1.msg +0 -0
  102. data/tools/common/common/test/data/find_test/test2.msg +0 -0
  103. data/tools/common/common/test/data/find_test/write_protected_file.txt +0 -0
  104. data/tools/common/common/test/data/foo.txt +9 -0
  105. data/tools/common/common/test/data/module.py +88 -0
  106. data/tools/common/common/test/data/module2.py +77 -0
  107. data/tools/common/common/test/data/newlines.txt +3 -0
  108. data/tools/common/common/test/data/noendingnewline.py +36 -0
  109. data/tools/common/common/test/data/nonregr.py +14 -0
  110. data/tools/common/common/test/data/normal_file.txt +0 -0
  111. data/tools/common/common/test/data/reference_dir/NOTHING +0 -0
  112. data/tools/common/common/test/data/reference_dir/README +1 -0
  113. data/tools/common/common/test/data/reference_dir/subdir/coin +1 -0
  114. data/tools/common/common/test/data/reference_dir/subdir/toto.txt +53 -0
  115. data/tools/common/common/test/data/same_dir/NOTHING +0 -0
  116. data/tools/common/common/test/data/same_dir/README +1 -0
  117. data/tools/common/common/test/data/same_dir/subdir/coin +1 -0
  118. data/tools/common/common/test/data/same_dir/subdir/toto.txt +53 -0
  119. data/tools/common/common/test/data/spam.txt +9 -0
  120. data/tools/common/common/test/data/sub/doc.txt +1 -0
  121. data/tools/common/common/test/data/sub/momo.py +1 -0
  122. data/tools/common/common/test/data/subdir_differ_dir/NOTHING +0 -0
  123. data/tools/common/common/test/data/subdir_differ_dir/README +1 -0
  124. data/tools/common/common/test/data/subdir_differ_dir/subdir/coin +1 -0
  125. data/tools/common/common/test/data/subdir_differ_dir/subdir/toto.txt +53 -0
  126. data/tools/common/common/test/data/test.ini +20 -0
  127. data/tools/common/common/test/data/test1.msg +30 -0
  128. data/tools/common/common/test/data/test2.msg +42 -0
  129. data/tools/common/common/test/data/write_protected_file.txt +0 -0
  130. data/tools/common/common/test/foomod.py +17 -0
  131. data/tools/common/common/test/unittest_cache.py +129 -0
  132. data/tools/common/common/test/unittest_changelog.py +37 -0
  133. data/tools/common/common/test/unittest_compat.py +239 -0
  134. data/tools/common/common/test/unittest_configuration.py +348 -0
  135. data/tools/common/common/test/unittest_date.py +154 -0
  136. data/tools/common/common/test/unittest_decorators.py +62 -0
  137. data/tools/common/common/test/unittest_deprecation.py +76 -0
  138. data/tools/common/common/test/unittest_fileutils.py +133 -0
  139. data/tools/common/common/test/unittest_graph.py +50 -0
  140. data/tools/common/common/test/unittest_html.py +76 -0
  141. data/tools/common/common/test/unittest_interface.py +87 -0
  142. data/tools/common/common/test/unittest_modutils.py +244 -0
  143. data/tools/common/common/test/unittest_pytest.py +50 -0
  144. data/tools/common/common/test/unittest_shellutils.py +248 -0
  145. data/tools/common/common/test/unittest_table.py +448 -0
  146. data/tools/common/common/test/unittest_taskqueue.py +71 -0
  147. data/tools/common/common/test/unittest_testlib.py +956 -0
  148. data/tools/common/common/test/unittest_textutils.py +247 -0
  149. data/tools/common/common/test/unittest_tree.py +248 -0
  150. data/tools/common/common/test/unittest_umessage.py +55 -0
  151. data/tools/common/common/test/unittest_ureports_html.py +64 -0
  152. data/tools/common/common/test/unittest_ureports_text.py +105 -0
  153. data/tools/common/common/test/unittest_xmlutils.py +75 -0
  154. data/tools/common/common/test/utils.py +87 -0
  155. data/tools/common/common/testlib.py +1927 -0
  156. data/tools/common/common/textutils.py +476 -0
  157. data/tools/common/common/tree.py +372 -0
  158. data/tools/common/common/umessage.py +161 -0
  159. data/tools/common/common/ureports/__init__.py +174 -0
  160. data/tools/common/common/ureports/docbook_writer.py +139 -0
  161. data/tools/common/common/ureports/html_writer.py +131 -0
  162. data/tools/common/common/ureports/nodes.py +201 -0
  163. data/tools/common/common/ureports/text_writer.py +140 -0
  164. data/tools/common/common/vcgutils.py +216 -0
  165. data/tools/common/common/visitor.py +107 -0
  166. data/tools/common/common/xmlrpcutils.py +136 -0
  167. data/tools/common/common/xmlutils.py +61 -0
  168. data/tools/compile/compile.py +16 -0
  169. data/tools/coverage/coverage.py +602 -0
  170. data/tools/epydoc/__init__.py +227 -0
  171. data/tools/epydoc/__init__.pyc +0 -0
  172. data/tools/epydoc/apidoc.py +2203 -0
  173. data/tools/epydoc/apidoc.pyc +0 -0
  174. data/tools/epydoc/checker.py +349 -0
  175. data/tools/epydoc/checker.pyc +0 -0
  176. data/tools/epydoc/cli.py +1470 -0
  177. data/tools/epydoc/cli.pyc +0 -0
  178. data/tools/epydoc/compat.py +250 -0
  179. data/tools/epydoc/compat.pyc +0 -0
  180. data/tools/epydoc/docbuilder.py +1358 -0
  181. data/tools/epydoc/docbuilder.pyc +0 -0
  182. data/tools/epydoc/docintrospecter.py +1056 -0
  183. data/tools/epydoc/docintrospecter.pyc +0 -0
  184. data/tools/epydoc/docparser.py +2113 -0
  185. data/tools/epydoc/docparser.pyc +0 -0
  186. data/tools/epydoc/docstringparser.py +1111 -0
  187. data/tools/epydoc/docstringparser.pyc +0 -0
  188. data/tools/epydoc/docwriter/__init__.py +12 -0
  189. data/tools/epydoc/docwriter/__init__.pyc +0 -0
  190. data/tools/epydoc/docwriter/dotgraph.py +1351 -0
  191. data/tools/epydoc/docwriter/dotgraph.pyc +0 -0
  192. data/tools/epydoc/docwriter/html.py +3491 -0
  193. data/tools/epydoc/docwriter/html.pyc +0 -0
  194. data/tools/epydoc/docwriter/html_colorize.py +909 -0
  195. data/tools/epydoc/docwriter/html_colorize.pyc +0 -0
  196. data/tools/epydoc/docwriter/html_css.py +550 -0
  197. data/tools/epydoc/docwriter/html_css.pyc +0 -0
  198. data/tools/epydoc/docwriter/html_help.py +190 -0
  199. data/tools/epydoc/docwriter/html_help.pyc +0 -0
  200. data/tools/epydoc/docwriter/latex.py +1187 -0
  201. data/tools/epydoc/docwriter/latex.pyc +0 -0
  202. data/tools/epydoc/docwriter/plaintext.py +276 -0
  203. data/tools/epydoc/docwriter/plaintext.pyc +0 -0
  204. data/tools/epydoc/docwriter/xlink.py +505 -0
  205. data/tools/epydoc/docwriter/xlink.pyc +0 -0
  206. data/tools/epydoc/gui.py +1148 -0
  207. data/tools/epydoc/gui.pyc +0 -0
  208. data/tools/epydoc/log.py +204 -0
  209. data/tools/epydoc/log.pyc +0 -0
  210. data/tools/epydoc/markup/__init__.py +623 -0
  211. data/tools/epydoc/markup/__init__.pyc +0 -0
  212. data/tools/epydoc/markup/doctest.py +311 -0
  213. data/tools/epydoc/markup/doctest.pyc +0 -0
  214. data/tools/epydoc/markup/epytext.py +2116 -0
  215. data/tools/epydoc/markup/epytext.pyc +0 -0
  216. data/tools/epydoc/markup/javadoc.py +250 -0
  217. data/tools/epydoc/markup/javadoc.pyc +0 -0
  218. data/tools/epydoc/markup/plaintext.py +78 -0
  219. data/tools/epydoc/markup/plaintext.pyc +0 -0
  220. data/tools/epydoc/markup/pyval_repr.py +532 -0
  221. data/tools/epydoc/markup/pyval_repr.pyc +0 -0
  222. data/tools/epydoc/markup/restructuredtext.py +906 -0
  223. data/tools/epydoc/markup/restructuredtext.pyc +0 -0
  224. data/tools/epydoc/test/__init__.py +97 -0
  225. data/tools/epydoc/test/__init__.pyc +0 -0
  226. data/tools/epydoc/test/util.py +226 -0
  227. data/tools/epydoc/test/util.pyc +0 -0
  228. data/tools/epydoc/util.py +289 -0
  229. data/tools/epydoc/util.pyc +0 -0
  230. data/tools/logilab/logilab/__init__.py +5 -0
  231. data/tools/logilab/logilab/astng/__init__.py +82 -0
  232. data/tools/logilab/logilab/astng/__pkginfo__.py +76 -0
  233. data/tools/logilab/logilab/astng/_exceptions.py +64 -0
  234. data/tools/logilab/logilab/astng/_nodes_ast.py +667 -0
  235. data/tools/logilab/logilab/astng/_nodes_compiler.py +758 -0
  236. data/tools/logilab/logilab/astng/bases.py +608 -0
  237. data/tools/logilab/logilab/astng/builder.py +239 -0
  238. data/tools/logilab/logilab/astng/inference.py +426 -0
  239. data/tools/logilab/logilab/astng/inspector.py +289 -0
  240. data/tools/logilab/logilab/astng/manager.py +421 -0
  241. data/tools/logilab/logilab/astng/mixins.py +165 -0
  242. data/tools/logilab/logilab/astng/node_classes.py +848 -0
  243. data/tools/logilab/logilab/astng/nodes.py +85 -0
  244. data/tools/logilab/logilab/astng/nodes_as_string.py +389 -0
  245. data/tools/logilab/logilab/astng/patchcomptransformer.py +159 -0
  246. data/tools/logilab/logilab/astng/protocols.py +333 -0
  247. data/tools/logilab/logilab/astng/raw_building.py +212 -0
  248. data/tools/logilab/logilab/astng/rebuilder.py +307 -0
  249. data/tools/logilab/logilab/astng/scoped_nodes.py +951 -0
  250. data/tools/logilab/logilab/astng/test/__init__.py +19 -0
  251. data/tools/logilab/logilab/astng/test/data/MyPyPa-0.1.0-py2.5.egg +0 -0
  252. data/tools/logilab/logilab/astng/test/data/MyPyPa-0.1.0-py2.5.zip +0 -0
  253. data/tools/logilab/logilab/astng/test/data/SSL1/Connection1.py +33 -0
  254. data/tools/logilab/logilab/astng/test/data/SSL1/__init__.py +20 -0
  255. data/tools/logilab/logilab/astng/test/data/__init__.py +20 -0
  256. data/tools/logilab/logilab/astng/test/data/all.py +29 -0
  257. data/tools/logilab/logilab/astng/test/data/appl/__init__.py +23 -0
  258. data/tools/logilab/logilab/astng/test/data/appl/myConnection.py +30 -0
  259. data/tools/logilab/logilab/astng/test/data/format.py +34 -0
  260. data/tools/logilab/logilab/astng/test/data/module.py +90 -0
  261. data/tools/logilab/logilab/astng/test/data/module2.py +112 -0
  262. data/tools/logilab/logilab/astng/test/data/noendingnewline.py +57 -0
  263. data/tools/logilab/logilab/astng/test/data/nonregr.py +76 -0
  264. data/tools/logilab/logilab/astng/test/data/notall.py +28 -0
  265. data/tools/logilab/logilab/astng/test/data2/__init__.py +20 -0
  266. data/tools/logilab/logilab/astng/test/data2/clientmodule_test.py +51 -0
  267. data/tools/logilab/logilab/astng/test/data2/suppliermodule_test.py +32 -0
  268. data/tools/logilab/logilab/astng/test/regrtest.py +135 -0
  269. data/tools/logilab/logilab/astng/test/regrtest_data/absimport.py +22 -0
  270. data/tools/logilab/logilab/astng/test/regrtest_data/descriptor_crash.py +31 -0
  271. data/tools/logilab/logilab/astng/test/regrtest_data/import_package_subpackage_module.py +68 -0
  272. data/tools/logilab/logilab/astng/test/regrtest_data/package/__init__.py +24 -0
  273. data/tools/logilab/logilab/astng/test/regrtest_data/package/subpackage/__init__.py +20 -0
  274. data/tools/logilab/logilab/astng/test/regrtest_data/package/subpackage/module.py +20 -0
  275. data/tools/logilab/logilab/astng/test/unittest_builder.py +684 -0
  276. data/tools/logilab/logilab/astng/test/unittest_inference.py +1112 -0
  277. data/tools/logilab/logilab/astng/test/unittest_inspector.py +105 -0
  278. data/tools/logilab/logilab/astng/test/unittest_lookup.py +302 -0
  279. data/tools/logilab/logilab/astng/test/unittest_manager.py +98 -0
  280. data/tools/logilab/logilab/astng/test/unittest_nodes.py +302 -0
  281. data/tools/logilab/logilab/astng/test/unittest_scoped_nodes.py +501 -0
  282. data/tools/logilab/logilab/astng/test/unittest_utils.py +104 -0
  283. data/tools/logilab/logilab/astng/utils.py +342 -0
  284. data/tools/logilab/logilab/common/__init__.py +140 -0
  285. data/tools/logilab/logilab/common/__pkginfo__.py +43 -0
  286. data/tools/logilab/logilab/common/adbh.py +35 -0
  287. data/tools/logilab/logilab/common/cache.py +114 -0
  288. data/tools/logilab/logilab/common/changelog.py +234 -0
  289. data/tools/logilab/logilab/common/clcommands.py +181 -0
  290. data/tools/logilab/logilab/common/cli.py +212 -0
  291. data/tools/logilab/logilab/common/compat.py +328 -0
  292. data/tools/logilab/logilab/common/configuration.py +1087 -0
  293. data/tools/logilab/logilab/common/contexts.py +58 -0
  294. data/tools/logilab/logilab/common/corbautils.py +117 -0
  295. data/tools/logilab/logilab/common/daemon.py +171 -0
  296. data/tools/logilab/logilab/common/date.py +279 -0
  297. data/tools/logilab/logilab/common/db.py +49 -0
  298. data/tools/logilab/logilab/common/dbf.py +229 -0
  299. data/tools/logilab/logilab/common/debugger.py +208 -0
  300. data/tools/logilab/logilab/common/decorators.py +190 -0
  301. data/tools/logilab/logilab/common/deprecation.py +118 -0
  302. data/tools/logilab/logilab/common/fileutils.py +409 -0
  303. data/tools/logilab/logilab/common/graph.py +259 -0
  304. data/tools/logilab/logilab/common/html.py +142 -0
  305. data/tools/logilab/logilab/common/interface.py +76 -0
  306. data/tools/logilab/logilab/common/logging_ext.py +166 -0
  307. data/tools/logilab/logilab/common/modutils.py +670 -0
  308. data/tools/logilab/logilab/common/optik_ext.py +383 -0
  309. data/tools/logilab/logilab/common/optparser.py +92 -0
  310. data/tools/logilab/logilab/common/pdf_ext.py +111 -0
  311. data/tools/logilab/logilab/common/proc.py +276 -0
  312. data/tools/logilab/logilab/common/pyro_ext.py +146 -0
  313. data/tools/logilab/logilab/common/pytest.py +754 -0
  314. data/tools/logilab/logilab/common/shellutils.py +383 -0
  315. data/tools/logilab/logilab/common/sphinx_ext.py +87 -0
  316. data/tools/logilab/logilab/common/sphinxutils.py +122 -0
  317. data/tools/logilab/logilab/common/sqlgen.py +31 -0
  318. data/tools/logilab/logilab/common/table.py +930 -0
  319. data/tools/logilab/logilab/common/tasksqueue.py +97 -0
  320. data/tools/logilab/logilab/common/test/__init__.py +1 -0
  321. data/tools/logilab/logilab/common/test/data/ChangeLog +184 -0
  322. data/tools/logilab/logilab/common/test/data/MyPyPa-0.1.0-py2.5.egg +0 -0
  323. data/tools/logilab/logilab/common/test/data/__init__.py +1 -0
  324. data/tools/logilab/logilab/common/test/data/content_differ_dir/NOTHING +0 -0
  325. data/tools/logilab/logilab/common/test/data/content_differ_dir/README +1 -0
  326. data/tools/logilab/logilab/common/test/data/content_differ_dir/subdir/coin +1 -0
  327. data/tools/logilab/logilab/common/test/data/content_differ_dir/subdir/toto.txt +53 -0
  328. data/tools/logilab/logilab/common/test/data/file_differ_dir/NOTHING +0 -0
  329. data/tools/logilab/logilab/common/test/data/file_differ_dir/README +1 -0
  330. data/tools/logilab/logilab/common/test/data/file_differ_dir/subdir/toto.txt +53 -0
  331. data/tools/logilab/logilab/common/test/data/file_differ_dir/subdirtwo/Hello +0 -0
  332. data/tools/logilab/logilab/common/test/data/find_test/__init__.py +0 -0
  333. data/tools/logilab/logilab/common/test/data/find_test/foo.txt +0 -0
  334. data/tools/logilab/logilab/common/test/data/find_test/module.py +0 -0
  335. data/tools/logilab/logilab/common/test/data/find_test/module2.py +0 -0
  336. data/tools/logilab/logilab/common/test/data/find_test/newlines.txt +0 -0
  337. data/tools/logilab/logilab/common/test/data/find_test/noendingnewline.py +0 -0
  338. data/tools/logilab/logilab/common/test/data/find_test/nonregr.py +0 -0
  339. data/tools/logilab/logilab/common/test/data/find_test/normal_file.txt +0 -0
  340. data/tools/logilab/logilab/common/test/data/find_test/spam.txt +0 -0
  341. data/tools/logilab/logilab/common/test/data/find_test/sub/doc.txt +0 -0
  342. data/tools/logilab/logilab/common/test/data/find_test/sub/momo.py +0 -0
  343. data/tools/logilab/logilab/common/test/data/find_test/test.ini +0 -0
  344. data/tools/logilab/logilab/common/test/data/find_test/test1.msg +0 -0
  345. data/tools/logilab/logilab/common/test/data/find_test/test2.msg +0 -0
  346. data/tools/logilab/logilab/common/test/data/find_test/write_protected_file.txt +0 -0
  347. data/tools/logilab/logilab/common/test/data/foo.txt +9 -0
  348. data/tools/logilab/logilab/common/test/data/module.py +88 -0
  349. data/tools/logilab/logilab/common/test/data/module2.py +77 -0
  350. data/tools/logilab/logilab/common/test/data/newlines.txt +3 -0
  351. data/tools/logilab/logilab/common/test/data/noendingnewline.py +36 -0
  352. data/tools/logilab/logilab/common/test/data/nonregr.py +14 -0
  353. data/tools/logilab/logilab/common/test/data/normal_file.txt +0 -0
  354. data/tools/logilab/logilab/common/test/data/reference_dir/NOTHING +0 -0
  355. data/tools/logilab/logilab/common/test/data/reference_dir/README +1 -0
  356. data/tools/logilab/logilab/common/test/data/reference_dir/subdir/coin +1 -0
  357. data/tools/logilab/logilab/common/test/data/reference_dir/subdir/toto.txt +53 -0
  358. data/tools/logilab/logilab/common/test/data/same_dir/NOTHING +0 -0
  359. data/tools/logilab/logilab/common/test/data/same_dir/README +1 -0
  360. data/tools/logilab/logilab/common/test/data/same_dir/subdir/coin +1 -0
  361. data/tools/logilab/logilab/common/test/data/same_dir/subdir/toto.txt +53 -0
  362. data/tools/logilab/logilab/common/test/data/spam.txt +9 -0
  363. data/tools/logilab/logilab/common/test/data/sub/doc.txt +1 -0
  364. data/tools/logilab/logilab/common/test/data/sub/momo.py +1 -0
  365. data/tools/logilab/logilab/common/test/data/subdir_differ_dir/NOTHING +0 -0
  366. data/tools/logilab/logilab/common/test/data/subdir_differ_dir/README +1 -0
  367. data/tools/logilab/logilab/common/test/data/subdir_differ_dir/subdir/coin +1 -0
  368. data/tools/logilab/logilab/common/test/data/subdir_differ_dir/subdir/toto.txt +53 -0
  369. data/tools/logilab/logilab/common/test/data/test.ini +20 -0
  370. data/tools/logilab/logilab/common/test/data/test1.msg +30 -0
  371. data/tools/logilab/logilab/common/test/data/test2.msg +42 -0
  372. data/tools/logilab/logilab/common/test/data/write_protected_file.txt +0 -0
  373. data/tools/logilab/logilab/common/test/foomod.py +17 -0
  374. data/tools/logilab/logilab/common/test/unittest_cache.py +129 -0
  375. data/tools/logilab/logilab/common/test/unittest_changelog.py +37 -0
  376. data/tools/logilab/logilab/common/test/unittest_compat.py +239 -0
  377. data/tools/logilab/logilab/common/test/unittest_configuration.py +348 -0
  378. data/tools/logilab/logilab/common/test/unittest_date.py +154 -0
  379. data/tools/logilab/logilab/common/test/unittest_decorators.py +62 -0
  380. data/tools/logilab/logilab/common/test/unittest_deprecation.py +76 -0
  381. data/tools/logilab/logilab/common/test/unittest_fileutils.py +133 -0
  382. data/tools/logilab/logilab/common/test/unittest_graph.py +50 -0
  383. data/tools/logilab/logilab/common/test/unittest_html.py +76 -0
  384. data/tools/logilab/logilab/common/test/unittest_interface.py +87 -0
  385. data/tools/logilab/logilab/common/test/unittest_modutils.py +244 -0
  386. data/tools/logilab/logilab/common/test/unittest_pytest.py +50 -0
  387. data/tools/logilab/logilab/common/test/unittest_shellutils.py +248 -0
  388. data/tools/logilab/logilab/common/test/unittest_table.py +448 -0
  389. data/tools/logilab/logilab/common/test/unittest_taskqueue.py +71 -0
  390. data/tools/logilab/logilab/common/test/unittest_testlib.py +956 -0
  391. data/tools/logilab/logilab/common/test/unittest_textutils.py +247 -0
  392. data/tools/logilab/logilab/common/test/unittest_tree.py +248 -0
  393. data/tools/logilab/logilab/common/test/unittest_umessage.py +55 -0
  394. data/tools/logilab/logilab/common/test/unittest_ureports_html.py +64 -0
  395. data/tools/logilab/logilab/common/test/unittest_ureports_text.py +105 -0
  396. data/tools/logilab/logilab/common/test/unittest_xmlutils.py +75 -0
  397. data/tools/logilab/logilab/common/test/utils.py +87 -0
  398. data/tools/logilab/logilab/common/testlib.py +1927 -0
  399. data/tools/logilab/logilab/common/textutils.py +476 -0
  400. data/tools/logilab/logilab/common/tree.py +372 -0
  401. data/tools/logilab/logilab/common/umessage.py +161 -0
  402. data/tools/logilab/logilab/common/ureports/__init__.py +174 -0
  403. data/tools/logilab/logilab/common/ureports/docbook_writer.py +139 -0
  404. data/tools/logilab/logilab/common/ureports/html_writer.py +131 -0
  405. data/tools/logilab/logilab/common/ureports/nodes.py +201 -0
  406. data/tools/logilab/logilab/common/ureports/text_writer.py +140 -0
  407. data/tools/logilab/logilab/common/vcgutils.py +216 -0
  408. data/tools/logilab/logilab/common/visitor.py +107 -0
  409. data/tools/logilab/logilab/common/xmlrpcutils.py +136 -0
  410. data/tools/logilab/logilab/common/xmlutils.py +61 -0
  411. data/tools/pychecker/COPYRIGHT +31 -0
  412. data/tools/pychecker/ChangeLog +349 -0
  413. data/tools/pychecker/CodeChecks.py +1969 -0
  414. data/tools/pychecker/CodeChecks.pyc +0 -0
  415. data/tools/pychecker/CodeChecks.pyo +0 -0
  416. data/tools/pychecker/Config.py +475 -0
  417. data/tools/pychecker/Config.pyc +0 -0
  418. data/tools/pychecker/Config.pyo +0 -0
  419. data/tools/pychecker/KNOWN_BUGS +100 -0
  420. data/tools/pychecker/MAINTAINERS +81 -0
  421. data/tools/pychecker/NEWS +406 -0
  422. data/tools/pychecker/OP.py +131 -0
  423. data/tools/pychecker/OP.pyc +0 -0
  424. data/tools/pychecker/OP.pyo +0 -0
  425. data/tools/pychecker/OptionTypes.py +117 -0
  426. data/tools/pychecker/OptionTypes.pyc +0 -0
  427. data/tools/pychecker/OptionTypes.pyo +0 -0
  428. data/tools/pychecker/README +152 -0
  429. data/tools/pychecker/Stack.py +115 -0
  430. data/tools/pychecker/Stack.pyc +0 -0
  431. data/tools/pychecker/Stack.pyo +0 -0
  432. data/tools/pychecker/TODO +101 -0
  433. data/tools/pychecker/VERSION +1 -0
  434. data/tools/pychecker/Warning.py +50 -0
  435. data/tools/pychecker/Warning.pyc +0 -0
  436. data/tools/pychecker/Warning.pyo +0 -0
  437. data/tools/pychecker/__init__.py +17 -0
  438. data/tools/pychecker/__init__.pyc +0 -0
  439. data/tools/pychecker/__init__.pyo +0 -0
  440. data/tools/pychecker/checker.py +961 -0
  441. data/tools/pychecker/checker.pyc +0 -0
  442. data/tools/pychecker/checker.pyo +0 -0
  443. data/tools/pychecker/function.py +159 -0
  444. data/tools/pychecker/function.pyc +0 -0
  445. data/tools/pychecker/function.pyo +0 -0
  446. data/tools/pychecker/msgs.py +175 -0
  447. data/tools/pychecker/msgs.pyc +0 -0
  448. data/tools/pychecker/msgs.pyo +0 -0
  449. data/tools/pychecker/options.py +275 -0
  450. data/tools/pychecker/options.pyc +0 -0
  451. data/tools/pychecker/options.pyo +0 -0
  452. data/tools/pychecker/pcmodules.py +19 -0
  453. data/tools/pychecker/pcmodules.pyc +0 -0
  454. data/tools/pychecker/pcmodules.pyo +0 -0
  455. data/tools/pychecker/printer.py +47 -0
  456. data/tools/pychecker/printer.pyc +0 -0
  457. data/tools/pychecker/printer.pyo +0 -0
  458. data/tools/pychecker/python.py +427 -0
  459. data/tools/pychecker/python.pyc +0 -0
  460. data/tools/pychecker/python.pyo +0 -0
  461. data/tools/pychecker/utils.py +102 -0
  462. data/tools/pychecker/utils.pyc +0 -0
  463. data/tools/pychecker/utils.pyo +0 -0
  464. data/tools/pychecker/warn.py +778 -0
  465. data/tools/pychecker/warn.pyc +0 -0
  466. data/tools/pychecker/warn.pyo +0 -0
  467. data/tools/pylint2/pylint/__init__.py +16 -0
  468. data/tools/pylint2/pylint/__pkginfo__.py +67 -0
  469. data/tools/pylint2/pylint/checkers/__init__.py +155 -0
  470. data/tools/pylint2/pylint/checkers/base.py +749 -0
  471. data/tools/pylint2/pylint/checkers/classes.py +527 -0
  472. data/tools/pylint2/pylint/checkers/design_analysis.py +344 -0
  473. data/tools/pylint2/pylint/checkers/exceptions.py +183 -0
  474. data/tools/pylint2/pylint/checkers/format.py +367 -0
  475. data/tools/pylint2/pylint/checkers/imports.py +379 -0
  476. data/tools/pylint2/pylint/checkers/logging.py +98 -0
  477. data/tools/pylint2/pylint/checkers/misc.py +128 -0
  478. data/tools/pylint2/pylint/checkers/newstyle.py +107 -0
  479. data/tools/pylint2/pylint/checkers/raw_metrics.py +125 -0
  480. data/tools/pylint2/pylint/checkers/similar.py +333 -0
  481. data/tools/pylint2/pylint/checkers/string_format.py +239 -0
  482. data/tools/pylint2/pylint/checkers/typecheck.py +364 -0
  483. data/tools/pylint2/pylint/checkers/utils.py +208 -0
  484. data/tools/pylint2/pylint/checkers/variables.py +498 -0
  485. data/tools/pylint2/pylint/config.py +149 -0
  486. data/tools/pylint2/pylint/epylint.py +149 -0
  487. data/tools/pylint2/pylint/gui.py +433 -0
  488. data/tools/pylint2/pylint/interfaces.py +98 -0
  489. data/tools/pylint2/pylint/lint.py +914 -0
  490. data/tools/pylint2/pylint/pyreverse/__init__.py +5 -0
  491. data/tools/pylint2/pylint/pyreverse/diadefslib.py +229 -0
  492. data/tools/pylint2/pylint/pyreverse/diagrams.py +247 -0
  493. data/tools/pylint2/pylint/pyreverse/main.py +123 -0
  494. data/tools/pylint2/pylint/pyreverse/utils.py +131 -0
  495. data/tools/pylint2/pylint/pyreverse/writer.py +196 -0
  496. data/tools/pylint2/pylint/reporters/__init__.py +67 -0
  497. data/tools/pylint2/pylint/reporters/guireporter.py +36 -0
  498. data/tools/pylint2/pylint/reporters/html.py +69 -0
  499. data/tools/pylint2/pylint/reporters/text.py +156 -0
  500. data/tools/pylint2/pylint/utils.py +518 -0
  501. data/tools/pylint2/pylint.py +16 -0
  502. data/tools/test/suite.py +35 -0
  503. metadata +566 -0
@@ -0,0 +1,1470 @@
1
+ # epydoc -- Command line interface
2
+ #
3
+ # Copyright (C) 2005 Edward Loper
4
+ # Author: Edward Loper <edloper@loper.org>
5
+ # URL: <http://epydoc.sf.net>
6
+ #
7
+ # $Id: cli.py,v 1.1 2009/11/26 13:20:36 casa Exp $
8
+
9
+ """
10
+ Command-line interface for epydoc. Abbreviated Usage::
11
+
12
+ epydoc [options] NAMES...
13
+
14
+ NAMES... The Python modules to document.
15
+ --html Generate HTML output (default).
16
+ --latex Generate LaTeX output.
17
+ --pdf Generate pdf output, via LaTeX.
18
+ -o DIR, --output DIR The output directory.
19
+ --inheritance STYLE The format for showing inherited objects.
20
+ -V, --version Print the version of epydoc.
21
+ -h, --help Display a usage message.
22
+
23
+ Run \"epydoc --help\" for a complete option list. See the epydoc(1)
24
+ man page for more information.
25
+
26
+ Config Files
27
+ ============
28
+ Configuration files can be specified with the C{--config} option.
29
+ These files are read using U{ConfigParser
30
+ <http://docs.python.org/lib/module-ConfigParser.html>}. Configuration
31
+ files may set options or add names of modules to document. Option
32
+ names are (usually) identical to the long names of command line
33
+ options. To specify names to document, use any of the following
34
+ option names::
35
+
36
+ module modules value values object objects
37
+
38
+ A simple example of a config file is::
39
+
40
+ [epydoc]
41
+ modules: sys, os, os.path, re, %(MYSANDBOXPATH)/utilities.py
42
+ name: Example
43
+ graph: classtree
44
+ introspect: no
45
+
46
+ All ConfigParser interpolations are done using local values and the
47
+ environment variables.
48
+
49
+
50
+ Verbosity Levels
51
+ ================
52
+ The C{-v} and C{-q} options increase and decrease verbosity,
53
+ respectively. The default verbosity level is zero. The verbosity
54
+ levels are currently defined as follows::
55
+
56
+ Progress Markup warnings Warnings Errors
57
+ -3 none no no no
58
+ -2 none no no yes
59
+ -1 none no yes yes
60
+ 0 (default) bar no yes yes
61
+ 1 bar yes yes yes
62
+ 2 list yes yes yes
63
+ """
64
+ __docformat__ = 'epytext en'
65
+
66
+ import sys, os, time, re, pickle, textwrap
67
+ from glob import glob
68
+ from optparse import OptionParser, OptionGroup, SUPPRESS_HELP
69
+ import optparse
70
+ import epydoc
71
+ from epydoc import log
72
+ from epydoc.util import wordwrap, run_subprocess, RunSubprocessError
73
+ from epydoc.util import plaintext_to_html
74
+ from epydoc.apidoc import UNKNOWN
75
+ from epydoc.compat import *
76
+ import ConfigParser
77
+ from epydoc.docwriter.html_css import STYLESHEETS as CSS_STYLESHEETS
78
+
79
+ # This module is only available if Docutils are in the system
80
+ try:
81
+ from epydoc.docwriter import xlink
82
+ except:
83
+ xlink = None
84
+
85
+ INHERITANCE_STYLES = ('grouped', 'listed', 'included')
86
+ GRAPH_TYPES = ('classtree', 'callgraph', 'umlclasstree')
87
+ ACTIONS = ('html', 'text', 'latex', 'dvi', 'ps', 'pdf', 'check')
88
+ DEFAULT_DOCFORMAT = 'epytext'
89
+ PROFILER = 'profile' #: Which profiler to use: 'hotshot' or 'profile'
90
+
91
+ ######################################################################
92
+ #{ Help Topics
93
+ ######################################################################
94
+
95
+ DOCFORMATS = ('epytext', 'plaintext', 'restructuredtext', 'javadoc')
96
+ HELP_TOPICS = {
97
+ 'docformat': textwrap.dedent('''\
98
+ __docformat__ is a module variable that specifies the markup
99
+ language for the docstrings in a module. Its value is a
100
+ string, consisting the name of a markup language, optionally
101
+ followed by a language code (such as "en" for English). Epydoc
102
+ currently recognizes the following markup language names:
103
+ ''' + ', '.join(DOCFORMATS)),
104
+ 'inheritance': textwrap.dedent('''\
105
+ The following inheritance formats are currently supported:
106
+ - grouped: inherited objects are gathered into groups,
107
+ based on what class they were inherited from.
108
+ - listed: inherited objects are listed in a short list
109
+ at the end of their section.
110
+ - included: inherited objects are mixed in with
111
+ non-inherited objects.'''),
112
+ 'css': textwrap.dedent(
113
+ 'The following built-in CSS stylesheets are available:\n' +
114
+ '\n'.join([' %10s: %s' % (key, descr)
115
+ for (key, (sheet, descr))
116
+ in CSS_STYLESHEETS.items()])),
117
+ #'checks': textwrap.dedent('''\
118
+ #
119
+ # '''),
120
+ }
121
+
122
+
123
+ HELP_TOPICS['topics'] = wordwrap(
124
+ 'Epydoc can provide additional help for the following topics: ' +
125
+ ', '.join(['%r' % topic for topic in HELP_TOPICS.keys()]))
126
+
127
+ ######################################################################
128
+ #{ Argument & Config File Parsing
129
+ ######################################################################
130
+
131
+ OPTION_DEFAULTS = dict(
132
+ action="html", show_frames=True, docformat=DEFAULT_DOCFORMAT,
133
+ show_private=True, show_imports=False, inheritance="listed",
134
+ verbose=0, quiet=0, load_pickle=False, parse=True, introspect=True,
135
+ debug=epydoc.DEBUG, profile=False, graphs=[],
136
+ list_classes_separately=False, graph_font=None, graph_font_size=None,
137
+ include_source_code=True, pstat_files=[], simple_term=False, fail_on=None,
138
+ exclude=[], exclude_parse=[], exclude_introspect=[],
139
+ external_api=[], external_api_file=[], external_api_root=[],
140
+ redundant_details=False, src_code_tab_width=8)
141
+
142
+ def parse_arguments():
143
+ # Construct the option parser.
144
+ usage = '%prog [ACTION] [options] NAMES...'
145
+ version = "Epydoc, version %s" % epydoc.__version__
146
+ optparser = OptionParser(usage=usage, add_help_option=False)
147
+
148
+ optparser.add_option('--config',
149
+ action='append', dest="configfiles", metavar='FILE',
150
+ help=("A configuration file, specifying additional OPTIONS "
151
+ "and/or NAMES. This option may be repeated."))
152
+
153
+ optparser.add_option("--output", "-o",
154
+ dest="target", metavar="PATH",
155
+ help="The output directory. If PATH does not exist, then "
156
+ "it will be created.")
157
+
158
+ optparser.add_option("--quiet", "-q",
159
+ action="count", dest="quiet",
160
+ help="Decrease the verbosity.")
161
+
162
+ optparser.add_option("--verbose", "-v",
163
+ action="count", dest="verbose",
164
+ help="Increase the verbosity.")
165
+
166
+ optparser.add_option("--debug",
167
+ action="store_true", dest="debug",
168
+ help="Show full tracebacks for internal errors.")
169
+
170
+ optparser.add_option("--simple-term",
171
+ action="store_true", dest="simple_term",
172
+ help="Do not try to use color or cursor control when displaying "
173
+ "the progress bar, warnings, or errors.")
174
+
175
+
176
+ action_group = OptionGroup(optparser, 'Actions')
177
+ optparser.add_option_group(action_group)
178
+
179
+ action_group.add_option("--html",
180
+ action="store_const", dest="action", const="html",
181
+ help="Write HTML output.")
182
+
183
+ action_group.add_option("--text",
184
+ action="store_const", dest="action", const="text",
185
+ help="Write plaintext output. (not implemented yet)")
186
+
187
+ action_group.add_option("--latex",
188
+ action="store_const", dest="action", const="latex",
189
+ help="Write LaTeX output.")
190
+
191
+ action_group.add_option("--dvi",
192
+ action="store_const", dest="action", const="dvi",
193
+ help="Write DVI output.")
194
+
195
+ action_group.add_option("--ps",
196
+ action="store_const", dest="action", const="ps",
197
+ help="Write Postscript output.")
198
+
199
+ action_group.add_option("--pdf",
200
+ action="store_const", dest="action", const="pdf",
201
+ help="Write PDF output.")
202
+
203
+ action_group.add_option("--check",
204
+ action="store_const", dest="action", const="check",
205
+ help="Check completeness of docs.")
206
+
207
+ action_group.add_option("--pickle",
208
+ action="store_const", dest="action", const="pickle",
209
+ help="Write the documentation to a pickle file.")
210
+
211
+ # Provide our own --help and --version options.
212
+ action_group.add_option("--version",
213
+ action="store_const", dest="action", const="version",
214
+ help="Show epydoc's version number and exit.")
215
+
216
+ action_group.add_option("-h", "--help",
217
+ action="store_const", dest="action", const="help",
218
+ help="Show this message and exit. For help on specific "
219
+ "topics, use \"--help TOPIC\". Use \"--help topics\" for a "
220
+ "list of available help topics")
221
+
222
+
223
+ generation_group = OptionGroup(optparser, 'Generation Options')
224
+ optparser.add_option_group(generation_group)
225
+
226
+ generation_group.add_option("--docformat",
227
+ dest="docformat", metavar="NAME",
228
+ help="The default markup language for docstrings. Defaults "
229
+ "to \"%s\"." % DEFAULT_DOCFORMAT)
230
+
231
+ generation_group.add_option("--parse-only",
232
+ action="store_false", dest="introspect",
233
+ help="Get all information from parsing (don't introspect)")
234
+
235
+ generation_group.add_option("--introspect-only",
236
+ action="store_false", dest="parse",
237
+ help="Get all information from introspecting (don't parse)")
238
+
239
+ generation_group.add_option("--exclude",
240
+ dest="exclude", metavar="PATTERN", action="append",
241
+ help="Exclude modules whose dotted name matches "
242
+ "the regular expression PATTERN")
243
+
244
+ generation_group.add_option("--exclude-introspect",
245
+ dest="exclude_introspect", metavar="PATTERN", action="append",
246
+ help="Exclude introspection of modules whose dotted name matches "
247
+ "the regular expression PATTERN")
248
+
249
+ generation_group.add_option("--exclude-parse",
250
+ dest="exclude_parse", metavar="PATTERN", action="append",
251
+ help="Exclude parsing of modules whose dotted name matches "
252
+ "the regular expression PATTERN")
253
+
254
+ generation_group.add_option("--inheritance",
255
+ dest="inheritance", metavar="STYLE",
256
+ help="The format for showing inheritance objects. STYLE "
257
+ "should be one of: %s." % ', '.join(INHERITANCE_STYLES))
258
+
259
+ generation_group.add_option("--show-private",
260
+ action="store_true", dest="show_private",
261
+ help="Include private variables in the output. (default)")
262
+
263
+ generation_group.add_option("--no-private",
264
+ action="store_false", dest="show_private",
265
+ help="Do not include private variables in the output.")
266
+
267
+ generation_group.add_option("--show-imports",
268
+ action="store_true", dest="show_imports",
269
+ help="List each module's imports.")
270
+
271
+ generation_group.add_option("--no-imports",
272
+ action="store_false", dest="show_imports",
273
+ help="Do not list each module's imports. (default)")
274
+
275
+ generation_group.add_option('--show-sourcecode',
276
+ action='store_true', dest='include_source_code',
277
+ help=("Include source code with syntax highlighting in the "
278
+ "HTML output. (default)"))
279
+
280
+ generation_group.add_option('--no-sourcecode',
281
+ action='store_false', dest='include_source_code',
282
+ help=("Do not include source code with syntax highlighting in the "
283
+ "HTML output."))
284
+
285
+ generation_group.add_option('--include-log',
286
+ action='store_true', dest='include_log',
287
+ help=("Include a page with the process log (epydoc-log.html)"))
288
+
289
+ generation_group.add_option(
290
+ '--redundant-details',
291
+ action='store_true', dest='redundant_details',
292
+ help=("Include values in the details lists even if all info "
293
+ "about them is already provided by the summary table."))
294
+
295
+ output_group = OptionGroup(optparser, 'Output Options')
296
+ optparser.add_option_group(output_group)
297
+
298
+ output_group.add_option("--name", "-n",
299
+ dest="prj_name", metavar="NAME",
300
+ help="The documented project's name (for the navigation bar).")
301
+
302
+ output_group.add_option("--css", "-c",
303
+ dest="css", metavar="STYLESHEET",
304
+ help="The CSS stylesheet. STYLESHEET can be either a "
305
+ "builtin stylesheet or the name of a CSS file.")
306
+
307
+ output_group.add_option("--url", "-u",
308
+ dest="prj_url", metavar="URL",
309
+ help="The documented project's URL (for the navigation bar).")
310
+
311
+ output_group.add_option("--navlink",
312
+ dest="prj_link", metavar="HTML",
313
+ help="HTML code for a navigation link to place in the "
314
+ "navigation bar.")
315
+
316
+ output_group.add_option("--top",
317
+ dest="top_page", metavar="PAGE",
318
+ help="The \"top\" page for the HTML documentation. PAGE can "
319
+ "be a URL, the name of a module or class, or one of the "
320
+ "special names \"trees.html\", \"indices.html\", or \"help.html\"")
321
+
322
+ output_group.add_option("--help-file",
323
+ dest="help_file", metavar="FILE",
324
+ help="An alternate help file. FILE should contain the body "
325
+ "of an HTML file -- navigation bars will be added to it.")
326
+
327
+ output_group.add_option("--show-frames",
328
+ action="store_true", dest="show_frames",
329
+ help="Include frames in the HTML output. (default)")
330
+
331
+ output_group.add_option("--no-frames",
332
+ action="store_false", dest="show_frames",
333
+ help="Do not include frames in the HTML output.")
334
+
335
+ output_group.add_option('--separate-classes',
336
+ action='store_true', dest='list_classes_separately',
337
+ help=("When generating LaTeX or PDF output, list each class in "
338
+ "its own section, instead of listing them under their "
339
+ "containing module."))
340
+
341
+ output_group.add_option('--src-code-tab-width',
342
+ action='store', type='int', dest='src_code_tab_width',
343
+ help=("When generating HTML output, sets the number of spaces "
344
+ "each tab in source code listings is replaced with."))
345
+
346
+ # The group of external API options.
347
+ # Skip if the module couldn't be imported (usually missing docutils)
348
+ if xlink is not None:
349
+ link_group = OptionGroup(optparser,
350
+ xlink.ApiLinkReader.settings_spec[0])
351
+ optparser.add_option_group(link_group)
352
+
353
+ for help, names, opts in xlink.ApiLinkReader.settings_spec[2]:
354
+ opts = opts.copy()
355
+ opts['help'] = help
356
+ link_group.add_option(*names, **opts)
357
+
358
+ graph_group = OptionGroup(optparser, 'Graph Options')
359
+ optparser.add_option_group(graph_group)
360
+
361
+ graph_group.add_option('--graph',
362
+ action='append', dest='graphs', metavar='GRAPHTYPE',
363
+ help=("Include graphs of type GRAPHTYPE in the generated output. "
364
+ "Graphs are generated using the Graphviz dot executable. "
365
+ "If this executable is not on the path, then use --dotpath "
366
+ "to specify its location. This option may be repeated to "
367
+ "include multiple graph types in the output. GRAPHTYPE "
368
+ "should be one of: all, %s." % ', '.join(GRAPH_TYPES)))
369
+
370
+ graph_group.add_option("--dotpath",
371
+ dest="dotpath", metavar='PATH',
372
+ help="The path to the Graphviz 'dot' executable.")
373
+
374
+ graph_group.add_option('--graph-font',
375
+ dest='graph_font', metavar='FONT',
376
+ help=("Specify the font used to generate Graphviz graphs. (e.g., "
377
+ "helvetica or times)."))
378
+
379
+ graph_group.add_option('--graph-font-size',
380
+ dest='graph_font_size', metavar='SIZE',
381
+ help=("Specify the font size used to generate Graphviz graphs, "
382
+ "in points."))
383
+
384
+ graph_group.add_option('--pstat',
385
+ action='append', dest='pstat_files', metavar='FILE',
386
+ help="A pstat output file, to be used in generating call graphs.")
387
+
388
+ # this option is for developers, not users.
389
+ graph_group.add_option("--profile-epydoc",
390
+ action="store_true", dest="profile",
391
+ help=SUPPRESS_HELP or
392
+ ("Run the hotshot profiler on epydoc itself. Output "
393
+ "will be written to profile.out."))
394
+
395
+
396
+ return_group = OptionGroup(optparser, 'Return Value Options')
397
+ optparser.add_option_group(return_group)
398
+
399
+ return_group.add_option("--fail-on-error",
400
+ action="store_const", dest="fail_on", const=log.ERROR,
401
+ help="Return a non-zero exit status, indicating failure, if any "
402
+ "errors are encountered.")
403
+
404
+ return_group.add_option("--fail-on-warning",
405
+ action="store_const", dest="fail_on", const=log.WARNING,
406
+ help="Return a non-zero exit status, indicating failure, if any "
407
+ "errors or warnings are encountered (not including docstring "
408
+ "warnings).")
409
+
410
+ return_group.add_option("--fail-on-docstring-warning",
411
+ action="store_const", dest="fail_on", const=log.DOCSTRING_WARNING,
412
+ help="Return a non-zero exit status, indicating failure, if any "
413
+ "errors or warnings are encountered (including docstring "
414
+ "warnings).")
415
+
416
+ # Set the option parser's defaults.
417
+ optparser.set_defaults(**OPTION_DEFAULTS)
418
+
419
+ # Parse the arguments.
420
+ options, names = optparser.parse_args()
421
+
422
+ # Print help message, if requested. We also provide support for
423
+ # --help [topic]
424
+ if options.action == 'help':
425
+ names = set([n.lower() for n in names])
426
+ for (topic, msg) in HELP_TOPICS.items():
427
+ if topic.lower() in names:
428
+ print '\n' + msg.rstrip() + '\n'
429
+ sys.exit(0)
430
+ optparser.print_help()
431
+ sys.exit(0)
432
+
433
+ # Print version message, if requested.
434
+ if options.action == 'version':
435
+ print version
436
+ sys.exit(0)
437
+
438
+ # Process any config files.
439
+ if options.configfiles:
440
+ try:
441
+ parse_configfiles(options.configfiles, options, names)
442
+ except (KeyboardInterrupt,SystemExit): raise
443
+ except Exception, e:
444
+ if len(options.configfiles) == 1:
445
+ cf_name = 'config file %s' % options.configfiles[0]
446
+ else:
447
+ cf_name = 'config files %s' % ', '.join(options.configfiles)
448
+ optparser.error('Error reading %s:\n %s' % (cf_name, e))
449
+
450
+ # Check if the input file is a pickle file.
451
+ for name in names:
452
+ if name.endswith('.pickle'):
453
+ if len(names) != 1:
454
+ optparser.error("When a pickle file is specified, no other "
455
+ "input files may be specified.")
456
+ options.load_pickle = True
457
+
458
+ # Check to make sure all options are valid.
459
+ if len(names) == 0:
460
+ optparser.error("No names specified.")
461
+
462
+ # perform shell expansion.
463
+ for i, name in reversed(list(enumerate(names[:]))):
464
+ if '?' in name or '*' in name:
465
+ names[i:i+1] = glob(name)
466
+
467
+ if options.inheritance not in INHERITANCE_STYLES:
468
+ optparser.error("Bad inheritance style. Valid options are " +
469
+ ",".join(INHERITANCE_STYLES))
470
+ if not options.parse and not options.introspect:
471
+ optparser.error("Invalid option combination: --parse-only "
472
+ "and --introspect-only.")
473
+ if options.action == 'text' and len(names) > 1:
474
+ optparser.error("--text option takes only one name.")
475
+
476
+ # Check the list of requested graph types to make sure they're
477
+ # acceptable.
478
+ options.graphs = [graph_type.lower() for graph_type in options.graphs]
479
+ for graph_type in options.graphs:
480
+ if graph_type == 'callgraph' and not options.pstat_files:
481
+ optparser.error('"callgraph" graph type may only be used if '
482
+ 'one or more pstat files are specified.')
483
+ # If it's 'all', then add everything (but don't add callgraph if
484
+ # we don't have any profiling info to base them on).
485
+ if graph_type == 'all':
486
+ if options.pstat_files:
487
+ options.graphs = GRAPH_TYPES
488
+ else:
489
+ options.graphs = [g for g in GRAPH_TYPES if g != 'callgraph']
490
+ break
491
+ elif graph_type not in GRAPH_TYPES:
492
+ optparser.error("Invalid graph type %s." % graph_type)
493
+
494
+ # Calculate verbosity.
495
+ verbosity = getattr(options, 'verbosity', 0)
496
+ options.verbosity = verbosity + options.verbose - options.quiet
497
+
498
+ # The target default depends on the action.
499
+ if options.target is None:
500
+ options.target = options.action
501
+
502
+ # Return parsed args.
503
+ options.names = names
504
+ return options, names
505
+
506
+ def parse_configfiles(configfiles, options, names):
507
+ configparser = ConfigParser.ConfigParser()
508
+ # ConfigParser.read() silently ignores errors, so open the files
509
+ # manually (since we want to notify the user of any errors).
510
+ for configfile in configfiles:
511
+ fp = open(configfile, 'r') # may raise IOError.
512
+ configparser.readfp(fp, configfile)
513
+ fp.close()
514
+ for optname in configparser.options('epydoc'):
515
+ val = configparser.get('epydoc', optname, vars=os.environ).strip()
516
+ optname = optname.lower().strip()
517
+
518
+ if optname in ('modules', 'objects', 'values',
519
+ 'module', 'object', 'value'):
520
+ names.extend(_str_to_list(val))
521
+ elif optname == 'target':
522
+ options.target = val
523
+ elif optname == 'output':
524
+ if val.lower() not in ACTIONS:
525
+ raise ValueError('"%s" expected one of: %s' %
526
+ (optname, ', '.join(ACTIONS)))
527
+ options.action = val.lower()
528
+ elif optname == 'verbosity':
529
+ options.verbosity = _str_to_int(val, optname)
530
+ elif optname == 'debug':
531
+ options.debug = _str_to_bool(val, optname)
532
+ elif optname in ('simple-term', 'simple_term'):
533
+ options.simple_term = _str_to_bool(val, optname)
534
+
535
+ # Generation options
536
+ elif optname == 'docformat':
537
+ options.docformat = val
538
+ elif optname == 'parse':
539
+ options.parse = _str_to_bool(val, optname)
540
+ elif optname == 'introspect':
541
+ options.introspect = _str_to_bool(val, optname)
542
+ elif optname == 'exclude':
543
+ options.exclude.extend(_str_to_list(val))
544
+ elif optname in ('exclude-parse', 'exclude_parse'):
545
+ options.exclude_parse.extend(_str_to_list(val))
546
+ elif optname in ('exclude-introspect', 'exclude_introspect'):
547
+ options.exclude_introspect.extend(_str_to_list(val))
548
+ elif optname == 'inheritance':
549
+ if val.lower() not in INHERITANCE_STYLES:
550
+ raise ValueError('"%s" expected one of: %s.' %
551
+ (optname, ', '.join(INHERITANCE_STYLES)))
552
+ options.inheritance = val.lower()
553
+ elif optname =='private':
554
+ options.show_private = _str_to_bool(val, optname)
555
+ elif optname =='imports':
556
+ options.show_imports = _str_to_bool(val, optname)
557
+ elif optname == 'sourcecode':
558
+ options.include_source_code = _str_to_bool(val, optname)
559
+ elif optname in ('include-log', 'include_log'):
560
+ options.include_log = _str_to_bool(val, optname)
561
+ elif optname in ('redundant-details', 'redundant_details'):
562
+ options.redundant_details = _str_to_bool(val, optname)
563
+
564
+ # Output options
565
+ elif optname == 'name':
566
+ options.prj_name = val
567
+ elif optname == 'css':
568
+ options.css = val
569
+ elif optname == 'url':
570
+ options.prj_url = val
571
+ elif optname == 'link':
572
+ options.prj_link = val
573
+ elif optname == 'top':
574
+ options.top_page = val
575
+ elif optname == 'help':
576
+ options.help_file = val
577
+ elif optname =='frames':
578
+ options.show_frames = _str_to_bool(val, optname)
579
+ elif optname in ('separate-classes', 'separate_classes'):
580
+ options.list_classes_separately = _str_to_bool(val, optname)
581
+ elif optname in ('src-code-tab-width', 'src_code_tab_width'):
582
+ options.src_code_tab_width = _str_to_int(val, optname)
583
+
584
+ # External API
585
+ elif optname in ('external-api', 'external_api'):
586
+ options.external_api.extend(_str_to_list(val))
587
+ elif optname in ('external-api-file', 'external_api_file'):
588
+ options.external_api_file.extend(_str_to_list(val))
589
+ elif optname in ('external-api-root', 'external_api_root'):
590
+ options.external_api_root.extend(_str_to_list(val))
591
+
592
+ # Graph options
593
+ elif optname == 'graph':
594
+ graphtypes = _str_to_list(val)
595
+ for graphtype in graphtypes:
596
+ if graphtype not in GRAPH_TYPES + ('all',):
597
+ raise ValueError('"%s" expected one of: all, %s.' %
598
+ (optname, ', '.join(GRAPH_TYPES)))
599
+ options.graphs.extend(graphtypes)
600
+ elif optname == 'dotpath':
601
+ options.dotpath = val
602
+ elif optname in ('graph-font', 'graph_font'):
603
+ options.graph_font = val
604
+ elif optname in ('graph-font-size', 'graph_font_size'):
605
+ options.graph_font_size = _str_to_int(val, optname)
606
+ elif optname == 'pstat':
607
+ options.pstat_files.extend(_str_to_list(val))
608
+
609
+ # Return value options
610
+ elif optname in ('failon', 'fail-on', 'fail_on'):
611
+ if val.lower().strip() in ('error', 'errors'):
612
+ options.fail_on = log.ERROR
613
+ elif val.lower().strip() in ('warning', 'warnings'):
614
+ options.fail_on = log.WARNING
615
+ elif val.lower().strip() in ('docstring_warning',
616
+ 'docstring_warnings'):
617
+ options.fail_on = log.DOCSTRING_WARNING
618
+ else:
619
+ raise ValueError("%r expected one of: error, warning, "
620
+ "docstring_warning" % optname)
621
+ else:
622
+ raise ValueError('Unknown option %s' % optname)
623
+
624
+ def _str_to_bool(val, optname):
625
+ if val.lower() in ('0', 'no', 'false', 'n', 'f', 'hide'):
626
+ return False
627
+ elif val.lower() in ('1', 'yes', 'true', 'y', 't', 'show'):
628
+ return True
629
+ else:
630
+ raise ValueError('"%s" option expected a boolean' % optname)
631
+
632
+ def _str_to_int(val, optname):
633
+ try:
634
+ return int(val)
635
+ except ValueError:
636
+ raise ValueError('"%s" option expected an int' % optname)
637
+
638
+ def _str_to_list(val):
639
+ return val.replace(',', ' ').split()
640
+
641
+ ######################################################################
642
+ #{ Interface
643
+ ######################################################################
644
+
645
+ def main(options, names):
646
+ # Set the debug flag, if '--debug' was specified.
647
+ if options.debug:
648
+ epydoc.DEBUG = True
649
+
650
+ ## [XX] Did this serve a purpose? Commenting out for now:
651
+ #if options.action == 'text':
652
+ # if options.parse and options.introspect:
653
+ # options.parse = False
654
+
655
+ # Set up the logger
656
+ if options.simple_term:
657
+ TerminalController.FORCE_SIMPLE_TERM = True
658
+ if options.action == 'text':
659
+ logger = None # no logger for text output.
660
+ elif options.verbosity > 1:
661
+ logger = ConsoleLogger(options.verbosity)
662
+ log.register_logger(logger)
663
+ else:
664
+ # Each number is a rough approximation of how long we spend on
665
+ # that task, used to divide up the unified progress bar.
666
+ stages = [40, # Building documentation
667
+ 7, # Merging parsed & introspected information
668
+ 1, # Linking imported variables
669
+ 3, # Indexing documentation
670
+ 1, # Checking for overridden methods
671
+ 30, # Parsing Docstrings
672
+ 1, # Inheriting documentation
673
+ 2] # Sorting & Grouping
674
+ if options.load_pickle:
675
+ stages = [30] # Loading pickled documentation
676
+ if options.action == 'html': stages += [100]
677
+ elif options.action == 'text': stages += [30]
678
+ elif options.action == 'latex': stages += [60]
679
+ elif options.action == 'dvi': stages += [60,30]
680
+ elif options.action == 'ps': stages += [60,40]
681
+ elif options.action == 'pdf': stages += [60,50]
682
+ elif options.action == 'check': stages += [10]
683
+ elif options.action == 'pickle': stages += [10]
684
+ else: raise ValueError, '%r not supported' % options.action
685
+ if options.parse and not options.introspect:
686
+ del stages[1] # no merging
687
+ if options.introspect and not options.parse:
688
+ del stages[1:3] # no merging or linking
689
+ logger = UnifiedProgressConsoleLogger(options.verbosity, stages)
690
+ log.register_logger(logger)
691
+
692
+ # check the output directory.
693
+ if options.action not in ('text', 'check', 'pickle'):
694
+ if os.path.exists(options.target):
695
+ if not os.path.isdir(options.target):
696
+ log.error("%s is not a directory" % options.target)
697
+ sys.exit(1)
698
+
699
+ if options.include_log:
700
+ if options.action == 'html':
701
+ if not os.path.exists(options.target):
702
+ os.mkdir(options.target)
703
+ log.register_logger(HTMLLogger(options.target, options))
704
+ else:
705
+ log.warning("--include-log requires --html")
706
+
707
+ # Set the default docformat
708
+ from epydoc import docstringparser
709
+ docstringparser.DEFAULT_DOCFORMAT = options.docformat
710
+
711
+ # Configure the external API linking
712
+ if xlink is not None:
713
+ try:
714
+ xlink.ApiLinkReader.read_configuration(options, problematic=False)
715
+ except Exception, exc:
716
+ log.error("Error while configuring external API linking: %s: %s"
717
+ % (exc.__class__.__name__, exc))
718
+
719
+ # Set the dot path
720
+ if options.dotpath:
721
+ from epydoc.docwriter import dotgraph
722
+ dotgraph.DOT_COMMAND = options.dotpath
723
+
724
+ # Set the default graph font & size
725
+ if options.graph_font:
726
+ from epydoc.docwriter import dotgraph
727
+ fontname = options.graph_font
728
+ dotgraph.DotGraph.DEFAULT_NODE_DEFAULTS['fontname'] = fontname
729
+ dotgraph.DotGraph.DEFAULT_EDGE_DEFAULTS['fontname'] = fontname
730
+ if options.graph_font_size:
731
+ from epydoc.docwriter import dotgraph
732
+ fontsize = options.graph_font_size
733
+ dotgraph.DotGraph.DEFAULT_NODE_DEFAULTS['fontsize'] = fontsize
734
+ dotgraph.DotGraph.DEFAULT_EDGE_DEFAULTS['fontsize'] = fontsize
735
+
736
+ # If the input name is a pickle file, then read the docindex that
737
+ # it contains. Otherwise, build the docs for the input names.
738
+ if options.load_pickle:
739
+ assert len(names) == 1
740
+ log.start_progress('Deserializing')
741
+ log.progress(0.1, 'Loading %r' % names[0])
742
+ t0 = time.time()
743
+ unpickler = pickle.Unpickler(open(names[0], 'rb'))
744
+ unpickler.persistent_load = pickle_persistent_load
745
+ docindex = unpickler.load()
746
+ log.debug('deserialization time: %.1f sec' % (time.time()-t0))
747
+ log.end_progress()
748
+ else:
749
+ # Build docs for the named values.
750
+ from epydoc.docbuilder import build_doc_index
751
+ exclude_parse = '|'.join(options.exclude_parse+options.exclude)
752
+ exclude_introspect = '|'.join(options.exclude_introspect+
753
+ options.exclude)
754
+ docindex = build_doc_index(names, options.introspect, options.parse,
755
+ add_submodules=(options.action!='text'),
756
+ exclude_introspect=exclude_introspect,
757
+ exclude_parse=exclude_parse)
758
+
759
+ if docindex is None:
760
+ if log.ERROR in logger.reported_message_levels:
761
+ sys.exit(1)
762
+ else:
763
+ return # docbuilder already logged an error.
764
+
765
+ # Load profile information, if it was given.
766
+ if options.pstat_files:
767
+ try: import pstats
768
+ except ImportError:
769
+ log.error("Could not import pstats -- ignoring pstat files.")
770
+ try:
771
+ profile_stats = pstats.Stats(options.pstat_files[0])
772
+ for filename in options.pstat_files[1:]:
773
+ profile_stats.add(filename)
774
+ except KeyboardInterrupt: raise
775
+ except Exception, e:
776
+ log.error("Error reading pstat file: %s" % e)
777
+ profile_stats = None
778
+ if profile_stats is not None:
779
+ docindex.read_profiling_info(profile_stats)
780
+
781
+ # Perform the specified action.
782
+ if options.action == 'html':
783
+ write_html(docindex, options)
784
+ elif options.action in ('latex', 'dvi', 'ps', 'pdf'):
785
+ write_latex(docindex, options, options.action)
786
+ elif options.action == 'text':
787
+ write_text(docindex, options)
788
+ elif options.action == 'check':
789
+ check_docs(docindex, options)
790
+ elif options.action == 'pickle':
791
+ write_pickle(docindex, options)
792
+ else:
793
+ print >>sys.stderr, '\nUnsupported action %s!' % options.action
794
+
795
+ # If we suppressed docstring warnings, then let the user know.
796
+ if logger is not None and logger.suppressed_docstring_warning:
797
+ if logger.suppressed_docstring_warning == 1:
798
+ prefix = '1 markup error was found'
799
+ else:
800
+ prefix = ('%d markup errors were found' %
801
+ logger.suppressed_docstring_warning)
802
+ log.warning("%s while processing docstrings. Use the verbose "
803
+ "switch (-v) to display markup errors." % prefix)
804
+
805
+ # Basic timing breakdown:
806
+ if options.verbosity >= 2 and logger is not None:
807
+ logger.print_times()
808
+
809
+ # If we encountered any message types that we were requested to
810
+ # fail on, then exit with status 2.
811
+ if options.fail_on is not None:
812
+ max_reported_message_level = max(logger.reported_message_levels)
813
+ if max_reported_message_level >= options.fail_on:
814
+ sys.exit(2)
815
+
816
+ def write_html(docindex, options):
817
+ from epydoc.docwriter.html import HTMLWriter
818
+ html_writer = HTMLWriter(docindex, **options.__dict__)
819
+ if options.verbose > 0:
820
+ log.start_progress('Writing HTML docs to %r' % options.target)
821
+ else:
822
+ log.start_progress('Writing HTML docs')
823
+ html_writer.write(options.target)
824
+ log.end_progress()
825
+
826
+ def write_pickle(docindex, options):
827
+ """Helper for writing output to a pickle file, which can then be
828
+ read in at a later time. But loading the pickle is only marginally
829
+ faster than building the docs from scratch, so this has pretty
830
+ limited application."""
831
+ if options.target == 'pickle':
832
+ options.target = 'api.pickle'
833
+ elif not options.target.endswith('.pickle'):
834
+ options.target += '.pickle'
835
+
836
+ log.start_progress('Serializing output')
837
+ log.progress(0.2, 'Writing %r' % options.target)
838
+ outfile = open(options.target, 'wb')
839
+ pickler = pickle.Pickler(outfile, protocol=0)
840
+ pickler.persistent_id = pickle_persistent_id
841
+ pickler.dump(docindex)
842
+ outfile.close()
843
+ log.end_progress()
844
+
845
+ def pickle_persistent_id(obj):
846
+ """Helper for pickling, which allows us to save and restore UNKNOWN,
847
+ which is required to be identical to apidoc.UNKNOWN."""
848
+ if obj is UNKNOWN: return 'UNKNOWN'
849
+ else: return None
850
+
851
+ def pickle_persistent_load(identifier):
852
+ """Helper for pickling, which allows us to save and restore UNKNOWN,
853
+ which is required to be identical to apidoc.UNKNOWN."""
854
+ if identifier == 'UNKNOWN': return UNKNOWN
855
+ else: raise pickle.UnpicklingError, 'Invalid persistent id'
856
+
857
+ _RERUN_LATEX_RE = re.compile(r'(?im)^LaTeX\s+Warning:\s+Label\(s\)\s+may'
858
+ r'\s+have\s+changed.\s+Rerun')
859
+
860
+ def write_latex(docindex, options, format):
861
+ from epydoc.docwriter.latex import LatexWriter
862
+ latex_writer = LatexWriter(docindex, **options.__dict__)
863
+ log.start_progress('Writing LaTeX docs')
864
+ latex_writer.write(options.target)
865
+ log.end_progress()
866
+ # If we're just generating the latex, and not any output format,
867
+ # then we're done.
868
+ if format == 'latex': return
869
+
870
+ if format == 'dvi': steps = 4
871
+ elif format == 'ps': steps = 5
872
+ elif format == 'pdf': steps = 6
873
+
874
+ log.start_progress('Processing LaTeX docs')
875
+ oldpath = os.path.abspath(os.curdir)
876
+ running = None # keep track of what we're doing.
877
+ try:
878
+ try:
879
+ os.chdir(options.target)
880
+
881
+ # Clear any old files out of the way.
882
+ for ext in 'tex aux log out idx ilg toc ind'.split():
883
+ if os.path.exists('apidoc.%s' % ext):
884
+ os.remove('apidoc.%s' % ext)
885
+
886
+ # The first pass generates index files.
887
+ running = 'latex'
888
+ log.progress(0./steps, 'LaTeX: First pass')
889
+ run_subprocess('latex api.tex')
890
+
891
+ # Build the index.
892
+ running = 'makeindex'
893
+ log.progress(1./steps, 'LaTeX: Build index')
894
+ run_subprocess('makeindex api.idx')
895
+
896
+ # The second pass generates our output.
897
+ running = 'latex'
898
+ log.progress(2./steps, 'LaTeX: Second pass')
899
+ out, err = run_subprocess('latex api.tex')
900
+
901
+ # The third pass is only necessary if the second pass
902
+ # changed what page some things are on.
903
+ running = 'latex'
904
+ if _RERUN_LATEX_RE.match(out):
905
+ log.progress(3./steps, 'LaTeX: Third pass')
906
+ out, err = run_subprocess('latex api.tex')
907
+
908
+ # A fourth path should (almost?) never be necessary.
909
+ running = 'latex'
910
+ if _RERUN_LATEX_RE.match(out):
911
+ log.progress(3./steps, 'LaTeX: Fourth pass')
912
+ run_subprocess('latex api.tex')
913
+
914
+ # If requested, convert to postscript.
915
+ if format in ('ps', 'pdf'):
916
+ running = 'dvips'
917
+ log.progress(4./steps, 'dvips')
918
+ run_subprocess('dvips api.dvi -o api.ps -G0 -Ppdf')
919
+
920
+ # If requested, convert to pdf.
921
+ if format in ('pdf'):
922
+ running = 'ps2pdf'
923
+ log.progress(5./steps, 'ps2pdf')
924
+ run_subprocess(
925
+ 'ps2pdf -sPAPERSIZE#letter -dMaxSubsetPct#100 '
926
+ '-dSubsetFonts#true -dCompatibilityLevel#1.2 '
927
+ '-dEmbedAllFonts#true api.ps api.pdf')
928
+ except RunSubprocessError, e:
929
+ if running == 'latex':
930
+ e.out = re.sub(r'(?sm)\A.*?!( LaTeX Error:)?', r'', e.out)
931
+ e.out = re.sub(r'(?sm)\s*Type X to quit.*', '', e.out)
932
+ e.out = re.sub(r'(?sm)^! Emergency stop.*', '', e.out)
933
+ log.error("%s failed: %s" % (running, (e.out+e.err).lstrip()))
934
+ except OSError, e:
935
+ log.error("%s failed: %s" % (running, e))
936
+ finally:
937
+ os.chdir(oldpath)
938
+ log.end_progress()
939
+
940
+ def write_text(docindex, options):
941
+ log.start_progress('Writing output')
942
+ from epydoc.docwriter.plaintext import PlaintextWriter
943
+ plaintext_writer = PlaintextWriter()
944
+ s = ''
945
+ for apidoc in docindex.root:
946
+ s += plaintext_writer.write(apidoc)
947
+ log.end_progress()
948
+ if isinstance(s, unicode):
949
+ s = s.encode('ascii', 'backslashreplace')
950
+ print s
951
+
952
+ def check_docs(docindex, options):
953
+ from epydoc.checker import DocChecker
954
+ DocChecker(docindex).check()
955
+
956
+ def cli():
957
+ # Parse command-line arguments.
958
+ options, names = parse_arguments()
959
+
960
+ try:
961
+ try:
962
+ if options.profile:
963
+ _profile()
964
+ else:
965
+ main(options, names)
966
+ finally:
967
+ log.close()
968
+ except SystemExit:
969
+ raise
970
+ except KeyboardInterrupt:
971
+ print '\n\n'
972
+ print >>sys.stderr, 'Keyboard interrupt.'
973
+ except:
974
+ if options.debug: raise
975
+ print '\n\n'
976
+ exc_info = sys.exc_info()
977
+ if isinstance(exc_info[0], basestring): e = exc_info[0]
978
+ else: e = exc_info[1]
979
+ print >>sys.stderr, ('\nUNEXPECTED ERROR:\n'
980
+ '%s\n' % (str(e) or e.__class__.__name__))
981
+ print >>sys.stderr, 'Use --debug to see trace information.'
982
+ sys.exit(3)
983
+
984
+ def _profile():
985
+ # Hotshot profiler.
986
+ if PROFILER == 'hotshot':
987
+ try: import hotshot, hotshot.stats
988
+ except ImportError:
989
+ print >>sys.stderr, "Could not import profile module!"
990
+ return
991
+ try:
992
+ prof = hotshot.Profile('hotshot.out')
993
+ prof = prof.runctx('main(*parse_arguments())', globals(), {})
994
+ except SystemExit:
995
+ pass
996
+ prof.close()
997
+ # Convert profile.hotshot -> profile.out
998
+ print 'Consolidating hotshot profiling info...'
999
+ hotshot.stats.load('hotshot.out').dump_stats('profile.out')
1000
+
1001
+ # Standard 'profile' profiler.
1002
+ elif PROFILER == 'profile':
1003
+ # cProfile module was added in Python 2.5 -- use it if its'
1004
+ # available, since it's faster.
1005
+ try: from cProfile import Profile
1006
+ except ImportError:
1007
+ try: from profile import Profile
1008
+ except ImportError:
1009
+ print >>sys.stderr, "Could not import profile module!"
1010
+ return
1011
+
1012
+ # There was a bug in Python 2.4's profiler. Check if it's
1013
+ # present, and if so, fix it. (Bug was fixed in 2.4maint:
1014
+ # <http://mail.python.org/pipermail/python-checkins/
1015
+ # 2005-September/047099.html>)
1016
+ if (hasattr(Profile, 'dispatch') and
1017
+ Profile.dispatch['c_exception'] is
1018
+ Profile.trace_dispatch_exception.im_func):
1019
+ trace_dispatch_return = Profile.trace_dispatch_return.im_func
1020
+ Profile.dispatch['c_exception'] = trace_dispatch_return
1021
+ try:
1022
+ prof = Profile()
1023
+ prof = prof.runctx('main(*parse_arguments())', globals(), {})
1024
+ except SystemExit:
1025
+ pass
1026
+ prof.dump_stats('profile.out')
1027
+
1028
+ else:
1029
+ print >>sys.stderr, 'Unknown profiler %s' % PROFILER
1030
+ return
1031
+
1032
+ ######################################################################
1033
+ #{ Logging
1034
+ ######################################################################
1035
+
1036
+ class TerminalController:
1037
+ """
1038
+ A class that can be used to portably generate formatted output to
1039
+ a terminal. See
1040
+ U{http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/475116}
1041
+ for documentation. (This is a somewhat stripped-down version.)
1042
+ """
1043
+ BOL = '' #: Move the cursor to the beginning of the line
1044
+ UP = '' #: Move the cursor up one line
1045
+ DOWN = '' #: Move the cursor down one line
1046
+ LEFT = '' #: Move the cursor left one char
1047
+ RIGHT = '' #: Move the cursor right one char
1048
+ CLEAR_EOL = '' #: Clear to the end of the line.
1049
+ CLEAR_LINE = '' #: Clear the current line; cursor to BOL.
1050
+ BOLD = '' #: Turn on bold mode
1051
+ NORMAL = '' #: Turn off all modes
1052
+ COLS = 75 #: Width of the terminal (default to 75)
1053
+ BLACK = BLUE = GREEN = CYAN = RED = MAGENTA = YELLOW = WHITE = ''
1054
+
1055
+ _STRING_CAPABILITIES = """
1056
+ BOL=cr UP=cuu1 DOWN=cud1 LEFT=cub1 RIGHT=cuf1
1057
+ CLEAR_EOL=el BOLD=bold UNDERLINE=smul NORMAL=sgr0""".split()
1058
+ _COLORS = """BLACK BLUE GREEN CYAN RED MAGENTA YELLOW WHITE""".split()
1059
+ _ANSICOLORS = "BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE".split()
1060
+
1061
+ #: If this is set to true, then new TerminalControllers will
1062
+ #: assume that the terminal is not capable of doing manipulation
1063
+ #: of any kind.
1064
+ FORCE_SIMPLE_TERM = False
1065
+
1066
+ def __init__(self, term_stream=sys.stdout):
1067
+ # If the stream isn't a tty, then assume it has no capabilities.
1068
+ if not term_stream.isatty(): return
1069
+ if self.FORCE_SIMPLE_TERM: return
1070
+
1071
+ # Curses isn't available on all platforms
1072
+ try: import curses
1073
+ except:
1074
+ # If it's not available, then try faking enough to get a
1075
+ # simple progress bar.
1076
+ self.BOL = '\r'
1077
+ self.CLEAR_LINE = '\r' + ' '*self.COLS + '\r'
1078
+
1079
+ # Check the terminal type. If we fail, then assume that the
1080
+ # terminal has no capabilities.
1081
+ try: curses.setupterm()
1082
+ except: return
1083
+
1084
+ # Look up numeric capabilities.
1085
+ self.COLS = curses.tigetnum('cols')
1086
+
1087
+ # Look up string capabilities.
1088
+ for capability in self._STRING_CAPABILITIES:
1089
+ (attrib, cap_name) = capability.split('=')
1090
+ setattr(self, attrib, self._tigetstr(cap_name) or '')
1091
+ if self.BOL and self.CLEAR_EOL:
1092
+ self.CLEAR_LINE = self.BOL+self.CLEAR_EOL
1093
+
1094
+ # Colors
1095
+ set_fg = self._tigetstr('setf')
1096
+ if set_fg:
1097
+ for i,color in zip(range(len(self._COLORS)), self._COLORS):
1098
+ setattr(self, color, curses.tparm(set_fg, i) or '')
1099
+ set_fg_ansi = self._tigetstr('setaf')
1100
+ if set_fg_ansi:
1101
+ for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS):
1102
+ setattr(self, color, curses.tparm(set_fg_ansi, i) or '')
1103
+
1104
+ def _tigetstr(self, cap_name):
1105
+ # String capabilities can include "delays" of the form "$<2>".
1106
+ # For any modern terminal, we should be able to just ignore
1107
+ # these, so strip them out.
1108
+ import curses
1109
+ cap = curses.tigetstr(cap_name) or ''
1110
+ return re.sub(r'\$<\d+>[/*]?', '', cap)
1111
+
1112
+ class ConsoleLogger(log.Logger):
1113
+ def __init__(self, verbosity, progress_mode=None):
1114
+ self._verbosity = verbosity
1115
+ self._progress = None
1116
+ self._message_blocks = []
1117
+ # For ETA display:
1118
+ self._progress_start_time = None
1119
+ # For per-task times:
1120
+ self._task_times = []
1121
+ self._progress_header = None
1122
+
1123
+ self.reported_message_levels = set()
1124
+ """This set contains all the message levels (WARNING, ERROR,
1125
+ etc) that have been reported. It is used by the options
1126
+ --fail-on-warning etc to determine the return value."""
1127
+
1128
+ self.suppressed_docstring_warning = 0
1129
+ """This variable will be incremented once every time a
1130
+ docstring warning is reported tothe logger, but the verbosity
1131
+ level is too low for it to be displayed."""
1132
+
1133
+ self.term = TerminalController()
1134
+
1135
+ # Set the progress bar mode.
1136
+ if verbosity >= 2: self._progress_mode = 'list'
1137
+ elif verbosity >= 0:
1138
+ if progress_mode is not None:
1139
+ self._progress_mode = progress_mode
1140
+ elif self.term.COLS < 15:
1141
+ self._progress_mode = 'simple-bar'
1142
+ elif self.term.BOL and self.term.CLEAR_EOL and self.term.UP:
1143
+ self._progress_mode = 'multiline-bar'
1144
+ elif self.term.BOL and self.term.CLEAR_LINE:
1145
+ self._progress_mode = 'bar'
1146
+ else:
1147
+ self._progress_mode = 'simple-bar'
1148
+ else: self._progress_mode = 'hide'
1149
+
1150
+ def start_block(self, header):
1151
+ self._message_blocks.append( (header, []) )
1152
+
1153
+ def end_block(self):
1154
+ header, messages = self._message_blocks.pop()
1155
+ if messages:
1156
+ width = self.term.COLS - 5 - 2*len(self._message_blocks)
1157
+ prefix = self.term.CYAN+self.term.BOLD+'| '+self.term.NORMAL
1158
+ divider = (self.term.CYAN+self.term.BOLD+'+'+'-'*(width-1)+
1159
+ self.term.NORMAL)
1160
+ # Mark up the header:
1161
+ header = wordwrap(header, right=width-2, splitchars='\\/').rstrip()
1162
+ header = '\n'.join([prefix+self.term.CYAN+l+self.term.NORMAL
1163
+ for l in header.split('\n')])
1164
+ # Construct the body:
1165
+ body = ''
1166
+ for message in messages:
1167
+ if message.endswith('\n'): body += message
1168
+ else: body += message+'\n'
1169
+ # Indent the body:
1170
+ body = '\n'.join([prefix+' '+l for l in body.split('\n')])
1171
+ # Put it all together:
1172
+ message = divider + '\n' + header + '\n' + body + '\n'
1173
+ self._report(message)
1174
+
1175
+ def _format(self, prefix, message, color):
1176
+ """
1177
+ Rewrap the message; but preserve newlines, and don't touch any
1178
+ lines that begin with spaces.
1179
+ """
1180
+ lines = message.split('\n')
1181
+ startindex = indent = len(prefix)
1182
+ for i in range(len(lines)):
1183
+ if lines[i].startswith(' '):
1184
+ lines[i] = ' '*(indent-startindex) + lines[i] + '\n'
1185
+ else:
1186
+ width = self.term.COLS - 5 - 4*len(self._message_blocks)
1187
+ lines[i] = wordwrap(lines[i], indent, width, startindex, '\\/')
1188
+ startindex = 0
1189
+ return color+prefix+self.term.NORMAL+''.join(lines)
1190
+
1191
+ def log(self, level, message):
1192
+ self.reported_message_levels.add(level)
1193
+ if self._verbosity >= -2 and level >= log.ERROR:
1194
+ message = self._format(' Error: ', message, self.term.RED)
1195
+ elif self._verbosity >= -1 and level >= log.WARNING:
1196
+ message = self._format('Warning: ', message, self.term.YELLOW)
1197
+ elif self._verbosity >= 1 and level >= log.DOCSTRING_WARNING:
1198
+ message = self._format('Warning: ', message, self.term.YELLOW)
1199
+ elif self._verbosity >= 3 and level >= log.INFO:
1200
+ message = self._format(' Info: ', message, self.term.NORMAL)
1201
+ elif epydoc.DEBUG and level == log.DEBUG:
1202
+ message = self._format(' Debug: ', message, self.term.CYAN)
1203
+ else:
1204
+ if level >= log.DOCSTRING_WARNING:
1205
+ self.suppressed_docstring_warning += 1
1206
+ return
1207
+
1208
+ self._report(message)
1209
+
1210
+ def _report(self, message):
1211
+ if not message.endswith('\n'): message += '\n'
1212
+
1213
+ if self._message_blocks:
1214
+ self._message_blocks[-1][-1].append(message)
1215
+ else:
1216
+ # If we're in the middle of displaying a progress bar,
1217
+ # then make room for the message.
1218
+ if self._progress_mode == 'simple-bar':
1219
+ if self._progress is not None:
1220
+ print
1221
+ self._progress = None
1222
+ if self._progress_mode == 'bar':
1223
+ sys.stdout.write(self.term.CLEAR_LINE)
1224
+ if self._progress_mode == 'multiline-bar':
1225
+ sys.stdout.write((self.term.CLEAR_EOL + '\n')*2 +
1226
+ self.term.CLEAR_EOL + self.term.UP*2)
1227
+
1228
+ # Display the message message.
1229
+ sys.stdout.write(message)
1230
+ sys.stdout.flush()
1231
+
1232
+ def progress(self, percent, message=''):
1233
+ percent = min(1.0, percent)
1234
+ message = '%s' % message
1235
+
1236
+ if self._progress_mode == 'list':
1237
+ if message:
1238
+ print '[%3d%%] %s' % (100*percent, message)
1239
+ sys.stdout.flush()
1240
+
1241
+ elif self._progress_mode == 'bar':
1242
+ dots = int((self.term.COLS/2-8)*percent)
1243
+ background = '-'*(self.term.COLS/2-8)
1244
+ if len(message) > self.term.COLS/2:
1245
+ message = message[:self.term.COLS/2-3]+'...'
1246
+ sys.stdout.write(self.term.CLEAR_LINE + '%3d%% '%(100*percent) +
1247
+ self.term.GREEN + '[' + self.term.BOLD +
1248
+ '='*dots + background[dots:] + self.term.NORMAL +
1249
+ self.term.GREEN + '] ' + self.term.NORMAL +
1250
+ message + self.term.BOL)
1251
+ sys.stdout.flush()
1252
+ self._progress = percent
1253
+ elif self._progress_mode == 'multiline-bar':
1254
+ dots = int((self.term.COLS-10)*percent)
1255
+ background = '-'*(self.term.COLS-10)
1256
+
1257
+ if len(message) > self.term.COLS-10:
1258
+ message = message[:self.term.COLS-10-3]+'...'
1259
+ else:
1260
+ message = message.center(self.term.COLS-10)
1261
+
1262
+ time_elapsed = time.time()-self._progress_start_time
1263
+ if percent > 0:
1264
+ time_remain = (time_elapsed / percent) * (1-percent)
1265
+ else:
1266
+ time_remain = 0
1267
+
1268
+ sys.stdout.write(
1269
+ # Line 1:
1270
+ self.term.CLEAR_EOL + ' ' +
1271
+ '%-8s' % self._timestr(time_elapsed) +
1272
+ self.term.BOLD + 'Progress:'.center(self.term.COLS-26) +
1273
+ self.term.NORMAL + '%8s' % self._timestr(time_remain) + '\n' +
1274
+ # Line 2:
1275
+ self.term.CLEAR_EOL + ('%3d%% ' % (100*percent)) +
1276
+ self.term.GREEN + '[' + self.term.BOLD + '='*dots +
1277
+ background[dots:] + self.term.NORMAL + self.term.GREEN +
1278
+ ']' + self.term.NORMAL + '\n' +
1279
+ # Line 3:
1280
+ self.term.CLEAR_EOL + ' ' + message + self.term.BOL +
1281
+ self.term.UP + self.term.UP)
1282
+
1283
+ sys.stdout.flush()
1284
+ self._progress = percent
1285
+ elif self._progress_mode == 'simple-bar':
1286
+ if self._progress is None:
1287
+ sys.stdout.write(' [')
1288
+ self._progress = 0.0
1289
+ dots = int((self.term.COLS-2)*percent)
1290
+ progress_dots = int((self.term.COLS-2)*self._progress)
1291
+ if dots > progress_dots:
1292
+ sys.stdout.write('.'*(dots-progress_dots))
1293
+ sys.stdout.flush()
1294
+ self._progress = percent
1295
+
1296
+ def _timestr(self, dt):
1297
+ dt = int(dt)
1298
+ if dt >= 3600:
1299
+ return '%d:%02d:%02d' % (dt/3600, dt%3600/60, dt%60)
1300
+ else:
1301
+ return '%02d:%02d' % (dt/60, dt%60)
1302
+
1303
+ def start_progress(self, header=None):
1304
+ if self._progress is not None:
1305
+ raise ValueError
1306
+ self._progress = None
1307
+ self._progress_start_time = time.time()
1308
+ self._progress_header = header
1309
+ if self._progress_mode != 'hide' and header:
1310
+ print self.term.BOLD + header + self.term.NORMAL
1311
+
1312
+ def end_progress(self):
1313
+ self.progress(1.)
1314
+ if self._progress_mode == 'bar':
1315
+ sys.stdout.write(self.term.CLEAR_LINE)
1316
+ if self._progress_mode == 'multiline-bar':
1317
+ sys.stdout.write((self.term.CLEAR_EOL + '\n')*2 +
1318
+ self.term.CLEAR_EOL + self.term.UP*2)
1319
+ if self._progress_mode == 'simple-bar':
1320
+ print ']'
1321
+ self._progress = None
1322
+ self._task_times.append( (time.time()-self._progress_start_time,
1323
+ self._progress_header) )
1324
+
1325
+ def print_times(self):
1326
+ print
1327
+ print 'Timing summary:'
1328
+ total = sum([time for (time, task) in self._task_times])
1329
+ max_t = max([time for (time, task) in self._task_times])
1330
+ for (time, task) in self._task_times:
1331
+ task = task[:31]
1332
+ print ' %s%s %7.1fs' % (task, '.'*(35-len(task)), time),
1333
+ if self.term.COLS > 55:
1334
+ print '|'+'=' * int((self.term.COLS-53) * time / max_t)
1335
+ else:
1336
+ print
1337
+ print
1338
+
1339
+ class UnifiedProgressConsoleLogger(ConsoleLogger):
1340
+ def __init__(self, verbosity, stages, progress_mode=None):
1341
+ self.stage = 0
1342
+ self.stages = stages
1343
+ self.task = None
1344
+ ConsoleLogger.__init__(self, verbosity, progress_mode)
1345
+
1346
+ def progress(self, percent, message=''):
1347
+ #p = float(self.stage-1+percent)/self.stages
1348
+ i = self.stage-1
1349
+ p = ((sum(self.stages[:i]) + percent*self.stages[i]) /
1350
+ float(sum(self.stages)))
1351
+
1352
+ if message is UNKNOWN: message = None
1353
+ if message: message = '%s: %s' % (self.task, message)
1354
+ ConsoleLogger.progress(self, p, message)
1355
+
1356
+ def start_progress(self, header=None):
1357
+ self.task = header
1358
+ if self.stage == 0:
1359
+ ConsoleLogger.start_progress(self)
1360
+ self.stage += 1
1361
+
1362
+ def end_progress(self):
1363
+ if self.stage == len(self.stages):
1364
+ ConsoleLogger.end_progress(self)
1365
+
1366
+ def print_times(self):
1367
+ pass
1368
+
1369
+ class HTMLLogger(log.Logger):
1370
+ """
1371
+ A logger used to generate a log of all warnings and messages to an
1372
+ HTML file.
1373
+ """
1374
+
1375
+ FILENAME = "epydoc-log.html"
1376
+ HEADER = textwrap.dedent('''\
1377
+ <?xml version="1.0" encoding="ascii"?>
1378
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
1379
+ "DTD/xhtml1-transitional.dtd">
1380
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
1381
+ <head>
1382
+ <title>Epydoc Log</title>
1383
+ <link rel="stylesheet" href="epydoc.css" type="text/css" />
1384
+ </head>
1385
+
1386
+ <body bgcolor="white" text="black" link="blue" vlink="#204080"
1387
+ alink="#204080">
1388
+ <h1 class="epydoc">Epydoc Log</h1>
1389
+ <p class="log">Epydoc started at %s</p>''')
1390
+ START_BLOCK = '<div class="log-block"><h2 class="log-hdr">%s</h2>'
1391
+ MESSAGE = ('<div class="log-%s"><b>%s</b>: \n'
1392
+ '%s</div>\n')
1393
+ END_BLOCK = '</div>'
1394
+ FOOTER = "</body>\n</html>\n"
1395
+
1396
+ def __init__(self, directory, options):
1397
+ self.start_time = time.time()
1398
+ self.out = open(os.path.join(directory, self.FILENAME), 'w')
1399
+ self.out.write(self.HEADER % time.ctime(self.start_time))
1400
+ self.is_empty = True
1401
+ self.options = options
1402
+
1403
+ def write_options(self, options):
1404
+ self.out.write(self.START_BLOCK % 'Epydoc Options')
1405
+ msg = '<table border="0" cellpadding="0" cellspacing="0">\n'
1406
+ opts = [(key, getattr(options, key)) for key in dir(options)
1407
+ if key not in dir(optparse.Values)]
1408
+ opts = [(val==OPTION_DEFAULTS.get(key), key, val)
1409
+ for (key, val) in opts]
1410
+ for is_default, key, val in sorted(opts):
1411
+ css = is_default and 'opt-default' or 'opt-changed'
1412
+ msg += ('<tr valign="top" class="%s"><td valign="top">%s</td>'
1413
+ '<td valign="top"><tt>&nbsp;=&nbsp;</tt></td>'
1414
+ '<td valign="top"><tt>%s</tt></td></tr>' %
1415
+ (css, key, plaintext_to_html(repr(val))))
1416
+ msg += '</table>\n'
1417
+ self.out.write('<div class="log-info">\n%s</div>\n' % msg)
1418
+ self.out.write(self.END_BLOCK)
1419
+
1420
+ def start_block(self, header):
1421
+ self.out.write(self.START_BLOCK % header)
1422
+
1423
+ def end_block(self):
1424
+ self.out.write(self.END_BLOCK)
1425
+
1426
+ def log(self, level, message):
1427
+ if message.endswith("(-v) to display markup errors."): return
1428
+ if level >= log.ERROR:
1429
+ self.out.write(self._message('error', message))
1430
+ elif level >= log.WARNING:
1431
+ self.out.write(self._message('warning', message))
1432
+ elif level >= log.DOCSTRING_WARNING:
1433
+ self.out.write(self._message('docstring warning', message))
1434
+
1435
+ def _message(self, level, message):
1436
+ self.is_empty = False
1437
+ message = plaintext_to_html(message)
1438
+ if '\n' in message:
1439
+ message = '<pre class="log">%s</pre>' % message
1440
+ hdr = ' '.join([w.capitalize() for w in level.split()])
1441
+ return self.MESSAGE % (level.split()[-1], hdr, message)
1442
+
1443
+ def close(self):
1444
+ if self.is_empty:
1445
+ self.out.write('<div class="log-info">'
1446
+ 'No warnings or errors!</div>')
1447
+ self.write_options(self.options)
1448
+ self.out.write('<p class="log">Epydoc finished at %s</p>\n'
1449
+ '<p class="log">(Elapsed time: %s)</p>' %
1450
+ (time.ctime(), self._elapsed_time()))
1451
+ self.out.write(self.FOOTER)
1452
+ self.out.close()
1453
+
1454
+ def _elapsed_time(self):
1455
+ secs = int(time.time()-self.start_time)
1456
+ if secs < 60:
1457
+ return '%d seconds' % secs
1458
+ if secs < 3600:
1459
+ return '%d minutes, %d seconds' % (secs/60, secs%60)
1460
+ else:
1461
+ return '%d hours, %d minutes' % (secs/3600, secs%3600)
1462
+
1463
+
1464
+ ######################################################################
1465
+ ## main
1466
+ ######################################################################
1467
+
1468
+ if __name__ == '__main__':
1469
+ cli()
1470
+