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,150 @@
1
+ require 'base64'
2
+ require 'zlib'
3
+ require 'csv'
4
+ require 'marty/data_conversion'
5
+
6
+ class Marty::DataExporter
7
+ # given an array of hashes, return set of all keys
8
+ def self.hash_array_keys(hl)
9
+ hl.each_with_object(Set.new) { |h, keys| keys.merge(h.keys) }
10
+ end
11
+
12
+ def self.hash_array_merge(hl, transpose)
13
+ # given a list of hashes hl, generates a merged hash. The
14
+ # resulting hash contains a superset of all the hash keys. The
15
+ # values are corresponding values from each hash in hl.
16
+ # e.g. the following
17
+ #
18
+ # [{"a"=>1, "b"=>2}, {"a"=>11, "c"=>33}, {"a"=>1111, "b"=>222, "c"=>333}]
19
+ #
20
+ # maps to ...
21
+ #
22
+ # [["a", "b", "c"], [1, 2, nil], [11, nil, 33], [1111, 222, 333]]
23
+
24
+ keys = hash_array_keys(hl)
25
+
26
+ return keys.each_with_object({}) { |k, rh|
27
+ rh[k] = hl.map { |h| h[k] }
28
+ } if transpose
29
+
30
+ [keys.to_a] + hl.map {|h| keys.map {|k| h[k]}}
31
+ end
32
+
33
+ def self.encode_json(s)
34
+ Base64.strict_encode64 Zlib.deflate(s)
35
+ end
36
+
37
+ def self.decode_json(s)
38
+ Zlib.inflate Base64.strict_decode64(s)
39
+ end
40
+
41
+ def self.to_csv(obj, config=nil)
42
+ obj = [obj] unless obj.respond_to? :map
43
+
44
+ config ||= {}
45
+
46
+ # if all array items are hashes, we merge them
47
+ obj = hash_array_merge(obj, config["transpose"]) if
48
+ obj.is_a?(Array) && obj.map {|x| x.is_a? Hash}.all?
49
+
50
+ # symbolize config keys as expected by CSV.generate
51
+ conf = config.each_with_object({}) { |(k,v), h|
52
+ h[k.to_sym] = v unless k.to_s == "transpose"
53
+ }
54
+
55
+ # FIXME: very hacky to default row_sep to CRLF
56
+ conf[:row_sep] ||= "\r\n"
57
+
58
+ # FIXME: the following is ridiculously complex. We have different
59
+ # data paths for hashes and arrays. Also, arrays can turn into
60
+ # hashes is all their items are hashes! We map to complex objects
61
+ # to JSON when inside hashes, but not arrays. Really need to
62
+ # rethink this. Probably should have separate functions for
63
+ # to_csv for hash and arrays.
64
+
65
+ return CSV.generate(conf) do |csv|
66
+ obj.each do |x|
67
+ csv << x.flatten(1).map(&:to_s)
68
+ end
69
+ end if obj.is_a?(Hash)
70
+
71
+ CSV.generate(conf) do |csv|
72
+ obj.each do |x|
73
+ x = [x] unless x.respond_to? :map
74
+ csv << x.map { |v|
75
+ v.is_a?(Array) || v.is_a?(Hash) ? encode_json(v.to_json) : v.to_s
76
+ }
77
+ end
78
+ end
79
+ end
80
+
81
+ def self.export_attrs(klass, obj, attrs=nil)
82
+ col_types = Marty::DataConversion.col_types(klass)
83
+
84
+ (attrs || col_types.keys).map do
85
+ |c|
86
+
87
+ v = obj.send(c.to_sym)
88
+
89
+ c = c.to_s
90
+ type = col_types[c]
91
+
92
+ # return [value] if not assoc or nil
93
+ next [v] if v.nil? || !type.is_a?(Hash)
94
+
95
+ assoc_keys = type[:assoc_keys]
96
+ assoc_class = type[:assoc_class]
97
+ assoc_obj = assoc_class.find(v)
98
+
99
+ # FIXME: this recursion will fail if a reference which then
100
+ # makes sub-references is nil. To handle this, we'd need to
101
+ # create the export structure first.
102
+ export_attrs(assoc_class, assoc_obj, assoc_keys).flatten(1)
103
+ end
104
+ end
105
+
106
+ def self.export_headers(klass, attrs=nil)
107
+ col_types = Marty::DataConversion.col_types(klass)
108
+
109
+ (attrs || col_types.keys).map do
110
+ |c|
111
+
112
+ c = c.to_s
113
+ type = col_types[c]
114
+
115
+ next c unless type.is_a?(Hash)
116
+
117
+ # remove _id
118
+ c = c[0..-4]
119
+
120
+ assoc_keys = type[:assoc_keys]
121
+
122
+ # if association has a single key, just use col name
123
+ next c if assoc_keys.length == 1
124
+
125
+ assoc_class = type[:assoc_class]
126
+
127
+ export_headers(assoc_class, assoc_keys).map {|k| "#{c}__#{k}"}
128
+ end
129
+ end
130
+
131
+ # Given a Mcfly klass, generate an export array. Can potentially
132
+ # use up a lot of memory if the result set is large.
133
+ def self.do_export(ts, klass, sort_field=nil)
134
+ query = klass
135
+
136
+ if Mcfly.has_mcfly?(klass)
137
+ ts = Mcfly.normalize_infinity(ts)
138
+ query = query.where("obsoleted_dt >= ? AND created_dt < ?", ts, ts)
139
+ end
140
+
141
+ do_export_query_result(klass, query.order(sort_field || :id))
142
+ end
143
+
144
+ def self.do_export_query_result(klass, qres)
145
+ # strip _id from assoc fields
146
+ header = [ export_headers(klass).flatten ]
147
+
148
+ header + qres.map {|obj| export_attrs(klass, obj).flatten(1)}
149
+ end
150
+ end
@@ -0,0 +1,137 @@
1
+ require 'base64'
2
+ require 'zlib'
3
+
4
+ class Marty::DataExporter
5
+ # given an array of hashes, return set of all keys
6
+ def self.hash_array_keys(hl)
7
+ hl.each_with_object(Set.new) { |h, keys| keys.merge(h.keys) }
8
+ end
9
+
10
+ def self.hash_array_merge(hl, transpose)
11
+ # given a list of hashes hl, generates a merged hash. The
12
+ # resulting hash contains a superset of all the hash keys. The
13
+ # values are corresponding values from each hash in hl.
14
+ keys = hash_array_keys(hl)
15
+
16
+ if transpose
17
+ keys.each_with_object({}) { |k, rh|
18
+ rh[k] = hl.map { |h| h[k] }
19
+ }
20
+ else
21
+ [keys.to_a] + hl.map {|h| keys.map {|k| h[k]}}
22
+ end
23
+ end
24
+
25
+ def self.encode_json(s)
26
+ Base64.strict_encode64 Zlib.deflate(s)
27
+ end
28
+
29
+ def self.decode_json(s)
30
+ Zlib.inflate Base64.strict_decode64(s)
31
+ end
32
+
33
+ def self.to_csv(obj, config=nil)
34
+ obj = [obj] unless obj.respond_to? :map
35
+
36
+ config ||= {}
37
+
38
+ # if all array items are hashes, we merge them
39
+ obj = hash_array_merge(obj, config["transpose"]) if
40
+ obj.is_a?(Array) && obj.map {|x| x.is_a? Hash}.all?
41
+
42
+ # symbolize config keys as expected by CSV.generate
43
+ conf = config.each_with_object({}) { |(k,v), h|
44
+ h[k.to_sym] = v unless k.to_s == "transpose"
45
+ }
46
+
47
+ # FIXME: very hacky to default row_sep to CRLF
48
+ conf[:row_sep] ||= "\r\n"
49
+
50
+ # FIXME: the following is ridiculously complex. We have different
51
+ # data paths for hashes and arrays. Also, arrays can turn into
52
+ # hashes is all their items are hashes! We map to complex objects
53
+ # to JSON when inside hashes, but not arrays. Really need to
54
+ # rethink this. Probably should have separate functions for
55
+ # to_csv for hash and arrays.
56
+
57
+ if obj.is_a? Hash
58
+ csv_string = CSV.generate(conf) do |csv|
59
+ obj.each do |x|
60
+ csv << x.flatten(1).map(&:to_s)
61
+ end
62
+ end
63
+ else
64
+ csv_string = CSV.generate(conf) do |csv|
65
+ obj.each do |x|
66
+ x = [x] unless x.respond_to? :map
67
+ csv << x.map { |v|
68
+ v.is_a?(Array) || v.is_a?(Hash) ? encode_json(v.to_json) : v.to_s
69
+ }
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ def self.class_info(klass)
76
+ @class_info ||= {}
77
+
78
+ return @class_info[klass] if @class_info[klass]
79
+
80
+ associations = klass.reflect_on_all_associations.map(&:name)
81
+
82
+ @class_info[klass] = {
83
+ cols:
84
+ klass.columns.map(&:name) - Marty::DataRowProcessor::MCFLY_COLUMNS.to_a,
85
+
86
+ assoc:
87
+ associations.each_with_object({}) { |a, h|
88
+ h["#{a}_id"] = Marty::DataRowProcessor.assoc_info(klass, a)
89
+ },
90
+ }
91
+ end
92
+
93
+ def self.export_attr(obj, c, info)
94
+ v = obj.send(c.to_sym)
95
+ assoc_info = info[:assoc][c] unless v.nil?
96
+ return [v] unless assoc_info
97
+
98
+ assoc_obj = assoc_info[:assoc_class].find(v)
99
+
100
+ assoc_info[:assoc_keys].map {|k| assoc_obj.send(k.to_sym)}
101
+ end
102
+
103
+ def self.export_header_attr(c, info)
104
+ assoc_info = info[:assoc][c]
105
+ return c unless assoc_info
106
+
107
+ # remove _id
108
+ c = c[0..-4]
109
+
110
+ assoc_keys = assoc_info[:assoc_keys]
111
+
112
+ # FIXME: this doesn't work if k is also an association. Needs to
113
+ # be recursive.
114
+ assoc_keys.length > 1 ? assoc_keys.map {|k| "#{c}__#{k}"} : c
115
+ end
116
+
117
+ # Given a Mcfly klass, generate an export array. Can potentially
118
+ # use up a lot of memory if the result set is large.
119
+ def self.do_export(ts, klass, sort_field=nil)
120
+ info = class_info(klass)
121
+
122
+ # strip _id from assoc fields
123
+ header = [ info[:cols].map {|c| export_header_attr(c, info)}.flatten(1) ]
124
+
125
+ query = klass
126
+
127
+ # is it Mcfly?
128
+ if (klass.const_get(:MCFLY_UNIQUENESS) rescue nil)
129
+ ts = Mcfly.normalize_infinity(ts)
130
+ query = query.where("obsoleted_dt >= ? AND created_dt < ?", ts, ts)
131
+ end
132
+
133
+ header + query.
134
+ order(sort_field || :id).
135
+ map {|obj| info[:cols].map {|c| export_attr(obj, c, info)}.flatten(1)}
136
+ end
137
+ end
@@ -0,0 +1,122 @@
1
+ require 'csv'
2
+ require 'marty/data_conversion'
3
+
4
+ module Marty
5
+ class DataImporterError < StandardError
6
+ attr_reader :lines
7
+
8
+ def initialize(message, lines)
9
+ msg = lines && lines.respond_to?(:join) ?
10
+ "#{message} - lines: #{lines.join(',')}" : message
11
+
12
+ super(msg)
13
+ @lines = lines
14
+ end
15
+ end
16
+
17
+ class DataImporter
18
+ # perform cleaning and do_import and summarize its results
19
+ def self.do_import_summary(klass,
20
+ data,
21
+ dt = 'infinity',
22
+ cleaner_function = nil,
23
+ validation_function = nil,
24
+ col_sep = "\t",
25
+ allow_dups = false,
26
+ preprocess_function = nil
27
+ )
28
+
29
+ recs = self.do_import(klass,
30
+ data,
31
+ dt,
32
+ cleaner_function,
33
+ validation_function,
34
+ col_sep,
35
+ allow_dups,
36
+ preprocess_function,
37
+ )
38
+
39
+ recs.each_with_object(Hash.new(0)) {|(op, id), h|
40
+ h[op] += 1
41
+ }
42
+ end
43
+
44
+ # Given a Mcfly klass and CSV data, import data into the database
45
+ # and report on affected rows. Result is an array of tuples.
46
+ # Each tuple is associated with one data row and looks like [tag,
47
+ # id]. Tag is one of :same, :update, :create and "id" is the id
48
+ # of the affected row.
49
+ def self.do_import(klass,
50
+ data,
51
+ dt = 'infinity',
52
+ cleaner_function = nil,
53
+ validation_function = nil,
54
+ col_sep = "\t",
55
+ allow_dups = false,
56
+ preprocess_function = nil
57
+ )
58
+
59
+ parsed = data.is_a?(Array) ? data :
60
+ CSV.new(data, headers: true, col_sep: col_sep)
61
+
62
+ # run preprocessor
63
+ parsed = klass.send(preprocess_function.to_sym, parsed) if
64
+ preprocess_function
65
+
66
+ klass.transaction do
67
+ cleaner_ids = cleaner_function ? klass.send(cleaner_function.to_sym) :
68
+ []
69
+
70
+ raise "bad cleaner function result" unless
71
+ cleaner_ids.all? {|id| id.is_a?(Fixnum) }
72
+
73
+ eline = 0
74
+
75
+ begin
76
+ res = parsed.each_with_index.map do
77
+ |row, line|
78
+ eline = line
79
+
80
+ # skip lines which are all nil
81
+ next :blank if row.to_hash.values.none?
82
+
83
+ Marty::DataConversion.create_or_update(klass, row, dt)
84
+ end
85
+ rescue => exc
86
+ # to find problems with the importer, comment out the rescue block
87
+ raise Marty::DataImporterError.new(exc.to_s, [eline])
88
+ end
89
+
90
+ ids = {}
91
+
92
+ # raise an error if record referenced more than once.
93
+ res.each_with_index do
94
+ |(op, id), line|
95
+ raise Marty::DataImporterError.
96
+ new("record referenced more than once", [ids[id], line]) if
97
+ op != :blank && ids.member?(id) && !allow_dups
98
+
99
+ ids[id] = line
100
+ end
101
+
102
+ begin
103
+ # Validate affected rows if necessary
104
+ klass.send(validation_function.to_sym, ids.keys) if
105
+ validation_function
106
+ rescue => exc
107
+ raise Marty::DataImporterError.new(exc.to_s, [])
108
+ end
109
+
110
+ remainder_ids = cleaner_ids - ids.keys
111
+
112
+ raise Marty::DataImporterError.
113
+ new("Missing import data. " +
114
+ "Please provide header line and at least one data line.", [1]) if
115
+ ids.keys.compact.count == 0
116
+
117
+ klass.delete(remainder_ids)
118
+ res + remainder_ids.map {|id| [:clean, id]}
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,114 @@
1
+ module Marty
2
+ class DataImporterError < StandardError
3
+ attr_reader :lines
4
+
5
+ def initialize(message, lines)
6
+ super(message)
7
+ @lines = lines
8
+ end
9
+ end
10
+
11
+ class DataImporter
12
+ # perform cleaning and do_import and summarize its results
13
+ def self.do_import_summary(klass,
14
+ data,
15
+ dt='infinity',
16
+ cleaner_function=nil,
17
+ validation_function=nil,
18
+ col_sep="\t",
19
+ allow_dups=false
20
+ )
21
+
22
+ recs = self.do_import(klass,
23
+ data,
24
+ dt,
25
+ cleaner_function,
26
+ validation_function,
27
+ col_sep,
28
+ allow_dups,
29
+ )
30
+
31
+ recs.each_with_object(Hash.new(0)) {|(op, id), h|
32
+ h[op] += 1
33
+ }
34
+ end
35
+
36
+ # Given a Mcfly klass and CSV data, import data into the database
37
+ # and report on affected rows. Result is an array of tuples.
38
+ # Each tuple is associated with one data row and looks like [tag,
39
+ # id]. Tag is one of :same, :update, :create and "id" is the id
40
+ # of the affected row.
41
+ def self.do_import(klass,
42
+ data,
43
+ dt='infinity',
44
+ cleaner_function=nil,
45
+ validation_function=nil,
46
+ col_sep="\t",
47
+ allow_dups=false
48
+ )
49
+
50
+ parsed = data.is_a?(Array) ? data :
51
+ CSV.new(data, headers: true, col_sep: col_sep)
52
+
53
+ klass.transaction do
54
+ cleaner_ids = cleaner_function ? klass.send(cleaner_function.to_sym) :
55
+ []
56
+
57
+ raise "bad cleaner function result" unless
58
+ cleaner_ids.all? {|id| id.is_a?(Fixnum) }
59
+
60
+ row_proc = nil
61
+ eline = 0
62
+
63
+ begin
64
+ res = parsed.each_with_index.map { |row, line|
65
+ eline = line
66
+
67
+ row_proc ||= Marty::DataRowProcessor.
68
+ new(klass,
69
+ row.respond_to?(:headers) ? row.headers : row.keys,
70
+ dt,
71
+ )
72
+ # skip lines which are all nil
73
+ next :blank if row.to_hash.values.none?
74
+
75
+ row_proc.create_or_update(row)
76
+ }
77
+ rescue => exc
78
+ # to find problems with the importer, comment out the rescue block
79
+ raise Marty::DataImporterError.new(exc.to_s, [eline])
80
+ end
81
+
82
+ ids = {}
83
+
84
+ # raise an error if record referenced more than once.
85
+ res.each_with_index do
86
+ |(op, id), line|
87
+ raise Marty::DataImporterError.
88
+ new("record referenced more than once", [ids[id], line]) if
89
+ op != :blank && ids.member?(id) && !allow_dups
90
+
91
+ ids[id] = line
92
+ end
93
+
94
+ begin
95
+ # Validate affected rows if necessary
96
+ klass.send(validation_function.to_sym, ids.keys) if
97
+ validation_function
98
+ rescue => exc
99
+ raise Marty::DataImporterError.new(exc.to_s, [])
100
+ end
101
+
102
+ remainder_ids = cleaner_ids - ids.keys
103
+
104
+ raise Marty::DataImporterError.
105
+ new("Missing import data. " +
106
+ "Please provide header line and at least one data line.", [1]) if
107
+ ids.keys.compact.count == 0
108
+
109
+ klass.delete(remainder_ids)
110
+ res + remainder_ids.map {|id| [:clean, id]}
111
+ end
112
+ end
113
+ end
114
+ end