csvpath 0.0.533__tar.gz → 0.0.534__tar.gz

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 (301) hide show
  1. {csvpath-0.0.533 → csvpath-0.0.534}/PKG-INFO +5 -2
  2. {csvpath-0.0.533 → csvpath-0.0.534/assets}/config/config.ini +13 -2
  3. csvpath-0.0.534/assets/config/jenkins-local-filesystem-mysql.ini +138 -0
  4. {csvpath-0.0.533 → csvpath-0.0.534}/assets/config/jenkins-local-gcs.ini +1 -1
  5. {csvpath-0.0.533/assets → csvpath-0.0.534}/config/config.ini +13 -2
  6. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/files/file_manager.py +3 -0
  7. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/files/file_metadata.py +1 -0
  8. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/files/file_registrar.py +7 -1
  9. csvpath-0.0.534/csvpath/managers/integrations/sql/engine.py +24 -0
  10. csvpath-0.0.534/csvpath/managers/integrations/sql/sql_file_listener.py +85 -0
  11. csvpath-0.0.534/csvpath/managers/integrations/sql/sql_listener.py +29 -0
  12. csvpath-0.0.534/csvpath/managers/integrations/sql/sql_paths_listener.py +78 -0
  13. csvpath-0.0.534/csvpath/managers/integrations/sql/sql_result_listener.py +100 -0
  14. csvpath-0.0.534/csvpath/managers/integrations/sql/sql_results_listener.py +115 -0
  15. csvpath-0.0.534/csvpath/managers/integrations/sql/tables.py +185 -0
  16. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/sqlite/sqlite_result_listener.py +1 -1
  17. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/metadata.py +7 -4
  18. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/results/result_serializer.py +1 -1
  19. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/results/results_metadata.py +1 -0
  20. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/config.py +13 -2
  21. {csvpath-0.0.533 → csvpath-0.0.534}/pyproject.toml +5 -2
  22. {csvpath-0.0.533 → csvpath-0.0.534}/LICENSE +0 -0
  23. {csvpath-0.0.533 → csvpath-0.0.534}/README.md +0 -0
  24. {csvpath-0.0.533 → csvpath-0.0.534}/assets/config/function.imports +0 -0
  25. {csvpath-0.0.533 → csvpath-0.0.534}/assets/config/jenkins-local-azure.ini +0 -0
  26. {csvpath-0.0.533 → csvpath-0.0.534}/assets/config/jenkins-local-filesystem.ini +0 -0
  27. {csvpath-0.0.533 → csvpath-0.0.534}/assets/config/jenkins-local-sftp.ini +0 -0
  28. {csvpath-0.0.533 → csvpath-0.0.534}/assets/config/jenkins-s3.ini +0 -0
  29. {csvpath-0.0.533 → csvpath-0.0.534}/assets/config/jenkins-windows-azure.ini +0 -0
  30. {csvpath-0.0.533 → csvpath-0.0.534}/assets/config/jenkins-windows-local.ini +0 -0
  31. {csvpath-0.0.533 → csvpath-0.0.534}/assets/config/jenkins-windows-sftp.ini +0 -0
  32. {csvpath-0.0.533 → csvpath-0.0.534}/assets/config/local-localhost-sftp.ini +0 -0
  33. {csvpath-0.0.533 → csvpath-0.0.534}/assets/integrations/sftpplus/handle_auto_arrival.bat +0 -0
  34. {csvpath-0.0.533 → csvpath-0.0.534}/assets/integrations/sftpplus/handle_auto_arrival.py +0 -0
  35. {csvpath-0.0.533 → csvpath-0.0.534}/assets/integrations/sftpplus/handle_auto_arrival.sh +0 -0
  36. {csvpath-0.0.533 → csvpath-0.0.534}/assets/integrations/sftpplus/handle_mailbox_arrival.bat +0 -0
  37. {csvpath-0.0.533 → csvpath-0.0.534}/assets/integrations/sftpplus/handle_mailbox_arrival.py +0 -0
  38. {csvpath-0.0.533 → csvpath-0.0.534}/assets/integrations/sftpplus/handle_mailbox_arrival.sh +0 -0
  39. {csvpath-0.0.533 → csvpath-0.0.534}/assets/integrations/sqlite/csvpath +0 -0
  40. {csvpath-0.0.533 → csvpath-0.0.534}/assets/integrations/sqlite/schema.sql +0 -0
  41. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/__init__.py +0 -0
  42. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/cli/__init__.py +0 -0
  43. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/cli/asker.py +0 -0
  44. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/cli/cli.py +0 -0
  45. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/cli/const.py +0 -0
  46. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/cli/debug_config.py +0 -0
  47. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/cli/drill_down.py +0 -0
  48. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/cli/function_describer.py +0 -0
  49. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/cli/function_lister.py +0 -0
  50. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/cli/selecter.py +0 -0
  51. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/csvpath.py +0 -0
  52. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/csvpaths.py +0 -0
  53. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/__init__.py +0 -0
  54. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/errors/error.py +0 -0
  55. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/errors/error_collector.py +0 -0
  56. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/errors/error_comms.py +0 -0
  57. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/errors/error_manager.py +0 -0
  58. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/files/files_listener.py +0 -0
  59. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/files/lines_and_headers_cacher.py +0 -0
  60. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/ckan/ckan.py +0 -0
  61. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/ckan/ckan_listener.py +0 -0
  62. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/ckan/datafile.py +0 -0
  63. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/ckan/dataset.py +0 -0
  64. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/ol/event.py +0 -0
  65. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/ol/event_result.py +0 -0
  66. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/ol/file_listener_ol.py +0 -0
  67. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/ol/job.py +0 -0
  68. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/ol/ol_listener.py +0 -0
  69. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/ol/paths_listener_ol.py +0 -0
  70. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/ol/result_listener_ol.py +0 -0
  71. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/ol/results_listener_ol.py +0 -0
  72. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/ol/run.py +0 -0
  73. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/ol/run_listener_ol.py +0 -0
  74. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/ol/run_state.py +0 -0
  75. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/ol/sender.py +0 -0
  76. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/otlp/error_metrics.py +0 -0
  77. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/otlp/metrics.py +0 -0
  78. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/otlp/otlp_error_listener.py +0 -0
  79. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/otlp/otlp_listener.py +0 -0
  80. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/otlp/otlp_result_listener.py +0 -0
  81. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/otlp/otlp_results_listener.py +0 -0
  82. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/sftp/sftp_sender.py +0 -0
  83. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/sftpplus/arrival_handler.py +0 -0
  84. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/sftpplus/rpc.py +0 -0
  85. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/sftpplus/sftpplus_listener.py +0 -0
  86. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/sftpplus/transfer_creator.py +0 -0
  87. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/sftpplus/transfers.py +0 -0
  88. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/slack/event.py +0 -0
  89. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/slack/sender.py +0 -0
  90. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/sqlite/schema.sql +0 -0
  91. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/integrations/sqlite/sqlite_results_listener.py +0 -0
  92. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/listener.py +0 -0
  93. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/paths/paths_listener.py +0 -0
  94. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/paths/paths_manager.py +0 -0
  95. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/paths/paths_metadata.py +0 -0
  96. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/paths/paths_registrar.py +0 -0
  97. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/registrar.py +0 -0
  98. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/results/readers/file_errors_reader.py +0 -0
  99. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/results/readers/file_lines_reader.py +0 -0
  100. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/results/readers/file_printouts_reader.py +0 -0
  101. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/results/readers/file_unmatched_reader.py +0 -0
  102. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/results/readers/readers.py +0 -0
  103. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/results/result.py +0 -0
  104. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/results/result_file_reader.py +0 -0
  105. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/results/result_metadata.py +0 -0
  106. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/results/result_registrar.py +0 -0
  107. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/results/results_manager.py +0 -0
  108. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/results/results_registrar.py +0 -0
  109. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/run/run_listener_stdout.py +0 -0
  110. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/run/run_metadata.py +0 -0
  111. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/managers/run/run_registrar.py +0 -0
  112. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/__init__.py +0 -0
  113. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/__init__.py +0 -0
  114. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/args.py +0 -0
  115. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/args_helper.py +0 -0
  116. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/boolean/all.py +0 -0
  117. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/boolean/andf.py +0 -0
  118. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/boolean/any.py +0 -0
  119. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/boolean/between.py +0 -0
  120. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/boolean/empty.py +0 -0
  121. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/boolean/exists.py +0 -0
  122. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/boolean/inf.py +0 -0
  123. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/boolean/no.py +0 -0
  124. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/boolean/notf.py +0 -0
  125. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/boolean/orf.py +0 -0
  126. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/boolean/yes.py +0 -0
  127. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/counting/count.py +0 -0
  128. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/counting/count_bytes.py +0 -0
  129. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/counting/count_headers.py +0 -0
  130. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/counting/count_lines.py +0 -0
  131. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/counting/count_scans.py +0 -0
  132. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/counting/counter.py +0 -0
  133. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/counting/every.py +0 -0
  134. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/counting/has_matches.py +0 -0
  135. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/counting/increment.py +0 -0
  136. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/counting/tally.py +0 -0
  137. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/counting/total_lines.py +0 -0
  138. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/dates/now.py +0 -0
  139. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/function.py +0 -0
  140. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/function_factory.py +0 -0
  141. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/function_finder.py +0 -0
  142. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/function_focus.py +0 -0
  143. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/headers/append.py +0 -0
  144. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/headers/collect.py +0 -0
  145. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/headers/empty_stack.py +0 -0
  146. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/headers/end.py +0 -0
  147. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/headers/header_name.py +0 -0
  148. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/headers/header_names_mismatch.py +0 -0
  149. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/headers/headers.py +0 -0
  150. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/headers/insert.py +0 -0
  151. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/headers/mismatch.py +0 -0
  152. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/headers/replace.py +0 -0
  153. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/headers/reset_headers.py +0 -0
  154. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/lines/advance.py +0 -0
  155. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/lines/after_blank.py +0 -0
  156. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/lines/dups.py +0 -0
  157. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/lines/first.py +0 -0
  158. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/lines/first_line.py +0 -0
  159. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/lines/last.py +0 -0
  160. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/lines/stop.py +0 -0
  161. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/math/above.py +0 -0
  162. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/math/add.py +0 -0
  163. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/math/divide.py +0 -0
  164. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/math/equals.py +0 -0
  165. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/math/intf.py +0 -0
  166. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/math/mod.py +0 -0
  167. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/math/multiply.py +0 -0
  168. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/math/odd.py +0 -0
  169. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/math/round.py +0 -0
  170. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/math/subtotal.py +0 -0
  171. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/math/subtract.py +0 -0
  172. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/math/sum.py +0 -0
  173. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/misc/fingerprint.py +0 -0
  174. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/misc/importf.py +0 -0
  175. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/misc/random.py +0 -0
  176. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/print/jinjaf.py +0 -0
  177. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/print/print_line.py +0 -0
  178. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/print/print_queue.py +0 -0
  179. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/print/printf.py +0 -0
  180. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/print/table.py +0 -0
  181. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/stats/minf.py +0 -0
  182. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/stats/percent.py +0 -0
  183. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/stats/percent_unique.py +0 -0
  184. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/stats/stdev.py +0 -0
  185. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/strings/alter.py +0 -0
  186. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/strings/caps.py +0 -0
  187. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/strings/concat.py +0 -0
  188. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/strings/contains.py +0 -0
  189. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/strings/length.py +0 -0
  190. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/strings/lower.py +0 -0
  191. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/strings/metaphone.py +0 -0
  192. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/strings/regex.py +0 -0
  193. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/strings/starts_with.py +0 -0
  194. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/strings/strip.py +0 -0
  195. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/strings/substring.py +0 -0
  196. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/strings/upper.py +0 -0
  197. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/testing/debug.py +0 -0
  198. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/types/__init__.py +0 -0
  199. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/types/boolean.py +0 -0
  200. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/types/datef.py +0 -0
  201. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/types/decimal.py +0 -0
  202. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/types/email.py +0 -0
  203. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/types/nonef.py +0 -0
  204. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/types/string.py +0 -0
  205. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/types/type.py +0 -0
  206. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/types/url.py +0 -0
  207. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/validity/fail.py +0 -0
  208. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/validity/failed.py +0 -0
  209. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/validity/line.py +0 -0
  210. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/variables/get.py +0 -0
  211. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/variables/pushpop.py +0 -0
  212. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/variables/put.py +0 -0
  213. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/variables/track.py +0 -0
  214. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/functions/variables/variables.py +0 -0
  215. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/lark_parser.py +0 -0
  216. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/lark_transformer.py +0 -0
  217. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/matcher.py +0 -0
  218. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/productions/__init__.py +0 -0
  219. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/productions/equality.py +0 -0
  220. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/productions/expression.py +0 -0
  221. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/productions/header.py +0 -0
  222. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/productions/matchable.py +0 -0
  223. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/productions/qualified.py +0 -0
  224. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/productions/reference.py +0 -0
  225. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/productions/term.py +0 -0
  226. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/productions/variable.py +0 -0
  227. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/util/exceptions.py +0 -0
  228. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/util/expression_encoder.py +0 -0
  229. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/util/expression_utility.py +0 -0
  230. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/util/lark_print_parser.py +0 -0
  231. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/util/print_parser.py +0 -0
  232. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/matching/util/runtime_data_collector.py +0 -0
  233. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/modes/error_mode.py +0 -0
  234. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/modes/explain_mode.py +0 -0
  235. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/modes/files_mode.py +0 -0
  236. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/modes/logic_mode.py +0 -0
  237. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/modes/mode_controller.py +0 -0
  238. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/modes/print_mode.py +0 -0
  239. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/modes/return_mode.py +0 -0
  240. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/modes/run_mode.py +0 -0
  241. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/modes/source_mode.py +0 -0
  242. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/modes/transfer_mode.py +0 -0
  243. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/modes/unmatched_mode.py +0 -0
  244. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/modes/validation_mode.py +0 -0
  245. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/scanning/__init__.py +0 -0
  246. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/scanning/exceptions.py +0 -0
  247. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/scanning/parser.out +0 -0
  248. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/scanning/parsetab.py +0 -0
  249. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/scanning/scanner.py +0 -0
  250. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/scanning/scanning_lexer.py +0 -0
  251. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/azure/azure_data_reader.py +0 -0
  252. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/azure/azure_data_writer.py +0 -0
  253. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/azure/azure_fingerprinter.py +0 -0
  254. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/azure/azure_nos.py +0 -0
  255. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/azure/azure_utils.py +0 -0
  256. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/azure/azure_xlsx_data_reader.py +0 -0
  257. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/box.py +0 -0
  258. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/cache.py +0 -0
  259. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/caser.py +0 -0
  260. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/class_loader.py +0 -0
  261. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/code.py +0 -0
  262. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/config_exception.py +0 -0
  263. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/exceptions.py +0 -0
  264. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/file_info.py +0 -0
  265. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/file_readers.py +0 -0
  266. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/file_writers.py +0 -0
  267. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/gcs/gcs_data_reader.py +0 -0
  268. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/gcs/gcs_data_writer.py +0 -0
  269. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/gcs/gcs_fingerprinter.py +0 -0
  270. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/gcs/gcs_nos.py +0 -0
  271. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/gcs/gcs_utils.py +0 -0
  272. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/gcs/gcs_xlsx_data_reader.py +0 -0
  273. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/hasher.py +0 -0
  274. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/http/http_data_reader.py +0 -0
  275. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/intermediary.py +0 -0
  276. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/last_line_stats.py +0 -0
  277. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/line_counter.py +0 -0
  278. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/line_monitor.py +0 -0
  279. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/line_spooler.py +0 -0
  280. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/log_utility.py +0 -0
  281. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/metadata_parser.py +0 -0
  282. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/nos.py +0 -0
  283. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/pandas_data_reader.py +0 -0
  284. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/path_util.py +0 -0
  285. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/printer.py +0 -0
  286. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/reference_finder.py +0 -0
  287. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/reference_parser.py +0 -0
  288. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/s3/s3_data_reader.py +0 -0
  289. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/s3/s3_data_writer.py +0 -0
  290. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/s3/s3_fingerprinter.py +0 -0
  291. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/s3/s3_nos.py +0 -0
  292. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/s3/s3_utils.py +0 -0
  293. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/s3/s3_xlsx_data_reader.py +0 -0
  294. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/sftp/sftp_config.py +0 -0
  295. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/sftp/sftp_data_reader.py +0 -0
  296. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/sftp/sftp_data_writer.py +0 -0
  297. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/sftp/sftp_fingerprinter.py +0 -0
  298. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/sftp/sftp_nos.py +0 -0
  299. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/sftp/sftp_xlsx_data_reader.py +0 -0
  300. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/sqliter.py +0 -0
  301. {csvpath-0.0.533 → csvpath-0.0.534}/csvpath/util/var_utility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: csvpath
