marty 0.5.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (345) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +84 -0
  4. data/Rakefile +29 -0
  5. data/app/assets/javascripts/marty/application.js +15 -0
  6. data/app/assets/stylesheets/marty/application.css +13 -0
  7. data/app/components/marty/api_auth_view.rb +32 -0
  8. data/app/components/marty/auth_app.rb +55 -0
  9. data/app/components/marty/auth_app.rb~ +51 -0
  10. data/app/components/marty/auth_app/javascripts/auth_app.js +91 -0
  11. data/app/components/marty/auth_app/javascripts/auth_app.js~ +91 -0
  12. data/app/components/marty/cm_form_panel.rb~ +5 -0
  13. data/app/components/marty/cm_grid_panel.rb~ +35 -0
  14. data/app/components/marty/data_import_view.rb~ +142 -0
  15. data/app/components/marty/extras/layout.rb +46 -0
  16. data/app/components/marty/extras/layout.rb~ +46 -0
  17. data/app/components/marty/extras/misc.rb +18 -0
  18. data/app/components/marty/form.rb +6 -0
  19. data/app/components/marty/grid.rb +45 -0
  20. data/app/components/marty/grid_append_only.rb +12 -0
  21. data/app/components/marty/import_type_view.rb +53 -0
  22. data/app/components/marty/live_search_grid_panel.rb +46 -0
  23. data/app/components/marty/live_search_grid_panel.rb~ +49 -0
  24. data/app/components/marty/main_auth_app.rb +269 -0
  25. data/app/components/marty/main_auth_app.rb~ +238 -0
  26. data/app/components/marty/mcfly_grid_panel.rb +62 -0
  27. data/app/components/marty/mcfly_grid_panel.rb~ +80 -0
  28. data/app/components/marty/new_posting_form.rb +46 -0
  29. data/app/components/marty/new_posting_form.rb~ +46 -0
  30. data/app/components/marty/new_posting_window.rb +21 -0
  31. data/app/components/marty/new_posting_window.rb~ +21 -0
  32. data/app/components/marty/panel.rb +12 -0
  33. data/app/components/marty/pivot_grid.rb +52 -0
  34. data/app/components/marty/pivot_grid/endpoints.rb +45 -0
  35. data/app/components/marty/pivot_grid/javascripts/extensions.js +150 -0
  36. data/app/components/marty/pivot_grid/javascripts/pivot_grid.js +86 -0
  37. data/app/components/marty/pivot_grid/services.rb +44 -0
  38. data/app/components/marty/posting_grid.rb +139 -0
  39. data/app/components/marty/posting_grid.rb~ +140 -0
  40. data/app/components/marty/posting_window.rb +27 -0
  41. data/app/components/marty/promise_view.rb +177 -0
  42. data/app/components/marty/promise_view.rb~ +157 -0
  43. data/app/components/marty/promise_view/stylesheets/promise_view.css +26 -0
  44. data/app/components/marty/promise_view/stylesheets/promise_view.css~ +15 -0
  45. data/app/components/marty/report_form.rb +225 -0
  46. data/app/components/marty/report_form.rb~ +217 -0
  47. data/app/components/marty/report_select.rb +145 -0
  48. data/app/components/marty/report_select.rb~ +133 -0
  49. data/app/components/marty/reporting.rb +39 -0
  50. data/app/components/marty/reporting.rb~ +39 -0
  51. data/app/components/marty/script_detail.rb~ +430 -0
  52. data/app/components/marty/script_form.rb +233 -0
  53. data/app/components/marty/script_form.rb~ +233 -0
  54. data/app/components/marty/script_form/javascripts/Ext.ux.form.field.CodeMirror.js +698 -0
  55. data/app/components/marty/script_form/javascripts/Ext.ux.form.field.CodeMirror.js~ +909 -0
  56. data/app/components/marty/script_form/javascripts/codemirror.js +3130 -0
  57. data/app/components/marty/script_form/javascripts/mode/clike/clike.js +284 -0
  58. data/app/components/marty/script_form/javascripts/mode/clike/index.html +102 -0
  59. data/app/components/marty/script_form/javascripts/mode/clike/scala.html +766 -0
  60. data/app/components/marty/script_form/javascripts/mode/clojure/clojure.js +206 -0
  61. data/app/components/marty/script_form/javascripts/mode/clojure/index.html +67 -0
  62. data/app/components/marty/script_form/javascripts/mode/coffeescript/LICENSE +22 -0
  63. data/app/components/marty/script_form/javascripts/mode/coffeescript/coffeescript.js +346 -0
  64. data/app/components/marty/script_form/javascripts/mode/coffeescript/index.html +728 -0
  65. data/app/components/marty/script_form/javascripts/mode/commonlisp/commonlisp.js +101 -0
  66. data/app/components/marty/script_form/javascripts/mode/commonlisp/index.html +165 -0
  67. data/app/components/marty/script_form/javascripts/mode/css/css.js +448 -0
  68. data/app/components/marty/script_form/javascripts/mode/css/index.html +58 -0
  69. data/app/components/marty/script_form/javascripts/mode/css/test.js +501 -0
  70. data/app/components/marty/script_form/javascripts/mode/delorean/delorean.js +189 -0
  71. data/app/components/marty/script_form/javascripts/mode/diff/diff.js +32 -0
  72. data/app/components/marty/script_form/javascripts/mode/diff/index.html +105 -0
  73. data/app/components/marty/script_form/javascripts/mode/ecl/ecl.js +203 -0
  74. data/app/components/marty/script_form/javascripts/mode/ecl/index.html +42 -0
  75. data/app/components/marty/script_form/javascripts/mode/erlang/erlang.js +463 -0
  76. data/app/components/marty/script_form/javascripts/mode/erlang/index.html +63 -0
  77. data/app/components/marty/script_form/javascripts/mode/gfm/gfm.js +150 -0
  78. data/app/components/marty/script_form/javascripts/mode/gfm/index.html +48 -0
  79. data/app/components/marty/script_form/javascripts/mode/go/go.js +170 -0
  80. data/app/components/marty/script_form/javascripts/mode/go/index.html +73 -0
  81. data/app/components/marty/script_form/javascripts/mode/groovy/groovy.js +210 -0
  82. data/app/components/marty/script_form/javascripts/mode/groovy/index.html +72 -0
  83. data/app/components/marty/script_form/javascripts/mode/haskell/haskell.js +242 -0
  84. data/app/components/marty/script_form/javascripts/mode/haskell/index.html +61 -0
  85. data/app/components/marty/script_form/javascripts/mode/haxe/haxe.js +429 -0
  86. data/app/components/marty/script_form/javascripts/mode/haxe/index.html +91 -0
  87. data/app/components/marty/script_form/javascripts/mode/htmlembedded/htmlembedded.js +72 -0
  88. data/app/components/marty/script_form/javascripts/mode/htmlembedded/index.html +50 -0
  89. data/app/components/marty/script_form/javascripts/mode/htmlmixed/htmlmixed.js +84 -0
  90. data/app/components/marty/script_form/javascripts/mode/htmlmixed/index.html +52 -0
  91. data/app/components/marty/script_form/javascripts/mode/javascript/index.html +78 -0
  92. data/app/components/marty/script_form/javascripts/mode/javascript/javascript.js +361 -0
  93. data/app/components/marty/script_form/javascripts/mode/jinja2/index.html +38 -0
  94. data/app/components/marty/script_form/javascripts/mode/jinja2/jinja2.js +42 -0
  95. data/app/components/marty/script_form/javascripts/mode/less/index.html +740 -0
  96. data/app/components/marty/script_form/javascripts/mode/less/less.js +266 -0
  97. data/app/components/marty/script_form/javascripts/mode/lua/index.html +73 -0
  98. data/app/components/marty/script_form/javascripts/mode/lua/lua.js +140 -0
  99. data/app/components/marty/script_form/javascripts/mode/markdown/index.html +343 -0
  100. data/app/components/marty/script_form/javascripts/mode/markdown/markdown.js +382 -0
  101. data/app/components/marty/script_form/javascripts/mode/markdown/test.js +1084 -0
  102. data/app/components/marty/script_form/javascripts/mode/mysql/index.html +42 -0
  103. data/app/components/marty/script_form/javascripts/mode/mysql/mysql.js +186 -0
  104. data/app/components/marty/script_form/javascripts/mode/ntriples/index.html +33 -0
  105. data/app/components/marty/script_form/javascripts/mode/ntriples/ntriples.js +172 -0
  106. data/app/components/marty/script_form/javascripts/mode/ocaml/index.html +130 -0
  107. data/app/components/marty/script_form/javascripts/mode/ocaml/ocaml.js +114 -0
  108. data/app/components/marty/script_form/javascripts/mode/pascal/LICENSE +7 -0
  109. data/app/components/marty/script_form/javascripts/mode/pascal/index.html +49 -0
  110. data/app/components/marty/script_form/javascripts/mode/pascal/pascal.js +94 -0
  111. data/app/components/marty/script_form/javascripts/mode/perl/LICENSE +19 -0
  112. data/app/components/marty/script_form/javascripts/mode/perl/index.html +63 -0
  113. data/app/components/marty/script_form/javascripts/mode/perl/perl.js +816 -0
  114. data/app/components/marty/script_form/javascripts/mode/php/index.html +49 -0
  115. data/app/components/marty/script_form/javascripts/mode/php/php.js +148 -0
  116. data/app/components/marty/script_form/javascripts/mode/pig/index.html +43 -0
  117. data/app/components/marty/script_form/javascripts/mode/pig/pig.js +172 -0
  118. data/app/components/marty/script_form/javascripts/mode/plsql/index.html +63 -0
  119. data/app/components/marty/script_form/javascripts/mode/plsql/plsql.js +217 -0
  120. data/app/components/marty/script_form/javascripts/mode/properties/index.html +41 -0
  121. data/app/components/marty/script_form/javascripts/mode/properties/properties.js +63 -0
  122. data/app/components/marty/script_form/javascripts/mode/python/LICENSE.txt +21 -0
  123. data/app/components/marty/script_form/javascripts/mode/python/index.html +123 -0
  124. data/app/components/marty/script_form/javascripts/mode/python/python.js +338 -0
  125. data/app/components/marty/script_form/javascripts/mode/r/LICENSE +24 -0
  126. data/app/components/marty/script_form/javascripts/mode/r/index.html +74 -0
  127. data/app/components/marty/script_form/javascripts/mode/r/r.js +141 -0
  128. data/app/components/marty/script_form/javascripts/mode/rpm/changes/changes.js +19 -0
  129. data/app/components/marty/script_form/javascripts/mode/rpm/changes/index.html +54 -0
  130. data/app/components/marty/script_form/javascripts/mode/rpm/spec/index.html +100 -0
  131. data/app/components/marty/script_form/javascripts/mode/rpm/spec/spec.css +5 -0
  132. data/app/components/marty/script_form/javascripts/mode/rpm/spec/spec.js +66 -0
  133. data/app/components/marty/script_form/javascripts/mode/rst/index.html +526 -0
  134. data/app/components/marty/script_form/javascripts/mode/rst/rst.js +326 -0
  135. data/app/components/marty/script_form/javascripts/mode/ruby/LICENSE +24 -0
  136. data/app/components/marty/script_form/javascripts/mode/ruby/index.html +172 -0
  137. data/app/components/marty/script_form/javascripts/mode/ruby/ruby.js +195 -0
  138. data/app/components/marty/script_form/javascripts/mode/rust/index.html +49 -0
  139. data/app/components/marty/script_form/javascripts/mode/rust/rust.js +432 -0
  140. data/app/components/marty/script_form/javascripts/mode/scheme/index.html +65 -0
  141. data/app/components/marty/script_form/javascripts/mode/scheme/scheme.js +230 -0
  142. data/app/components/marty/script_form/javascripts/mode/shell/index.html +50 -0
  143. data/app/components/marty/script_form/javascripts/mode/shell/shell.js +118 -0
  144. data/app/components/marty/script_form/javascripts/mode/sieve/LICENSE +23 -0
  145. data/app/components/marty/script_form/javascripts/mode/sieve/index.html +81 -0
  146. data/app/components/marty/script_form/javascripts/mode/sieve/sieve.js +156 -0
  147. data/app/components/marty/script_form/javascripts/mode/smalltalk/index.html +56 -0
  148. data/app/components/marty/script_form/javascripts/mode/smalltalk/smalltalk.js +139 -0
  149. data/app/components/marty/script_form/javascripts/mode/smarty/index.html +83 -0
  150. data/app/components/marty/script_form/javascripts/mode/smarty/smarty.js +148 -0
  151. data/app/components/marty/script_form/javascripts/mode/sparql/index.html +41 -0
  152. data/app/components/marty/script_form/javascripts/mode/sparql/sparql.js +143 -0
  153. data/app/components/marty/script_form/javascripts/mode/stex/index.html +98 -0
  154. data/app/components/marty/script_form/javascripts/mode/stex/stex.js +182 -0
  155. data/app/components/marty/script_form/javascripts/mode/stex/test.js +343 -0
  156. data/app/components/marty/script_form/javascripts/mode/tiddlywiki/index.html +141 -0
  157. data/app/components/marty/script_form/javascripts/mode/tiddlywiki/tiddlywiki.css +14 -0
  158. data/app/components/marty/script_form/javascripts/mode/tiddlywiki/tiddlywiki.js +384 -0
  159. data/app/components/marty/script_form/javascripts/mode/tiki/index.html +83 -0
  160. data/app/components/marty/script_form/javascripts/mode/tiki/tiki.css +26 -0
  161. data/app/components/marty/script_form/javascripts/mode/tiki/tiki.js +309 -0
  162. data/app/components/marty/script_form/javascripts/mode/vb/LICENSE.txt +21 -0
  163. data/app/components/marty/script_form/javascripts/mode/vb/index.html +89 -0
  164. data/app/components/marty/script_form/javascripts/mode/vb/vb.js +260 -0
  165. data/app/components/marty/script_form/javascripts/mode/vbscript/index.html +43 -0
  166. data/app/components/marty/script_form/javascripts/mode/vbscript/vbscript.js +26 -0
  167. data/app/components/marty/script_form/javascripts/mode/velocity/index.html +104 -0
  168. data/app/components/marty/script_form/javascripts/mode/velocity/velocity.js +146 -0
  169. data/app/components/marty/script_form/javascripts/mode/verilog/index.html +211 -0
  170. data/app/components/marty/script_form/javascripts/mode/verilog/verilog.js +194 -0
  171. data/app/components/marty/script_form/javascripts/mode/xml/index.html +45 -0
  172. data/app/components/marty/script_form/javascripts/mode/xml/xml.js +318 -0
  173. data/app/components/marty/script_form/javascripts/mode/xquery/LICENSE +20 -0
  174. data/app/components/marty/script_form/javascripts/mode/xquery/index.html +223 -0
  175. data/app/components/marty/script_form/javascripts/mode/xquery/test/index.html +27 -0
  176. data/app/components/marty/script_form/javascripts/mode/xquery/test/testBase.js +42 -0
  177. data/app/components/marty/script_form/javascripts/mode/xquery/test/testEmptySequenceKeyword.js +16 -0
  178. data/app/components/marty/script_form/javascripts/mode/xquery/test/testMultiAttr.js +16 -0
  179. data/app/components/marty/script_form/javascripts/mode/xquery/test/testNamespaces.js +91 -0
  180. data/app/components/marty/script_form/javascripts/mode/xquery/test/testProcessingInstructions.js +16 -0
  181. data/app/components/marty/script_form/javascripts/mode/xquery/test/testQuotes.js +19 -0
  182. data/app/components/marty/script_form/javascripts/mode/xquery/xquery.js +451 -0
  183. data/app/components/marty/script_form/javascripts/mode/yaml/index.html +68 -0
  184. data/app/components/marty/script_form/javascripts/mode/yaml/yaml.js +95 -0
  185. data/app/components/marty/script_form/javascripts/util/closetag.js +164 -0
  186. data/app/components/marty/script_form/javascripts/util/dialog.css +27 -0
  187. data/app/components/marty/script_form/javascripts/util/dialog.js +70 -0
  188. data/app/components/marty/script_form/javascripts/util/foldcode.js +196 -0
  189. data/app/components/marty/script_form/javascripts/util/formatting.js +193 -0
  190. data/app/components/marty/script_form/javascripts/util/javascript-hint.js +134 -0
  191. data/app/components/marty/script_form/javascripts/util/loadmode.js +51 -0
  192. data/app/components/marty/script_form/javascripts/util/match-highlighter.js +44 -0
  193. data/app/components/marty/script_form/javascripts/util/multiplex.js +77 -0
  194. data/app/components/marty/script_form/javascripts/util/overlay.js +54 -0
  195. data/app/components/marty/script_form/javascripts/util/pig-hint.js +123 -0
  196. data/app/components/marty/script_form/javascripts/util/runmode-standalone.js +90 -0
  197. data/app/components/marty/script_form/javascripts/util/runmode.js +53 -0
  198. data/app/components/marty/script_form/javascripts/util/search.js +118 -0
  199. data/app/components/marty/script_form/javascripts/util/searchcursor.js +119 -0
  200. data/app/components/marty/script_form/javascripts/util/simple-hint.css +16 -0
  201. data/app/components/marty/script_form/javascripts/util/simple-hint.js +97 -0
  202. data/app/components/marty/script_form/javascripts/util/xml-hint.js +137 -0
  203. data/app/components/marty/script_form/stylesheets/codemirror.css +172 -0
  204. data/app/components/marty/script_form/stylesheets/delorean.css +10 -0
  205. data/app/components/marty/script_form/stylesheets/theme/ambiance.css +81 -0
  206. data/app/components/marty/script_form/stylesheets/theme/blackboard.css +25 -0
  207. data/app/components/marty/script_form/stylesheets/theme/cobalt.css +18 -0
  208. data/app/components/marty/script_form/stylesheets/theme/eclipse.css +25 -0
  209. data/app/components/marty/script_form/stylesheets/theme/elegant.css +10 -0
  210. data/app/components/marty/script_form/stylesheets/theme/erlang-dark.css +21 -0
  211. data/app/components/marty/script_form/stylesheets/theme/lesser-dark.css +44 -0
  212. data/app/components/marty/script_form/stylesheets/theme/monokai.css +28 -0
  213. data/app/components/marty/script_form/stylesheets/theme/neat.css +9 -0
  214. data/app/components/marty/script_form/stylesheets/theme/night.css +21 -0
  215. data/app/components/marty/script_form/stylesheets/theme/rubyblue.css +21 -0
  216. data/app/components/marty/script_form/stylesheets/theme/vibrant-ink.css +27 -0
  217. data/app/components/marty/script_form/stylesheets/theme/xq-dark.css +46 -0
  218. data/app/components/marty/script_grid.rb +104 -0
  219. data/app/components/marty/script_grid.rb~ +99 -0
  220. data/app/components/marty/script_tester.rb +114 -0
  221. data/app/components/marty/script_tester.rb~ +213 -0
  222. data/app/components/marty/scripting.rb +132 -0
  223. data/app/components/marty/scripting.rb~ +124 -0
  224. data/app/components/marty/select_report.rb~ +143 -0
  225. data/app/components/marty/simple_app.rb +97 -0
  226. data/app/components/marty/simple_app.rb~ +101 -0
  227. data/app/components/marty/simple_app/javascripts/simple_app.js +50 -0
  228. data/app/components/marty/simple_app/javascripts/statusbar_ext.js +8 -0
  229. data/app/components/marty/tag_grid.rb +83 -0
  230. data/app/components/marty/tag_grid.rb~ +89 -0
  231. data/app/components/marty/tree_panel.rb~ +256 -0
  232. data/app/components/marty/tree_panel/javascripts/tree_panel.js~ +317 -0
  233. data/app/components/marty/user_pivot.rb +128 -0
  234. data/app/components/marty/user_view.rb +181 -0
  235. data/app/components/marty/user_view.rb~ +188 -0
  236. data/app/controllers/marty/application_controller.rb +124 -0
  237. data/app/controllers/marty/application_controller.rb~ +133 -0
  238. data/app/controllers/marty/components_controller.rb +41 -0
  239. data/app/controllers/marty/components_controller.rb~ +37 -0
  240. data/app/controllers/marty/job_controller.rb +28 -0
  241. data/app/controllers/marty/job_controller.rb~ +28 -0
  242. data/app/controllers/marty/rpc_controller.rb +64 -0
  243. data/app/controllers/marty/rpc_controller.rb~ +61 -0
  244. data/app/helpers/marty/application_helper.rb +4 -0
  245. data/app/helpers/marty/script_set.rb +57 -0
  246. data/app/helpers/marty/script_set.rb~ +59 -0
  247. data/app/models/marty/api_auth.rb +44 -0
  248. data/app/models/marty/api_auth.rb~ +48 -0
  249. data/app/models/marty/base.rb +4 -0
  250. data/app/models/marty/data_change.rb +179 -0
  251. data/app/models/marty/data_change.rb~ +141 -0
  252. data/app/models/marty/enum.rb +22 -0
  253. data/app/models/marty/enum.rb~ +16 -0
  254. data/app/models/marty/import_type.rb +44 -0
  255. data/app/models/marty/import_type.rb~ +48 -0
  256. data/app/models/marty/poop.rb~ +169 -0
  257. data/app/models/marty/posting.rb +101 -0
  258. data/app/models/marty/posting.rb~ +86 -0
  259. data/app/models/marty/posting_type.rb +12 -0
  260. data/app/models/marty/posting_type.rb~ +21 -0
  261. data/app/models/marty/promise.rb +252 -0
  262. data/app/models/marty/promise.rb~ +196 -0
  263. data/app/models/marty/role.rb +6 -0
  264. data/app/models/marty/role.rb~ +10 -0
  265. data/app/models/marty/script.rb +144 -0
  266. data/app/models/marty/script.rb~ +62 -0
  267. data/app/models/marty/tag.rb +96 -0
  268. data/app/models/marty/tag.rb~ +91 -0
  269. data/app/models/marty/token.rb +30 -0
  270. data/app/models/marty/user.rb +146 -0
  271. data/app/models/marty/user.rb~ +148 -0
  272. data/app/models/marty/user_role.rb +7 -0
  273. data/app/models/marty/user_role.rb~ +13 -0
  274. data/app/views/layouts/marty/application.html.erb +12 -0
  275. data/app/views/layouts/marty/application.html.erb~ +11 -0
  276. data/config/locales/en.yml +134 -0
  277. data/config/routes.rb +6 -0
  278. data/config/routes.rb~ +10 -0
  279. data/db/migrate/001_create_marty_scripts.rb +14 -0
  280. data/db/migrate/003_create_marty_users.rb +12 -0
  281. data/db/migrate/004_create_marty_roles.rb +7 -0
  282. data/db/migrate/005_create_marty_user_roles.rb +14 -0
  283. data/db/migrate/006_create_marty_tokens.rb +14 -0
  284. data/db/migrate/008_create_marty_posting_types.rb +7 -0
  285. data/db/migrate/019_create_marty_postings.rb +18 -0
  286. data/db/migrate/019_create_marty_postings.rb~ +19 -0
  287. data/db/migrate/068_create_marty_import_types.rb +12 -0
  288. data/db/migrate/069_create_marty_import_synonyms.rb +15 -0
  289. data/db/migrate/070_create_versions.rb +18 -0
  290. data/db/migrate/071_add_object_changes_column_to_versions.rb +9 -0
  291. data/db/migrate/072_add_validation_function_to_import_types.rb +6 -0
  292. data/db/migrate/073_add_preprocess_function_to_import_types.rb +5 -0
  293. data/db/migrate/090_create_delayed_jobs.rb +22 -0
  294. data/db/migrate/091_create_marty_promises.rb +36 -0
  295. data/db/migrate/095_create_marty_tags.rb +14 -0
  296. data/db/migrate/095_create_marty_tags.rb~ +19 -0
  297. data/db/migrate/096_add_user_roles_to_import_types.rb +11 -0
  298. data/db/migrate/097_drop_versions.rb +9 -0
  299. data/db/migrate/098_create_marty_api_auths.rb +20 -0
  300. data/db/seeds.rb +48 -0
  301. data/lib/marty.rb +18 -0
  302. data/lib/marty.rb~ +13 -0
  303. data/lib/marty/content_handler.rb +97 -0
  304. data/lib/marty/content_handler.rb~ +93 -0
  305. data/lib/marty/data_conversion.rb +298 -0
  306. data/lib/marty/data_exporter.rb +150 -0
  307. data/lib/marty/data_exporter.rb~ +137 -0
  308. data/lib/marty/data_importer.rb +122 -0
  309. data/lib/marty/data_importer.rb~ +114 -0
  310. data/lib/marty/data_row_processor.rb~ +206 -0
  311. data/lib/marty/drop_folder_hook.rb~ +17 -0
  312. data/lib/marty/engine.rb +10 -0
  313. data/lib/marty/folder_hook.rb~ +9 -0
  314. data/lib/marty/lazy_column_loader.rb +57 -0
  315. data/lib/marty/lazy_column_loader.rb~ +47 -0
  316. data/lib/marty/mcfly_query.rb +189 -0
  317. data/lib/marty/mcfly_query.rb~ +188 -0
  318. data/lib/marty/migrations.rb +108 -0
  319. data/lib/marty/migrations.rb~ +65 -0
  320. data/lib/marty/monkey.rb +163 -0
  321. data/lib/marty/monkey.rb~ +160 -0
  322. data/lib/marty/permissions.rb +64 -0
  323. data/lib/marty/permissions.rb~ +69 -0
  324. data/lib/marty/promise.rb~ +41 -0
  325. data/lib/marty/promise_job.rb +123 -0
  326. data/lib/marty/promise_job.rb~ +121 -0
  327. data/lib/marty/promise_proxy.rb +94 -0
  328. data/lib/marty/promise_proxy.rb~ +69 -0
  329. data/lib/marty/railtie.rb +5 -0
  330. data/lib/marty/relation.rb +39 -0
  331. data/lib/marty/util.rb +110 -0
  332. data/lib/marty/util.rb~ +80 -0
  333. data/lib/marty/version.rb +3 -0
  334. data/lib/marty/version.rb~ +3 -0
  335. data/lib/marty/xl.rb +527 -0
  336. data/lib/marty/xl.rb~ +526 -0
  337. data/lib/pyxll/README.txt +19 -0
  338. data/lib/pyxll/README.txt~ +16 -0
  339. data/lib/pyxll/gemini.py +155 -0
  340. data/lib/pyxll/gemini.py~ +110 -0
  341. data/lib/pyxll/pyxll.cfg +12 -0
  342. data/lib/pyxll/pyxll.cfg~ +12 -0
  343. data/lib/pyxll/sample.xlsx +0 -0
  344. data/lib/tasks/marty_tasks.rake +37 -0
  345. metadata +517 -0
