csvpath 0.0.586__tar.gz → 0.0.588__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 (376) hide show
  1. {csvpath-0.0.586 → csvpath-0.0.588}/PKG-INFO +1 -1
  2. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/function_factory.py +24 -4
  3. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/function_finder.py +33 -5
  4. csvpath-0.0.588/csvpath/util/class_loader.py +215 -0
  5. {csvpath-0.0.586 → csvpath-0.0.588}/pyproject.toml +1 -1
  6. csvpath-0.0.586/csvpath/util/class_loader.py +0 -105
  7. {csvpath-0.0.586 → csvpath-0.0.588}/LICENSE +0 -0
  8. {csvpath-0.0.586 → csvpath-0.0.588}/README.md +0 -0
  9. {csvpath-0.0.586 → csvpath-0.0.588}/assets/config/config.ini +0 -0
  10. {csvpath-0.0.586 → csvpath-0.0.588}/assets/config/extra-functions.imports +0 -0
  11. {csvpath-0.0.586 → csvpath-0.0.588}/assets/config/function.imports +0 -0
  12. {csvpath-0.0.586 → csvpath-0.0.588}/assets/config/jenkins-local-azure.ini +0 -0
  13. {csvpath-0.0.586 → csvpath-0.0.588}/assets/config/jenkins-local-filesystem-mysql.ini +0 -0
  14. {csvpath-0.0.586 → csvpath-0.0.588}/assets/config/jenkins-local-gcs.ini +0 -0
  15. {csvpath-0.0.586 → csvpath-0.0.588}/assets/config/jenkins-local-s3.ini +0 -0
  16. {csvpath-0.0.586 → csvpath-0.0.588}/assets/config/jenkins-local-sftp.ini +0 -0
  17. {csvpath-0.0.586 → csvpath-0.0.588}/assets/config/jenkins-windows-azure.ini +0 -0
  18. {csvpath-0.0.586 → csvpath-0.0.588}/assets/config/jenkins-windows-gcs.ini +0 -0
  19. {csvpath-0.0.586 → csvpath-0.0.588}/assets/config/jenkins-windows-local.ini +0 -0
  20. {csvpath-0.0.586 → csvpath-0.0.588}/assets/config/jenkins-windows-s3.ini +0 -0
  21. {csvpath-0.0.586 → csvpath-0.0.588}/assets/config/jenkins-windows-sftp.ini +0 -0
  22. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/mac/azure-pipeline.gopipeline.json +0 -0
  23. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/mac/azure.sh +0 -0
  24. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/mac/gcs-pipeline.gopipeline.json +0 -0
  25. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/mac/gcs.sh +0 -0
  26. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/mac/local-pipeline.gopipeline copy.json +0 -0
  27. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/mac/local.sh +0 -0
  28. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/mac/s3-pipeline.gopipeline.json +0 -0
  29. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/mac/s3.sh +0 -0
  30. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/mac/sftp-pipeline.gopipeline.json +0 -0
  31. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/mac/sftp.sh +0 -0
  32. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/windows/azure.bat +0 -0
  33. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/windows/gcs.bat +0 -0
  34. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/windows/local.bat +0 -0
  35. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/windows/s3.bat +0 -0
  36. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/windows/sftp.bat +0 -0
  37. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/windows/windows-azure.gopipeline.json +0 -0
  38. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/windows/windows-gcs.gopipeline.json +0 -0
  39. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/windows/windows-local.gopipeline.json +0 -0
  40. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/windows/windows-s3.gopipeline.json +0 -0
  41. {csvpath-0.0.586 → csvpath-0.0.588}/assets/gocd/windows/windows-sftp.gopipeline.json +0 -0
  42. {csvpath-0.0.586 → csvpath-0.0.588}/assets/integrations/sftpplus/handle_auto_arrival.bat +0 -0
  43. {csvpath-0.0.586 → csvpath-0.0.588}/assets/integrations/sftpplus/handle_auto_arrival.py +0 -0
  44. {csvpath-0.0.586 → csvpath-0.0.588}/assets/integrations/sftpplus/handle_auto_arrival.sh +0 -0
  45. {csvpath-0.0.586 → csvpath-0.0.588}/assets/integrations/sftpplus/handle_mailbox_arrival.bat +0 -0
  46. {csvpath-0.0.586 → csvpath-0.0.588}/assets/integrations/sftpplus/handle_mailbox_arrival.py +0 -0
  47. {csvpath-0.0.586 → csvpath-0.0.588}/assets/integrations/sftpplus/handle_mailbox_arrival.sh +0 -0
  48. {csvpath-0.0.586 → csvpath-0.0.588}/assets/integrations/sqlite/csvpath +0 -0
  49. {csvpath-0.0.586 → csvpath-0.0.588}/assets/integrations/sqlite/schema.sql +0 -0
  50. {csvpath-0.0.586 → csvpath-0.0.588}/config/config.ini +0 -0
  51. {csvpath-0.0.586 → csvpath-0.0.588}/config/env.json +0 -0
  52. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/__init__.py +0 -0
  53. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/cli/__init__.py +0 -0
  54. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/cli/asker.py +0 -0
  55. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/cli/cli.py +0 -0
  56. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/cli/const.py +0 -0
  57. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/cli/debug_config.py +0 -0
  58. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/cli/drill_down.py +0 -0
  59. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/cli/function_describer.py +0 -0
  60. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/cli/function_lister.py +0 -0
  61. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/cli/selecter.py +0 -0
  62. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/csvpath.py +0 -0
  63. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/csvpaths.py +0 -0
  64. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/__init__.py +0 -0
  65. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/errors/error.py +0 -0
  66. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/errors/error_collector.py +0 -0
  67. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/errors/error_comms.py +0 -0
  68. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/errors/error_manager.py +0 -0
  69. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/files/file_manager.py +0 -0
  70. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/files/file_metadata.py +0 -0
  71. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/files/file_registrar.py +0 -0
  72. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/files/files_listener.py +0 -0
  73. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/files/lines_and_headers_cacher.py +0 -0
  74. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/ckan/ckan.py +0 -0
  75. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/ckan/ckan_listener.py +0 -0
  76. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/ckan/datafile.py +0 -0
  77. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/ckan/dataset.py +0 -0
  78. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/ol/event.py +0 -0
  79. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/ol/event_result.py +0 -0
  80. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/ol/file_listener_ol.py +0 -0
  81. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/ol/job.py +0 -0
  82. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/ol/ol_listener.py +0 -0
  83. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/ol/paths_listener_ol.py +0 -0
  84. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/ol/result_listener_ol.py +0 -0
  85. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/ol/results_listener_ol.py +0 -0
  86. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/ol/run.py +0 -0
  87. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/ol/run_listener_ol.py +0 -0
  88. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/ol/run_state.py +0 -0
  89. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/ol/sender.py +0 -0
  90. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/otlp/error_metrics.py +0 -0
  91. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/otlp/metrics.py +0 -0
  92. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/otlp/otlp_error_listener.py +0 -0
  93. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/otlp/otlp_file_listener.py +0 -0
  94. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/otlp/otlp_listener.py +0 -0
  95. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/otlp/otlp_paths_listener.py +0 -0
  96. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/otlp/otlp_result_listener.py +0 -0
  97. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/otlp/otlp_results_listener.py +0 -0
  98. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/scripts/scripts_results_listener.py +0 -0
  99. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sftp/sftp_sender.py +0 -0
  100. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sftpplus/arrival_handler.py +0 -0
  101. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sftpplus/rpc.py +0 -0
  102. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sftpplus/sftpplus_listener.py +0 -0
  103. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sftpplus/transfer_creator.py +0 -0
  104. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sftpplus/transfers.py +0 -0
  105. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/slack/event.py +0 -0
  106. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/slack/sender.py +0 -0
  107. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sql/engine.py +0 -0
  108. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sql/sql_file_listener.py +0 -0
  109. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sql/sql_listener.py +0 -0
  110. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sql/sql_paths_listener.py +0 -0
  111. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sql/sql_result_listener.py +0 -0
  112. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sql/sql_results_listener.py +0 -0
  113. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sql/tables.py +0 -0
  114. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sql/updates.py +0 -0
  115. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sqlite/schema.sql +0 -0
  116. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sqlite/sqlite_result_listener.py +0 -0
  117. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/sqlite/sqlite_results_listener.py +0 -0
  118. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/webhook/webhook_listener.py +0 -0
  119. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/integrations/webhook/webhook_results_listener.py +0 -0
  120. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/listener.py +0 -0
  121. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/metadata.py +0 -0
  122. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/paths/paths_listener.py +0 -0
  123. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/paths/paths_manager.py +0 -0
  124. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/paths/paths_metadata.py +0 -0
  125. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/paths/paths_registrar.py +0 -0
  126. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/registrar.py +0 -0
  127. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/results/readers/file_errors_reader.py +0 -0
  128. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/results/readers/file_lines_reader.py +0 -0
  129. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/results/readers/file_printouts_reader.py +0 -0
  130. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/results/readers/file_unmatched_reader.py +0 -0
  131. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/results/readers/readers.py +0 -0
  132. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/results/result.py +0 -0
  133. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/results/result_file_reader.py +0 -0
  134. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/results/result_metadata.py +0 -0
  135. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/results/result_registrar.py +0 -0
  136. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/results/result_serializer.py +0 -0
  137. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/results/results_manager.py +0 -0
  138. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/results/results_metadata.py +0 -0
  139. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/results/results_registrar.py +0 -0
  140. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/run/run_listener_stdout.py +0 -0
  141. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/run/run_metadata.py +0 -0
  142. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/run/run_registrar.py +0 -0
  143. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/managers/test_listener.py +0 -0
  144. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/__init__.py +0 -0
  145. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/__init__.py +0 -0
  146. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/args.py +0 -0
  147. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/args_helper.py +0 -0
  148. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/boolean/all.py +0 -0
  149. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/boolean/andf.py +0 -0
  150. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/boolean/any.py +0 -0
  151. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/boolean/between.py +0 -0
  152. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/boolean/empty.py +0 -0
  153. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/boolean/exists.py +0 -0
  154. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/boolean/inf.py +0 -0
  155. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/boolean/no.py +0 -0
  156. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/boolean/notf.py +0 -0
  157. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/boolean/orf.py +0 -0
  158. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/boolean/yes.py +0 -0
  159. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/counting/count.py +0 -0
  160. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/counting/count_bytes.py +0 -0
  161. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/counting/count_headers.py +0 -0
  162. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/counting/count_lines.py +0 -0
  163. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/counting/count_scans.py +0 -0
  164. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/counting/counter.py +0 -0
  165. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/counting/every.py +0 -0
  166. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/counting/has_matches.py +0 -0
  167. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/counting/increment.py +0 -0
  168. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/counting/tally.py +0 -0
  169. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/counting/total_lines.py +0 -0
  170. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/dates/now.py +0 -0
  171. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/dates/part.py +0 -0
  172. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/dates/roll.py +0 -0
  173. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/function.py +0 -0
  174. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/function_focus.py +0 -0
  175. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/headers/append.py +0 -0
  176. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/headers/collect.py +0 -0
  177. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/headers/empty_stack.py +0 -0
  178. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/headers/end.py +0 -0
  179. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/headers/header_name.py +0 -0
  180. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/headers/header_names_mismatch.py +0 -0
  181. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/headers/headers.py +0 -0
  182. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/headers/headers_stack.py +0 -0
  183. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/headers/insert.py +0 -0
  184. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/headers/line_before.py +0 -0
  185. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/headers/mismatch.py +0 -0
  186. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/headers/remove.py +0 -0
  187. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/headers/rename.py +0 -0
  188. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/headers/replace.py +0 -0
  189. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/headers/reset_headers.py +0 -0
  190. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/json/jsonpath.py +0 -0
  191. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/lines/advance.py +0 -0
  192. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/lines/after_blank.py +0 -0
  193. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/lines/dups.py +0 -0
  194. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/lines/first.py +0 -0
  195. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/lines/first_line.py +0 -0
  196. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/lines/last.py +0 -0
  197. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/lines/stop.py +0 -0
  198. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/math/above.py +0 -0
  199. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/math/add.py +0 -0
  200. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/math/divide.py +0 -0
  201. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/math/equals.py +0 -0
  202. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/math/intf.py +0 -0
  203. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/math/mod.py +0 -0
  204. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/math/multiply.py +0 -0
  205. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/math/odd.py +0 -0
  206. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/math/round.py +0 -0
  207. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/math/subtotal.py +0 -0
  208. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/math/subtract.py +0 -0
  209. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/math/sum.py +0 -0
  210. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/misc/fingerprint.py +0 -0
  211. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/misc/importf.py +0 -0
  212. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/misc/random.py +0 -0
  213. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/print/jinjaf.py +0 -0
  214. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/print/print_line.py +0 -0
  215. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/print/print_queue.py +0 -0
  216. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/print/printf.py +0 -0
  217. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/print/table.py +0 -0
  218. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/stats/minf.py +0 -0
  219. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/stats/nminmax.py +0 -0
  220. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/stats/percent.py +0 -0
  221. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/stats/percent_unique.py +0 -0
  222. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/stats/stdev.py +0 -0
  223. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/strings/alter.py +0 -0
  224. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/strings/caps.py +0 -0
  225. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/strings/concat.py +0 -0
  226. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/strings/contains.py +0 -0
  227. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/strings/format.py +0 -0
  228. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/strings/length.py +0 -0
  229. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/strings/lower.py +0 -0
  230. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/strings/metaphone.py +0 -0
  231. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/strings/regex.py +0 -0
  232. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/strings/starts_with.py +0 -0
  233. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/strings/strip.py +0 -0
  234. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/strings/substring.py +0 -0
  235. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/strings/upper.py +0 -0
  236. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/testing/debug.py +0 -0
  237. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/types/__init__.py +0 -0
  238. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/types/blank.py +0 -0
  239. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/types/boolean.py +0 -0
  240. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/types/datatype.py +0 -0
  241. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/types/datef.py +0 -0
  242. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/types/decimal.py +0 -0
  243. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/types/email.py +0 -0
  244. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/types/nonef.py +0 -0
  245. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/types/string.py +0 -0
  246. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/types/type.py +0 -0
  247. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/types/url.py +0 -0
  248. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/types/wildcard.py +0 -0
  249. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/validity/fail.py +0 -0
  250. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/validity/failed.py +0 -0
  251. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/validity/line.py +0 -0
  252. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/variables/clear.py +0 -0
  253. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/variables/get.py +0 -0
  254. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/variables/index_of.py +0 -0
  255. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/variables/pushpop.py +0 -0
  256. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/variables/put.py +0 -0
  257. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/variables/track.py +0 -0
  258. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/variables/variables.py +0 -0
  259. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/functions/xml/xpath.py +0 -0
  260. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/lark_parser.py +0 -0
  261. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/lark_transformer.py +0 -0
  262. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/matcher.py +0 -0
  263. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/productions/__init__.py +0 -0
  264. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/productions/equality.py +0 -0
  265. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/productions/expression.py +0 -0
  266. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/productions/header.py +0 -0
  267. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/productions/matchable.py +0 -0
  268. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/productions/qualified.py +0 -0
  269. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/productions/reference.py +0 -0
  270. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/productions/term.py +0 -0
  271. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/productions/variable.py +0 -0
  272. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/util/exceptions.py +0 -0
  273. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/util/expression_encoder.py +0 -0
  274. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/util/expression_utility.py +0 -0
  275. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/util/lark_print_parser.py +0 -0
  276. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/util/print_parser.py +0 -0
  277. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/matching/util/runtime_data_collector.py +0 -0
  278. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/modes/error_mode.py +0 -0
  279. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/modes/explain_mode.py +0 -0
  280. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/modes/files_mode.py +0 -0
  281. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/modes/logic_mode.py +0 -0
  282. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/modes/mode_controller.py +0 -0
  283. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/modes/print_mode.py +0 -0
  284. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/modes/return_mode.py +0 -0
  285. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/modes/run_mode.py +0 -0
  286. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/modes/source_mode.py +0 -0
  287. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/modes/transfer_mode.py +0 -0
  288. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/modes/unmatched_mode.py +0 -0
  289. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/modes/validation_mode.py +0 -0
  290. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/scanning/__init__.py +0 -0
  291. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/scanning/scanner2.py +0 -0
  292. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/scanning/scanner2_parser.py +0 -0
  293. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/scanning/scanner2_transformer.py +0 -0
  294. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/azure/azure_data_reader.py +0 -0
  295. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/azure/azure_data_writer.py +0 -0
  296. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/azure/azure_fingerprinter.py +0 -0
  297. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/azure/azure_json_data_reader.py +0 -0
  298. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/azure/azure_nos.py +0 -0
  299. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/azure/azure_utils.py +0 -0
  300. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/azure/azure_xlsx_data_reader.py +0 -0
  301. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/backend_check.py +0 -0
  302. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/box.py +0 -0
  303. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/cache.py +0 -0
  304. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/caser.py +0 -0
  305. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/code.py +0 -0
  306. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/config.py +0 -0
  307. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/config_env.py +0 -0
  308. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/config_exception.py +0 -0
  309. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/date_util.py +0 -0
  310. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/exceptions.py +0 -0
  311. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/file_info.py +0 -0
  312. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/file_readers.py +0 -0
  313. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/file_writers.py +0 -0
  314. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/gcs/gcs_data_reader.py +0 -0
  315. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/gcs/gcs_data_writer.py +0 -0
  316. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/gcs/gcs_fingerprinter.py +0 -0
  317. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/gcs/gcs_json_data_reader.py +0 -0
  318. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/gcs/gcs_nos.py +0 -0
  319. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/gcs/gcs_utils.py +0 -0
  320. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/gcs/gcs_xlsx_data_reader.py +0 -0
  321. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/hasher.py +0 -0
  322. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/http/http_data_reader.py +0 -0
  323. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/intermediary.py +0 -0
  324. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/json/json_data_reader.py +0 -0
  325. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/json/json_reader_helper.py +0 -0
  326. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/last_line_stats.py +0 -0
  327. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/line_counter.py +0 -0
  328. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/line_monitor.py +0 -0
  329. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/line_spooler.py +0 -0
  330. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/log_utility.py +0 -0
  331. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/metadata_parser.py +0 -0
  332. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/nos.py +0 -0
  333. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/pandas_data_reader.py +0 -0
  334. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/path_util.py +0 -0
  335. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/printer.py +0 -0
  336. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/py_file_utility.py +0 -0
  337. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/files_reference_finder_2.py +0 -0
  338. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/files_tools/fingerprint_finder.py +0 -0
  339. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/files_tools/range_finder.py +0 -0
  340. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/ref_utils.py +0 -0
  341. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/reference_exceptions.py +0 -0
  342. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/reference_grammar.py +0 -0
  343. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/reference_manifest_entry_finder.py +0 -0
  344. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/reference_parser.py +0 -0
  345. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/reference_results.py +0 -0
  346. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/reference_transformer.py +0 -0
  347. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/results_reference_finder_2.py +0 -0
  348. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/results_tools/data_finder.py +0 -0
  349. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/results_tools/date_filter.py +0 -0
  350. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/results_tools/identity_finder.py +0 -0
  351. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/results_tools/path_filter.py +0 -0
  352. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/results_tools/resolve_possibles.py +0 -0
  353. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/results_tools/token_filters.py +0 -0
  354. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/results_tools/yesterday_or_today_translator.py +0 -0
  355. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/references/tools/date_completer.py +0 -0
  356. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/run_home_maker.py +0 -0
  357. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/s3/s3_data_reader.py +0 -0
  358. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/s3/s3_data_writer.py +0 -0
  359. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/s3/s3_fingerprinter.py +0 -0
  360. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/s3/s3_json_data_reader.py +0 -0
  361. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/s3/s3_nos.py +0 -0
  362. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/s3/s3_utils.py +0 -0
  363. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/s3/s3_xlsx_data_reader.py +0 -0
  364. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/sftp/sftp_config.py +0 -0
  365. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/sftp/sftp_data_reader.py +0 -0
  366. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/sftp/sftp_data_writer.py +0 -0
  367. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/sftp/sftp_fingerprinter.py +0 -0
  368. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/sftp/sftp_json_data_reader.py +0 -0
  369. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/sftp/sftp_nos.py +0 -0
  370. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/sftp/sftp_walk.py +0 -0
  371. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/sftp/sftp_xlsx_data_reader.py +0 -0
  372. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/sqliter.py +0 -0
  373. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/template_util.py +0 -0
  374. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/var_utility.py +0 -0
  375. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/xlsx/xlsx_data_reader.py +0 -0
  376. {csvpath-0.0.586 → csvpath-0.0.588}/csvpath/util/xlsx/xlsx_reader_helper.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: csvpath