3
- Version: 0.0.533
3
+ Version: 0.0.534
4
4
  Summary: A data preboarding framework for managing and validating CSV, Excel, and other tabular data files using a Collect, Store, Validate, Publish pattern to create a trusted publisher for downstream data consumers.
5
5
  Author: David Kershaw
6
6
  Author-email: dk107dk@hotmail.com
@@ -27,22 +27,25 @@ Requires-Dist: ckanapi (>=4.8,<5.0)
27
27
  Requires-Dist: email-validator (>=2.2.0,<3.0.0)
28
28
  Requires-Dist: google-cloud-storage (>=3.1.0,<4.0.0)
29
29
  Requires-Dist: inflect (>=7.4.0,<8.0.0)
30
- Requires-Dist: jinja2 (>=3.1.4,<4.0.0)
30
+ Requires-Dist: jinja2 (>=3.1.6,<4.0.0)
31
31
  Requires-Dist: lark (>=1.2.2,<2.0.0)
32
32
  Requires-Dist: marquez-python (>=0.50.0,<0.51.0)
33
33
  Requires-Dist: metaphone (>=0.6,<0.7)
34
+ Requires-Dist: mysqlclient (>=2.2.7,<3.0.0)
34
35
  Requires-Dist: openlineage-python (>=1.25.0,<2.0.0)
