exercism-analysis 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (579) hide show
  1. checksums.yaml +7 -0
  2. data/exercism-analysis.gemspec +30 -0
  3. data/lib/exercism-analysis.rb +38 -0
  4. data/lib/exercism-analysis/adapters/adapter.rb +23 -0
  5. data/lib/exercism-analysis/adapters/clojure.rb +13 -0
  6. data/lib/exercism-analysis/adapters/go.rb +19 -0
  7. data/lib/exercism-analysis/adapters/javascript.rb +13 -0
  8. data/lib/exercism-analysis/adapters/python.rb +13 -0
  9. data/lib/exercism-analysis/adapters/ruby.rb +19 -0
  10. data/lib/exercism-analysis/analysis.rb +18 -0
  11. data/lib/exercism-analysis/analyzers/analyzer.rb +54 -0
  12. data/lib/exercism-analysis/analyzers/clojure/kibit.rb +25 -0
  13. data/lib/exercism-analysis/analyzers/go/golint.rb +23 -0
  14. data/lib/exercism-analysis/analyzers/javascript/jslint.rb +24 -0
  15. data/lib/exercism-analysis/analyzers/python/pylint.rb +24 -0
  16. data/lib/exercism-analysis/analyzers/ruby/control_flow.rb +21 -0
  17. data/lib/exercism-analysis/analyzers/ruby/enumerable_condition.rb +21 -0
  18. data/lib/exercism-analysis/analyzers/ruby/for_loop.rb +29 -0
  19. data/lib/exercism-analysis/analyzers/ruby/indentation.rb +21 -0
  20. data/lib/exercism-analysis/analyzers/ruby/iter_mutation.rb +37 -0
  21. data/lib/exercism-analysis/analyzers/ruby/output.rb +20 -0
  22. data/lib/exercism-analysis/analyzers/ruby/range.rb +28 -0
  23. data/lib/exercism-analysis/analyzers/ruby/roodi.rb +19 -0
  24. data/lib/exercism-analysis/analyzers/ruby/send.rb +25 -0
  25. data/lib/exercism-analysis/analyzers/ruby/shebang.rb +23 -0
  26. data/lib/exercism-analysis/analyzers/ruby/tab.rb +38 -0
  27. data/lib/exercism-analysis/processors/call_processor.rb +39 -0
  28. data/lib/exercism-analysis/processors/control_flow_processor.rb +27 -0
  29. data/lib/exercism-analysis/processors/enumerable_condition_processor.rb +31 -0
  30. data/lib/exercism-analysis/processors/for_loop_processor.rb +21 -0
  31. data/lib/exercism-analysis/processors/indentation_processor.rb +69 -0
  32. data/lib/exercism-analysis/processors/iter_mutation_processor.rb +50 -0
  33. data/lib/exercism-analysis/processors/processor.rb +34 -0
  34. data/lib/exercism-analysis/processors/range_processor.rb +23 -0
  35. data/lib/exercism-analysis/processors/send_processor.rb +23 -0
  36. data/lib/exercism-analysis/templates/each_to_map.rb +29 -0
  37. data/lib/exercism-analysis/templates/each_to_select.rb +31 -0
  38. data/lib/exercism-analysis/templates/range_exclusive.rb +19 -0
  39. data/lib/exercism-analysis/templates/template.rb +29 -0
  40. data/vendor/clojure/kibit-runner/LICENSE +214 -0
  41. data/vendor/clojure/kibit-runner/project.clj +10 -0
  42. data/vendor/clojure/kibit-runner/src/kibit_runner/core.clj +17 -0
  43. data/vendor/clojure/kibit-runner/target/kibit-runner-0.1.0-SNAPSHOT-standalone.jar +0 -0
  44. data/vendor/clojure/kibit-runner/target/kibit-runner-0.1.0-SNAPSHOT.jar +0 -0
  45. data/vendor/clojure/kibit-runner/target/stale/extract-native.dependencies +1 -0
  46. data/vendor/go/src/github.com/golang/lint/LICENSE +27 -0
  47. data/vendor/go/src/github.com/golang/lint/README +59 -0
  48. data/vendor/go/src/github.com/golang/lint/golint/golint.go +67 -0
  49. data/vendor/go/src/github.com/golang/lint/lint.go +1061 -0
  50. data/vendor/go/src/runner/golint_runner.go +23 -0
  51. data/vendor/javascript/jshint_runner.js +6 -0
  52. data/vendor/javascript/node_modules/jshint/README.md +47 -0
  53. data/vendor/javascript/node_modules/jshint/bin/apply +6 -0
  54. data/vendor/javascript/node_modules/jshint/bin/build +36 -0
  55. data/vendor/javascript/node_modules/jshint/bin/changelog +36 -0
  56. data/vendor/javascript/node_modules/jshint/bin/jshint +3 -0
  57. data/vendor/javascript/node_modules/jshint/bin/land +34 -0
  58. data/vendor/javascript/node_modules/jshint/data/ascii-identifier-data.js +22 -0
  59. data/vendor/javascript/node_modules/jshint/data/non-ascii-identifier-part-only.js +1570 -0
  60. data/vendor/javascript/node_modules/jshint/data/non-ascii-identifier-start.js +48477 -0
  61. data/vendor/javascript/node_modules/jshint/dist/jshint-rhino.js +60642 -0
  62. data/vendor/javascript/node_modules/jshint/dist/jshint.js +60525 -0
  63. data/vendor/javascript/node_modules/jshint/node_modules/cli/README.md +196 -0
  64. data/vendor/javascript/node_modules/jshint/node_modules/cli/cli.js +1139 -0
  65. data/vendor/javascript/node_modules/jshint/node_modules/cli/examples/cat.js +17 -0
  66. data/vendor/javascript/node_modules/jshint/node_modules/cli/examples/command.js +16 -0
  67. data/vendor/javascript/node_modules/jshint/node_modules/cli/examples/echo.js +54 -0
  68. data/vendor/javascript/node_modules/jshint/node_modules/cli/examples/glob.js +6 -0
  69. data/vendor/javascript/node_modules/jshint/node_modules/cli/examples/long_desc.js +20 -0
  70. data/vendor/javascript/node_modules/jshint/node_modules/cli/examples/progress.js +11 -0
  71. data/vendor/javascript/node_modules/jshint/node_modules/cli/examples/sort.js +18 -0
  72. data/vendor/javascript/node_modules/jshint/node_modules/cli/examples/spinner.js +9 -0
  73. data/vendor/javascript/node_modules/jshint/node_modules/cli/examples/static.coffee +27 -0
  74. data/vendor/javascript/node_modules/jshint/node_modules/cli/examples/static.js +25 -0
  75. data/vendor/javascript/node_modules/jshint/node_modules/cli/index.js +1 -0
  76. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/LICENSE +27 -0
  77. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/README.md +250 -0
  78. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/examples/g.js +9 -0
  79. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/examples/usr-local.js +9 -0
  80. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/glob.js +728 -0
  81. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/LICENSE +16 -0
  82. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/README.md +42 -0
  83. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/inherits.js +1 -0
  84. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/inherits_browser.js +23 -0
  85. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/package.json +51 -0
  86. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/inherits/test.js +25 -0
  87. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/package.json +58 -0
  88. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/test/00-setup.js +176 -0
  89. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-comparison.js +63 -0
  90. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-results.json +351 -0
  91. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/test/cwd-test.js +55 -0
  92. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/test/globstar-match.js +19 -0
  93. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/test/mark.js +118 -0
  94. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/test/new-glob-optional-options.js +10 -0
  95. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/test/nocase-nomagic.js +113 -0
  96. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/test/pause-resume.js +73 -0
  97. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/test/readme-issue.js +36 -0
  98. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/test/root-nomount.js +39 -0
  99. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/test/root.js +46 -0
  100. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/test/stat.js +32 -0
  101. data/vendor/javascript/node_modules/jshint/node_modules/cli/node_modules/glob/test/zz-cleanup.js +11 -0
  102. data/vendor/javascript/node_modules/jshint/node_modules/cli/package.json +70 -0
  103. data/vendor/javascript/node_modules/jshint/node_modules/console-browserify/LICENCE +19 -0
  104. data/vendor/javascript/node_modules/jshint/node_modules/console-browserify/README.md +33 -0
  105. data/vendor/javascript/node_modules/jshint/node_modules/console-browserify/index.js +86 -0
  106. data/vendor/javascript/node_modules/jshint/node_modules/console-browserify/node_modules/date-now/LICENCE +19 -0
  107. data/vendor/javascript/node_modules/jshint/node_modules/console-browserify/node_modules/date-now/README.md +45 -0
  108. data/vendor/javascript/node_modules/jshint/node_modules/console-browserify/node_modules/date-now/index.js +5 -0
  109. data/vendor/javascript/node_modules/jshint/node_modules/console-browserify/node_modules/date-now/package.json +89 -0
  110. data/vendor/javascript/node_modules/jshint/node_modules/console-browserify/node_modules/date-now/seed.js +16 -0
  111. data/vendor/javascript/node_modules/jshint/node_modules/console-browserify/node_modules/date-now/test/index.js +28 -0
  112. data/vendor/javascript/node_modules/jshint/node_modules/console-browserify/node_modules/date-now/test/static/index.html +10 -0
  113. data/vendor/javascript/node_modules/jshint/node_modules/console-browserify/package.json +88 -0
  114. data/vendor/javascript/node_modules/jshint/node_modules/console-browserify/test/index.js +67 -0
  115. data/vendor/javascript/node_modules/jshint/node_modules/console-browserify/test/static/index.html +12 -0
  116. data/vendor/javascript/node_modules/jshint/node_modules/console-browserify/test/static/test-adapter.js +53 -0
  117. data/vendor/javascript/node_modules/jshint/node_modules/exit/Gruntfile.js +48 -0
  118. data/vendor/javascript/node_modules/jshint/node_modules/exit/LICENSE-MIT +22 -0
  119. data/vendor/javascript/node_modules/jshint/node_modules/exit/README.md +75 -0
  120. data/vendor/javascript/node_modules/jshint/node_modules/exit/lib/exit.js +41 -0
  121. data/vendor/javascript/node_modules/jshint/node_modules/exit/package.json +69 -0
  122. data/vendor/javascript/node_modules/jshint/node_modules/exit/test/exit_test.js +121 -0
  123. data/vendor/javascript/node_modules/jshint/node_modules/exit/test/fixtures/10-stderr.txt +10 -0
  124. data/vendor/javascript/node_modules/jshint/node_modules/exit/test/fixtures/10-stdout-stderr.txt +20 -0
  125. data/vendor/javascript/node_modules/jshint/node_modules/exit/test/fixtures/10-stdout.txt +10 -0
  126. data/vendor/javascript/node_modules/jshint/node_modules/exit/test/fixtures/100-stderr.txt +100 -0
  127. data/vendor/javascript/node_modules/jshint/node_modules/exit/test/fixtures/100-stdout-stderr.txt +200 -0
  128. data/vendor/javascript/node_modules/jshint/node_modules/exit/test/fixtures/100-stdout.txt +100 -0
  129. data/vendor/javascript/node_modules/jshint/node_modules/exit/test/fixtures/1000-stderr.txt +1000 -0
  130. data/vendor/javascript/node_modules/jshint/node_modules/exit/test/fixtures/1000-stdout-stderr.txt +2000 -0
  131. data/vendor/javascript/node_modules/jshint/node_modules/exit/test/fixtures/1000-stdout.txt +1000 -0
  132. data/vendor/javascript/node_modules/jshint/node_modules/exit/test/fixtures/create-files.sh +8 -0
  133. data/vendor/javascript/node_modules/jshint/node_modules/exit/test/fixtures/log-broken.js +23 -0
  134. data/vendor/javascript/node_modules/jshint/node_modules/exit/test/fixtures/log.js +25 -0
  135. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/LICENSE +18 -0
  136. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/README.md +83 -0
  137. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/lib/CollectingHandler.js +55 -0
  138. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/lib/FeedHandler.js +95 -0
  139. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/lib/Parser.js +337 -0
  140. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/lib/ProxyHandler.js +27 -0
  141. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/lib/Stream.js +35 -0
  142. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/lib/Tokenizer.js +891 -0
  143. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/lib/WritableStream.js +21 -0
  144. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/lib/index.js +68 -0
  145. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domelementtype/LICENSE +11 -0
  146. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domelementtype/index.js +14 -0
  147. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domelementtype/package.json +40 -0
  148. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domelementtype/readme.md +1 -0
  149. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/LICENSE +11 -0
  150. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/index.js +211 -0
  151. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/package.json +68 -0
  152. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/readme.md +102 -0
  153. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/01-basic.json +57 -0
  154. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/02-single_tag_1.json +21 -0
  155. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/03-single_tag_2.json +21 -0
  156. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/04-unescaped_in_script.json +27 -0
  157. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/05-tags_in_comment.json +18 -0
  158. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/06-comment_in_script.json +18 -0
  159. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/07-unescaped_in_style.json +20 -0
  160. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/08-extra_spaces_in_tag.json +20 -0
  161. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/09-unquoted_attrib.json +20 -0
  162. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/10-singular_attribute.json +15 -0
  163. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/11-text_outside_tags.json +40 -0
  164. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/12-text_only.json +11 -0
  165. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/13-comment_in_text.json +19 -0
  166. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/14-comment_in_text_in_script.json +18 -0
  167. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/15-non-verbose.json +22 -0
  168. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/16-normalize_whitespace.json +47 -0
  169. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/17-xml_namespace.json +18 -0
  170. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/18-enforce_empty_tags.json +16 -0
  171. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/19-ignore_empty_tags.json +20 -0
  172. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/20-template_script_tags.json +20 -0
  173. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/21-conditional_comments.json +15 -0
  174. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/22-lowercase_tags.json +41 -0
  175. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/cases/23-dom-lvl1.json +121 -0
  176. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domhandler/test/tests.js +58 -0
  177. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domutils/LICENSE +11 -0
  178. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domutils/index.js +14 -0
  179. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domutils/lib/helpers.js +141 -0
  180. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domutils/lib/legacy.js +87 -0
  181. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domutils/lib/manipulation.js +77 -0
  182. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domutils/lib/querying.js +94 -0
  183. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domutils/lib/stringify.js +93 -0
  184. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domutils/lib/traversal.js +24 -0
  185. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domutils/package.json +71 -0
  186. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domutils/readme.md +1 -0
  187. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domutils/test/fixture.js +6 -0
  188. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domutils/test/tests/helpers.js +89 -0
  189. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domutils/test/tests/legacy.js +119 -0
  190. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/domutils/test/utils.js +9 -0
  191. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/entities/LICENSE +11 -0
  192. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/entities/index.js +31 -0
  193. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/entities/lib/decode.js +72 -0
  194. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/entities/lib/decode_codepoint.js +26 -0
  195. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/entities/lib/encode.js +48 -0
  196. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/entities/maps/decode.json +1 -0
  197. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/entities/maps/entities.json +1 -0
  198. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/entities/maps/legacy.json +1 -0
  199. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/entities/maps/xml.json +1 -0
  200. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/entities/package.json +79 -0
  201. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/entities/readme.md +31 -0
  202. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/entities/test/mocha.opts +2 -0
  203. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/entities/test/test.js +150 -0
  204. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/LICENSE +18 -0
  205. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/README.md +15 -0
  206. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/duplex.js +1 -0
  207. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/float.patch +923 -0
  208. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/lib/_stream_duplex.js +89 -0
  209. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/lib/_stream_passthrough.js +46 -0
  210. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/lib/_stream_readable.js +944 -0
  211. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/lib/_stream_transform.js +209 -0
  212. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/lib/_stream_writable.js +472 -0
  213. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/core-util-is/README.md +3 -0
  214. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/core-util-is/float.patch +604 -0
  215. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/core-util-is/lib/util.js +107 -0
  216. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/core-util-is/package.json +53 -0
  217. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/core-util-is/util.js +106 -0
  218. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/inherits/LICENSE +16 -0
  219. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/inherits/README.md +42 -0
  220. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/inherits/inherits.js +1 -0
  221. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/inherits/inherits_browser.js +23 -0
  222. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/inherits/package.json +51 -0
  223. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/inherits/test.js +25 -0
  224. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/isarray/README.md +54 -0
  225. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/isarray/build/build.js +209 -0
  226. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/isarray/component.json +19 -0
  227. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/isarray/index.js +3 -0
  228. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/isarray/package.json +54 -0
  229. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/string_decoder/LICENSE +20 -0
  230. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/string_decoder/README.md +7 -0
  231. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/string_decoder/index.js +200 -0
  232. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/string_decoder/package.json +53 -0
  233. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/package.json +68 -0
  234. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/passthrough.js +1 -0
  235. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/readable.js +7 -0
  236. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/transform.js +1 -0
  237. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/writable.js +1 -0
  238. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/package.json +90 -0
  239. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/01-events.js +9 -0
  240. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/02-stream.js +23 -0
  241. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/03-feed.js +19 -0
  242. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Documents/Atom_Example.xml +25 -0
  243. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Documents/Attributes.html +16 -0
  244. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Documents/Basic.html +1 -0
  245. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Documents/RDF_Example.xml +63 -0
  246. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Documents/RSS_Example.xml +48 -0
  247. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/01-simple.json +44 -0
  248. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/02-template.json +63 -0
  249. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/03-lowercase_tags.json +46 -0
  250. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/04-cdata.json +50 -0
  251. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/05-cdata-special.json +35 -0
  252. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/06-leading-lt.json +16 -0
  253. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/07-self-closing.json +67 -0
  254. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/08-implicit-close-tags.json +59 -0
  255. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/09-attributes.json +68 -0
  256. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/10-crazy-attrib.json +52 -0
  257. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/11-script_in_script.json +54 -0
  258. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/12-long-comment-end.json +20 -0
  259. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/13-long-cdata-end.json +22 -0
  260. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/14-implicit-open-tags.json +27 -0
  261. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/15-lt-whitespace.json +16 -0
  262. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/16-double_attribs.json +45 -0
  263. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/17-numeric_entities.json +16 -0
  264. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/18-legacy_entities.json +16 -0
  265. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/19-named_entities.json +16 -0
  266. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/20-xml_entities.json +16 -0
  267. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/21-entity_in_attribute.json +38 -0
  268. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/22-double_brackets.json +41 -0
  269. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/23-legacy_entity_fail.json +16 -0
  270. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/24-special_special.json +133 -0
  271. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/25-empty_tag_name.json +13 -0
  272. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/26-not-quite-closed.json +35 -0
  273. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/27-entities_in_attributes.json +62 -0
  274. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/28-cdata_in_html.json +9 -0
  275. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/29-comment_edge-cases.json +18 -0
  276. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Events/30-cdata_edge-cases.json +22 -0
  277. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Feeds/01-rss.js +34 -0
  278. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Feeds/02-atom.js +18 -0
  279. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Feeds/03-rdf.js +20 -0
  280. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Stream/01-basic.json +83 -0
  281. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Stream/02-RSS.json +1093 -0
  282. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Stream/03-Atom.json +644 -0
  283. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Stream/04-RDF.json +1399 -0
  284. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/Stream/05-Attributes.json +354 -0
  285. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/api.js +63 -0
  286. data/vendor/javascript/node_modules/jshint/node_modules/htmlparser2/test/test-helper.js +83 -0
  287. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/LICENSE +23 -0
  288. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/README.md +218 -0
  289. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/minimatch.js +1061 -0
  290. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/CONTRIBUTORS +14 -0
  291. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/LICENSE +23 -0
  292. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/README.md +97 -0
  293. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js +252 -0
  294. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/package.json +50 -0
  295. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/basic.js +369 -0
  296. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/foreach.js +52 -0
  297. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js +50 -0
  298. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/LICENSE +27 -0
  299. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/README.md +53 -0
  300. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/bench.js +283 -0
  301. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/package.json +58 -0
  302. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/sigmund.js +39 -0
  303. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/node_modules/sigmund/test/basic.js +24 -0
  304. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/package.json +57 -0
  305. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/test/basic.js +399 -0
  306. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/test/brace-expand.js +33 -0
  307. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/test/caching.js +14 -0
  308. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/test/defaults.js +274 -0
  309. data/vendor/javascript/node_modules/jshint/node_modules/minimatch/test/extglob-ending-with-state-char.js +8 -0
  310. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/LICENSE +26 -0
  311. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/README.md +569 -0
  312. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/bin/shjs +51 -0
  313. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/global.js +3 -0
  314. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/make.js +47 -0
  315. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/package.json +61 -0
  316. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/scripts/generate-docs.js +21 -0
  317. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/scripts/run-tests.js +50 -0
  318. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/shell.js +157 -0
  319. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/cat.js +43 -0
  320. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/cd.js +19 -0
  321. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/chmod.js +208 -0
  322. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/common.js +203 -0
  323. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/cp.js +201 -0
  324. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/dirs.js +191 -0
  325. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/echo.js +20 -0
  326. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/error.js +10 -0
  327. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/exec.js +181 -0
  328. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/find.js +51 -0
  329. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/grep.js +52 -0
  330. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/ln.js +53 -0
  331. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/ls.js +126 -0
  332. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/mkdir.js +68 -0
  333. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/mv.js +80 -0
  334. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/popd.js +1 -0
  335. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/pushd.js +1 -0
  336. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/pwd.js +11 -0
  337. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/rm.js +145 -0
  338. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/sed.js +43 -0
  339. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/tempdir.js +56 -0
  340. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/test.js +85 -0
  341. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/to.js +29 -0
  342. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/toEnd.js +29 -0
  343. data/vendor/javascript/node_modules/jshint/node_modules/shelljs/src/which.js +83 -0
  344. data/vendor/javascript/node_modules/jshint/node_modules/strip-json-comments/cli.js +41 -0
  345. data/vendor/javascript/node_modules/jshint/node_modules/strip-json-comments/package.json +76 -0
  346. data/vendor/javascript/node_modules/jshint/node_modules/strip-json-comments/readme.md +74 -0
  347. data/vendor/javascript/node_modules/jshint/node_modules/strip-json-comments/strip-json-comments.js +64 -0
  348. data/vendor/javascript/node_modules/jshint/node_modules/underscore/LICENSE +23 -0
  349. data/vendor/javascript/node_modules/jshint/node_modules/underscore/README.md +22 -0
  350. data/vendor/javascript/node_modules/jshint/node_modules/underscore/package.json +66 -0
  351. data/vendor/javascript/node_modules/jshint/node_modules/underscore/underscore-min.js +6 -0
  352. data/vendor/javascript/node_modules/jshint/node_modules/underscore/underscore.js +1343 -0
  353. data/vendor/javascript/node_modules/jshint/package.json +80 -0
  354. data/vendor/javascript/node_modules/jshint/src/cli.js +731 -0
  355. data/vendor/javascript/node_modules/jshint/src/jshint.js +5023 -0
  356. data/vendor/javascript/node_modules/jshint/src/lex.js +1650 -0
  357. data/vendor/javascript/node_modules/jshint/src/messages.js +223 -0
  358. data/vendor/javascript/node_modules/jshint/src/platforms/rhino.js +115 -0
  359. data/vendor/javascript/node_modules/jshint/src/reg.js +38 -0
  360. data/vendor/javascript/node_modules/jshint/src/reporters/checkstyle.js +81 -0
  361. data/vendor/javascript/node_modules/jshint/src/reporters/default.js +34 -0
  362. data/vendor/javascript/node_modules/jshint/src/reporters/jslint_xml.js +57 -0
  363. data/vendor/javascript/node_modules/jshint/src/reporters/non_error.js +52 -0
  364. data/vendor/javascript/node_modules/jshint/src/state.js +28 -0
  365. data/vendor/javascript/node_modules/jshint/src/style.js +143 -0
  366. data/vendor/javascript/node_modules/jshint/src/vars.js +658 -0
  367. data/vendor/python/astroid/COPYING +339 -0
  368. data/vendor/python/astroid/COPYING.LESSER +510 -0
  369. data/vendor/python/astroid/ChangeLog +574 -0
  370. data/vendor/python/astroid/MANIFEST.in +9 -0
  371. data/vendor/python/astroid/README +56 -0
  372. data/vendor/python/astroid/README.Python3 +26 -0
  373. data/vendor/python/astroid/__init__.py +118 -0
  374. data/vendor/python/astroid/__init__.pyc +0 -0
  375. data/vendor/python/astroid/__pkginfo__.py +48 -0
  376. data/vendor/python/astroid/__pkginfo__.pyc +0 -0
  377. data/vendor/python/astroid/announce.txt +23 -0
  378. data/vendor/python/astroid/as_string.py +496 -0
  379. data/vendor/python/astroid/as_string.pyc +0 -0
  380. data/vendor/python/astroid/bases.py +618 -0
  381. data/vendor/python/astroid/bases.pyc +0 -0
  382. data/vendor/python/astroid/brain/py2gi.py +159 -0
  383. data/vendor/python/astroid/brain/py2gi.pyc +0 -0
  384. data/vendor/python/astroid/brain/py2mechanize.py +20 -0
  385. data/vendor/python/astroid/brain/py2mechanize.pyc +0 -0
  386. data/vendor/python/astroid/brain/py2qt4.py +25 -0
  387. data/vendor/python/astroid/brain/py2qt4.pyc +0 -0
  388. data/vendor/python/astroid/brain/py2stdlib.py +252 -0
  389. data/vendor/python/astroid/brain/py2stdlib.pyc +0 -0
  390. data/vendor/python/astroid/builder.py +238 -0
  391. data/vendor/python/astroid/builder.pyc +0 -0
  392. data/vendor/python/astroid/exceptions.py +51 -0
  393. data/vendor/python/astroid/exceptions.pyc +0 -0
  394. data/vendor/python/astroid/inference.py +393 -0
  395. data/vendor/python/astroid/inference.pyc +0 -0
  396. data/vendor/python/astroid/inspector.py +275 -0
  397. data/vendor/python/astroid/manager.py +336 -0
  398. data/vendor/python/astroid/manager.pyc +0 -0
  399. data/vendor/python/astroid/mixins.py +122 -0
  400. data/vendor/python/astroid/mixins.pyc +0 -0
  401. data/vendor/python/astroid/node_classes.py +928 -0
  402. data/vendor/python/astroid/node_classes.pyc +0 -0
  403. data/vendor/python/astroid/nodes.py +73 -0
  404. data/vendor/python/astroid/nodes.pyc +0 -0
  405. data/vendor/python/astroid/protocols.py +322 -0
  406. data/vendor/python/astroid/protocols.pyc +0 -0
  407. data/vendor/python/astroid/raw_building.py +361 -0
  408. data/vendor/python/astroid/raw_building.pyc +0 -0
  409. data/vendor/python/astroid/rebuilder.py +954 -0
  410. data/vendor/python/astroid/rebuilder.pyc +0 -0
  411. data/vendor/python/astroid/scoped_nodes.py +1118 -0
  412. data/vendor/python/astroid/scoped_nodes.pyc +0 -0
  413. data/vendor/python/astroid/setup.py +184 -0
  414. data/vendor/python/astroid/tox.ini +10 -0
  415. data/vendor/python/astroid/utils.py +236 -0
  416. data/vendor/python/astroid/utils.pyc +0 -0
  417. data/vendor/python/logilab/__init__.py +0 -0
  418. data/vendor/python/logilab/__init__.pyc +0 -0
  419. data/vendor/python/logilab/common/COPYING +339 -0
  420. data/vendor/python/logilab/common/COPYING.LESSER +510 -0
  421. data/vendor/python/logilab/common/ChangeLog +1517 -0
  422. data/vendor/python/logilab/common/MANIFEST.in +13 -0
  423. data/vendor/python/logilab/common/README +185 -0
  424. data/vendor/python/logilab/common/README.Python3 +29 -0
  425. data/vendor/python/logilab/common/__init__.py +171 -0
  426. data/vendor/python/logilab/common/__init__.pyc +0 -0
  427. data/vendor/python/logilab/common/__pkginfo__.py +53 -0
  428. data/vendor/python/logilab/common/__pkginfo__.pyc +0 -0
  429. data/vendor/python/logilab/common/announce.txt +25 -0
  430. data/vendor/python/logilab/common/bin/pytest +7 -0
  431. data/vendor/python/logilab/common/bin/pytest.bat +17 -0
  432. data/vendor/python/logilab/common/cache.py +114 -0
  433. data/vendor/python/logilab/common/changelog.py +236 -0
  434. data/vendor/python/logilab/common/changelog.pyc +0 -0
  435. data/vendor/python/logilab/common/clcommands.py +332 -0
  436. data/vendor/python/logilab/common/cli.py +208 -0
  437. data/vendor/python/logilab/common/compat.py +243 -0
  438. data/vendor/python/logilab/common/compat.pyc +0 -0
  439. data/vendor/python/logilab/common/configuration.py +1094 -0
  440. data/vendor/python/logilab/common/configuration.pyc +0 -0
  441. data/vendor/python/logilab/common/contexts.py +5 -0
  442. data/vendor/python/logilab/common/corbautils.py +117 -0
  443. data/vendor/python/logilab/common/daemon.py +100 -0
  444. data/vendor/python/logilab/common/date.py +333 -0
  445. data/vendor/python/logilab/common/dbf.py +229 -0
  446. data/vendor/python/logilab/common/debugger.py +210 -0
  447. data/vendor/python/logilab/common/decorators.py +281 -0
  448. data/vendor/python/logilab/common/decorators.pyc +0 -0
  449. data/vendor/python/logilab/common/deprecation.py +188 -0
  450. data/vendor/python/logilab/common/deprecation.pyc +0 -0
  451. data/vendor/python/logilab/common/fileutils.py +402 -0
  452. data/vendor/python/logilab/common/graph.py +276 -0
  453. data/vendor/python/logilab/common/graph.pyc +0 -0
  454. data/vendor/python/logilab/common/hg.py +130 -0
  455. data/vendor/python/logilab/common/interface.py +71 -0
  456. data/vendor/python/logilab/common/interface.pyc +0 -0
  457. data/vendor/python/logilab/common/logging_ext.py +193 -0
  458. data/vendor/python/logilab/common/modutils.py +695 -0
  459. data/vendor/python/logilab/common/modutils.pyc +0 -0
  460. data/vendor/python/logilab/common/optik_ext.py +391 -0
  461. data/vendor/python/logilab/common/optik_ext.pyc +0 -0
  462. data/vendor/python/logilab/common/optparser.py +90 -0
  463. data/vendor/python/logilab/common/proc.py +277 -0
  464. data/vendor/python/logilab/common/pyro_ext.py +180 -0
  465. data/vendor/python/logilab/common/pytest.py +1177 -0
  466. data/vendor/python/logilab/common/python-logilab-common.spec +184 -0
  467. data/vendor/python/logilab/common/registry.py +1113 -0
  468. data/vendor/python/logilab/common/setup.cfg +3 -0
  469. data/vendor/python/logilab/common/setup.py +189 -0
  470. data/vendor/python/logilab/common/shellutils.py +455 -0
  471. data/vendor/python/logilab/common/sphinx_ext.py +87 -0
  472. data/vendor/python/logilab/common/sphinxutils.py +122 -0
  473. data/vendor/python/logilab/common/table.py +925 -0
  474. data/vendor/python/logilab/common/tasksqueue.py +100 -0
  475. data/vendor/python/logilab/common/textutils.py +534 -0
  476. data/vendor/python/logilab/common/textutils.pyc +0 -0
  477. data/vendor/python/logilab/common/tree.py +369 -0
  478. data/vendor/python/logilab/common/tree.pyc +0 -0
  479. data/vendor/python/logilab/common/umessage.py +190 -0
  480. data/vendor/python/logilab/common/ureports/__init__.py +174 -0
  481. data/vendor/python/logilab/common/ureports/__init__.pyc +0 -0
  482. data/vendor/python/logilab/common/ureports/docbook_writer.py +139 -0
  483. data/vendor/python/logilab/common/ureports/html_writer.py +131 -0
  484. data/vendor/python/logilab/common/ureports/html_writer.pyc +0 -0
  485. data/vendor/python/logilab/common/ureports/nodes.py +201 -0
  486. data/vendor/python/logilab/common/ureports/nodes.pyc +0 -0
  487. data/vendor/python/logilab/common/ureports/text_writer.py +140 -0
  488. data/vendor/python/logilab/common/ureports/text_writer.pyc +0 -0
  489. data/vendor/python/logilab/common/urllib2ext.py +87 -0
  490. data/vendor/python/logilab/common/vcgutils.py +216 -0
  491. data/vendor/python/logilab/common/visitor.py +107 -0
  492. data/vendor/python/logilab/common/visitor.pyc +0 -0
  493. data/vendor/python/logilab/common/xmlrpcutils.py +131 -0
  494. data/vendor/python/logilab/common/xmlutils.py +61 -0
  495. data/vendor/python/pylint/CONTRIBUTORS.txt +38 -0
  496. data/vendor/python/pylint/COPYING +340 -0
  497. data/vendor/python/pylint/ChangeLog +1437 -0
  498. data/vendor/python/pylint/DEPENDS +3 -0
  499. data/vendor/python/pylint/MANIFEST.in +14 -0
  500. data/vendor/python/pylint/README +50 -0
  501. data/vendor/python/pylint/README.Python3 +37 -0
  502. data/vendor/python/pylint/__init__.py +44 -0
  503. data/vendor/python/pylint/__init__.pyc +0 -0
  504. data/vendor/python/pylint/__main__.py +3 -0
  505. data/vendor/python/pylint/__pkginfo__.py +74 -0
  506. data/vendor/python/pylint/__pkginfo__.pyc +0 -0
  507. data/vendor/python/pylint/bin/epylint +3 -0
  508. data/vendor/python/pylint/bin/epylint.bat +5 -0
  509. data/vendor/python/pylint/bin/pylint +3 -0
  510. data/vendor/python/pylint/bin/pylint-gui +3 -0
  511. data/vendor/python/pylint/bin/pylint-gui.bat +5 -0
  512. data/vendor/python/pylint/bin/pylint.bat +5 -0
  513. data/vendor/python/pylint/bin/pyreverse +3 -0
  514. data/vendor/python/pylint/bin/pyreverse.bat +5 -0
  515. data/vendor/python/pylint/bin/symilar +3 -0
  516. data/vendor/python/pylint/bin/symilar.bat +5 -0
  517. data/vendor/python/pylint/checkers/__init__.py +145 -0
  518. data/vendor/python/pylint/checkers/__init__.pyc +0 -0
  519. data/vendor/python/pylint/checkers/base.py +1141 -0
  520. data/vendor/python/pylint/checkers/base.pyc +0 -0
  521. data/vendor/python/pylint/checkers/classes.py +792 -0
  522. data/vendor/python/pylint/checkers/classes.pyc +0 -0
  523. data/vendor/python/pylint/checkers/design_analysis.py +367 -0
  524. data/vendor/python/pylint/checkers/design_analysis.pyc +0 -0
  525. data/vendor/python/pylint/checkers/exceptions.py +306 -0
  526. data/vendor/python/pylint/checkers/exceptions.pyc +0 -0
  527. data/vendor/python/pylint/checkers/format.py +943 -0
  528. data/vendor/python/pylint/checkers/format.pyc +0 -0
  529. data/vendor/python/pylint/checkers/imports.py +394 -0
  530. data/vendor/python/pylint/checkers/imports.pyc +0 -0
  531. data/vendor/python/pylint/checkers/logging.py +213 -0
  532. data/vendor/python/pylint/checkers/logging.pyc +0 -0
  533. data/vendor/python/pylint/checkers/misc.py +90 -0
  534. data/vendor/python/pylint/checkers/misc.pyc +0 -0
  535. data/vendor/python/pylint/checkers/newstyle.py +151 -0
  536. data/vendor/python/pylint/checkers/newstyle.pyc +0 -0
  537. data/vendor/python/pylint/checkers/raw_metrics.py +129 -0
  538. data/vendor/python/pylint/checkers/raw_metrics.pyc +0 -0
  539. data/vendor/python/pylint/checkers/similar.py +365 -0
  540. data/vendor/python/pylint/checkers/similar.pyc +0 -0
  541. data/vendor/python/pylint/checkers/stdlib.py +69 -0
  542. data/vendor/python/pylint/checkers/stdlib.pyc +0 -0
  543. data/vendor/python/pylint/checkers/strings.py +304 -0
  544. data/vendor/python/pylint/checkers/strings.pyc +0 -0
  545. data/vendor/python/pylint/checkers/typecheck.py +451 -0
  546. data/vendor/python/pylint/checkers/typecheck.pyc +0 -0
  547. data/vendor/python/pylint/checkers/utils.py +416 -0
  548. data/vendor/python/pylint/checkers/utils.pyc +0 -0
  549. data/vendor/python/pylint/checkers/variables.py +741 -0
  550. data/vendor/python/pylint/checkers/variables.pyc +0 -0
  551. data/vendor/python/pylint/config.py +156 -0
  552. data/vendor/python/pylint/config.pyc +0 -0
  553. data/vendor/python/pylint/epylint.py +175 -0
  554. data/vendor/python/pylint/gui.py +508 -0
  555. data/vendor/python/pylint/interfaces.py +72 -0
  556. data/vendor/python/pylint/interfaces.pyc +0 -0
  557. data/vendor/python/pylint/lint.py +1106 -0
  558. data/vendor/python/pylint/lint.pyc +0 -0
  559. data/vendor/python/pylint/pyreverse/__init__.py +5 -0
  560. data/vendor/python/pylint/pyreverse/diadefslib.py +233 -0
  561. data/vendor/python/pylint/pyreverse/diagrams.py +247 -0
  562. data/vendor/python/pylint/pyreverse/main.py +124 -0
  563. data/vendor/python/pylint/pyreverse/utils.py +131 -0
  564. data/vendor/python/pylint/pyreverse/writer.py +199 -0
  565. data/vendor/python/pylint/reporters/__init__.py +138 -0
  566. data/vendor/python/pylint/reporters/__init__.pyc +0 -0
  567. data/vendor/python/pylint/reporters/guireporter.py +28 -0
  568. data/vendor/python/pylint/reporters/guireporter.pyc +0 -0
  569. data/vendor/python/pylint/reporters/html.py +70 -0
  570. data/vendor/python/pylint/reporters/html.pyc +0 -0
  571. data/vendor/python/pylint/reporters/text.py +143 -0
  572. data/vendor/python/pylint/reporters/text.pyc +0 -0
  573. data/vendor/python/pylint/setup.cfg +3 -0
  574. data/vendor/python/pylint/setup.py +203 -0
  575. data/vendor/python/pylint/tox.ini +10 -0
  576. data/vendor/python/pylint/utils.py +744 -0
  577. data/vendor/python/pylint/utils.pyc +0 -0
  578. data/vendor/python/pylint_runner.py +22 -0
  579. metadata +675 -0
@@ -0,0 +1,1177 @@
1
+ # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
2
+ # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
3
+ #
4
+ # This file is part of logilab-common.
5
+ #
6
+ # logilab-common is free software: you can redistribute it and/or modify it under
7
+ # the terms of the GNU Lesser General Public License as published by the Free
8
+ # Software Foundation, either version 2.1 of the License, or (at your option) any
9
+ # later version.
10
+ #
11
+ # logilab-common is distributed in the hope that it will be useful, but WITHOUT
12
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14
+ # details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public License along
17
+ # with logilab-common. If not, see <http://www.gnu.org/licenses/>.
18
+ """pytest is a tool that eases test running and debugging.
19
+
20
+ To be able to use pytest, you should either write tests using
21
+ the logilab.common.testlib's framework or the unittest module of the
22
+ Python's standard library.
23
+
24
+ You can customize pytest's behaviour by defining a ``pytestconf.py`` file
25
+ somewhere in your test directory. In this file, you can add options or
26
+ change the way tests are run.
27
+
28
+ To add command line options, you must define a ``update_parser`` function in
29
+ your ``pytestconf.py`` file. The function must accept a single parameter
30
+ that will be the OptionParser's instance to customize.
31
+
32
+ If you wish to customize the tester, you'll have to define a class named
33
+ ``CustomPyTester``. This class should extend the default `PyTester` class
34
+ defined in the pytest module. Take a look at the `PyTester` and `DjangoTester`
35
+ classes for more information about what can be done.
36
+
37
+ For instance, if you wish to add a custom -l option to specify a loglevel, you
38
+ could define the following ``pytestconf.py`` file ::
39
+
40
+ import logging
41
+ from logilab.common.pytest import PyTester
42
+
43
+ def update_parser(parser):
44
+ parser.add_option('-l', '--loglevel', dest='loglevel', action='store',
45
+ choices=('debug', 'info', 'warning', 'error', 'critical'),
46
+ default='critical', help="the default log level possible choices are "
47
+ "('debug', 'info', 'warning', 'error', 'critical')")
48
+ return parser
49
+
50
+
51
+ class CustomPyTester(PyTester):
52
+ def __init__(self, cvg, options):
53
+ super(CustomPyTester, self).__init__(cvg, options)
54
+ loglevel = options.loglevel.upper()
55
+ logger = logging.getLogger('erudi')
56
+ logger.setLevel(logging.getLevelName(loglevel))
57
+
58
+
59
+ In your TestCase class you can then get the value of a specific option with
60
+ the ``optval`` method::
61
+
62
+ class MyTestCase(TestCase):
63
+ def test_foo(self):
64
+ loglevel = self.optval('loglevel')
65
+ # ...
66
+
67
+
68
+ You can also tag your tag your test for fine filtering
69
+
70
+ With those tag::
71
+
72
+ from logilab.common.testlib import tag, TestCase
73
+
74
+ class Exemple(TestCase):
75
+
76
+ @tag('rouge', 'carre')
77
+ def toto(self):
78
+ pass
79
+
80
+ @tag('carre', 'vert')
81
+ def tata(self):
82
+ pass
83
+
84
+ @tag('rouge')
85
+ def titi(test):
86
+ pass
87
+
88
+ you can filter the function with a simple python expression
89
+
90
+ * ``toto`` and ``titi`` match ``rouge``
91
+ * ``toto``, ``tata`` and ``titi``, match ``rouge or carre``
92
+ * ``tata`` and ``titi`` match``rouge ^ carre``
93
+ * ``titi`` match ``rouge and not carre``
94
+ """
95
+ __docformat__ = "restructuredtext en"
96
+
97
+ PYTEST_DOC = """%prog [OPTIONS] [testfile [testpattern]]
98
+
99
+ examples:
100
+
101
+ pytest path/to/mytests.py
102
+ pytest path/to/mytests.py TheseTests
103
+ pytest path/to/mytests.py TheseTests.test_thisone
104
+ pytest path/to/mytests.py -m '(not long and database) or regr'
105
+
106
+ pytest one (will run both test_thisone and test_thatone)
107
+ pytest path/to/mytests.py -s not (will skip test_notthisone)
108
+
109
+ pytest --coverage test_foo.py
110
+ (only if logilab.devtools is available)
111
+ """
112
+
113
+ ENABLE_DBC = False
114
+ FILE_RESTART = ".pytest.restart"
115
+
116
+ import os, sys, re
117
+ import os.path as osp
118
+ from time import time, clock
119
+ import warnings
120
+ import types
121
+
122
+ from logilab.common.fileutils import abspath_listdir
123
+ from logilab.common import textutils
124
+ from logilab.common import testlib, STD_BLACKLIST
125
+ # use the same unittest module as testlib
126
+ from logilab.common.testlib import unittest, start_interactive_mode
127
+ from logilab.common.compat import any
128
+ import doctest
129
+
130
+ import unittest as unittest_legacy
131
+ if not getattr(unittest_legacy, "__package__", None):
132
+ try:
133
+ import unittest2.suite as unittest_suite
134
+ except ImportError:
135
+ sys.exit("You have to install python-unittest2 to use this module")
136
+ else:
137
+ import unittest.suite as unittest_suite
138
+
139
+ try:
140
+ import django
141
+ from logilab.common.modutils import modpath_from_file, load_module_from_modpath
142
+ DJANGO_FOUND = True
143
+ except ImportError:
144
+ DJANGO_FOUND = False
145
+
146
+ CONF_FILE = 'pytestconf.py'
147
+
148
+ ## coverage hacks, do not read this, do not read this, do not read this
149
+
150
+ # hey, but this is an aspect, right ?!!!
151
+ class TraceController(object):
152
+ nesting = 0
153
+
154
+ def pause_tracing(cls):
155
+ if not cls.nesting:
156
+ cls.tracefunc = staticmethod(getattr(sys, '__settrace__', sys.settrace))
157
+ cls.oldtracer = getattr(sys, '__tracer__', None)
158
+ sys.__notrace__ = True
159
+ cls.tracefunc(None)
160
+ cls.nesting += 1
161
+ pause_tracing = classmethod(pause_tracing)
162
+
163
+ def resume_tracing(cls):
164
+ cls.nesting -= 1
165
+ assert cls.nesting >= 0
166
+ if not cls.nesting:
167
+ cls.tracefunc(cls.oldtracer)
168
+ delattr(sys, '__notrace__')
169
+ resume_tracing = classmethod(resume_tracing)
170
+
171
+
172
+ pause_tracing = TraceController.pause_tracing
173
+ resume_tracing = TraceController.resume_tracing
174
+
175
+
176
+ def nocoverage(func):
177
+ if hasattr(func, 'uncovered'):
178
+ return func
179
+ func.uncovered = True
180
+ def not_covered(*args, **kwargs):
181
+ pause_tracing()
182
+ try:
183
+ return func(*args, **kwargs)
184
+ finally:
185
+ resume_tracing()
186
+ not_covered.uncovered = True
187
+ return not_covered
188
+
189
+
190
+ ## end of coverage hacks
191
+
192
+
193
+ TESTFILE_RE = re.compile("^((unit)?test.*|smoketest)\.py$")
194
+ def this_is_a_testfile(filename):
195
+ """returns True if `filename` seems to be a test file"""
196
+ return TESTFILE_RE.match(osp.basename(filename))
197
+
198
+ TESTDIR_RE = re.compile("^(unit)?tests?$")
199
+ def this_is_a_testdir(dirpath):
200
+ """returns True if `filename` seems to be a test directory"""
201
+ return TESTDIR_RE.match(osp.basename(dirpath))
202
+
203
+
204
+ def load_pytest_conf(path, parser):
205
+ """loads a ``pytestconf.py`` file and update default parser
206
+ and / or tester.
207
+ """
208
+ namespace = {}
209
+ execfile(path, namespace)
210
+ if 'update_parser' in namespace:
211
+ namespace['update_parser'](parser)
212
+ return namespace.get('CustomPyTester', PyTester)
213
+
214
+
215
+ def project_root(parser, projdir=os.getcwd()):
216
+ """try to find project's root and add it to sys.path"""
217
+ previousdir = curdir = osp.abspath(projdir)
218
+ testercls = PyTester
219
+ conf_file_path = osp.join(curdir, CONF_FILE)
220
+ if osp.isfile(conf_file_path):
221
+ testercls = load_pytest_conf(conf_file_path, parser)
222
+ while this_is_a_testdir(curdir) or \
223
+ osp.isfile(osp.join(curdir, '__init__.py')):
224
+ newdir = osp.normpath(osp.join(curdir, os.pardir))
225
+ if newdir == curdir:
226
+ break
227
+ previousdir = curdir
228
+ curdir = newdir
229
+ conf_file_path = osp.join(curdir, CONF_FILE)
230
+ if osp.isfile(conf_file_path):
231
+ testercls = load_pytest_conf(conf_file_path, parser)
232
+ return previousdir, testercls
233
+
234
+
235
+ class GlobalTestReport(object):
236
+ """this class holds global test statistics"""
237
+ def __init__(self):
238
+ self.ran = 0
239
+ self.skipped = 0
240
+ self.failures = 0
241
+ self.errors = 0
242
+ self.ttime = 0
243
+ self.ctime = 0
244
+ self.modulescount = 0
245
+ self.errmodules = []
246
+
247
+ def feed(self, filename, testresult, ttime, ctime):
248
+ """integrates new test information into internal statistics"""
249
+ ran = testresult.testsRun
250
+ self.ran += ran
251
+ self.skipped += len(getattr(testresult, 'skipped', ()))
252
+ self.failures += len(testresult.failures)
253
+ self.errors += len(testresult.errors)
254
+ self.ttime += ttime
255
+ self.ctime += ctime
256
+ self.modulescount += 1
257
+ if not testresult.wasSuccessful():
258
+ problems = len(testresult.failures) + len(testresult.errors)
259
+ self.errmodules.append((filename[:-3], problems, ran))
260
+
261
+ def failed_to_test_module(self, filename):
262
+ """called when the test module could not be imported by unittest
263
+ """
264
+ self.errors += 1
265
+ self.modulescount += 1
266
+ self.ran += 1
267
+ self.errmodules.append((filename[:-3], 1, 1))
268
+
269
+ def skip_module(self, filename):
270
+ self.modulescount += 1
271
+ self.ran += 1
272
+ self.errmodules.append((filename[:-3], 0, 0))
273
+
274
+ def __str__(self):
275
+ """this is just presentation stuff"""
276
+ line1 = ['Ran %s test cases in %.2fs (%.2fs CPU)'
277
+ % (self.ran, self.ttime, self.ctime)]
278
+ if self.errors:
279
+ line1.append('%s errors' % self.errors)
280
+ if self.failures:
281
+ line1.append('%s failures' % self.failures)
282
+ if self.skipped:
283
+ line1.append('%s skipped' % self.skipped)
284
+ modulesok = self.modulescount - len(self.errmodules)
285
+ if self.errors or self.failures:
286
+ line2 = '%s modules OK (%s failed)' % (modulesok,
287
+ len(self.errmodules))
288
+ descr = ', '.join(['%s [%s/%s]' % info for info in self.errmodules])
289
+ line3 = '\nfailures: %s' % descr
290
+ elif modulesok:
291
+ line2 = 'All %s modules OK' % modulesok
292
+ line3 = ''
293
+ else:
294
+ return ''
295
+ return '%s\n%s%s' % (', '.join(line1), line2, line3)
296
+
297
+
298
+
299
+ def remove_local_modules_from_sys(testdir):
300
+ """remove all modules from cache that come from `testdir`
301
+
302
+ This is used to avoid strange side-effects when using the
303
+ testall() mode of pytest.
304
+ For instance, if we run pytest on this tree::
305
+
306
+ A/test/test_utils.py
307
+ B/test/test_utils.py
308
+
309
+ we **have** to clean sys.modules to make sure the correct test_utils
310
+ module is ran in B
311
+ """
312
+ for modname, mod in sys.modules.items():
313
+ if mod is None:
314
+ continue
315
+ if not hasattr(mod, '__file__'):
316
+ # this is the case of some built-in modules like sys, imp, marshal
317
+ continue
318
+ modfile = mod.__file__
319
+ # if modfile is not an absolute path, it was probably loaded locally
320
+ # during the tests
321
+ if not osp.isabs(modfile) or modfile.startswith(testdir):
322
+ del sys.modules[modname]
323
+
324
+
325
+
326
+ class PyTester(object):
327
+ """encapsulates testrun logic"""
328
+
329
+ def __init__(self, cvg, options):
330
+ self.report = GlobalTestReport()
331
+ self.cvg = cvg
332
+ self.options = options
333
+ self.firstwrite = True
334
+ self._errcode = None
335
+
336
+ def show_report(self):
337
+ """prints the report and returns appropriate exitcode"""
338
+ # everything has been ran, print report
339
+ print "*" * 79
340
+ print self.report
341
+
342
+ def get_errcode(self):
343
+ # errcode set explicitly
344
+ if self._errcode is not None:
345
+ return self._errcode
346
+ return self.report.failures + self.report.errors
347
+
348
+ def set_errcode(self, errcode):
349
+ self._errcode = errcode
350
+ errcode = property(get_errcode, set_errcode)
351
+
352
+ def testall(self, exitfirst=False):
353
+ """walks through current working directory, finds something
354
+ which can be considered as a testdir and runs every test there
355
+ """
356
+ here = os.getcwd()
357
+ for dirname, dirs, _ in os.walk(here):
358
+ for skipped in STD_BLACKLIST:
359
+ if skipped in dirs:
360
+ dirs.remove(skipped)
361
+ basename = osp.basename(dirname)
362
+ if this_is_a_testdir(basename):
363
+ print "going into", dirname
364
+ # we found a testdir, let's explore it !
365
+ if not self.testonedir(dirname, exitfirst):
366
+ break
367
+ dirs[:] = []
368
+ if self.report.ran == 0:
369
+ print "no test dir found testing here:", here
370
+ # if no test was found during the visit, consider
371
+ # the local directory as a test directory even if
372
+ # it doesn't have a traditional test directory name
373
+ self.testonedir(here)
374
+
375
+ def testonedir(self, testdir, exitfirst=False):
376
+ """finds each testfile in the `testdir` and runs it
377
+
378
+ return true when all tests has been executed, false if exitfirst and
379
+ some test has failed.
380
+ """
381
+ for filename in abspath_listdir(testdir):
382
+ if this_is_a_testfile(filename):
383
+ if self.options.exitfirst and not self.options.restart:
384
+ # overwrite restart file
385
+ try:
386
+ restartfile = open(FILE_RESTART, "w")
387
+ restartfile.close()
388
+ except Exception, e:
389
+ print >> sys.__stderr__, "Error while overwriting \
390
+ succeeded test file :", osp.join(os.getcwd(), FILE_RESTART)
391
+ raise e
392
+ # run test and collect information
393
+ prog = self.testfile(filename, batchmode=True)
394
+ if exitfirst and (prog is None or not prog.result.wasSuccessful()):
395
+ return False
396
+ self.firstwrite = True
397
+ # clean local modules
398
+ remove_local_modules_from_sys(testdir)
399
+ return True
400
+
401
+ def testfile(self, filename, batchmode=False):
402
+ """runs every test in `filename`
403
+
404
+ :param filename: an absolute path pointing to a unittest file
405
+ """
406
+ here = os.getcwd()
407
+ dirname = osp.dirname(filename)
408
+ if dirname:
409
+ os.chdir(dirname)
410
+ # overwrite restart file if it has not been done already
411
+ if self.options.exitfirst and not self.options.restart and self.firstwrite:
412
+ try:
413
+ restartfile = open(FILE_RESTART, "w")
414
+ restartfile.close()
415
+ except Exception, e:
416
+ print >> sys.__stderr__, "Error while overwriting \
417
+ succeeded test file :", osp.join(os.getcwd(), FILE_RESTART)
418
+ raise e
419
+ modname = osp.basename(filename)[:-3]
420
+ try:
421
+ print >> sys.stderr, (' %s ' % osp.basename(filename)).center(70, '=')
422
+ except TypeError: # < py 2.4 bw compat
423
+ print >> sys.stderr, (' %s ' % osp.basename(filename)).center(70)
424
+ try:
425
+ tstart, cstart = time(), clock()
426
+ try:
427
+ testprog = SkipAwareTestProgram(modname, batchmode=batchmode, cvg=self.cvg,
428
+ options=self.options, outstream=sys.stderr)
429
+ except KeyboardInterrupt:
430
+ raise
431
+ except SystemExit, exc:
432
+ self.errcode = exc.code
433
+ raise
434
+ except testlib.SkipTest:
435
+ print "Module skipped:", filename
436
+ self.report.skip_module(filename)
437
+ return None
438
+ except Exception:
439
+ self.report.failed_to_test_module(filename)
440
+ print >> sys.stderr, 'unhandled exception occurred while testing', modname
441
+ import traceback
442
+ traceback.print_exc(file=sys.stderr)
443
+ return None
444
+
445
+ tend, cend = time(), clock()
446
+ ttime, ctime = (tend - tstart), (cend - cstart)
447
+ self.report.feed(filename, testprog.result, ttime, ctime)
448
+ return testprog
449
+ finally:
450
+ if dirname:
451
+ os.chdir(here)
452
+
453
+
454
+
455
+ class DjangoTester(PyTester):
456
+
457
+ def load_django_settings(self, dirname):
458
+ """try to find project's setting and load it"""
459
+ curdir = osp.abspath(dirname)
460
+ previousdir = curdir
461
+ while not osp.isfile(osp.join(curdir, 'settings.py')) and \
462
+ osp.isfile(osp.join(curdir, '__init__.py')):
463
+ newdir = osp.normpath(osp.join(curdir, os.pardir))
464
+ if newdir == curdir:
465
+ raise AssertionError('could not find settings.py')
466
+ previousdir = curdir
467
+ curdir = newdir
468
+ # late django initialization
469
+ settings = load_module_from_modpath(modpath_from_file(osp.join(curdir, 'settings.py')))
470
+ from django.core.management import setup_environ
471
+ setup_environ(settings)
472
+ settings.DEBUG = False
473
+ self.settings = settings
474
+ # add settings dir to pythonpath since it's the project's root
475
+ if curdir not in sys.path:
476
+ sys.path.insert(1, curdir)
477
+
478
+ def before_testfile(self):
479
+ # Those imports must be done **after** setup_environ was called
480
+ from django.test.utils import setup_test_environment
481
+ from django.test.utils import create_test_db
482
+ setup_test_environment()
483
+ create_test_db(verbosity=0)
484
+ self.dbname = self.settings.TEST_DATABASE_NAME
485
+
486
+ def after_testfile(self):
487
+ # Those imports must be done **after** setup_environ was called
488
+ from django.test.utils import teardown_test_environment
489
+ from django.test.utils import destroy_test_db
490
+ teardown_test_environment()
491
+ print 'destroying', self.dbname
492
+ destroy_test_db(self.dbname, verbosity=0)
493
+
494
+ def testall(self, exitfirst=False):
495
+ """walks through current working directory, finds something
496
+ which can be considered as a testdir and runs every test there
497
+ """
498
+ for dirname, dirs, files in os.walk(os.getcwd()):
499
+ for skipped in ('CVS', '.svn', '.hg'):
500
+ if skipped in dirs:
501
+ dirs.remove(skipped)
502
+ if 'tests.py' in files:
503
+ if not self.testonedir(dirname, exitfirst):
504
+ break
505
+ dirs[:] = []
506
+ else:
507
+ basename = osp.basename(dirname)
508
+ if basename in ('test', 'tests'):
509
+ print "going into", dirname
510
+ # we found a testdir, let's explore it !
511
+ if not self.testonedir(dirname, exitfirst):
512
+ break
513
+ dirs[:] = []
514
+
515
+ def testonedir(self, testdir, exitfirst=False):
516
+ """finds each testfile in the `testdir` and runs it
517
+
518
+ return true when all tests has been executed, false if exitfirst and
519
+ some test has failed.
520
+ """
521
+ # special django behaviour : if tests are splitted in several files,
522
+ # remove the main tests.py file and tests each test file separately
523
+ testfiles = [fpath for fpath in abspath_listdir(testdir)
524
+ if this_is_a_testfile(fpath)]
525
+ if len(testfiles) > 1:
526
+ try:
527
+ testfiles.remove(osp.join(testdir, 'tests.py'))
528
+ except ValueError:
529
+ pass
530
+ for filename in testfiles:
531
+ # run test and collect information
532
+ prog = self.testfile(filename, batchmode=True)
533
+ if exitfirst and (prog is None or not prog.result.wasSuccessful()):
534
+ return False
535
+ # clean local modules
536
+ remove_local_modules_from_sys(testdir)
537
+ return True
538
+
539
+ def testfile(self, filename, batchmode=False):
540
+ """runs every test in `filename`
541
+
542
+ :param filename: an absolute path pointing to a unittest file
543
+ """
544
+ here = os.getcwd()
545
+ dirname = osp.dirname(filename)
546
+ if dirname:
547
+ os.chdir(dirname)
548
+ self.load_django_settings(dirname)
549
+ modname = osp.basename(filename)[:-3]
550
+ print >>sys.stderr, (' %s ' % osp.basename(filename)).center(70, '=')
551
+ try:
552
+ try:
553
+ tstart, cstart = time(), clock()
554
+ self.before_testfile()
555
+ testprog = SkipAwareTestProgram(modname, batchmode=batchmode, cvg=self.cvg)
556
+ tend, cend = time(), clock()
557
+ ttime, ctime = (tend - tstart), (cend - cstart)
558
+ self.report.feed(filename, testprog.result, ttime, ctime)
559
+ return testprog
560
+ except SystemExit:
561
+ raise
562
+ except Exception, exc:
563
+ import traceback
564
+ traceback.print_exc()
565
+ self.report.failed_to_test_module(filename)
566
+ print 'unhandled exception occurred while testing', modname
567
+ print 'error: %s' % exc
568
+ return None
569
+ finally:
570
+ self.after_testfile()
571
+ if dirname:
572
+ os.chdir(here)
573
+
574
+
575
+ def make_parser():
576
+ """creates the OptionParser instance
577
+ """
578
+ from optparse import OptionParser
579
+ parser = OptionParser(usage=PYTEST_DOC)
580
+
581
+ parser.newargs = []
582
+ def rebuild_cmdline(option, opt, value, parser):
583
+ """carry the option to unittest_main"""
584
+ parser.newargs.append(opt)
585
+
586
+ def rebuild_and_store(option, opt, value, parser):
587
+ """carry the option to unittest_main and store
588
+ the value on current parser
589
+ """
590
+ parser.newargs.append(opt)
591
+ setattr(parser.values, option.dest, True)
592
+
593
+ def capture_and_rebuild(option, opt, value, parser):
594
+ warnings.simplefilter('ignore', DeprecationWarning)
595
+ rebuild_cmdline(option, opt, value, parser)
596
+
597
+ # pytest options
598
+ parser.add_option('-t', dest='testdir', default=None,
599
+ help="directory where the tests will be found")
600
+ parser.add_option('-d', dest='dbc', default=False,
601
+ action="store_true", help="enable design-by-contract")
602
+ # unittest_main options provided and passed through pytest
603
+ parser.add_option('-v', '--verbose', callback=rebuild_cmdline,
604
+ action="callback", help="Verbose output")
605
+ parser.add_option('-i', '--pdb', callback=rebuild_and_store,
606
+ dest="pdb", action="callback",
607
+ help="Enable test failure inspection (conflicts with --coverage)")
608
+ parser.add_option('-x', '--exitfirst', callback=rebuild_and_store,
609
+ dest="exitfirst", default=False,
610
+ action="callback", help="Exit on first failure "
611
+ "(only make sense when pytest run one test file)")
612
+ parser.add_option('-R', '--restart', callback=rebuild_and_store,
613
+ dest="restart", default=False,
614
+ action="callback",
615
+ help="Restart tests from where it failed (implies exitfirst) "
616
+ "(only make sense if tests previously ran with exitfirst only)")
617
+ parser.add_option('--color', callback=rebuild_cmdline,
618
+ action="callback",
619
+ help="colorize tracebacks")
620
+ parser.add_option('-s', '--skip',
621
+ # XXX: I wish I could use the callback action but it
622
+ # doesn't seem to be able to get the value
623
+ # associated to the option
624
+ action="store", dest="skipped", default=None,
625
+ help="test names matching this name will be skipped "
626
+ "to skip several patterns, use commas")
627
+ parser.add_option('-q', '--quiet', callback=rebuild_cmdline,
628
+ action="callback", help="Minimal output")
629
+ parser.add_option('-P', '--profile', default=None, dest='profile',
630
+ help="Profile execution and store data in the given file")
631
+ parser.add_option('-m', '--match', default=None, dest='tags_pattern',
632
+ help="only execute test whose tag match the current pattern")
633
+
634
+ try:
635
+ from logilab.devtools.lib.coverage import Coverage
636
+ parser.add_option('--coverage', dest="coverage", default=False,
637
+ action="store_true",
638
+ help="run tests with pycoverage (conflicts with --pdb)")
639
+ except ImportError:
640
+ pass
641
+
642
+ if DJANGO_FOUND:
643
+ parser.add_option('-J', '--django', dest='django', default=False,
644
+ action="store_true",
645
+ help='use pytest for django test cases')
646
+ return parser
647
+
648
+
649
+ def parseargs(parser):
650
+ """Parse the command line and return (options processed), (options to pass to
651
+ unittest_main()), (explicitfile or None).
652
+ """
653
+ # parse the command line
654
+ options, args = parser.parse_args()
655
+ if options.pdb and getattr(options, 'coverage', False):
656
+ parser.error("'pdb' and 'coverage' options are exclusive")
657
+ filenames = [arg for arg in args if arg.endswith('.py')]
658
+ if filenames:
659
+ if len(filenames) > 1:
660
+ parser.error("only one filename is acceptable")
661
+ explicitfile = filenames[0]
662
+ args.remove(explicitfile)
663
+ else:
664
+ explicitfile = None
665
+ # someone wants DBC
666
+ testlib.ENABLE_DBC = options.dbc
667
+ newargs = parser.newargs
668
+ if options.skipped:
669
+ newargs.extend(['--skip', options.skipped])
670
+ # restart implies exitfirst
671
+ if options.restart:
672
+ options.exitfirst = True
673
+ # append additional args to the new sys.argv and let unittest_main
674
+ # do the rest
675
+ newargs += args
676
+ return options, explicitfile
677
+
678
+
679
+
680
+ def run():
681
+ parser = make_parser()
682
+ rootdir, testercls = project_root(parser)
683
+ options, explicitfile = parseargs(parser)
684
+ # mock a new command line
685
+ sys.argv[1:] = parser.newargs
686
+ covermode = getattr(options, 'coverage', None)
687
+ cvg = None
688
+ if not '' in sys.path:
689
+ sys.path.insert(0, '')
690
+ if covermode:
691
+ # control_import_coverage(rootdir)
692
+ from logilab.devtools.lib.coverage import Coverage
693
+ cvg = Coverage([rootdir])
694
+ cvg.erase()
695
+ cvg.start()
696
+ if DJANGO_FOUND and options.django:
697
+ tester = DjangoTester(cvg, options)
698
+ else:
699
+ tester = testercls(cvg, options)
700
+ if explicitfile:
701
+ cmd, args = tester.testfile, (explicitfile,)
702
+ elif options.testdir:
703
+ cmd, args = tester.testonedir, (options.testdir, options.exitfirst)
704
+ else:
705
+ cmd, args = tester.testall, (options.exitfirst,)
706
+ try:
707
+ try:
708
+ if options.profile:
709
+ import hotshot
710
+ prof = hotshot.Profile(options.profile)
711
+ prof.runcall(cmd, *args)
712
+ prof.close()
713
+ print 'profile data saved in', options.profile
714
+ else:
715
+ cmd(*args)
716
+ except SystemExit:
717
+ raise
718
+ except:
719
+ import traceback
720
+ traceback.print_exc()
721
+ finally:
722
+ if covermode:
723
+ cvg.stop()
724
+ cvg.save()
725
+ tester.show_report()
726
+ if covermode:
727
+ print 'coverage information stored, use it with pycoverage -ra'
728
+ sys.exit(tester.errcode)
729
+
730
+ class SkipAwareTestProgram(unittest.TestProgram):
731
+ # XXX: don't try to stay close to unittest.py, use optparse
732
+ USAGE = """\
733
+ Usage: %(progName)s [options] [test] [...]
734
+
735
+ Options:
736
+ -h, --help Show this message
737
+ -v, --verbose Verbose output
738
+ -i, --pdb Enable test failure inspection
739
+ -x, --exitfirst Exit on first failure
740
+ -s, --skip skip test matching this pattern (no regexp for now)
741
+ -q, --quiet Minimal output
742
+ --color colorize tracebacks
743
+
744
+ -m, --match Run only test whose tag match this pattern
745
+
746
+ -P, --profile FILE: Run the tests using cProfile and saving results
747
+ in FILE
748
+
749
+ Examples:
750
+ %(progName)s - run default set of tests
751
+ %(progName)s MyTestSuite - run suite 'MyTestSuite'
752
+ %(progName)s MyTestCase.testSomething - run MyTestCase.testSomething
753
+ %(progName)s MyTestCase - run all 'test*' test methods
754
+ in MyTestCase
755
+ """
756
+ def __init__(self, module='__main__', defaultTest=None, batchmode=False,
757
+ cvg=None, options=None, outstream=sys.stderr):
758
+ self.batchmode = batchmode
759
+ self.cvg = cvg
760
+ self.options = options
761
+ self.outstream = outstream
762
+ super(SkipAwareTestProgram, self).__init__(
763
+ module=module, defaultTest=defaultTest,
764
+ testLoader=NonStrictTestLoader())
765
+
766
+ def parseArgs(self, argv):
767
+ self.pdbmode = False
768
+ self.exitfirst = False
769
+ self.skipped_patterns = []
770
+ self.test_pattern = None
771
+ self.tags_pattern = None
772
+ self.colorize = False
773
+ self.profile_name = None
774
+ import getopt
775
+ try:
776
+ options, args = getopt.getopt(argv[1:], 'hHvixrqcp:s:m:P:',
777
+ ['help', 'verbose', 'quiet', 'pdb',
778
+ 'exitfirst', 'restart',
779
+ 'skip=', 'color', 'match=', 'profile='])
780
+ for opt, value in options:
781
+ if opt in ('-h', '-H', '--help'):
782
+ self.usageExit()
783
+ if opt in ('-i', '--pdb'):
784
+ self.pdbmode = True
785
+ if opt in ('-x', '--exitfirst'):
786
+ self.exitfirst = True
787
+ if opt in ('-r', '--restart'):
788
+ self.restart = True
789
+ self.exitfirst = True
790
+ if opt in ('-q', '--quiet'):
791
+ self.verbosity = 0
792
+ if opt in ('-v', '--verbose'):
793
+ self.verbosity = 2
794
+ if opt in ('-s', '--skip'):
795
+ self.skipped_patterns = [pat.strip() for pat in
796
+ value.split(', ')]
797
+ if opt == '--color':
798
+ self.colorize = True
799
+ if opt in ('-m', '--match'):
800
+ #self.tags_pattern = value
801
+ self.options["tag_pattern"] = value
802
+ if opt in ('-P', '--profile'):
803
+ self.profile_name = value
804
+ self.testLoader.skipped_patterns = self.skipped_patterns
805
+ if len(args) == 0 and self.defaultTest is None:
806
+ suitefunc = getattr(self.module, 'suite', None)
807
+ if isinstance(suitefunc, (types.FunctionType,
808
+ types.MethodType)):
809
+ self.test = self.module.suite()
810
+ else:
811
+ self.test = self.testLoader.loadTestsFromModule(self.module)
812
+ return
813
+ if len(args) > 0:
814
+ self.test_pattern = args[0]
815
+ self.testNames = args
816
+ else:
817
+ self.testNames = (self.defaultTest, )
818
+ self.createTests()
819
+ except getopt.error, msg:
820
+ self.usageExit(msg)
821
+
822
+ def runTests(self):
823
+ if self.profile_name:
824
+ import cProfile
825
+ cProfile.runctx('self._runTests()', globals(), locals(), self.profile_name )
826
+ else:
827
+ return self._runTests()
828
+
829
+ def _runTests(self):
830
+ self.testRunner = SkipAwareTextTestRunner(verbosity=self.verbosity,
831
+ stream=self.outstream,
832
+ exitfirst=self.exitfirst,
833
+ pdbmode=self.pdbmode,
834
+ cvg=self.cvg,
835
+ test_pattern=self.test_pattern,
836
+ skipped_patterns=self.skipped_patterns,
837
+ colorize=self.colorize,
838
+ batchmode=self.batchmode,
839
+ options=self.options)
840
+
841
+ def removeSucceededTests(obj, succTests):
842
+ """ Recursive function that removes succTests from
843
+ a TestSuite or TestCase
844
+ """
845
+ if isinstance(obj, unittest.TestSuite):
846
+ removeSucceededTests(obj._tests, succTests)
847
+ if isinstance(obj, list):
848
+ for el in obj[:]:
849
+ if isinstance(el, unittest.TestSuite):
850
+ removeSucceededTests(el, succTests)
851
+ elif isinstance(el, unittest.TestCase):
852
+ descr = '.'.join((el.__class__.__module__,
853
+ el.__class__.__name__,
854
+ el._testMethodName))
855
+ if descr in succTests:
856
+ obj.remove(el)
857
+ # take care, self.options may be None
858
+ if getattr(self.options, 'restart', False):
859
+ # retrieve succeeded tests from FILE_RESTART
860
+ try:
861
+ restartfile = open(FILE_RESTART, 'r')
862
+ try:
863
+ succeededtests = list(elem.rstrip('\n\r') for elem in
864
+ restartfile.readlines())
865
+ removeSucceededTests(self.test, succeededtests)
866
+ finally:
867
+ restartfile.close()
868
+ except Exception, ex:
869
+ raise Exception("Error while reading succeeded tests into %s: %s"
870
+ % (osp.join(os.getcwd(), FILE_RESTART), ex))
871
+
872
+ result = self.testRunner.run(self.test)
873
+ # help garbage collection: we want TestSuite, which hold refs to every
874
+ # executed TestCase, to be gc'ed
875
+ del self.test
876
+ if getattr(result, "debuggers", None) and \
877
+ getattr(self, "pdbmode", None):
878
+ start_interactive_mode(result)
879
+ if not getattr(self, "batchmode", None):
880
+ sys.exit(not result.wasSuccessful())
881
+ self.result = result
882
+
883
+
884
+ class SkipAwareTextTestRunner(unittest.TextTestRunner):
885
+
886
+ def __init__(self, stream=sys.stderr, verbosity=1,
887
+ exitfirst=False, pdbmode=False, cvg=None, test_pattern=None,
888
+ skipped_patterns=(), colorize=False, batchmode=False,
889
+ options=None):
890
+ super(SkipAwareTextTestRunner, self).__init__(stream=stream,
891
+ verbosity=verbosity)
892
+ self.exitfirst = exitfirst
893
+ self.pdbmode = pdbmode
894
+ self.cvg = cvg
895
+ self.test_pattern = test_pattern
896
+ self.skipped_patterns = skipped_patterns
897
+ self.colorize = colorize
898
+ self.batchmode = batchmode
899
+ self.options = options
900
+
901
+ def _this_is_skipped(self, testedname):
902
+ return any([(pat in testedname) for pat in self.skipped_patterns])
903
+
904
+ def _runcondition(self, test, skipgenerator=True):
905
+ if isinstance(test, testlib.InnerTest):
906
+ testname = test.name
907
+ else:
908
+ if isinstance(test, testlib.TestCase):
909
+ meth = test._get_test_method()
910
+ func = meth.im_func
911
+ testname = '%s.%s' % (meth.im_class.__name__, func.__name__)
912
+ elif isinstance(test, types.FunctionType):
913
+ func = test
914
+ testname = func.__name__
915
+ elif isinstance(test, types.MethodType):
916
+ func = test.im_func
917
+ testname = '%s.%s' % (test.im_class.__name__, func.__name__)
918
+ else:
919
+ return True # Not sure when this happens
920
+ if testlib.is_generator(test) and skipgenerator:
921
+ return self.does_match_tags(test) # Let inner tests decide at run time
922
+ if self._this_is_skipped(testname):
923
+ return False # this was explicitly skipped
924
+ if self.test_pattern is not None:
925
+ try:
926
+ classpattern, testpattern = self.test_pattern.split('.')
927
+ klass, name = testname.split('.')
928
+ if classpattern not in klass or testpattern not in name:
929
+ return False
930
+ except ValueError:
931
+ if self.test_pattern not in testname:
932
+ return False
933
+
934
+ return self.does_match_tags(test)
935
+
936
+ def does_match_tags(self, test):
937
+ if self.options is not None:
938
+ tags_pattern = getattr(self.options, 'tags_pattern', None)
939
+ if tags_pattern is not None:
940
+ tags = getattr(test, 'tags', testlib.Tags())
941
+ if tags.inherit and isinstance(test, types.MethodType):
942
+ tags = tags | getattr(test.im_class, 'tags', testlib.Tags())
943
+ return tags.match(tags_pattern)
944
+ return True # no pattern
945
+
946
+ def _makeResult(self):
947
+ return testlib.SkipAwareTestResult(self.stream, self.descriptions,
948
+ self.verbosity, self.exitfirst,
949
+ self.pdbmode, self.cvg, self.colorize)
950
+
951
+ def run(self, test):
952
+ "Run the given test case or test suite."
953
+ result = self._makeResult()
954
+ startTime = time()
955
+ test(result, runcondition=self._runcondition, options=self.options)
956
+ stopTime = time()
957
+ timeTaken = stopTime - startTime
958
+ result.printErrors()
959
+ if not self.batchmode:
960
+ self.stream.writeln(result.separator2)
961
+ run = result.testsRun
962
+ self.stream.writeln("Ran %d test%s in %.3fs" %
963
+ (run, run != 1 and "s" or "", timeTaken))
964
+ self.stream.writeln()
965
+ if not result.wasSuccessful():
966
+ if self.colorize:
967
+ self.stream.write(textutils.colorize_ansi("FAILED", color='red'))
968
+ else:
969
+ self.stream.write("FAILED")
970
+ else:
971
+ if self.colorize:
972
+ self.stream.write(textutils.colorize_ansi("OK", color='green'))
973
+ else:
974
+ self.stream.write("OK")
975
+ failed, errored, skipped = map(len, (result.failures,
976
+ result.errors,
977
+ result.skipped))
978
+
979
+ det_results = []
980
+ for name, value in (("failures", result.failures),
981
+ ("errors",result.errors),
982
+ ("skipped", result.skipped)):
983
+ if value:
984
+ det_results.append("%s=%i" % (name, len(value)))
985
+ if det_results:
986
+ self.stream.write(" (")
987
+ self.stream.write(', '.join(det_results))
988
+ self.stream.write(")")
989
+ self.stream.writeln("")
990
+ return result
991
+
992
+ class NonStrictTestLoader(unittest.TestLoader):
993
+ """
994
+ Overrides default testloader to be able to omit classname when
995
+ specifying tests to run on command line.
996
+
997
+ For example, if the file test_foo.py contains ::
998
+
999
+ class FooTC(TestCase):
1000
+ def test_foo1(self): # ...
1001
+ def test_foo2(self): # ...
1002
+ def test_bar1(self): # ...
1003
+
1004
+ class BarTC(TestCase):
1005
+ def test_bar2(self): # ...
1006
+
1007
+ 'python test_foo.py' will run the 3 tests in FooTC
1008
+ 'python test_foo.py FooTC' will run the 3 tests in FooTC
1009
+ 'python test_foo.py test_foo' will run test_foo1 and test_foo2
1010
+ 'python test_foo.py test_foo1' will run test_foo1
1011
+ 'python test_foo.py test_bar' will run FooTC.test_bar1 and BarTC.test_bar2
1012
+ """
1013
+
1014
+ def __init__(self):
1015
+ self.skipped_patterns = ()
1016
+
1017
+ # some magic here to accept empty list by extending
1018
+ # and to provide callable capability
1019
+ def loadTestsFromNames(self, names, module=None):
1020
+ suites = []
1021
+ for name in names:
1022
+ suites.extend(self.loadTestsFromName(name, module))
1023
+ return self.suiteClass(suites)
1024
+
1025
+ def _collect_tests(self, module):
1026
+ tests = {}
1027
+ for obj in vars(module).values():
1028
+ if (issubclass(type(obj), (types.ClassType, type)) and
1029
+ issubclass(obj, unittest.TestCase)):
1030
+ classname = obj.__name__
1031
+ if classname[0] == '_' or self._this_is_skipped(classname):
1032
+ continue
1033
+ methodnames = []
1034
+ # obj is a TestCase class
1035
+ for attrname in dir(obj):
1036
+ if attrname.startswith(self.testMethodPrefix):
1037
+ attr = getattr(obj, attrname)
1038
+ if callable(attr):
1039
+ methodnames.append(attrname)
1040
+ # keep track of class (obj) for convenience
1041
+ tests[classname] = (obj, methodnames)
1042
+ return tests
1043
+
1044
+ def loadTestsFromSuite(self, module, suitename):
1045
+ try:
1046
+ suite = getattr(module, suitename)()
1047
+ except AttributeError:
1048
+ return []
1049
+ assert hasattr(suite, '_tests'), \
1050
+ "%s.%s is not a valid TestSuite" % (module.__name__, suitename)
1051
+ # python2.3 does not implement __iter__ on suites, we need to return
1052
+ # _tests explicitly
1053
+ return suite._tests
1054
+
1055
+ def loadTestsFromName(self, name, module=None):
1056
+ parts = name.split('.')
1057
+ if module is None or len(parts) > 2:
1058
+ # let the base class do its job here
1059
+ return [super(NonStrictTestLoader, self).loadTestsFromName(name)]
1060
+ tests = self._collect_tests(module)
1061
+ collected = []
1062
+ if len(parts) == 1:
1063
+ pattern = parts[0]
1064
+ if callable(getattr(module, pattern, None)
1065
+ ) and pattern not in tests:
1066
+ # consider it as a suite
1067
+ return self.loadTestsFromSuite(module, pattern)
1068
+ if pattern in tests:
1069
+ # case python unittest_foo.py MyTestTC
1070
+ klass, methodnames = tests[pattern]
1071
+ for methodname in methodnames:
1072
+ collected = [klass(methodname)
1073
+ for methodname in methodnames]
1074
+ else:
1075
+ # case python unittest_foo.py something
1076
+ for klass, methodnames in tests.values():
1077
+ # skip methodname if matched by skipped_patterns
1078
+ for skip_pattern in self.skipped_patterns:
1079
+ methodnames = [methodname
1080
+ for methodname in methodnames
1081
+ if skip_pattern not in methodname]
1082
+ collected += [klass(methodname)
1083
+ for methodname in methodnames
1084
+ if pattern in methodname]
1085
+ elif len(parts) == 2:
1086
+ # case "MyClass.test_1"
1087
+ classname, pattern = parts
1088
+ klass, methodnames = tests.get(classname, (None, []))
1089
+ for methodname in methodnames:
1090
+ collected = [klass(methodname) for methodname in methodnames
1091
+ if pattern in methodname]
1092
+ return collected
1093
+
1094
+ def _this_is_skipped(self, testedname):
1095
+ return any([(pat in testedname) for pat in self.skipped_patterns])
1096
+
1097
+ def getTestCaseNames(self, testCaseClass):
1098
+ """Return a sorted sequence of method names found within testCaseClass
1099
+ """
1100
+ is_skipped = self._this_is_skipped
1101
+ classname = testCaseClass.__name__
1102
+ if classname[0] == '_' or is_skipped(classname):
1103
+ return []
1104
+ testnames = super(NonStrictTestLoader, self).getTestCaseNames(
1105
+ testCaseClass)
1106
+ return [testname for testname in testnames if not is_skipped(testname)]
1107
+
1108
+ def _ts_run(self, result, runcondition=None, options=None):
1109
+ self._wrapped_run(result,runcondition=runcondition, options=options)
1110
+ self._tearDownPreviousClass(None, result)
1111
+ self._handleModuleTearDown(result)
1112
+ return result
1113
+
1114
+ def _ts_wrapped_run(self, result, debug=False, runcondition=None, options=None):
1115
+ for test in self:
1116
+ if result.shouldStop:
1117
+ break
1118
+ if unittest_suite._isnotsuite(test):
1119
+ self._tearDownPreviousClass(test, result)
1120
+ self._handleModuleFixture(test, result)
1121
+ self._handleClassSetUp(test, result)
1122
+ result._previousTestClass = test.__class__
1123
+ if (getattr(test.__class__, '_classSetupFailed', False) or
1124
+ getattr(result, '_moduleSetUpFailed', False)):
1125
+ continue
1126
+
1127
+ if hasattr(test, '_wrapped_run'):
1128
+ try:
1129
+ test._wrapped_run(result, debug, runcondition=runcondition, options=options)
1130
+ except TypeError:
1131
+ test._wrapped_run(result, debug)
1132
+ elif not debug:
1133
+ try:
1134
+ test(result, runcondition, options)
1135
+ except TypeError:
1136
+ test(result)
1137
+ else:
1138
+ test.debug()
1139
+
1140
+
1141
+ def enable_dbc(*args):
1142
+ """
1143
+ Without arguments, return True if contracts can be enabled and should be
1144
+ enabled (see option -d), return False otherwise.
1145
+
1146
+ With arguments, return False if contracts can't or shouldn't be enabled,
1147
+ otherwise weave ContractAspect with items passed as arguments.
1148
+ """
1149
+ if not ENABLE_DBC:
1150
+ return False
1151
+ try:
1152
+ from logilab.aspects.weaver import weaver
1153
+ from logilab.aspects.lib.contracts import ContractAspect
1154
+ except ImportError:
1155
+ sys.stderr.write(
1156
+ 'Warning: logilab.aspects is not available. Contracts disabled.')
1157
+ return False
1158
+ for arg in args:
1159
+ weaver.weave_module(arg, ContractAspect)
1160
+ return True
1161
+
1162
+
1163
+ # monkeypatch unittest and doctest (ouch !)
1164
+ unittest._TextTestResult = testlib.SkipAwareTestResult
1165
+ unittest.TextTestRunner = SkipAwareTextTestRunner
1166
+ unittest.TestLoader = NonStrictTestLoader
1167
+ unittest.TestProgram = SkipAwareTestProgram
1168
+
1169
+ if sys.version_info >= (2, 4):
1170
+ doctest.DocTestCase.__bases__ = (testlib.TestCase,)
1171
+ # XXX check python2.6 compatibility
1172
+ #doctest.DocTestCase._cleanups = []
1173
+ #doctest.DocTestCase._out = []
1174
+ else:
1175
+ unittest.FunctionTestCase.__bases__ = (testlib.TestCase,)
1176
+ unittest.TestSuite.run = _ts_run
1177
+ unittest.TestSuite._wrapped_run = _ts_wrapped_run