3
- Version: 0.0.586
3
+ Version: 0.0.588
4
4
  Summary: A data preboarding framework for ingesting, managing, and validating CSV, Excel, and other tabular data files using a Collect, Store, Validate, Publish architecture to create a trusted publisher for downstream data consumers.
5
5
  Author: David Kershaw
6
6
  Author-email: info@csvpath.org
@@ -139,6 +139,7 @@ class FunctionFactory:
139
139
  @classmethod
140
140
  def add_function(cls, name: str, function: Function) -> None:
141
141
  """use to add a new, external function at runtime"""
142
+
142
143
  if name is None:
143
144
  name = function.name
144
145
  if name is None:
@@ -150,18 +151,31 @@ class FunctionFactory:
150
151
  raise InvalidNameException("Name must not be an empty string")
151
152
  if not cls.valid_function_name(name): # name.isalpha():
152
153
  raise InvalidNameException(f"Name {name} is not valid")
154
+ cls._debug(function.matcher, "Looking for an existing function named %s", name)
153
155
  if cls.get_function(None, name=name, find_external_functions=False) is not None:
154
156
  function.matcher.csvpath.logger.warning(
155
157
  "Internal function is overriden by external function: %s", name
156
158
  )
157
- # raise InvalidNameException("Built-in functions cannot be overriden")
158
159
  if not isinstance(function, Function):