35
36
  Requires-Dist: opentelemetry-distro[otlp] (>=0.50b0,<0.51)
36
37
  Requires-Dist: paramiko (>=3.5.0,<4.0.0)
37
38
  Requires-Dist: pdoc (>=15.0.1,<16.0.0)
38
39
  Requires-Dist: ply (>=3.11,<4.0)
39
40
  Requires-Dist: prompt-toolkit (>=3.0.50,<4.0.0)
41
+ Requires-Dist: psycopg2-binary (>=2.9.10,<3.0.0)
40
42
  Requires-Dist: pylightxl (>=1.61,<2.0)
41
43
  Requires-Dist: pytest (>=8.3.3,<9.0.0)
42
44
  Requires-Dist: python-dateutil (>=2.9.0.post0,<3.0.0)
43
45
  Requires-Dist: pytz (>=2024.2,<2025.0)
44
46
  Requires-Dist: requests (>=2.32.3,<3.0.0)
45
47
  Requires-Dist: smart-open (>=7.1.0,<8.0.0)
48
+ Requires-Dist: sqlalchemy (>=2.0.38,<3.0.0)
46
49
  Requires-Dist: tabulate (>=0.9.0,<0.10.0)
47
50
  Requires-Dist: validators (>=0.34.0,<0.35.0)