@@ -0,0 +1,169 @@
1
+ class Marty::Promise < Marty::Base
2
+
3
+ # default timeout (seconds) to wait for promise values
4
+ DEFAULT_PROMISE_TIMEOUT = 30
5
+
6
+ # default timeout (seconds) to wait for jobs to start
7
+ DEFAULT_JOB_TIMEOUT = 10
8
+
9
+ attr_accessible :title,
10
+ :cformat,
11
+ :parent_id,
12
+ :job_id,
13
+ :status,
14
+ :result,
15
+ :start_dt,
16
+ :end_dt
17
+
18
+ serialize :result, Hash
19
+
20
+ validates_presence_of :title
21
+
22
+ has_many :children, foreign_key: 'parent_id', class_name: "Marty::Promise"
23
+ belongs_to :parent, class_name: "Marty::Promise"
24
+
25
+ def raw_conn
26
+ self.class.connection.raw_connection
27
+ end
28
+
29
+ def pg_notify
30
+ raw_conn.async_exec("NOTIFY promise_#{id}")
31
+ end
32
+
33
+ def set_start
34
+ log "LOGLOG #{Rails.logger}"
35
+
36
+ if self.start_dt || self.result != {}
37
+ Marty::Util.logger.error("promise already started: #{self}")
38
+ return
39
+ end
40
+
41
+ # mark promise as started
42
+ self.start_dt = DateTime.now
43
+ self.save!
44
+ end
45
+
46
+ def set_result(res)
47
+ log "SETRES #{Process.pid} #{res} #{self}"
48
+
49
+ # promise must have been started and not yet ended
50
+ if !self.start_dt || self.end_dt || self.result != {}
51
+ log "SETERR #{Process.pid} #{self}"
52
+ Marty::Util.logger.error("unexpected promise state: #{self}")
53
+ return
54
+ end
55
+
56
+ raise "bad result" unless res.is_a?(Hash)
57
+
58
+ self.status = res["error"].nil?
59
+ self.result = res
60
+
61
+ # update title/format from result hash (somewhat hacky)
62
+ self.title = res["title"].to_s if res["title"]
63
+ self.cformat = res["format"].to_s if res["format"]
64
+
65
+ # mark promise as ended
66
+ self.end_dt = DateTime.now
67
+ self.save!
68
+
69
+ log "NOTIFY #{Process.pid}"
70
+ pg_notify
71
+ end
72
+
73
+ def to_s
74
+ inspect
75
+ end
76
+
77
+ def log(msg)
78
+ open('/tmp/dj.out', 'a') { |f| f.puts msg }
79
+ end
80
+
81
+ def wait_for_my_notify(timeout)
82
+ while true do
83
+ # FIXME: we keep using the same timeout. The timeout should be
84
+ # reduced by total time spent here.
85
+ n = raw_conn.wait_for_notify(timeout)
86
+ return n if !n || n=="promise_#{id}"
87
+ end
88
+ end
89
+
90
+ def latest
91
+ # latest uncached version
92
+ Marty::Promise.uncached {Marty::Promise.find(id)}
93
+ end
94
+
95
+ def work_off_job(job)
96
+ # Create a temporary worker to work off the job
97
+ Delayed::Job.where(id: job.id).
98
+ update_all(locked_at: Delayed::Job.db_time_now, locked_by: "Temp")
99
+ w = Delayed::Worker.new
100
+ w.run(job)
101
+ end
102
+
103
+ def wait_for_result(timeout)
104
+ return self.result if self.result != {}
105
+
106
+ # FIXME: instead of using latest(), should look at how delayed
107
+ # jobs are loaded. i.e. use reset+reload.
108
+
109
+ begin
110
+ # start listening on promise's notification
111
+ raw_conn.exec("LISTEN promise_#{id}")
112
+
113
+ last = latest
114
+
115
+ # if job hasn't started yet, wait for it to start
116
+ if !last.start_dt
117
+ log "AAAA #{Process.pid} #{last}"
118
+
119
+ job = Delayed::Job.find_by_id(last.job_id)
120
+ job.reload if job # paranoid
121
+
122
+ if !job && job.locked_at
123
+ # job has been locked, so it looks like it started already
124
+ # and we need to wait for it.
125
+ wait_for_my_notify(Marty::Promise::DEFAULT_JOB_TIMEOUT)
126
+ else
127
+ # work off the job instead of waiting for a real worker to
128
+ # pick it up.
129
+ log "OFFF #{Process.pid} #{last}"
130
+ work_off_job(job)
131
+ end
132
+
133
+ last = latest
134
+
135
+ # we waited for it but it never started. So, mark it with a
136
+ # timeout error.
137
+ if !last.start_dt
138
+ log "TO11 #{Process.pid} #{last}"
139
+ return {"error" => "promise #{last.id} timed out (never started)"}
140
+ end
141
+ end
142
+
143
+ # reload promise in case out copy doesn't have a result yet
144
+ last = latest unless last.end_dt
145
+
146
+ # at this point, we know the promise has already started
147
+ if !last.end_dt
148
+ wait_for_my_notify(timeout)
149
+ log "UUUU #{Process.pid} #{id} #{Time.now.to_f}"
150
+ last = latest
151
+
152
+ log "XXXX #{Process.pid} #{Time.now.to_f} #{last}"
153
+
154
+ if !last.end_dt
155
+ log "TO22 #{Process.pid} #{last}"
156
+ return {"error" => "promise #{last.id} timed out (didn't end)"}
157
+ end
158
+ end
159
+
160
+ log "RRRR #{Process.pid} #{last} #{Time.now.to_f}"
161
+
162
+ last.result
163
+ ensure
164
+ # Stop listening to the promise notifications
165
+ raw_conn.exec("UNLISTEN promise_#{id}")
166
+ end
167
+
168
+ end
169
+ end
@@ -0,0 +1,101 @@
1
+ class Marty::Posting < Marty::Base
2
+ has_mcfly append_only: true
3
+
4
+ mcfly_validates_uniqueness_of :name
5
+ validates_presence_of :name, :posting_type_id, :comment
6
+
7
+ belongs_to :user, class_name: "Marty::User"
8
+ belongs_to :posting_type
9
+
10
+ def self.make_name(posting_type, dt)
11
+ return 'NOW' if Mcfly.is_infinity(dt)
12
+
13
+ return unless posting_type
14
+
15
+ # If no dt is provided (which is the usual non-testing case), we
16
+ # use Time.now.strftime to name the posting. This has the effect
17
+ # of using the host's timezone. i.e. since we're in PST8PDT, names
18
+ # will be based off of the Pacific TZ.
19
+ dt ||= Time.now
20
+ "#{posting_type.name}-#{dt.strftime('%Y%m%d-%H%M')}"
21
+ end
22
+
23
+ before_validation :set_posting_name
24
+ def set_posting_name
25
+ posting_type = Marty::PostingType.find_by_id(self.posting_type_id)
26
+ self.name = self.class.make_name(posting_type, self.created_dt)
27
+ true
28
+ end
29
+
30
+ def self.do_create(type_name, dt, comment)
31
+ posting_type = Marty::PostingType.find_by_name(type_name)
32
+
33
+ raise "unknown posting type #{name}" unless posting_type
34
+
35
+ o = new
36
+ o.posting_type = posting_type
37
+ o.comment = comment
38
+ o.created_dt = dt
39
+ o.save!
40
+ o
41
+ end
42
+
43
+ # Not using mcfly_lookup since we don't want these time-warp markers
44
+ # time-warped. FIXME: perhaps this should use mcfly_lookup since we
45
+ # may allow deletion of postings. i.e. a new one with same name
46
+ # might be created. Or, use regular validates_uniqueness_of instead
47
+ # of mcfly_validates_uniqueness_of.
48
+ delorean_fn :lookup, sig: 1 do
49
+ |name|
50
+ self.find_by_name(name)
51
+ end
52
+
53
+ delorean_fn :lookup_dt, sig: 1 do
54
+ |name|
55
+ lookup(name).try(:created_dt)
56
+ end
57
+
58
+ delorean_fn :first_match, sig: [1, 2] do
59
+ |dt, posting_type=nil|
60
+ raise "bad posting type" if
61
+ posting_type && !posting_type.is_a?(Marty::PostingType)
62
+
63
+ q = where("created_dt <= ?", dt)
64
+ q = q.where(posting_type_id: posting_type.id) if posting_type
65
+ q.order("created_dt DESC").first
66
+ end
67
+
68
+ delorean_fn :get_latest, sig: [1, 2] do
69
+ |limit, is_test=nil|
70
+ # IMPORTANT: is_test arg is ignored (KEEP for backward compat.)
71
+
72
+ where("created_dt <> 'infinity'").
73
+ order("created_dt DESC").limit(limit).to_a
74
+ end
75
+
76
+ delorean_fn :get_latest_by_type, sig: [2, 2] do
77
+ |limit, posting_types=[]|
78
+ raise "missing posting types list" unless posting_types
79
+ raise "bad posting types list" unless posting_types.is_a?(Array)
80
+
81
+ joins(:posting_type).where("created_dt <> 'infinity'").
82
+ where(marty_posting_types: { name: posting_types } ).
83
+ order("created_dt DESC").limit(limit || 1).to_a
84
+ end
85
+
86
+ delorean_fn :get_last, sig: [0, 1] do
87
+ |posting_type=nil|
88
+
89
+ raise "bad posting type" if
90
+ posting_type && !posting_type.is_a?(Marty::PostingType)
91
+
92
+ q = where("created_dt <> 'infinity'")
93
+ q = q.where(posting_type_id: posting_type.id) if posting_type
94
+ q.order("created_dt DESC").first
95
+ end
96
+
97
+ delorean_fn :is_today, sig: 1 do
98
+ |posting|
99
+ posting.created_dt.to_date == Date.today
100
+ end
101
+ end
@@ -0,0 +1,86 @@
1
+ class Marty::Posting < Marty::Base
2
+ has_mcfly append_only: true
3
+
4
+ mcfly_validates_uniqueness_of :name
5
+ validates_presence_of :name, :posting_type_id, :comment
6
+
7
+ belongs_to :user, class_name: "Marty::User"
8
+ belongs_to :posting_type
9
+
10
+ def self.make_name(posting_type, dt)
11
+ return 'NOW' if Mcfly.is_infinity(dt)
12
+
13
+ return unless posting_type
14
+
15
+ # If no dt is provided (which is the usual non-testing case), we
16
+ # use Time.now.strftime to name the posting. This has the effect
17
+ # of using the host's timezone. i.e. since we're in PST8PDT, names
18
+ # will be based off of the Pacific TZ.
19
+ dt ||= Time.now
20
+ "#{posting_type.name}-#{dt.strftime('%Y%m%d-%H%M')}"
21
+ end
22
+
23
+ before_validation :set_posting_name
24
+ def set_posting_name
25
+ posting_type = Marty::PostingType.find_by_id(self.posting_type_id)
26
+ self.name = self.class.make_name(posting_type, self.created_dt)
27
+ true
28
+ end
29
+
30
+ def self.do_create(type_name, dt, comment)
31
+ posting_type = Marty::PostingType.find_by_name(type_name)
32
+
33
+ raise "unknown posting type #{name}" unless posting_type
34
+
35
+ o = new
36
+ o.posting_type = posting_type
37
+ o.comment = comment
38
+ o.created_dt = dt
39
+ o.save!
40
+ o
41
+ end
42
+
43
+ # Not using mcfly_lookup since we don't want these time-warp markers
44
+ # time-warped. FIXME: perhaps this should use mcfly_lookup since we
45
+ # may allow deletion of postings. i.e. a new one with same name
46
+ # might be created. Or, use regular validates_uniqueness_of instead
47
+ # of mcfly_validates_uniqueness_of.
48
+ delorean_fn :lookup, sig: 1 do
49
+ |name|
50
+ self.find_by_name(name)
51
+ end
52
+
53
+ delorean_fn :lookup_dt, sig: 1 do
54
+ |name|
55
+ lookup(name).try(:created_dt)
56
+ end
57
+
58
+ delorean_fn :first_match, sig: 1 do
59
+ |dt|
60
+ where("created_dt <= ?", dt).order("created_dt DESC").first
61
+ end
62
+
63
+ delorean_fn :get_latest, sig: [1, 2] do
64
+ |limit, is_test=nil|
65
+ # IMPORTANT: is_test arg is ignored (KEEP for backward compat.)
66
+
67
+ where("created_dt <> 'infinity'").
68
+ order("created_dt DESC").limit(limit).to_a
69
+ end
70
+
71
+ delorean_fn :get_last, sig: [0, 1] do
72
+ |posting_type=nil|
73
+
74
+ raise "bad posting type" if
75
+ posting_type && !posting_type.is_a?(Marty::PostingType)
76
+
77
+ q = where("created_dt <> 'infinity'")
78
+ q = q.where(posting_type_id: posting_type.id) if posting_type
79
+ q.order("created_dt DESC").first
80
+ end
81
+
82
+ delorean_fn :is_today, sig: 1 do
83
+ |posting|
84
+ posting.created_dt.to_date == Date.today
85
+ end
86
+ end
@@ -0,0 +1,12 @@
1
+ class Marty::PostingType < Marty::Base
2
+ extend Marty::Enum
3
+
4
+ validates_presence_of :name
5
+ validates_uniqueness_of :name
6
+
7
+ # NOTE: lookup fn for backward compat -- to index enums, use []
8
+ delorean_fn :lookup, sig: 1 do
9
+ |name|
10
+ self.find_by_name(name)
11
+ end
12
+ end
@@ -0,0 +1,21 @@
1
+ class Marty::PostingType < Marty::Base
2
+ extend Marty::Enum
3
+
4
+ <<<<<<< HEAD
5
+ # attr_accessible :name
6
+ =======
7
+ >>>>>>> master
8
+ validates_presence_of :name
9
+ validates_uniqueness_of :name
10
+
11
+ delorean_fn :lookup, sig: 1 do
12
+ |name|
13
+ self.find_by_name(name)
14
+ end
15
+
16
+ def self.seed
17
+ ['BASE', 'CLOSE', 'INTRA', 'RULE'].each { |type|
18
+ create name: type
19
+ }
20
+ end
21
+ end
@@ -0,0 +1,252 @@
1
+ class Marty::Promise < Marty::Base
2
+ class MarshalResult
3
+ def dump(v)
4
+ Marshal.dump(v)
5
+ end
6
+
7
+ def load(v)
8
+ # Marshal.load can't handle nil
9
+ v ? Marshal.load(v) : {}
10
+ end
11
+ end
12
+
13
+ # default timeout (seconds) to wait for promise values
14
+ DEFAULT_PROMISE_TIMEOUT = Rails.configuration.marty.promise_timeout || 30
15
+
16
+ # default timeout (seconds) to wait for jobs to start
17
+ DEFAULT_JOB_TIMEOUT = Rails.configuration.marty.job_timeout || 10
18
+
19
+ lazy_load :result
20
+
21
+ serialize :result, MarshalResult.new
22
+
23
+ validates_presence_of :title
24
+
25
+ has_many :children,
26
+ foreign_key: 'parent_id',
27
+ class_name: "Marty::Promise",
28
+ dependent: :destroy
29
+
30
+ belongs_to :parent, class_name: "Marty::Promise"
31
+ belongs_to :user, class_name: "Marty::User"
32
+
33
+ def self.cleanup(all=false)
34
+ begin
35
+ where('start_dt < ? AND parent_id IS NULL',
36
+ DateTime.now - (all ? 0.hours : 4.hours)).destroy_all
37
+ rescue => exc
38
+ Marty::Util.logger.error("promise GC error: #{exc}")
39
+ end
40
+ end
41
+
42
+ class VirtualRoot
43
+ def self.primary_key
44
+ 'id'
45
+ end
46
+
47
+ def id
48
+ 'root'
49
+ end
50
+
51
+ def user_id
52
+ 0
53
+ end
54
+ alias_method :job_id, :user_id
55
+
56
+ def result
57
+ nil
58
+ end
59
+ [:start_dt, :end_dt].each { |m| alias_method m, :result }
60
+
61
+ def status
62
+ true
63
+ end
64
+ end
65
+
66
+ def self.root
67
+ VirtualRoot.new
68
+ end
69
+
70
+ def self.children_for_id(id, search_order)
71
+ if id == 'root'
72
+ where(parent_id: nil).live_search(search_order).order(id: :desc).includes(:children, :user)
73
+ else
74
+ find(id).children.live_search(search_order).order(id: :desc).includes(:children, :user)
75
+ end
76
+ end
77
+
78
+ def leaf
79
+ children.empty?
80
+ end
81
+
82
+ def raw_conn
83
+ self.class.connection.raw_connection
84
+ end
85
+
86
+ def pg_notify
87
+ raw_conn.async_exec("NOTIFY promise_#{id}")
88
+ end
89
+
90
+ def set_start
91
+ if self.start_dt || self.result != {}
92
+ Marty::Util.logger.error("promise already started: #{self}")
93
+ return
94
+ end
95
+
96
+ # mark promise as started
97
+ self.start_dt = DateTime.now
98
+ self.save!
99
+ end
100
+
101
+ def set_result(res)
102
+ # log "SETRES #{Process.pid} #{self}"
103
+
104
+ # promise must have been started and not yet ended
105
+ if !self.start_dt || self.end_dt || self.result != {}
106
+ # log "SETERR #{Process.pid} #{self}"
107
+ Marty::Util.logger.error("unexpected promise state: #{self}")
108
+ return
109
+ end
110
+
111
+ raise "bad result" unless res.is_a?(Hash)
112
+
113
+ self.status = res["error"].nil?
114
+ self.result = res
115
+
116
+ # update title/format from result hash (somewhat hacky)
117
+ self.title = res["title"].to_s if res["title"]
118
+ self.cformat = res["format"].to_s if res["format"]
119
+
120
+ # mark promise as ended
121
+ self.end_dt = DateTime.now
122
+ self.save!
123
+
124
+ # log "NOTIFY #{Process.pid}"
125
+ pg_notify
126
+ end
127
+
128
+ def to_s
129
+ inspect
130
+ end
131
+
132
+ # def log(msg)
133
+ # open('/tmp/dj.out', 'a') { |f| f.puts msg }
134
+ # end
135
+
136
+ def wait_for_my_notify(timeout)
137
+ while true do
138
+ # FIXME: we keep using the same timeout. The timeout should be
139
+ # reduced by total time spent here.
140
+ n = raw_conn.wait_for_notify(timeout)
141
+ return n if !n || n=="promise_#{id}"
142
+ end
143
+ end
144
+
145
+ def latest
146
+ # FIXME: Not sure if this is idiomatic. What's the best way to
147
+ # force AR to reload the promise object? reset+reload doesn't
148
+ # seems to work.
149
+
150
+ # get latest uncached version
151
+ Marty::Promise.uncached {Marty::Promise.find(id)}
152
+ end
153
+
154
+ def self.job_by_id(job_id)
155
+ Delayed::Job.uncached {Delayed::Job.find_by_id(job_id)}
156
+ end
157
+
158
+ def work_off_job(job)
159
+ # Create a temporary worker to work off the job
160
+ Delayed::Job.where(id: job.id).
161
+ update_all(locked_at: Delayed::Job.db_time_now, locked_by: "Temp")
162
+ w = Delayed::Worker.new
163
+ w.run(job)
164
+ end
165
+
166
+ def wait_for_result(timeout)
167
+ return self.result if self.result != {}
168
+
169
+ begin
170
+ # start listening on promise's notification
171
+ raw_conn.exec("LISTEN promise_#{id}")
172
+
173
+ last = latest
174
+
175
+ # if job hasn't started yet, wait for it to start
176
+ if !last.start_dt
177
+ job = Marty::Promise.job_by_id(last.job_id)
178
+
179
+ # log "AAAA #{Process.pid} #{last} #{job}"
180
+
181
+ if !job || job.locked_at
182
+ # job has been locked, so it looks like it started already
183
+ # and we need to wait for it.
184
+ wait_for_my_notify(Marty::Promise::DEFAULT_JOB_TIMEOUT)
185
+ else
186
+ # work off the job instead of waiting for a real worker to
187
+ # pick it up.
188
+ # log "OFF0 #{Process.pid} #{last}"
189
+ begin
190
+ work_off_job(job)
191
+ rescue => exc
192
+ # log "OFFERR #{exc}"
193
+ res = Delorean::Engine.grok_runtime_exception(exc)
194
+ last.set_result(res)
195
+ end
196
+ # log "OFF1 #{Process.pid} #{last}"
197
+ end
198
+
199
+ last = latest
200
+
201
+ # we waited for it but it never started. So, mark it with a
202
+ # timeout error.
203
+ if !last.start_dt
204
+ # log "TO11 #{Process.pid} #{last}"
205
+ return {"error" => "promise #{last.id} timed out (never started)"}
206
+ end
207
+ end
208
+
209
+ # reload promise in case out copy doesn't have a result yet
210
+ last = latest unless last.end_dt
211
+
212
+ # at this point, we know the promise has already started
213
+ if !last.end_dt
214
+ wait_for_my_notify(timeout)
215
+ # log "UUUU #{Process.pid} #{id} #{Time.now.to_f}"
216
+ last = latest
217
+
218
+ # log "XXXX #{Process.pid} #{Time.now.to_f} #{last}"
219
+
220
+ if !last.end_dt
221
+ # log "TO22 #{Process.pid} #{last}"
222
+ return {"error" => "promise #{last.id} timed out (didn't end)"}
223
+ end
224
+ end
225
+
226
+ # log "RRRR #{Process.pid} #{last} #{Time.now.to_f}"
227
+
228
+ last.result
229
+ ensure
230
+ # Stop listening to the promise notifications
231
+ raw_conn.exec("UNLISTEN promise_#{id}")
232
+ end
233
+ end
234
+
235
+ # Support UI live search -- FIXME: hacky to have UI scoping here
236
+ scope :live_search, lambda { |search_text|
237
+ return if !search_text || search_text.strip.length < 1
238
+
239
+ # Searches user login/firstname/lastname
240
+ query = [
241
+ "marty_users.login ILIKE ?",
242
+ "marty_users.firstname ILIKE ?",
243
+ "marty_users.lastname ILIKE ?",
244
+ "marty_roles.name ILIKE ?",
245
+ ].join(' OR ')
246
+
247
+ st = "%#{search_text}%"
248
+ # Convert "Role Name" or "Role name" to "role_name" (underscore is key)
249
+ st2 = "%#{search_text.titleize.gsub(/\s/, '').underscore}%"
250
+ joins({:user => :roles}).where(query, st, st, st, st2).distinct
251
+ }
252
+ end