159
160
  # pass as an instance, not a class, for specificity. good to do?
160
161
  raise InvalidChildException(
161
162
  "Function being registered must be passed as an instance"
162
163
  )
164
+ cls._debug(function.matcher, "Adding %s as key to %s", name, function.__class__)
163
165
  cls.NOT_MY_FUNCTION[name] = function.__class__
164
166
 
167
+ @classmethod
168
+ def _debug(cls, matcher, txt: str, obj=None, obj2=None) -> None:
169
+ if matcher is None:
170
+ return
171
+ if matcher.csvpath is None:
172
+ return
173
+ if obj2 is None:
174
+ matcher.csvpath.logger.debug(txt, str(obj))
175
+ else:
176
+ matcher.csvpath.logger.debug(txt, str(obj), str(obj2))
177
+
178
+
165
179
  #
166
180
  # valid function names start with a letter and contain only letters,
167
181
  # numbers, periods, and/or underscores. the grammar allows '.' and '_' at the
@@ -287,9 +301,15 @@ class FunctionFactory:
287
301
  # if proj not set we check for name
288
302
  #
289
303
  qname = cls.qname(matcher=matcher, name=name)
304
+ cls._debug(matcher, "Qualified name of %s is %s", name, qname)
290
305
  if qname in FunctionFactory.NOT_MY_FUNCTION:
291
306
  f = cls.NOT_MY_FUNCTION[qname]
292
307
  f = f(matcher, name, child)
308
+ cls._debug(matcher, "Found %s as %s", qname, f)
309
+ if f is None:
310
+ cls._debug(
311
+ matcher, "%s not in: %s", qname, FunctionFactory.NOT_MY_FUNCTION
312
+ )
293
313
  return f
294
314
 
295
315
  @classmethod
@@ -308,10 +328,10 @@ class FunctionFactory:
308
328
  return qname
309
329
 
310
330
  @classmethod
311
- def improve_name(cls, name:str) -> str:
331
+ def improve_name(cls, name: str) -> str:
312
332
  ffrom = " `~!@#$%^&*()_+-=[]\\{}|;':\",./<>?"
313
- to = "1234567890abcdefghijklmnopqrstuvw"
314
- table = str.maketrans(ffrom,to)
333
+ to = "1234567890abcdefghijklmnopqrstuvw"
334
+ table = str.maketrans(ffrom, to)
315
335
  name = name.translate(table)
316
336
  return name
317
337
 
@@ -24,6 +24,7 @@ class FunctionFinder: # pylint: disable=R0903
24
24
  if path is None or path.strip() == "":
25
25
  matcher.csvpath.logger.error("No [functions][imports] in config.ini")