48
51
  Project-URL: Csvpath.org, https://www.csvpath.org
@@ -33,9 +33,9 @@ archive = archive
33
33
 
34
34
  [inputs]
35
35
  files = inputs/named_files
36
+ csvpaths = inputs/named_paths
36
37
  #csvpaths = s3://csvpath-example-1/inputs/named_paths
37
38
  #files = sftp://172.17.0.3:10022/inputs/named_files
38
-
39
39
  on_unmatched_file_fingerprints = halt
40
40
 
41
41
  #
@@ -46,7 +46,13 @@ on_unmatched_file_fingerprints = halt
46
46
  groups =
47
47
  #slack, marquez, ckan, sftp, sftpplus, otlp, default, sqlite
48
48
 
49
- # add sqlite to capture staging, loads, and results in a local sqlite db
49
+ # add sql to capture staging, loads, and results in mysql, postgres, ms sql server, or sqlite
50
+ sql.file = from csvpath.managers.integrations.sql.sql_file_listener import SqlFileListener
51
+ sql.paths = from csvpath.managers.integrations.sql.sql_paths_listener import SqlPathsListener
52
+ sql.result = from csvpath.managers.integrations.sql.sql_result_listener import SqlResultListener
53
+ sql.results = from csvpath.managers.integrations.sql.sql_results_listener import SqlResultsListener
54
+
55
+ # add sqlite to capture staging, loads, and results in a local sqlite file
50
56
  sqlite.result = from csvpath.managers.integrations.sqlite.sqlite_result_listener import SqliteResultListener
51
57
  sqlite.results = from csvpath.managers.integrations.sqlite.sqlite_results_listener import SqliteResultsListener
52
58
 
@@ -99,6 +105,11 @@ password = tinpenny
99
105
  [sqlite]
100
106
  db = archive/csvpath.db
101
107
 
108
+ [sql]
109
+ # sqlite, mysql, postgres, or sql_server
110
+ dialect = sqlite
111
+ connection_string = sqlite:///archive/csvpath-sqlite.db
112
+
102
113
  [sftpplus]
103
114
  # these are only needed by the csvpath writer
104
115
  mailbox_user = MAILBOX_USER
@@ -0,0 +1,138 @@
1
+ [csvpath_files]
2
+ extensions = txt, csvpath, csvpaths
3
+
4
+ [csv_files]
5
+ extensions = txt, csv, tsv, dat, tab, psv, ssv
6
+
7
+ [errors]
8
+ csvpath = raise, collect, stop, fail, print
9
+ csvpaths = raise, collect
10
+ use_format = full
11
+ pattern = {time}:{file}:{line}:{paths}:{instance}:{chain}: {message}
12
+
13
+ [logging]
14
+ csvpath = debug
15
+ csvpaths = debug
16
+ log_file = logs/csvpath.log
17
+ log_files_to_keep = 100
18
+ log_file_size = 52428800
19
+
20
+ [config]
21
+ path = assets/config/jenkins-local-filesystem.ini
22
+
23
+ [cache]
24
+ path = cache
25
+ use_cache = no
26
+
27
+ [functions]
28
+ imports = config/functions.imports
29
+
30
+ [results]
31
+ archive = archive
32
+
33
+ [inputs]
34
+ files = inputs/named_files
35
+ csvpaths = inputs/named_paths
36
+ on_unmatched_file_fingerprints = halt
37
+
38
+ #
39
+ # integrations activation
40
+ #
41
+
42
+ [listeners]
43
+ groups = sql
44
+ #slack, marquez, ckan, sftp, sftpplus, otlp, default, sqlite
45
+
46
+ sql.file = from csvpath.managers.integrations.sql.sql_file_listener import SqlFileListener
47
+ sql.paths = from csvpath.managers.integrations.sql.sql_paths_listener import SqlPathsListener
48
+ sql.result = from csvpath.managers.integrations.sql.sql_result_listener import SqlResultListener
49
+ sql.results = from csvpath.managers.integrations.sql.sql_results_listener import SqlResultsListener
50
+
51
+ # add sqlite to capture staging, loads, and results in a local sqlite db
52
+ sqlite.result = from csvpath.managers.integrations.sqlite.sqlite_result_listener import SqliteResultListener
53
+ sqlite.results = from csvpath.managers.integrations.sqlite.sqlite_results_listener import SqliteResultsListener
54
+
55
+ # these simple default listeners track all files staged and all paths loaded in
56
+ # central manifests. unlike other manifest writers, if they have multiple
57
+ # concurrent users they have potential a race condition. users that do not
58
+ # share inputs directories do not need to worry about this. you should vet
59
+ # using them against your use case; potential utility vs. the modest but non-0
60
+ # risk of lost updates. they can be disabled with little loss of function.
61
+ # alternatively a database-backed version may be more suitable.
62
+ default.file = from csvpath.managers.files.files_listener import FilesListener
63
+ default.paths = from csvpath.managers.paths.paths_listener import PathsListener
64
+
65
+ # add otlp to support any OpenTelemetry backend
66
+ otlp.result = from csvpath.managers.integrations.otlp.otlp_result_listener import OpenTelemetryResultListener
67
+ otlp.results = from csvpath.managers.integrations.otlp.otlp_results_listener import OpenTelemetryResultsListener
68
+ otlp.errors = from csvpath.managers.integrations.otlp.otlp_error_listener import OpenTelemetryErrorListener
69
+
70
+ # add sftpplus to the list of groups above to automate registration and named-paths group runs on file arrival at an SFTPPlus server
71
+ sftpplus.paths = from csvpath.managers.integrations.sftpplus.sftpplus_listener import SftpPlusListener
72
+
73
+ # add sftp to the list of groups above to push results to an sftp account
74
+ sftp.results = from csvpath.managers.integrations.sftp.sftp_listener import SftpListener
75
+
76
+ # add ckan to the list of groups above for alerts to slack webhooks
77
+ ckan.results = from csvpath.managers.integrations.ckan.ckan_listener import CkanListener
78
+
79
+ #add marquez to the list of groups above for OpenLineage events to a Marquez server
80
+ marquez.file = from csvpath.managers.integrations.ol.file_listener_ol import OpenLineageFileListener
81
+ marquez.paths = from csvpath.managers.integrations.ol.paths_listener_ol import OpenLineagePathsListener
82
+ marquez.result = from csvpath.managers.integrations.ol.result_listener_ol import OpenLineageResultListener
83
+ marquez.results = from csvpath.managers.integrations.ol.results_listener_ol import OpenLineageResultsListener
84
+
85
+ # add slack to the list of groups above for alerts to slack webhooks
86
+ slack.file = from csvpath.managers.integrations.slack.sender import SlackSender
87
+ slack.paths = from csvpath.managers.integrations.slack.sender import SlackSender
88
+ slack.result = from csvpath.managers.integrations.slack.sender import SlackSender
89
+ slack.results = from csvpath.managers.integrations.slack.sender import SlackSender
90
+
91
+ #
92
+ # integrations setup
93
+ #
94
+
95
+ [sftp]
96
+ server = 192.168.67.2
97
+ port = 10022
98
+ username = tinpenny
99
+ password = tinpenny
100
+
101
+ [sql]
102
+ dialect = mysql
103
+ connection_string = mysql://csvpath:hangzhou@127.0.0.1/csvpath
104
+
105
+ [sqlite]
106
+ db = archive/csvpath.db
107
+
108
+ [sftpplus]
109
+ # these are only needed by the csvpath writer
110
+ mailbox_user = MAILBOX_USER
111
+ mailbox_password = MAILBOX_PASSWORD
112
+ server = SFTPPLUS_SERVER
113
+ port = SFTPPLUS_PORT
114
+ # these are only needed on the server
115
+ admin_username = SFTPPLUS_ADMIN_USERNAME
116
+ admin_password = SFTPPLUS_ADMIN_PASSWORD
117
+ api_url = https://localhost:10020/json
118
+ scripts_dir =
119
+ execute_timeout = 300
120
+
121
+ [ckan]
122
+ server = http://localhost:80
123
+ api_token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3akJwc1ZuSkVrZm1aNnBtVTJfTW5CNlJXZ211YjdOOHVXZ1l1cUFDa0Q4IiwiaWF0IjoxNzM0NzE4NDQ3fQ.QXWXoJoSxVES4NwXYBteYUD7enX9D5T2htmETLGFzrs
124
+
125
+ [marquez]
126
+ base_url = http://localhost:5000
127
+ endpoint = api/v1/lineage
128
+ api_key = "none"
129
+ timeout = 5
130
+ verify = False
131
+
132
+ [slack]
133
+ # add your main webhook here. to set webhooks on a csvpath-by-csvpath basis add
134
+ # on-valid-slack: webhook-minus-'https://' and/or
135
+ # on-invalid-slack: webhook-minus-'https://'
136
+ webhook_url =
137
+
138
+
@@ -18,7 +18,7 @@ log_files_to_keep = 100
18
18
  log_file_size = 52428800
19
19
 
20
20
  [config]
21
- path = assets/config/jenkins-local-azure.ini
21
+ path = assets/config/jenkins-local-gcs.ini
22
22
 
23
23
  [cache]
24
24
  path = cache
@@ -33,9 +33,9 @@ archive = archive
33
33
 
34
34
  [inputs]
35
35
  files = inputs/named_files
36
+ csvpaths = inputs/named_paths
36
37
  #csvpaths = s3://csvpath-example-1/inputs/named_paths
37
38
  #files = sftp://172.17.0.3:10022/inputs/named_files
38
-
39
39
  on_unmatched_file_fingerprints = halt
40
40
 
41
41
  #
@@ -46,7 +46,13 @@ on_unmatched_file_fingerprints = halt
46
46
  groups =
47
47
  #slack, marquez, ckan, sftp, sftpplus, otlp, default, sqlite
48
48
 
49
- # add sqlite to capture staging, loads, and results in a local sqlite db
49
+ # add sql to capture staging, loads, and results in mysql, postgres, ms sql server, or sqlite
50
+ sql.file = from csvpath.managers.integrations.sql.sql_file_listener import SqlFileListener
51
+ sql.paths = from csvpath.managers.integrations.sql.sql_paths_listener import SqlPathsListener
52
+ sql.result = from csvpath.managers.integrations.sql.sql_result_listener import SqlResultListener
53
+ sql.results = from csvpath.managers.integrations.sql.sql_results_listener import SqlResultsListener
54
+
55
+ # add sqlite to capture staging, loads, and results in a local sqlite file
50
56
  sqlite.result = from csvpath.managers.integrations.sqlite.sqlite_result_listener import SqliteResultListener
51
57
  sqlite.results = from csvpath.managers.integrations.sqlite.sqlite_results_listener import SqliteResultsListener
52
58
 
@@ -99,6 +105,11 @@ password = tinpenny
99
105
  [sqlite]
100
106
  db = archive/csvpath.db
101
107
 
108
+ [sql]
109
+ # sqlite, mysql, postgres, or sql_server
110
+ dialect = sqlite
111
+ connection_string = sqlite:///archive/csvpath-sqlite.db
112
+
102
113
  [sftpplus]
103
114
  # these are only needed by the csvpath writer
104
115
  mailbox_user = MAILBOX_USER
@@ -302,6 +302,9 @@ class FileManager:
302
302
  mdata.file_name = file_home[file_home.rfind(nos.sep) + 1 :]
303
303
  mdata.name_home = name_home
304
304
  mdata.mark = mark
305
+ #
306
+ # TODO: add file_size. move FileInfo into Nos. for now it is 0.
307
+ #
305
308
  self.registrar.register_complete(mdata)
306
309
 
307
310
  def _clean_file_name(self, fname: str) -> str:
@@ -22,3 +22,4 @@ class FileMetadata(Metadata):
22
22
  self.mark = None
23
23
  # like csv
24
24
  self.type = None
25
+ self.file_size = 0
@@ -49,6 +49,10 @@ class FileRegistrar(Registrar, Listener):
49
49
  return j
50
50
 
51
51
  def patch_named_file(self, *, name, patch, index=-1) -> None:
52
+ #
53
+ # TODO: distribute an metadata event to give metadata stores a
54
+ # chance to update their info re: the file
55
+ #
52
56
  home = self.csvpaths.file_manager.named_file_home(name)
53
57
  mp = self.manifest_path(home)
54
58
  mani = self.get_manifest(mp)
@@ -140,10 +144,12 @@ class FileRegistrar(Registrar, Listener):
140
144
  f"File mgr and registrar marks should match: {mdata.mark}, {mark}"
141
145
  )
142
146
  if (
147
+ # TODO: s3 can do nos.exists
143
148
  not path.startswith("s3:")
149
+ # Nos doesn't handle http files. they are special--inbound only.
144
150
  and not path.startswith("http:")
145
151
  and not path.startswith("https:")
146
- # and not azure?
152
+ # and not azure? gcp? should be handled by nos anyway.
147
153
  and not Nos(path).exists()
148
154
  ):
149
155
  # if not path.startswith("s3:") and not os.path.exists(path):
@@ -0,0 +1,24 @@
1
+ from sqlalchemy import create_engine, Engine
2
+ from csvpath.util.config import Config
3
+
4
+
5
+ class Db:
6
+ @classmethod
7
+ def get(self, config: Config) -> Engine:
8
+ dialect = config.get(section="sql", name="dialect")
9
+ c_str = config.get(section="sql", name="connection_string")
10
+ if dialect == "sqlite":
11
+ # sqlite:///example.db
12
+ engine = create_engine(c_str)
13
+ elif dialect == "postgres":
14
+ # postgresql+psycopg2://user:password@localhost/dbname
15
+ engine = create_engine(c_str)
16
+ elif dialect == "mysql":
17
+ # mysql+pymysql://user:password@localhost/dbname
18
+ engine = create_engine(c_str)
19
+ elif dialect == "sql_server":
20
+ # mssql+pyodbc://user:password@localhost/dbname
21
+ engine = create_engine(c_str)
22
+ else:
23
+ raise ValueError("Unknown RDBMS dialect %s", dialect)
24
+ return engine
@@ -0,0 +1,85 @@
1
+ from sqlalchemy import Table
2
+ from sqlalchemy.dialects.postgresql import insert as pg_insert
3
+ from sqlalchemy.dialects.mysql import insert as mysql_insert
4
+ from sqlalchemy.dialects.sqlite import insert as sqlite_insert
5
+ from csvpath.managers.metadata import Metadata
6
+ from .sql_listener import SqlListener
7
+
8
+
9
+ class SqlFileListener(SqlListener):
10
+ def __init__(self, config=None):
11
+ SqlListener.__init__(self, config=config)
12
+ self._named_file = None
13
+
14
+ @property
15
+ def named_file(self) -> Table:
16
+ if self._named_file is None:
17
+ self._named_file = self.tables.named_file
18
+ return self._named_file
19
+
20
+ def metadata_update(self, mdata: Metadata) -> None:
21
+ if not self.csvpaths:
22
+ raise RuntimeError("CsvPaths cannot be None")
23
+ named_file_data = {
24
+ "uuid": mdata.uuid_string,
25
+ "at": mdata.time,
26
+ "named_file_name": mdata.named_file_name,
27
+ "origin_path": mdata.origin_path,
28
+ "name_home": mdata.name_home,
29
+ "file_home": mdata.file_home,
30
+ "file_path": mdata.file_path,
31
+ "file_name": mdata.file_name,
32
+ "mark": mdata.mark,
33
+ "type": mdata.type,
34
+ "file_size": mdata.file_size,
35
+ "ip_address": mdata.ip_address,
36
+ "hostname": mdata.hostname,
37
+ "username": mdata.username,
38
+ "files_root": mdata.named_files_root,
39
+ "base_path": mdata.base_path,
40
+ "manifest_path": mdata.manifest_path,
41
+ }
42
+ self._upsert_named_file(named_file_data)
43
+
44
+ def _upsert_named_file(self, named_file_data: dict, *, dispose: bool = True):
45
+ with self.engine.connect() as conn:
46
+ dialect = conn.dialect.name
47
+ self.csvpaths.logger.info("Inserting named-file metadata into %s", dialect)
48
+ stmt = None
49
+ if dialect in ["postgresql", "sqlite"]:
50
+ ist = pg_insert if dialect == "postgresql" else sqlite_insert
51
+ stmt = (
52
+ ist(self.named_file)
53
+ .values(named_file_data)
54
+ .on_conflict_do_update(
55
+ index_elements=["uuid"], set_=self._set(named_file_data)
56
+ )
57
+ )
58
+ elif dialect == "mysql":
59
+ stmt = (
60
+ mysql_insert(self.named_file)
61
+ .values(named_file_data)
62
+ .on_duplicate_key_update(self._set(named_file_data))
63
+ )
64
+ elif dialect == "mssql":
65
+ raise NotImplementedError("SQL Server support is not yet implemented.")
66
+ else:
67
+ raise ValueError(f"Unsupported database dialect: {dialect}")
68
+ conn.execute(stmt)
69
+ conn.commit()
70
+ if dispose is True:
71
+ self.engine.dispose()
72
+
73
+ def _set(self, named_file_data) -> dict:
74
+ return {
75
+ "files_root": named_file_data["files_root"],
76
+ "file_home": named_file_data["file_home"],
77
+ "file_path": named_file_data["file_path"],
78
+ "file_name": named_file_data["file_name"],
79
+ "mark": named_file_data["mark"],
80
+ "type": named_file_data["type"],
81
+ "file_size": named_file_data["file_size"],
82
+ "ip_address": named_file_data["ip_address"],
83
+ "hostname": named_file_data["hostname"],
84
+ "username": named_file_data["username"],
85
+ }
@@ -0,0 +1,29 @@
1
+ from sqlalchemy import Engine
2
+ from csvpath.managers.listener import Listener
3
+ from .engine import Db
4
+ from .tables import Tables
5
+
6
+
7
+ class SqlListener(Listener):
8
+ def __init__(self, config=None):
9
+ Listener.__init__(self, config=config)
10
+ self.csvpaths = None
11
+ self._tables = None
12
+ self._engine = None
13
+
14
+ @property
15
+ def tables(self) -> Tables:
16
+ if self._tables is None:
17
+ self._tables = Tables(self.config, engine=self.engine)
18
+ self._tables.assure_tables()
19
+ return self._tables
20
+
21
+ @property
22
+ def engine(self) -> Engine:
23
+ if self._engine is None:
24
+ self._engine = Db.get(self.config)
25
+ return self._engine
26
+
27
+ @engine.setter
28
+ def engine(self, engine: Engine):
29
+ self._engine = engine
@@ -0,0 +1,78 @@
1
+ from sqlalchemy import Table
2
+ from sqlalchemy.dialects.postgresql import insert as pg_insert
3
+ from sqlalchemy.dialects.mysql import insert as mysql_insert
4
+ from sqlalchemy.dialects.sqlite import insert as sqlite_insert
5
+ from csvpath.managers.metadata import Metadata
6
+ from .sql_listener import SqlListener
7
+
8
+
9
+ class SqlPathsListener(SqlListener):
10
+ def __init__(self, config=None):
11
+ SqlListener.__init__(self, config=config)
12
+ self._named_paths = None
13
+
14
+ @property
15
+ def named_paths(self) -> Table:
16
+ if self._named_paths is None:
17
+ self._named_paths = self.tables.named_paths
18
+ return self._named_paths
19
+
20
+ def metadata_update(self, mdata: Metadata) -> None:
21
+ if not self.csvpaths:
22
+ raise RuntimeError("CsvPaths cannot be None")
23
+ named_paths_data = {
24
+ "uuid": mdata.uuid_string,
25
+ "at": mdata.time,
26
+ "paths_root": mdata.named_paths_root,
27
+ "paths_name": mdata.named_paths_name,
28
+ "paths_home": mdata.named_paths_home,
29
+ "group_file_path": mdata.group_file_path,
30
+ "paths_count": mdata.named_paths_count,
31
+ "ip_address": mdata.ip_address,
32
+ "hostname": mdata.hostname,
33
+ "username": mdata.username,
34
+ "base_path": mdata.base_path,
35
+ "manifest_path": mdata.manifest_path,
36
+ }
37
+ self._upsert_named_paths(named_paths_data)
38
+
39
+ def _upsert_named_paths(self, named_paths_data: dict, *, dispose: bool = True):
40
+ with self.engine.connect() as conn:
41
+ dialect = conn.dialect.name
42
+ self.csvpaths.logger.info("Inserting named-paths metadata into %s", dialect)
43
+ stmt = None
44
+ if dialect in ["postgresql", "sqlite"]:
45
+ ist = pg_insert if dialect == "postgresql" else sqlite_insert
46
+ stmt = (
47
+ ist(self.named_paths)
48
+ .values(named_paths_data)
49
+ .on_conflict_do_update(
50
+ index_elements=["uuid"], set_=self._set(named_paths_data)
51
+ )
52
+ )
53
+ elif dialect == "mysql":
54
+ stmt = (
55
+ mysql_insert(self.named_paths)
56
+ .values(named_paths_data)
57
+ .on_duplicate_key_update(self._set(named_paths_data))
58
+ )
59
+ elif dialect == "mssql":
60
+ raise NotImplementedError("SQL Server support is not yet implemented.")
61
+ else:
62
+ raise ValueError(f"Unsupported database dialect: {dialect}")
63
+ conn.execute(stmt)
64
+ conn.commit()
65
+ if dispose is True:
66
+ self.engine.dispose()
67
+
68
+ def _set(self, named_paths_data) -> dict:
69
+ return {
70
+ "paths_root": named_paths_data["paths_name"],
71
+ "paths_name": named_paths_data["paths_name"],
72
+ "paths_home": named_paths_data["paths_home"],
73
+ "group_file_path": named_paths_data["group_file_path"],
74
+ "paths_count": named_paths_data["paths_count"],
75
+ "ip_address": named_paths_data["ip_address"],
76
+ "hostname": named_paths_data["hostname"],
77
+ "username": named_paths_data["username"],
78
+ }
@@ -0,0 +1,100 @@
1
+ from sqlalchemy import Table
2
+ from sqlalchemy.dialects.postgresql import insert as pg_insert
3
+ from sqlalchemy.dialects.mysql import insert as mysql_insert
4
+ from sqlalchemy.dialects.sqlite import insert as sqlite_insert
5
+ from csvpath.managers.metadata import Metadata
6
+ from .sql_listener import SqlListener
7
+
8
+
9
+ class SqlResultListener(SqlListener):
10
+ def __init__(self, config=None):
11
+ SqlListener.__init__(self, config=config)
12
+ self._instance_run = None
13
+
14
+ @property
15
+ def instance_run(self) -> Table:
16
+ if self._instance_run is None:
17
+ self._instance_run = self.tables.instance_run
18
+ return self._instance_run
19
+
20
+ def metadata_update(self, mdata: Metadata) -> None:
21
+ if not self.csvpaths:
22
+ raise RuntimeError("CsvPaths cannot be None")
23
+ instance_run_data = {
24
+ "uuid": mdata.uuid_string,
25
+ "at": mdata.time,
26
+ "group_run_uuid": mdata.named_paths_uuid_string,
27
+ "instance_identity": mdata.instance_identity,
28
+ "instance_index": mdata.instance_index,
29
+ "instance_home": mdata.instance_home,
30
+ "preceding_instance_identity": mdata.preceding_instance_identity,
31
+ "actual_data_file": mdata.actual_data_file,
32
+ "source_mode_preceding": "Y"
33
+ if (
34
+ mdata.source_mode_preceding is True
35
+ or mdata.source_mode_preceding == "Y"
36
+ )
37
+ else "N",
38
+ "valid": "Y" if (mdata.valid is True or mdata.valid == "Y") else "N",
39
+ "completed": "Y"
40
+ if (mdata.completed is True or mdata.completed == "Y")
41
+ else "N",
42
+ "files_expected": "Y"
43
+ if (mdata.files_expected is True or mdata.files_expected == "Y")
44
+ else "N",
45
+ "error_count": mdata.error_count if mdata.error_count else 0,
46
+ "number_of_files_expected": mdata.number_of_files_expected,
47
+ "number_of_files_generated": mdata.number_of_files_generated,
48
+ "lines_scanned": mdata.lines_scanned,
49
+ "lines_total": mdata.lines_total,
50
+ "lines_matched": mdata.lines_matched,
51
+ "manifest_path": mdata.manifest_path,
52
+ }
53
+ self._upsert_instance_run(instance_run_data)
54
+
55
+ def _upsert_instance_run(self, instance_run_data, *, dispose=True):
56
+ with self.engine.connect() as conn:
57
+ dialect = conn.dialect.name
58
+ self.csvpaths.logger.info("Inserting run result metadata into %s", dialect)
59
+ s = self._set(instance_run_data)
60
+ if dialect in ["postgresql", "sqlite"]:
61
+ ist = pg_insert if dialect == "postgresql" else sqlite_insert
62
+ stmt = (
63
+ ist(self.instance_run)
64
+ .values(instance_run_data)
65
+ .on_conflict_do_update(index_elements=["uuid"], set_=s)
66
+ )
67
+ elif dialect == "mysql":
68
+ stmt = (
69
+ mysql_insert(self.instance_run)
70
+ .values(instance_run_data)
71
+ .on_duplicate_key_update(self._set(instance_run_data))
72
+ )
73
+ elif dialect == "mssql":
74
+ raise NotImplementedError("SQL Server support is not yet implemented.")
75
+ else:
76
+ raise ValueError(f"Unsupported database dialect: {dialect}")
77
+ conn.execute(stmt)
78
+ conn.commit()
79
+ if dispose is True:
80
+ self.engine.dispose()
81
+
82
+ def _set(self, instance_run_data: dict) -> dict:
83
+ return {
84
+ "valid": "Y"
85
+ if (instance_run_data["valid"] is True or instance_run_data["valid"] == "Y")
86
+ else "N",
87
+ "completed": "Y"
88
+ if (
89
+ instance_run_data["completed"] is True
90
+ or instance_run_data["completed"] == "Y"
91
+ )
92
+ else "N",
93
+ "error_count": instance_run_data["error_count"],
94
+ "number_of_files_expected": instance_run_data["number_of_files_expected"],
95
+ "number_of_files_generated": instance_run_data["number_of_files_generated"],
96
+ "files_expected": instance_run_data["files_expected"],
97
+ "lines_scanned": instance_run_data["lines_scanned"],
98
+ "lines_total": instance_run_data["lines_total"],
99
+ "lines_matched": instance_run_data["lines_matched"],
100
+ }