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,206 @@
1
+ class Marty::DataRowProcessor
2
+ attr_accessor :klass, :headers, :dt, :key_attrs, :hmap
3
+
4
+ EXCEL_START_DATE = Date.parse('1/1/1900')-2
5
+
6
+ MCFLY_COLUMNS = Set[
7
+ "id",
8
+ "group_id",
9
+ "user_id",
10
+ "created_dt",
11
+ "obsoleted_dt",
12
+ "o_user_id",
13
+ ]
14
+
15
+ # Given a Mcfly class, return the set of attributes (excluding id)
16
+ # used to uniquely identify an instance.
17
+ def self.get_keys(klass)
18
+ raise "bad class arg #{klass}" unless
19
+ klass.is_a?(Class) && klass < ActiveRecord::Base
20
+
21
+ attrs = klass.const_get(:MCFLY_UNIQUENESS)
22
+
23
+ raise "class has no :MCFLY_UNIQUENESS" unless attrs
24
+
25
+ attrs = attrs[0..-2] + attrs.last.fetch(:scope, []) if
26
+ attrs.last.is_a?(Hash)
27
+ attrs -= [:obsoleted_dt]
28
+
29
+ raise "key list for #{klass} is empty" if attrs.empty?
30
+ attrs
31
+ end
32
+
33
+ def self.assoc_info(klass, a)
34
+ assoc_class = klass.reflect_on_association(a.to_sym).klass
35
+ keys = self.get_keys(assoc_class) rescue nil
36
+
37
+ assoc_keys = keys || [assoc_class.attribute_names.reject{|x| x=="id"}.first]
38
+
39
+ {assoc_keys: assoc_keys, assoc_class: assoc_class, mcfly: keys}
40
+ end
41
+
42
+ FLOAT_PAT = /^-?\d+(\.\d+)?$/
43
+
44
+ PATS = {
45
+ integer: /^-?\d+(\.0+)?$/,
46
+ float: FLOAT_PAT,
47
+ decimal: FLOAT_PAT,
48
+ }
49
+
50
+ def convert(v, type)
51
+ pat = PATS[type]
52
+
53
+ raise "bad #{type} #{v.inspect}" if
54
+ v.is_a?(String) && pat && !(v =~ pat)
55
+
56
+ case type
57
+ when :boolean
58
+ case v.downcase
59
+ when "true" then true
60
+ when "false" then false
61
+ else raise "unknown boolean #{v}"
62
+ end
63
+ when :string, :text
64
+ v
65
+ when :integer
66
+ v.to_i
67
+ when :float
68
+ v.to_f
69
+ when :decimal
70
+ v.to_d
71
+ when :date
72
+ # Dates are kept as float in Google spreadsheets. Need to
73
+ # convert them to dates. FIXME: 'infinity' as a date in
74
+ # Rails 3.2 appears to be broken. Setting a date field to
75
+ # 'infinity' sets it to nil.
76
+ v =~ FLOAT_PAT ? EXCEL_START_DATE + v.to_f :
77
+ Mcfly.is_infinity(v) ? 'infinity' : v.to_date
78
+ when :datetime
79
+ Mcfly.is_infinity(v) ? 'infinity' : v.to_datetime
80
+ when :numrange, :int4range, :int8range
81
+ v.to_s
82
+ when :float_array, :json
83
+ JSON.parse Marty::DataExporter.decode_json(v)
84
+ else
85
+ raise "unknown type #{type} for #{v}"
86
+ end
87
+ end
88
+
89
+ def initialize(klass, headers, dt)
90
+ @klass = klass
91
+ @headers = headers
92
+ @dt = dt
93
+ @key_attrs = self.class.get_keys(klass)
94
+
95
+ # # HACK: not sure why there's a nil at the end of headers sometimes
96
+ # headers.pop if headers[-1].nil?
97
+
98
+ raise "row headers have nil! #{headers.inspect}" unless headers.all?
99
+
100
+ associations = klass.reflect_on_all_associations.map(&:name)
101
+
102
+ cols = klass.columns.each_with_object({}) { |c, h|
103
+ h[c.name] = c
104
+ }
105
+
106
+ @hmap = headers.each_with_object({}) do
107
+ |a, h|
108
+ # handle klass__attr type headers generated by Netzke. Just
109
+ # keeps klass since we should be able to find the key attr.
110
+ aclass = a.split('__').first
111
+
112
+ if associations.member?(aclass.to_sym)
113
+ h[a] = self.class.assoc_info(klass, aclass)
114
+ next
115
+ end
116
+
117
+ raise "unknown column #{a}" unless cols[a]
118
+
119
+ # for JSON fields in Rails 3.x type is nil, so use sql_type
120
+ type = cols[a].type || cols[a].sql_type
121
+ type = "#{type}_array" if cols[a].array
122
+ h[a] = type.to_sym
123
+ end
124
+ end
125
+
126
+ def create_or_update(row)
127
+ assoc_options = {}
128
+
129
+ options = row.each_with_object({}) do |(a, v), h|
130
+ # ignore Mcfly columns
131
+ next if MCFLY_COLUMNS.member? a
132
+
133
+ if hmap[a].is_a?(Hash)
134
+ assoc_options[a] = v
135
+ else
136
+ raise "bad col #{a} value #{v}, row: #{row}" unless hmap[a]
137
+
138
+ # if it's not a hash (association) then its a type symbol
139
+ h[a] = v && convert(v, hmap[a])
140
+ end
141
+ end
142
+
143
+ assoc_groups = assoc_options.keys.group_by {|x| x.split('__').first}
144
+
145
+ assoc_groups.each do |aclass, attrs|
146
+ # if group has only one attr and the attr is nil or AR obj, then
147
+ # we don't need to search.
148
+ if attrs.length == 1
149
+ a = attrs.first
150
+ v = assoc_options[a]
151
+
152
+ if v.nil? || v.is_a?(ActiveRecord::Base)
153
+ options["#{aclass}_id"] = v && v.id
154
+ next
155
+ end
156
+ end
157
+
158
+ srch = attrs.each_with_object({}) do |a, h|
159
+ v = assoc_options[a]
160
+ ac, aa = a.split('__')
161
+
162
+ aa ||= hmap[a][:assoc_keys].first
163
+
164
+ h[aa] = v
165
+ h[:obsoleted_dt] = 'infinity' if hmap[a][:mcfly]
166
+ end
167
+
168
+ srch_class = hmap[attrs.first][:assoc_class]
169
+
170
+ av = srch_class.where(srch).first
171
+
172
+ raise "#{aclass} not found #{srch}" unless av
173
+
174
+ options[ "#{aclass}_id" ] = av.id
175
+ end
176
+
177
+ find_options = options.select { |k,v| key_attrs.member? k.to_sym }
178
+
179
+ raise "invalid entry" if find_options.empty?
180
+
181
+ find_options['obsoleted_dt'] = 'infinity'
182
+
183
+ obj = klass.where(find_options).first || klass.new
184
+
185
+ options.each do
186
+ |k, v|
187
+ # For each attr, check to see if it's begin changed before
188
+ # setting it. The AR obj.changed? doesn't work properly
189
+ # with array, JSON or lazy attrs.
190
+ obj.send("#{k}=", v) if obj.send(k) != v
191
+ end
192
+
193
+ # FIXME: obj.changed? doesn't work properly for timestamp
194
+ # fields in Rails 3.2. It evaluates to true even when datetime
195
+ # is not changed. Caused by lack of awareness of timezones.
196
+ tag = obj.new_record? ? :create : (obj.changed? ? :update : :same)
197
+
198
+ raise "old created_dt >= current #{obj} #{obj.created_dt} #{dt}" if
199
+ (tag == :update) && !Mcfly.is_infinity(dt) && (obj.created_dt > dt)
200
+
201
+ obj.created_dt = dt unless tag == :same || Mcfly.is_infinity(dt)
202
+ obj.save!
203
+
204
+ [tag, obj.id]
205
+ end
206
+ end
@@ -0,0 +1,17 @@
1
+ class Marty::DropFolderHook
2
+ def initialize(login)
3
+ @login = login
4
+ end
5
+
6
+ def run(res)
7
+ p 'H.'*10, res
8
+ drop_path = "/tmp/#{@login}"
9
+
10
+ begin
11
+ Dir.mkdir(drop_path) unless File.directory?(drop_path)
12
+ rescue => exc
13
+ Marty::Util.logger.error "Can't create
14
+
15
+
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ module Marty
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Marty
4
+
5
+ # generators add rspec tests
6
+ config.generators do |g|
7
+ g.test_framework :rspec, :view_specs => false
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ class Marty::FolderHook
2
+ def initialize
3
+ end
4
+
5
+ def run(res)
6
+ p 'H.'*10, res
7
+ end
8
+
9
+ end
@@ -0,0 +1,57 @@
1
+ # ATTRIBUTION NOTE: This module has been mostly copied from the
2
+ # lazy_columns gem. The original code can be found at:
3
+ # https://github.com/jorgemanrubia/lazy_columns
4
+
5
+ module Marty
6
+ module LazyColumnLoader
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ def lazy_load(*columns)
11
+ return unless table_exists?
12
+ columns = columns.collect(&:to_s)
13
+ exclude_columns_from_default_scope columns
14
+ define_lazy_accessors_for columns
15
+
16
+ # allow introspection of lazy-loaded column list
17
+ const_set(:LAZY_LOADED, columns)
18
+ end
19
+
20
+ private
21
+ def exclude_columns_from_default_scope(columns)
22
+ default_scope {
23
+ select((column_names - columns).map {
24
+ |column_name|
25
+ "#{table_name}.#{column_name}"
26
+ })
27
+ }
28
+ end
29
+
30
+ def define_lazy_accessors_for(columns)
31
+ columns.each { |column| define_lazy_accessor_for column }
32
+ end
33
+
34
+ def define_lazy_accessor_for(column)
35
+ define_method column do
36
+ unless has_attribute?(column)
37
+ changes_before_reload = self.changes.clone
38
+ self.reload
39
+ changes_before_reload.each{
40
+ |attribute_name, values|
41
+ self.send("#{attribute_name}=", values[1])
42
+ }
43
+ end
44
+ read_attribute column
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ if ActiveRecord::Base.respond_to?(:lazy_load)
52
+ $stderr.puts "ERROR: Method `.lazy_load` already defined in " +
53
+ "`ActiveRecord::Base`. This is incompatible with LazyColumnLoader " +
54
+ "and the module will be disabled."
55
+ else
56
+ ActiveRecord::Base.send :include, Marty::LazyColumnLoader
57
+ end
@@ -0,0 +1,47 @@
1
+ module Marty
2
+ module LazyColumnLoader
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def lazy_load(*columns)
7
+ return unless table_exists?
8
+ columns = columns.collect(&:to_s)
9
+ exclude_columns_from_default_scope columns
10
+ define_lazy_accessors_for columns
11
+ end
12
+
13
+ private
14
+ def exclude_columns_from_default_scope(columns)
15
+ default_scope select((
16
+ column_names - columns).map {
17
+ |column_name|
18
+ "#{table_name}.#{column_name}"
19
+ })
20
+ end
21
+
22
+ def define_lazy_accessors_for(columns)
23
+ columns.each { |column| define_lazy_accessor_for column }
24
+ end
25
+
26
+ def define_lazy_accessor_for(column)
27
+ define_method column do
28
+ unless has_attribute?(column)
29
+ changes_before_reload = self.changes.clone
30
+ self.reload
31
+ changes_before_reload.each{|attribute_name, values|
32
+ self.send("#{attribute_name}=", values[1])}
33
+ end
34
+ read_attribute column
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ if ActiveRecord::Base.respond_to?(:lazy_load)
42
+ $stderr.puts "ERROR: Method `.lazy_load` already defined in " +
43
+ "`ActiveRecord::Base`. This is incompatible with LazyColumnLoader " +
44
+ "and the module will be disabled."
45
+ else
46
+ ActiveRecord::Base.send :include, Marty::LazyColumnLoader
47
+ end
@@ -0,0 +1,189 @@
1
+ require 'mcfly'
2
+
3
+ module Mcfly
4
+ module Model
5
+
6
+ def self.included(base)
7
+ base.send :extend, ClassMethods
8
+ end
9
+
10
+ module ClassMethods
11
+ def clear_lookup_cache!
12
+ @LOOKUP_CACHE.clear if @LOOKUP_CACHE
13
+ end
14
+
15
+ # Implements a VERY HACKY class-based caching mechanism for
16
+ # database lookup results. Issues include: cached values are
17
+ # ActiveRecord objects. Not sure if these should be shared
18
+ # across connections. Query results can potentially be very
19
+ # large lists which we simply count as one item in the cache.
20
+ # Caching mechanism will result in large processes. Caches are
21
+ # not sharable across different Ruby processes.
22
+ def cached_delorean_fn(name, options = {}, &block)
23
+ @LOOKUP_CACHE ||= {}
24
+
25
+ delorean_fn(name, options) do |ts, *args|
26
+ cache_key = [name, ts] + args.map{ |a|
27
+ a.is_a?(ActiveRecord::Base) ? a.id : a
28
+ } unless Mcfly.is_infinity(ts)
29
+
30
+ next @LOOKUP_CACHE[cache_key] if
31
+ cache_key && @LOOKUP_CACHE.has_key?(cache_key)
32
+
33
+ res = block.call(ts, *args)
34
+
35
+ if cache_key
36
+ # Cache has >1000 items, clear out the oldest 200. FIXME:
37
+ # hard-coded, should be configurable. Cache
38
+ # size/invalidation should be per lookup and not class.
39
+ # We're invalidating cache items simply based on age and
40
+ # not usage. This is faster but not as fair.
41
+ if @LOOKUP_CACHE.count > 1000
42
+ @LOOKUP_CACHE.keys[0..200].each{|k| @LOOKUP_CACHE.delete(k)}
43
+ end
44
+ @LOOKUP_CACHE[cache_key] = res
45
+
46
+ # Since we're caching this object and don't want anyone
47
+ # changing it. FIXME: ideally should freeze this object
48
+ # recursively.
49
+ res.freeze unless res.is_a?(ActiveRecord::Relation)
50
+ end
51
+ res
52
+ end
53
+ end
54
+
55
+ # FIXME: duplicate code from Mcfly's mcfly_lookup.
56
+ def cached_mcfly_lookup(name, options = {}, &block)
57
+ cached_delorean_fn(name, options) do |ts, *args|
58
+ raise "time cannot be nil" if ts.nil?
59
+
60
+ ts = Mcfly.normalize_infinity(ts)
61
+
62
+ where("obsoleted_dt >= ? AND created_dt < ?", ts, ts).scoping do
63
+ block.call(ts, *args)
64
+ end
65
+ end
66
+ end
67
+
68
+ # FIXME: for validation purposes, this mechanism should make
69
+ # sure that the allable attrs are not required.
70
+ def gen_mcfly_lookup(name, attrs, options={})
71
+ raise "bad options" unless options.is_a?(Hash)
72
+
73
+ # FIXME: mode should be sent later, not as a part of
74
+ # gen_mcfly_lookup. i.e. we just generate the search and the
75
+ # mode is applied at runtime by delorean code. That would
76
+ # allow lookups to be used in either mode dynamically.
77
+ mode = options.fetch(:mode, :first)
78
+
79
+ assoc = Set.new(self.reflect_on_all_associations.map(&:name))
80
+ attr_names = attrs.keys
81
+
82
+ allables = attrs.select {|k, v| v}
83
+
84
+ order = allables.keys.reverse.map { |k|
85
+ k = "#{k}_id" if assoc.member?(k)
86
+ "#{k} NULLS LAST"
87
+ }.join(", ")
88
+
89
+ qstr = attrs.map {|k, v|
90
+ k = "#{k}_id" if assoc.member?(k)
91
+ v ? "(#{k} = ? OR #{k} IS NULL)" : "(#{k} = ?)"
92
+ }.join(" AND ")
93
+
94
+ cached_mcfly_lookup(name, sig: attrs.length+1) do
95
+ |t, *attr_list|
96
+
97
+ attr_list_ids = attr_list.each_with_index.map {|x, i|
98
+ assoc.member?(attr_names[i]) ?
99
+ (attr_list[i] && attr_list[i].id) : attr_list[i]
100
+ }
101
+
102
+ q = self.where(qstr, *attr_list_ids)
103
+ q = q.order(order) unless order.empty?
104
+ mode = :to_a if mode == :all
105
+ mode ? q.send(mode) : q
106
+ end
107
+ end
108
+
109
+ ######################################################################
110
+
111
+ # Generates categorization lookups. For instance,
112
+ # suppose we have the following in class GFee:
113
+ #
114
+ # gen_mcfly_lookup_cat :lookup_q,
115
+ # [:security_instrument,
116
+ # 'Gemini::SecurityInstrumentCategorization',
117
+ # :g_fee_category],
118
+ # {
119
+ # entity: true,
120
+ # security_instrument: true,
121
+ # coupon: true,
122
+ # },
123
+ # nil
124
+
125
+ # In the above case,
126
+ # rel_attr = :security_instrument
127
+ # cat_assoc_klass = Gemini::SecurityInstrumentCategorization
128
+ # cat_attr = :g_fee_category
129
+ # name = :lookup_q
130
+ # pc_name = :pc_lookup_q
131
+ # pc_attrs = {entity: true, security_instrument: true,
132
+ # g_fee_category: true, coupon: true}
133
+
134
+ def gen_mcfly_lookup_cat(name, catrel, attrs, options={})
135
+ rel_attr, cat_assoc_name, cat_attr = catrel
136
+
137
+ raise "#{rel_attr} should be mapped in attrs" if
138
+ attrs[rel_attr].nil?
139
+
140
+ cat_assoc_klass = cat_assoc_name.constantize
141
+
142
+ raise "need lookup method on #{cat_assoc_klass}" unless
143
+ cat_assoc_klass.respond_to? :lookup
144
+
145
+ # replace rel_attr with cat_attr in attrs
146
+ pc_attrs = attrs.each_with_object({}) {|(k, v), h|
147
+ h[k == rel_attr ? cat_attr : k] = v
148
+ }
149
+
150
+ pc_name = "pc_#{name}".to_sym
151
+ gen_mcfly_lookup(pc_name, pc_attrs, options)
152
+
153
+ lpi = attrs.keys.index rel_attr
154
+
155
+ raise "should not include #{cat_attr}" if
156
+ attrs.member?(cat_attr)
157
+
158
+ raise "need #{rel_attr} argument" unless lpi
159
+
160
+ delorean_fn(name, sig: attrs.length+1) do |ts, *args|
161
+ # Example: rel is a Gemini::SecurityInstrument instance.
162
+ rel = args[lpi]
163
+ raise "#{rel_attr} can't be nil" unless rel
164
+
165
+ # Assumes there's a mcfly :lookup function on
166
+ # cat_assoc_klass.
167
+ categorizing_obj = cat_assoc_klass.lookup(ts, rel)
168
+ raise "no categorization #{cat_assoc_klass} for #{rel}" unless
169
+ categorizing_obj
170
+
171
+ pc = categorizing_obj.send(cat_attr)
172
+ raise ("#{categorizing_obj} must have assoc." +
173
+ " #{cat_attr}/#{rel.inspect}") unless pc
174
+
175
+ args[lpi] = pc
176
+ self.send(pc_name, ts, *args)
177
+ end
178
+ end
179
+
180
+ end
181
+ end
182
+ end
183
+
184
+ module Mcfly::Controller
185
+ # define mcfly user to be Flowscape's current_user.
186
+ def user_for_mcfly
187
+ find_current_user rescue nil
188
+ end
189
+ end