26
26
  return
27
+ cls._debug(matcher, "Functions import file is at %s", path)
27
28
  if not os.path.exists(path):
28
29
  matcher.csvpath.logger.error(
29
30
  f"[functions][imports] path {path} in {config.configpath} does not exist"
@@ -35,15 +36,32 @@ class FunctionFinder: # pylint: disable=R0903
35
36
  i = 0
36
37
  for line in file:
37
38
  i += 1
38
- if str(line).strip() == "":
39
+ line = str(line).strip()
40
+ if line == "" or line.startswith("#"):
39
41
  continue
40
- cls._add_function(matcher, func_fact, line)
42
+ cls._debug(matcher, "Adding function %s", line)
43
+ try:
44
+ cls._add_function(matcher, func_fact, line)
45
+ except Exception as ex:
46
+ matcher.csvpath.logger.exception(f"Could not add function for '{line}'")
41
47
  matcher.csvpath.logger.info("Added %s external functions", i)
42
48
  # add a sentinel to keep us from attempting reload.
43
49
  # this instance will never be found, but the dict will
44
50
  # never be empty
45
51
  e = cls.externals_sentinel(matcher)
46
52
  func_fact.add_function(e, Yes(None, e))
53
+ cls._debug(matcher, "Added sentinel function %s", e)
54
+
55
+ @classmethod
56
+ def _debug(cls, matcher, txt: str, obj=None, obj2=None) -> None:
57
+ if matcher is None:
58
+ return
59
+ if matcher.csvpath is None:
60
+ return
61
+ if obj2 is None:
62
+ matcher.csvpath.logger.debug(txt, str(obj))
63
+ else:
64
+ matcher.csvpath.logger.debug(txt, str(obj), str(obj2))
47
65
 
48
66
  @classmethod
49
67
  def externals_sentinel(cls, matcher) -> str:
@@ -79,10 +97,20 @@ class FunctionFinder: # pylint: disable=R0903
79
97
  # lines in config are like:
80
98
  # from module import class as function-name
81
99
  #
100
+ cls._debug(matcher, "Import line is %s", cs)
82
101
  if len(cs) == 6 and cs[0] == "from" and cs[2] == "import" and cs[4] == "as":
83
102
  config = matcher.csvpath.config
84
- instance = ClassLoader.load_private_function(config, s, matcher, cs[5])
85
- qname = func_fact.qname(matcher=matcher, name=cs[5])
86
- func_fact.add_function(qname, instance)
103
+ try:
104
+ instance = ClassLoader.load_private_function(config, s, matcher, cs[5])
105
+ qname = func_fact.qname(matcher=matcher, name=cs[5])
106
+ cls._debug(matcher, "Adding custom function %s: %s", qname, instance)
107
+ func_fact.add_function(qname, instance)
108
+ except Exception as ex:
109
+ if matcher is not None and matcher.csvpath is not None:
110
+ matcher.csvpath.logger.exception(f"Cannot load class {cs}")
111
+ #
112
+ # matcher and csvpath will be present, but we check to be sure. there's no
113
+ # fallback because it is an unlikely scenario that would have its own logic.
114
+ #
87
115
  else:
88
116
  raise ConfigurationException("Unclear external function imports: {s}")
@@ -0,0 +1,215 @@
1
+ import importlib
2
+ import os
3
+ from typing import Any
4
+
5
+
6
+ class ClassLoadingError(RuntimeError):
7
+ ...
8
+
9
+
10
+ class ClassLoader:
11
+ #
12
+ # load is fine for classes we expect. e.g. we load specific types of data readers and writers
13
+ # using this method without any concerns about different projects needing to not collide. today
14
+ # we treat integration listeners the same way, but longer term we need those to be able to be
15
+ # custom loaded too.
16
+ #
17
+ @classmethod
18
+ def load(cls, s: str, args: list = None, kwargs: dict = None) -> Any:
19
+ s = s.strip()
20
+ if s != "":
21
+ instance = None
22
+ cs = s.split(" ")
23
+ #
24
+ # lines in config are like:
25
+ # from module import class
26
+ #
27
+ if len(cs) == 4 and cs[0] == "from" and cs[2] == "import":
28
+ module = importlib.import_module(cs[1])
29
+ class_ = getattr(module, cs[3])
30
+ args = args if args is not None else []
31
+ kwargs = kwargs if kwargs is not None else {}
32
+ instance = class_(*args, **kwargs)
33
+ return instance
34
+ else:
35
+ raise ClassLoadingError(f"Unclear class loading import statement: {s}")
36
+ return None
37
+
38
+ #
39
+ # this loads a custom function using a name that is distinct across projects so there
40
+ # is no risk of name collisions.
41
+ #
42
+ @classmethod
43
+ def load_private_function(cls, config, stmt: str, *args, **kwargs):
44
+ imports = config.get(section="functions", name="imports")
45
+ if not imports or str(imports).strip() == "":
46
+ raise ValueError("Imports cannot be None or ''")
47
+ imports = os.path.dirname(imports)
48
+ return cls.load_private_class(imports, stmt, *args, **kwargs)
49
+
50
+
51
+ """
52
+ @classmethod
53
+ def load_private_class(cls, base_path: str, stmt: str, *args, **kwargs):
54
+ if not stmt or stmt.strip() == "":
55
+ raise ValueError("Load statement cannot be None or ''")
56
+ module_name = None
57
+ class_name = None
58
+ #
59
+ # remove the imports file name. functions must be in or below the dir
60
+ # where the functions file is.
61
+ #
62
+ # /x/y/z/function.imports
63
+ # /x/y/z
64
+ # from a.b.c import C as cone
65
+ #
66
+ # we look in /x/y/z/a/b/c.py for class C
67
+ # base module clss
68
+ #
69
+ cs = stmt.split(" ")
70
+ if len(cs) >= 4 and cs[0] == "from" and cs[2] == "import":
71
+ module_name = cs[1]
72
+ class_name = cs[3]
73
+ else:
74
+ raise ClassLoadingError(f"Unclear class loading import statement: {stmt}")
75
+ #
76
+ # Resolve the file path for the module
77
+ #
78
+ module_path = os.path.join(base_path, module_name)
79
+ module_path = module_path.replace(".", os.sep)
80
+ module_path = f"{module_path}.py"
81
+ if not os.path.exists(module_path):
82
+ raise ImportError(f"Module {module_name} not found in {module_path}")
83
+ #
84
+ # create a unique module spec. we hash the full path to the bytes in order
85
+ # to make sure we have a distinct class, even if one project names and locates
86
+ # a class in the exact same relative location.
87
+ #
88
+ # e.g. project A has a function.imports file at config/function.imports that defines a class B as:
89
+ # from b import B as bee
90
+ # project B has a function.imports file at config/function.imports that defines a class B as:
91
+ # from b import B as bee
92
+ # These two class Bs would be identified exactly the same way even though they are different. We
93
+ # don't ever want a request for project B's class B to be returned when project A requests a
94
+ # class B. The hash keeps the names distinct.
95
+ #
96
+ try:
97
+ import py_compile
98
+ py_compile.compile(str(module_path), doraise=True)
99
+ print(f"Compiled fine")
100
+ except Exception as ex:
101
+ print(f"Cannot compile: {ex}")
102
+
103
+ try:
104
+ print("ABS:", os.path.abspath(module_path))
105
+ print("REAL:", os.path.realpath(module_path))
106
+ print("EXISTS:", os.path.exists(module_path))
107
+ print("ISFILE:", os.path.isfile(module_path))
108
+ print("ACCESS_R:", os.access(module_path, os.R_OK))
109
+ print("ACCESS_X:", os.access(module_path, os.X_OK))
110
+ except Exception as ex:
111
+ print(f"Cannot print module_path attributes: {ex}")
112
+
113
+ spec = importlib.util.spec_from_file_location(
114
+ f"{module_name}_{hash(module_path)}", # unique name per loader instance
115
+ str(module_path),
116
+ )
117
+ module = importlib.util.module_from_spec(spec)
118
+ loader = spec.loader
119
+ if loader is None:
120
+ raise ImportError(f"Could not load spec for {module_name} at {module_path}")
121
+ loader.exec_module(module)
122
+ cls = getattr(module, class_name)
123
+ instance = cls(*args, **kwargs)
124
+ return instance
125
+ """
126
+
127
+ @classmethod
128
+ def load_private_class(cls, base_path: str, stmt: str, *args, **kwargs):
129
+ if not stmt or stmt.strip() == "":
130
+ raise ValueError("Load statement cannot be None or ''")
131
+ module_name = None
132
+ class_name = None
133
+ #
134
+ # remove the imports file name. functions must be in or below the dir
135
+ # where the functions file is.
136
+ #
137
+ # /x/y/z/function.imports
138
+ # /x/y/z
139
+ # from a.b.c import C as cone
140
+ #
141
+ # we look in /x/y/z/a/b/c.py for class C
142
+ # base module clss
143
+ #
144
+ cs = stmt.split(" ")
145
+ if len(cs) >= 4 and cs[0] == "from" and cs[2] == "import":
146
+ module_name = cs[1]
147
+ class_name = cs[3]
148
+ else:
149
+ raise ClassLoadingError(f"Unclear class loading import statement: {stmt}")
150
+ #
151
+ # Resolve the file path for the module
152
+ #
153
+ module_path = os.path.join(base_path, module_name)
154
+ module_path = module_path.replace(".", os.sep)
155
+ module_path = f"{module_path}.py"
156
+ if not os.path.exists(module_path):
157
+ raise ImportError(f"Module {module_name} not found in {module_path}")
158
+ #
159
+ # create a unique module spec. we hash the full path to the bytes in order
160
+ # to make sure we have a distinct class, even if one project names and locates
161
+ # a class in the exact same relative location.
162
+ #
163
+ # e.g. project A has a function.imports file at config/function.imports that defines a class B as:
164
+ # from b import B as bee
165
+ # project B has a function.imports file at config/function.imports that defines a class B as:
166
+ # from b import B as bee
167
+ # These two class Bs would be identified exactly the same way even though they are different. We
168
+ # don't ever want a request for project B's class B to be returned when project A requests a
169
+ # class B. The hash keeps the names distinct.
170
+ #
171
+ compiled_path = None
172
+ try:
173
+ import py_compile
174
+ #py_compile.compile(str(module_path), doraise=True)
175
+
176
+ compiled_path = py_compile.compile(
177
+ str(module_path),
178
+ cfile=str(module_path) + "c", # or any path you choose
179
+ doraise=True
180
+ )
181
+
182
+ print(f"Compiled fine to: {compiled_path}")
183
+
184
+ except Exception as ex:
185
+ print(f"Cannot compile: {ex}")
186
+ try:
187
+ print("ABS:", os.path.abspath(module_path))
188
+ print("REAL:", os.path.realpath(module_path))
189
+ print("EXISTS:", os.path.exists(module_path))
190
+ print("ISFILE:", os.path.isfile(module_path))
191
+ print("ACCESS_R:", os.access(module_path, os.R_OK))
192
+ print("ACCESS_X:", os.access(module_path, os.X_OK))
193
+ except Exception as ex:
194
+ print(f"Cannot print module_path attributes: {ex}")
195
+ """
196
+ spec = importlib.util.spec_from_file_location(
197
+ f"{module_name}_{hash(module_path)}", # unique name per loader instance
198
+ str(module_path),
199
+ )
200
+ """
201
+ spec = importlib.util.spec_from_file_location(
202
+ f"{module_name}_{hash(compiled_path)}",
203
+ compiled_path
204
+ )
205
+ #module = importlib.util.module_from_spec(spec)
206
+ #spec.loader.exec_module(module)
207
+
208
+ module = importlib.util.module_from_spec(spec)
209
+ loader = spec.loader
210
+ if loader is None:
211
+ raise ImportError(f"Could not load spec for {module_name} at {module_path}")
212
+ loader.exec_module(module)
213
+ cls = getattr(module, class_name)
214
+ instance = cls(*args, **kwargs)
215
+ return instance
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "csvpath"
3
- version = "0.0.586"
3
+ version = "0.0.588"
4
4
  description = "A data preboarding framework for ingesting, managing, and validating CSV, Excel, and other tabular data files using a Collect, Store, Validate, Publish architecture to create a trusted publisher for downstream data consumers."
5
5
  authors = ["David Kershaw <info@csvpath.org>"]
6
6
  readme = "README.md"
@@ -1,105 +0,0 @@
1
- import importlib
2
- import os
3
- from typing import Any
4
-
5
-
6
- class ClassLoadingError(RuntimeError):
7
- ...
8
-
9
-
10
- class ClassLoader:
11
- #
12
- # load is fine for classes we expect. e.g. we load specific types of data readers and writers
13
- # using this method without any concerns about different projects needing to not collide. today
14
- # we treat integration listeners the same way, but longer term we need those to be able to be
15
- # custom loaded too.
16
- #
17
- @classmethod
18
- def load(cls, s: str, args: list = None, kwargs: dict = None) -> Any:
19
- s = s.strip()
20
- if s != "":
21
- instance = None
22
- cs = s.split(" ")
23
- #
24
- # lines in config are like:
25
- # from module import class
26
- #
27
- if len(cs) == 4 and cs[0] == "from" and cs[2] == "import":
28
- module = importlib.import_module(cs[1])
29
- class_ = getattr(module, cs[3])
30
- args = args if args is not None else []
31
- kwargs = kwargs if kwargs is not None else {}
32
- instance = class_(*args, **kwargs)
33
- return instance
34
- else:
35
- raise ClassLoadingError(f"Unclear class loading import statement: {s}")
36
- return None
37
-
38
- #
39
- # this loads a custom function using a name that is distinct across projects so there
40
- # is no risk of name collisions.
41
- #
42
- @classmethod
43
- def load_private_function(cls, config, stmt: str, *args, **kwargs):
44
- imports = config.get(section="functions", name="imports")
45
- if not imports or str(imports).strip() == "":
46
- raise ValueError("Imports cannot be None or ''")
47
- imports = os.path.dirname(imports)
48
- return cls.load_private_class(imports, stmt, *args, **kwargs)
49
-
50
- @classmethod
51
- def load_private_class(cls, base_path: str, stmt: str, *args, **kwargs):
52
- if not stmt or stmt.strip() == "":
53
- raise ValueError("Load statement cannot be None or ''")
54
- module_name = None
55
- class_name = None
56
- #
57
- # remove the imports file name. functions must be in or below the dir
58
- # where the functions file is.
59
- #
60
- # /x/y/z/function.imports
61
- # /x/y/z
62
- # from a.b.c import C as cone
63
- #
64
- # we look in /x/y/z/a/b/c.py for class C
65
- # base module clss
66
- #
67
- cs = stmt.split(" ")
68
- if len(cs) >= 4 and cs[0] == "from" and cs[2] == "import":
69
- module_name = cs[1]
70
- class_name = cs[3]
71
- else:
72
- raise ClassLoadingError(f"Unclear class loading import statement: {stmt}")
73
- #
74
- # Resolve the file path for the module
75
- #
76
- module_path = os.path.join(base_path, module_name)
77
- module_path = module_path.replace(".", os.sep)
78
- module_path = f"{module_path}.py"
79
- if not os.path.exists(module_path):
80
- raise ImportError(f"Module {module_name} not found in {module_path}")
81
- #
82
- # create a unique module spec. we hash the full path to the bytes in order
83
- # to make sure we have a distinct class, even if one project names and locates
84
- # a class in the exact same relative location.
85
- #
86
- # e.g. project A has a function.imports file at config/function.imports that defines a class B as:
87
- # from b import B as bee
88
- # project B has a function.imports file at config/function.imports that defines a class B as:
89
- # from b import B as bee
90
- # These two class Bs would be identified exactly the same way even though they are different. We
91
- # don't ever want a request for project B's class B to be returned when project A requests a
92
- # class B. The hash keeps the names distinct.
93
- #
94
- spec = importlib.util.spec_from_file_location(
95
- f"{module_name}_{hash(module_path)}", # unique name per loader instance
96
- str(module_path),
97
- )
98
- module = importlib.util.module_from_spec(spec)
99
- loader = spec.loader
100
- if loader is None:
101
- raise ImportError(f"Could not load spec for {module_name} at {module_path}")
102
- loader.exec_module(module)
103
- cls = getattr(module, class_name)
104
- instance = cls(*args, **kwargs)
105
- return instance
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes