csvpath 0.0.535__tar.gz → 0.0.537__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.
- {csvpath-0.0.535 → csvpath-0.0.537}/PKG-INFO +1 -1
- {csvpath-0.0.535 → csvpath-0.0.537/assets}/config/config.ini +17 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/config/jenkins-windows-local.ini +9 -39
- {csvpath-0.0.535/assets → csvpath-0.0.537}/config/config.ini +17 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/csvpaths.py +32 -2
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/errors/error.py +9 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/files/file_registrar.py +3 -1
- csvpath-0.0.537/csvpath/managers/integrations/scripts/scripts_results_listener.py +111 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sftp/sftp_sender.py +3 -1
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/slack/sender.py +2 -1
- csvpath-0.0.537/csvpath/managers/integrations/webhook/webhook_listener.py +135 -0
- csvpath-0.0.537/csvpath/managers/integrations/webhook/webhook_results_listener.py +149 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/paths/paths_manager.py +155 -2
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/results/result.py +7 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/results/result_registrar.py +6 -9
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/results/results_manager.py +136 -24
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/results/results_metadata.py +4 -1
- csvpath-0.0.537/csvpath/managers/test_listener.py +18 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/util/print_parser.py +3 -2
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/config.py +12 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/references/files_reference_finder.py +29 -13
- csvpath-0.0.537/csvpath/util/references/ref_utils.py +141 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/references/results_reference_finder.py +72 -29
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/sftp/sftp_config.py +25 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/var_utility.py +49 -20
- {csvpath-0.0.535 → csvpath-0.0.537}/pyproject.toml +1 -1
- csvpath-0.0.535/csvpath/util/references/ref_utils.py +0 -77
- {csvpath-0.0.535 → csvpath-0.0.537}/LICENSE +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/README.md +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/config/function.imports +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/config/jenkins-local-azure.ini +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/config/jenkins-local-filesystem-mysql.ini +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/config/jenkins-local-filesystem.ini +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/config/jenkins-local-gcs.ini +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/config/jenkins-local-sftp.ini +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/config/jenkins-s3.ini +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/config/jenkins-windows-azure.ini +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/config/jenkins-windows-sftp.ini +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/config/local-localhost-sftp.ini +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/integrations/sftpplus/handle_auto_arrival.bat +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/integrations/sftpplus/handle_auto_arrival.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/integrations/sftpplus/handle_auto_arrival.sh +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/integrations/sftpplus/handle_mailbox_arrival.bat +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/integrations/sftpplus/handle_mailbox_arrival.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/integrations/sftpplus/handle_mailbox_arrival.sh +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/integrations/sqlite/csvpath +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/assets/integrations/sqlite/schema.sql +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/__init__.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/cli/__init__.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/cli/asker.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/cli/cli.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/cli/const.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/cli/debug_config.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/cli/drill_down.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/cli/function_describer.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/cli/function_lister.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/cli/selecter.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/csvpath.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/__init__.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/errors/error_collector.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/errors/error_comms.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/errors/error_manager.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/files/file_manager.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/files/file_metadata.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/files/files_listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/files/lines_and_headers_cacher.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/ckan/ckan.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/ckan/ckan_listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/ckan/datafile.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/ckan/dataset.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/ol/event.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/ol/event_result.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/ol/file_listener_ol.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/ol/job.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/ol/ol_listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/ol/paths_listener_ol.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/ol/result_listener_ol.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/ol/results_listener_ol.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/ol/run.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/ol/run_listener_ol.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/ol/run_state.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/ol/sender.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/otlp/error_metrics.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/otlp/metrics.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/otlp/otlp_error_listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/otlp/otlp_listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/otlp/otlp_result_listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/otlp/otlp_results_listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sftpplus/arrival_handler.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sftpplus/rpc.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sftpplus/sftpplus_listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sftpplus/transfer_creator.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sftpplus/transfers.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/slack/event.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sql/engine.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sql/sql_file_listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sql/sql_listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sql/sql_paths_listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sql/sql_result_listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sql/sql_results_listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sql/tables.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sql/updates.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sqlite/schema.sql +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sqlite/sqlite_result_listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/integrations/sqlite/sqlite_results_listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/metadata.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/paths/paths_listener.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/paths/paths_metadata.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/paths/paths_registrar.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/registrar.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/results/readers/file_errors_reader.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/results/readers/file_lines_reader.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/results/readers/file_printouts_reader.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/results/readers/file_unmatched_reader.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/results/readers/readers.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/results/result_file_reader.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/results/result_metadata.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/results/result_serializer.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/results/results_registrar.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/run/run_listener_stdout.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/run/run_metadata.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/managers/run/run_registrar.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/__init__.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/__init__.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/args.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/args_helper.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/boolean/all.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/boolean/andf.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/boolean/any.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/boolean/between.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/boolean/empty.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/boolean/exists.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/boolean/inf.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/boolean/no.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/boolean/notf.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/boolean/orf.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/boolean/yes.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/counting/count.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/counting/count_bytes.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/counting/count_headers.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/counting/count_lines.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/counting/count_scans.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/counting/counter.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/counting/every.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/counting/has_matches.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/counting/increment.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/counting/tally.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/counting/total_lines.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/dates/now.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/function.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/function_factory.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/function_finder.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/function_focus.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/headers/append.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/headers/collect.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/headers/empty_stack.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/headers/end.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/headers/header_name.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/headers/header_names_mismatch.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/headers/headers.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/headers/insert.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/headers/mismatch.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/headers/replace.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/headers/reset_headers.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/lines/advance.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/lines/after_blank.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/lines/dups.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/lines/first.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/lines/first_line.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/lines/last.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/lines/stop.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/math/above.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/math/add.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/math/divide.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/math/equals.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/math/intf.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/math/mod.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/math/multiply.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/math/odd.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/math/round.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/math/subtotal.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/math/subtract.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/math/sum.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/misc/fingerprint.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/misc/importf.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/misc/random.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/print/jinjaf.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/print/print_line.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/print/print_queue.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/print/printf.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/print/table.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/stats/minf.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/stats/percent.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/stats/percent_unique.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/stats/stdev.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/strings/alter.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/strings/caps.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/strings/concat.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/strings/contains.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/strings/length.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/strings/lower.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/strings/metaphone.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/strings/regex.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/strings/starts_with.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/strings/strip.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/strings/substring.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/strings/upper.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/testing/debug.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/types/__init__.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/types/boolean.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/types/datef.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/types/decimal.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/types/email.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/types/nonef.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/types/string.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/types/type.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/types/url.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/validity/fail.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/validity/failed.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/validity/line.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/variables/get.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/variables/pushpop.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/variables/put.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/variables/track.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/functions/variables/variables.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/lark_parser.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/lark_transformer.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/matcher.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/productions/__init__.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/productions/equality.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/productions/expression.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/productions/header.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/productions/matchable.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/productions/qualified.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/productions/reference.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/productions/term.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/productions/variable.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/util/exceptions.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/util/expression_encoder.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/util/expression_utility.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/util/lark_print_parser.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/matching/util/runtime_data_collector.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/modes/error_mode.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/modes/explain_mode.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/modes/files_mode.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/modes/logic_mode.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/modes/mode_controller.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/modes/print_mode.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/modes/return_mode.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/modes/run_mode.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/modes/source_mode.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/modes/transfer_mode.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/modes/unmatched_mode.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/modes/validation_mode.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/scanning/__init__.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/scanning/exceptions.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/scanning/parser.out +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/scanning/parsetab.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/scanning/scanner.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/scanning/scanning_lexer.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/azure/azure_data_reader.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/azure/azure_data_writer.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/azure/azure_fingerprinter.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/azure/azure_nos.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/azure/azure_utils.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/azure/azure_xlsx_data_reader.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/box.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/cache.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/caser.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/class_loader.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/code.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/config_exception.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/exceptions.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/file_info.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/file_readers.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/file_writers.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/gcs/gcs_data_reader.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/gcs/gcs_data_writer.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/gcs/gcs_fingerprinter.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/gcs/gcs_nos.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/gcs/gcs_utils.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/gcs/gcs_xlsx_data_reader.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/hasher.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/http/http_data_reader.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/intermediary.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/last_line_stats.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/line_counter.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/line_monitor.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/line_spooler.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/log_utility.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/metadata_parser.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/nos.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/pandas_data_reader.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/path_util.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/printer.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/references/reference_parser.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/run_home_maker.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/s3/s3_data_reader.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/s3/s3_data_writer.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/s3/s3_fingerprinter.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/s3/s3_nos.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/s3/s3_utils.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/s3/s3_xlsx_data_reader.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/sftp/sftp_data_reader.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/sftp/sftp_data_writer.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/sftp/sftp_fingerprinter.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/sftp/sftp_nos.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/sftp/sftp_walk.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/sftp/sftp_xlsx_data_reader.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/sqliter.py +0 -0
- {csvpath-0.0.535 → csvpath-0.0.537}/csvpath/util/template_util.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: csvpath
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.537
|
|
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
|
|
@@ -40,6 +40,14 @@ csvpaths = inputs/named_paths
|
|
|
40
40
|
#files = sftp://172.17.0.3:10022/inputs/named_files
|
|
41
41
|
on_unmatched_file_fingerprints = halt
|
|
42
42
|
|
|
43
|
+
[testing]
|
|
44
|
+
azure.skip=yes
|
|
45
|
+
gcs.skip=yes
|
|
46
|
+
s3.skip=yes
|
|
47
|
+
sftp.skip=yes
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
43
51
|
#
|
|
44
52
|
# integrations activation
|
|
45
53
|
#
|
|
@@ -48,6 +56,12 @@ on_unmatched_file_fingerprints = halt
|
|
|
48
56
|
groups =
|
|
49
57
|
#slack, marquez, ckan, sftp, sftpplus, otlp, default, sqlite
|
|
50
58
|
|
|
59
|
+
# general purpose webhook caller
|
|
60
|
+
webhook.results = from csvpath.managers.integrations.webhook.webhook_results_listener import WebhookResultListener
|
|
61
|
+
|
|
62
|
+
# add a listener to exec scripts at the end of named-paths group runs
|
|
63
|
+
scripts.results = from csvpath.managers.integrations.scripts.scripts_results_listener import ScriptsResultsListener
|
|
64
|
+
|
|
51
65
|
# add sql to capture staging, loads, and results in mysql, postgres, ms sql server, or sqlite
|
|
52
66
|
sql.file = from csvpath.managers.integrations.sql.sql_file_listener import SqlFileListener
|
|
53
67
|
sql.paths = from csvpath.managers.integrations.sql.sql_paths_listener import SqlPathsListener
|
|
@@ -145,4 +159,7 @@ verify = False
|
|
|
145
159
|
# on-invalid-slack: webhook-minus-'https://'
|
|
146
160
|
webhook_url =
|
|
147
161
|
|
|
162
|
+
[scripts]
|
|
163
|
+
run_scripts = yes
|
|
164
|
+
shell = /bin/bash
|
|
148
165
|
|
|
@@ -5,8 +5,8 @@ extensions = txt, csvpath, csvpaths
|
|
|
5
5
|
extensions = txt, csv, tsv, dat, tab, psv, ssv
|
|
6
6
|
|
|
7
7
|
[errors]
|
|
8
|
-
csvpath = raise, collect,
|
|
9
|
-
csvpaths = raise, collect
|
|
8
|
+
csvpath = raise, collect, print
|
|
9
|
+
csvpaths = raise, collect, print
|
|
10
10
|
use_format = full
|
|
11
11
|
pattern = {time}:{file}:{line}:{paths}:{instance}:{chain}: {message}
|
|
12
12
|
|
|
@@ -16,7 +16,6 @@ csvpaths = debug
|
|
|
16
16
|
log_file = logs\csvpath.log
|
|
17
17
|
log_files_to_keep = 100
|
|
18
18
|
log_file_size = 52428800
|
|
19
|
-
# file or rotating
|
|
20
19
|
handler = file
|
|
21
20
|
|
|
22
21
|
[config]
|
|
@@ -37,58 +36,29 @@ files = inputs\named_files
|
|
|
37
36
|
csvpaths = inputs\named_paths
|
|
38
37
|
on_unmatched_file_fingerprints = halt
|
|
39
38
|
|
|
40
|
-
#
|
|
41
|
-
# integrations activation
|
|
42
|
-
#
|
|
43
|
-
|
|
44
39
|
[listeners]
|
|
45
|
-
groups =
|
|
46
|
-
|
|
40
|
+
groups = scripts
|
|
41
|
+
scripts.results = from csvpath.managers.integrations.scripts.scripts_results_listener import ScriptsResultsListener
|
|
47
42
|
|
|
48
|
-
# add sqlite to capture staging, loads, and results in a local sqlite db
|
|
49
43
|
sqlite.result = from csvpath.managers.integrations.sqlite.sqlite_result_listener import SqliteResultListener
|
|
50
44
|
sqlite.results = from csvpath.managers.integrations.sqlite.sqlite_results_listener import SqliteResultsListener
|
|
51
|
-
|
|
52
|
-
# these simple default listeners track all files staged and all paths loaded in
|
|
53
|
-
# central manifests. unlike other manifest writers, if they have multiple
|
|
54
|
-
# concurrent users they have potential a race condition. users that do not
|
|
55
|
-
# share inputs directories do not need to worry about this. you should vet
|
|
56
|
-
# using them against your use case; potential utility vs. the modest but non-0
|
|
57
|
-
# risk of lost updates. they can be disabled with little loss of function.
|
|
58
|
-
# alternatively a database-backed version may be more suitable.
|
|
59
45
|
default.file = from csvpath.managers.files.files_listener import FilesListener
|
|
60
46
|
default.paths = from csvpath.managers.paths.paths_listener import PathsListener
|
|
61
|
-
|
|
62
|
-
# add otlp to support any OpenTelemetry backend
|
|
63
47
|
otlp.result = from csvpath.managers.integrations.otlp.otlp_result_listener import OpenTelemetryResultListener
|
|
64
48
|
otlp.results = from csvpath.managers.integrations.otlp.otlp_results_listener import OpenTelemetryResultsListener
|
|
65
49
|
otlp.errors = from csvpath.managers.integrations.otlp.otlp_error_listener import OpenTelemetryErrorListener
|
|
66
|
-
|
|
67
|
-
# add sftpplus to the list of groups above to automate registration and named-paths group runs on file arrival at an SFTPPlus server
|
|
68
50
|
sftpplus.paths = from csvpath.managers.integrations.sftpplus.sftpplus_listener import SftpPlusListener
|
|
69
|
-
|
|
70
|
-
# add sftp to the list of groups above to push results to an sftp account
|
|
71
51
|
sftp.results = from csvpath.managers.integrations.sftp.sftp_listener import SftpListener
|
|
72
|
-
|
|
73
|
-
# add ckan to the list of groups above for alerts to slack webhooks
|
|
74
52
|
ckan.results = from csvpath.managers.integrations.ckan.ckan_listener import CkanListener
|
|
75
|
-
|
|
76
|
-
#add marquez to the list of groups above for OpenLineage events to a Marquez server
|
|
77
53
|
marquez.file = from csvpath.managers.integrations.ol.file_listener_ol import OpenLineageFileListener
|
|
78
54
|
marquez.paths = from csvpath.managers.integrations.ol.paths_listener_ol import OpenLineagePathsListener
|
|
79
55
|
marquez.result = from csvpath.managers.integrations.ol.result_listener_ol import OpenLineageResultListener
|
|
80
56
|
marquez.results = from csvpath.managers.integrations.ol.results_listener_ol import OpenLineageResultsListener
|
|
81
|
-
|
|
82
|
-
# add slack to the list of groups above for alerts to slack webhooks
|
|
83
57
|
slack.file = from csvpath.managers.integrations.slack.sender import SlackSender
|
|
84
58
|
slack.paths = from csvpath.managers.integrations.slack.sender import SlackSender
|
|
85
59
|
slack.result = from csvpath.managers.integrations.slack.sender import SlackSender
|
|
86
60
|
slack.results = from csvpath.managers.integrations.slack.sender import SlackSender
|
|
87
61
|
|
|
88
|
-
#
|
|
89
|
-
# integrations setup
|
|
90
|
-
#
|
|
91
|
-
|
|
92
62
|
[sftp]
|
|
93
63
|
server = 192.168.67.2
|
|
94
64
|
port = 10022
|
|
@@ -99,12 +69,10 @@ password = tinpenny
|
|
|
99
69
|
db = archive\csvpath.db
|
|
100
70
|
|
|
101
71
|
[sftpplus]
|
|
102
|
-
# these are only needed by the csvpath writer
|
|
103
72
|
mailbox_user = MAILBOX_USER
|
|
104
73
|
mailbox_password = MAILBOX_PASSWORD
|
|
105
74
|
server = SFTPPLUS_SERVER
|
|
106
75
|
port = SFTPPLUS_PORT
|
|
107
|
-
# these are only needed on the server
|
|
108
76
|
admin_username = SFTPPLUS_ADMIN_USERNAME
|
|
109
77
|
admin_password = SFTPPLUS_ADMIN_PASSWORD
|
|
110
78
|
api_url = https://localhost:10020/json
|
|
@@ -123,9 +91,11 @@ timeout = 5
|
|
|
123
91
|
verify = False
|
|
124
92
|
|
|
125
93
|
[slack]
|
|
126
|
-
# add your main webhook here. to set webhooks on a csvpath-by-csvpath basis add
|
|
127
|
-
# on-valid-slack: webhook-minus-'https://' and/or
|
|
128
|
-
# on-invalid-slack: webhook-minus-'https://'
|
|
129
94
|
webhook_url =
|
|
130
95
|
|
|
96
|
+
[scripts]
|
|
97
|
+
run_scripts = yes
|
|
98
|
+
shell = /bin/bash
|
|
99
|
+
|
|
100
|
+
|
|
131
101
|
|
|
@@ -40,6 +40,14 @@ csvpaths = inputs/named_paths
|
|
|
40
40
|
#files = sftp://172.17.0.3:10022/inputs/named_files
|
|
41
41
|
on_unmatched_file_fingerprints = halt
|
|
42
42
|
|
|
43
|
+
[testing]
|
|
44
|
+
azure.skip=yes
|
|
45
|
+
gcs.skip=yes
|
|
46
|
+
s3.skip=yes
|
|
47
|
+
sftp.skip=yes
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
43
51
|
#
|
|
44
52
|
# integrations activation
|
|
45
53
|
#
|
|
@@ -48,6 +56,12 @@ on_unmatched_file_fingerprints = halt
|
|
|
48
56
|
groups =
|
|
49
57
|
#slack, marquez, ckan, sftp, sftpplus, otlp, default, sqlite
|
|
50
58
|
|
|
59
|
+
# general purpose webhook caller
|
|
60
|
+
webhook.results = from csvpath.managers.integrations.webhook.webhook_results_listener import WebhookResultListener
|
|
61
|
+
|
|
62
|
+
# add a listener to exec scripts at the end of named-paths group runs
|
|
63
|
+
scripts.results = from csvpath.managers.integrations.scripts.scripts_results_listener import ScriptsResultsListener
|
|
64
|
+
|
|
51
65
|
# add sql to capture staging, loads, and results in mysql, postgres, ms sql server, or sqlite
|
|
52
66
|
sql.file = from csvpath.managers.integrations.sql.sql_file_listener import SqlFileListener
|
|
53
67
|
sql.paths = from csvpath.managers.integrations.sql.sql_paths_listener import SqlPathsListener
|
|
@@ -145,4 +159,7 @@ verify = False
|
|
|
145
159
|
# on-invalid-slack: webhook-minus-'https://'
|
|
146
160
|
webhook_url =
|
|
147
161
|
|
|
162
|
+
[scripts]
|
|
163
|
+
run_scripts = yes
|
|
164
|
+
shell = /bin/bash
|
|
148
165
|
|
|
@@ -128,8 +128,15 @@ class CsvPaths(CsvPathsCoordinator, ErrorCollector):
|
|
|
128
128
|
self._fail_all = False
|
|
129
129
|
self._skip_all = False
|
|
130
130
|
self._advance_all = 0
|
|
131
|
+
#
|
|
132
|
+
# TODO: we probably don't need all three of these
|
|
133
|
+
#
|
|
131
134
|
self._current_run_time = None
|
|
132
135
|
self._run_time_str = None
|
|
136
|
+
self._last_run_dir = None
|
|
137
|
+
#
|
|
138
|
+
#
|
|
139
|
+
#
|
|
133
140
|
self.named_paths_name = None
|
|
134
141
|
""" @private """
|
|
135
142
|
self.named_file_name = None
|
|
@@ -173,6 +180,10 @@ class CsvPaths(CsvPathsCoordinator, ErrorCollector):
|
|
|
173
180
|
"""@private"""
|
|
174
181
|
self._ecoms = ec
|
|
175
182
|
|
|
183
|
+
@property
|
|
184
|
+
def last_run_dir(self) -> str:
|
|
185
|
+
return self._last_run_dir
|
|
186
|
+
|
|
176
187
|
@property
|
|
177
188
|
def file_manager(self) -> FileManager:
|
|
178
189
|
return self._file_manager
|
|
@@ -297,7 +308,10 @@ class CsvPaths(CsvPathsCoordinator, ErrorCollector):
|
|
|
297
308
|
self._run_time_str = None
|
|
298
309
|
self.logger.debug("Cleared run coordination")
|
|
299
310
|
|
|
300
|
-
|
|
311
|
+
#
|
|
312
|
+
# we do not currently use the paths param. what was the purpose?
|
|
313
|
+
#
|
|
314
|
+
def clean(self, *, paths=None) -> None:
|
|
301
315
|
"""@private
|
|
302
316
|
at this time we do not recommend reusing CsvPaths, but it is doable
|
|
303
317
|
you should clean before reuse unless you want to accumulate results."""
|
|
@@ -518,6 +532,11 @@ class CsvPaths(CsvPathsCoordinator, ErrorCollector):
|
|
|
518
532
|
crt = maker.get_run_dir(
|
|
519
533
|
paths_name=pathsname, file_name=filename, template=template
|
|
520
534
|
)
|
|
535
|
+
#
|
|
536
|
+
# capture the last run dir for the benefit of the caller
|
|
537
|
+
#
|
|
538
|
+
self._last_run_dir = crt
|
|
539
|
+
|
|
521
540
|
results = []
|
|
522
541
|
#
|
|
523
542
|
# run starts here
|
|
@@ -647,6 +666,10 @@ class CsvPaths(CsvPathsCoordinator, ErrorCollector):
|
|
|
647
666
|
paths_name=pathsname, file_name=filename, template=template
|
|
648
667
|
)
|
|
649
668
|
#
|
|
669
|
+
# capture the last run dir for the benefit of the caller
|
|
670
|
+
#
|
|
671
|
+
self._last_run_dir = crt
|
|
672
|
+
#
|
|
650
673
|
# run starts here
|
|
651
674
|
#
|
|
652
675
|
self.run_metadata = self.results_manager.start_run(
|
|
@@ -746,6 +769,10 @@ class CsvPaths(CsvPathsCoordinator, ErrorCollector):
|
|
|
746
769
|
paths_name=pathsname, file_name=filename, template=template
|
|
747
770
|
)
|
|
748
771
|
#
|
|
772
|
+
# capture the last run dir for the benefit of the caller
|
|
773
|
+
#
|
|
774
|
+
self._last_run_dir = crt
|
|
775
|
+
#
|
|
749
776
|
# run starts here
|
|
750
777
|
#
|
|
751
778
|
self.run_metadata = self.results_manager.start_run(
|
|
@@ -980,7 +1007,6 @@ class CsvPaths(CsvPathsCoordinator, ErrorCollector):
|
|
|
980
1007
|
paths = self._get_named_paths(pathsname)
|
|
981
1008
|
if template is None:
|
|
982
1009
|
template = self.paths_manager.get_template_for_paths(pathsname)
|
|
983
|
-
|
|
984
1010
|
#
|
|
985
1011
|
# create run identity and directories
|
|
986
1012
|
#
|
|
@@ -989,6 +1015,10 @@ class CsvPaths(CsvPathsCoordinator, ErrorCollector):
|
|
|
989
1015
|
paths_name=pathsname, file_name=filename, template=template
|
|
990
1016
|
)
|
|
991
1017
|
#
|
|
1018
|
+
# capture the last run dir for the benefit of the caller
|
|
1019
|
+
#
|
|
1020
|
+
self._last_run_dir = crt
|
|
1021
|
+
#
|
|
992
1022
|
# also use of crt below
|
|
993
1023
|
#
|
|
994
1024
|
csvpath_objects = self._load_csvpath_objects(
|
|
@@ -43,6 +43,9 @@ class Error(Metadata):
|
|
|
43
43
|
self.message: str = msg
|
|
44
44
|
self.expanded_message: str = None
|
|
45
45
|
self.filename: str = None
|
|
46
|
+
self.run_dir = None
|
|
47
|
+
if error_manager and error_manager.csvpaths:
|
|
48
|
+
self.run_dir = error_manager.csvpaths.last_run_dir
|
|
46
49
|
self.cwd = os.getcwd()
|
|
47
50
|
self.pid = os.getpid()
|
|
48
51
|
|
|
@@ -67,6 +70,7 @@ class Error(Metadata):
|
|
|
67
70
|
and self.message == e.message
|
|
68
71
|
and self.identity == e.identity
|
|
69
72
|
and self.filename == e.filename
|
|
73
|
+
and self.run_dir == e.run_dir
|
|
70
74
|
and f"{self.time}" == f"{e.time}"
|
|
71
75
|
)
|
|
72
76
|
|
|
@@ -106,6 +110,8 @@ class Error(Metadata):
|
|
|
106
110
|
"filename": self.filename,
|
|
107
111
|
"time": f"{self.time}",
|
|
108
112
|
}
|
|
113
|
+
if self.run_dir is not None:
|
|
114
|
+
ret["run_dir"] = self.run_dir
|
|
109
115
|
return ret
|
|
110
116
|
|
|
111
117
|
def from_json(self, j: dict) -> None:
|
|
@@ -127,6 +133,8 @@ class Error(Metadata):
|
|
|
127
133
|
self.identity = j["identity"]
|
|
128
134
|
if "filename" in j:
|
|
129
135
|
self.filename = j["filename"]
|
|
136
|
+
if "run_dir" in j:
|
|
137
|
+
self.run_dir = j["run_dir"]
|
|
130
138
|
if "time" in j:
|
|
131
139
|
time = dateutil.parser.parse(j["time"])
|
|
132
140
|
self.time = time
|
|
@@ -152,6 +160,7 @@ ip_address: {self.ip_address},
|
|
|
152
160
|
username: {self.username},
|
|
153
161
|
named_paths_name: {self.named_paths_name if self.named_paths_name else ""},
|
|
154
162
|
named_file_name: {self.named_file_name if self.named_file_name else ""},
|
|
163
|
+
run_dir: {self.run_dir if self.run_dir else ""},
|
|
155
164
|
filename: {self.filename if self.filename else ""},
|
|
156
165
|
path identity: {self.identity if self.identity else ""},
|
|
157
166
|
expression_index: {self.expression_index if self.expression_index else ""},
|
|
@@ -194,7 +194,9 @@ class FileRegistrar(Registrar, Listener):
|
|
|
194
194
|
#
|
|
195
195
|
# log info so nobody has to dig to see why no update
|
|
196
196
|
#
|
|
197
|
-
self.csvpaths.logger.info(
|
|
197
|
+
self.csvpaths.logger.info(
|
|
198
|
+
"File has already been registered: %s", mdata.name_home
|
|
199
|
+
)
|
|
198
200
|
return
|
|
199
201
|
self.distribute_update(mdata)
|
|
200
202
|
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import subprocess
|
|
3
|
+
import threading
|
|
4
|
+
from datetime import datetime, timezone
|
|
5
|
+
from csvpath.managers.listener import Listener
|
|
6
|
+
from csvpath.managers.metadata import Metadata
|
|
7
|
+
from csvpath.util.file_writers import DataFileWriter
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ScriptsResultsListener(Listener, threading.Thread):
|
|
11
|
+
def __init__(self, config=None):
|
|
12
|
+
Listener.__init__(self, config=config)
|
|
13
|
+
threading.Thread.__init__(self)
|
|
14
|
+
self.csvpaths = None
|
|
15
|
+
|
|
16
|
+
def run(self):
|
|
17
|
+
self._metadata_update(self.metadata)
|
|
18
|
+
|
|
19
|
+
def metadata_update(self, mdata: Metadata) -> None:
|
|
20
|
+
self.metadata = mdata
|
|
21
|
+
self.start()
|
|
22
|
+
|
|
23
|
+
def _metadata_update(self, mdata: Metadata) -> None:
|
|
24
|
+
if not self.csvpaths:
|
|
25
|
+
raise RuntimeError(
|
|
26
|
+
"Scripts results listener cannot continue without a CsvPaths instance"
|
|
27
|
+
)
|
|
28
|
+
if mdata.time_completed is None:
|
|
29
|
+
return
|
|
30
|
+
#
|
|
31
|
+
# if we set a flag to run scripts we will, if any. otherwise, we skip.
|
|
32
|
+
#
|
|
33
|
+
run = self.csvpaths.config.get(section="scripts", name="run_scripts")
|
|
34
|
+
if run is None or run.strip() != "yes":
|
|
35
|
+
self.csvpaths.logger.info(
|
|
36
|
+
"Not running completion scripts, if any, because run_scripts is not yes"
|
|
37
|
+
)
|
|
38
|
+
return
|
|
39
|
+
#
|
|
40
|
+
# find any scripts
|
|
41
|
+
#
|
|
42
|
+
pm = self.csvpaths.paths_manager
|
|
43
|
+
cfg = pm.get_config_for_paths(mdata.named_paths_name)
|
|
44
|
+
if cfg is None:
|
|
45
|
+
return
|
|
46
|
+
#
|
|
47
|
+
# all runs for every execution, regardless of completeness, validity, etc.
|
|
48
|
+
#
|
|
49
|
+
t = "on_complete_all_script"
|
|
50
|
+
all_script = cfg.get(t)
|
|
51
|
+
if all_script is not None and all_script.strip() != "":
|
|
52
|
+
self._run(mdata=mdata, script_name=all_script, script_type=t)
|
|
53
|
+
#
|
|
54
|
+
# valid and invalid run according to the mdata:
|
|
55
|
+
# self.all_valid: bool = None
|
|
56
|
+
# self.error_count: int = None
|
|
57
|
+
#
|
|
58
|
+
if mdata.all_valid is True:
|
|
59
|
+
t = "on_complete_valid_script"
|
|
60
|
+
valid_script = cfg.get(t)
|
|
61
|
+
if valid_script is not None and valid_script.strip() != "":
|
|
62
|
+
self._run(mdata=mdata, script_name=valid_script, script_type=t)
|
|
63
|
+
else:
|
|
64
|
+
t = "on_complete_invalid_script"
|
|
65
|
+
invalid_script = cfg.get(t)
|
|
66
|
+
if invalid_script is not None and invalid_script.strip() != "":
|
|
67
|
+
self._run(mdata=mdata, script_name=invalid_script, script_type=t)
|
|
68
|
+
if mdata.error_count > 0:
|
|
69
|
+
t = "on_complete_error_script"
|
|
70
|
+
error_script = cfg.get(t)
|
|
71
|
+
if error_script is not None and error_script.strip() != "":
|
|
72
|
+
self._run(mdata=mdata, script_name=error_script, script_type=t)
|
|
73
|
+
|
|
74
|
+
def _run(self, *, mdata, script_name, script_type) -> None:
|
|
75
|
+
#
|
|
76
|
+
# get the script's bytes
|
|
77
|
+
# write to a temp file
|
|
78
|
+
# execute the file catching system out
|
|
79
|
+
# write system out to a script_name-timestamp.txt file in the results dir
|
|
80
|
+
#
|
|
81
|
+
try:
|
|
82
|
+
b = self.csvpaths.paths_manager.get_script_for_paths(
|
|
83
|
+
name=mdata.named_paths_name, script_type=script_type
|
|
84
|
+
)
|
|
85
|
+
path = os.path.dirname(mdata.manifest_path)
|
|
86
|
+
path = os.path.join(path, script_name)
|
|
87
|
+
with DataFileWriter(path=path) as to:
|
|
88
|
+
to.write(b)
|
|
89
|
+
#
|
|
90
|
+
# below is supposedly cross platform but just in case.
|
|
91
|
+
#
|
|
92
|
+
try:
|
|
93
|
+
os.chmod(path, 0o755)
|
|
94
|
+
except Exception:
|
|
95
|
+
...
|
|
96
|
+
result = subprocess.run([path], capture_output=True, text=True, check=True)
|
|
97
|
+
out = result.stdout
|
|
98
|
+
err = result.stderr
|
|
99
|
+
if err is not None and err.strip() != "":
|
|
100
|
+
out = f"{out}\n ===================== \n{err}"
|
|
101
|
+
n = datetime.now(timezone.utc)
|
|
102
|
+
script_out_name = f"{script_name}-{n.strftime('%Y-%m-%d_%H-%M-%S_%f')}.txt"
|
|
103
|
+
script_out_path = mdata.run_home
|
|
104
|
+
script_out_path = os.path.join(script_out_path, script_out_name)
|
|
105
|
+
with DataFileWriter(path=script_out_path) as writer:
|
|
106
|
+
writer.write(out)
|
|
107
|
+
except Exception as e:
|
|
108
|
+
msg = f"Run script failed on results {mdata.named_paths_name}, script_name {script_name}, with {type(e)}: {e}"
|
|
109
|
+
self.csvpaths.logger.error(msg)
|
|
110
|
+
if self.csvpaths.ecoms.do_i_raise():
|
|
111
|
+
raise RuntimeError(msg) from e
|
|
@@ -48,7 +48,9 @@ class SftpSender(Listener, threading.Thread):
|
|
|
48
48
|
self._password = VarUtility.get_str(m, v, "sftp-password")
|
|
49
49
|
self._target_path = VarUtility.get_str(m, v, "sftp-target-path")
|
|
50
50
|
self._original = VarUtility.get_bool(m, v, "sftp-original-data")
|
|
51
|
-
self._files = VarUtility.get_value_pairs(
|
|
51
|
+
self._files = VarUtility.get_value_pairs(
|
|
52
|
+
metadata=m, variables=v, key="sftp-files"
|
|
53
|
+
)
|
|
52
54
|
|
|
53
55
|
def run(self):
|
|
54
56
|
self.csvpaths.logger.info("Checking for requests to send result files by SFTP")
|
|
@@ -9,7 +9,8 @@ from .event import EventBuilder
|
|
|
9
9
|
|
|
10
10
|
class SlackSender(Listener, threading.Thread):
|
|
11
11
|
def __init__(self, *, config=None):
|
|
12
|
-
|
|
12
|
+
Listener.__init__(self, config=config)
|
|
13
|
+
threading.Thread.__init__(self)
|
|
13
14
|
self._url = None
|
|
14
15
|
self.csvpaths = None
|
|
15
16
|
self.result = None
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import threading
|
|
3
|
+
|
|
4
|
+
from abc import ABC
|
|
5
|
+
from csvpath.managers.metadata import Metadata
|
|
6
|
+
from csvpath.managers.listener import Listener
|
|
7
|
+
from csvpath.matching.util.expression_utility import ExpressionUtility
|
|
8
|
+
|
|
9
|
+
#
|
|
10
|
+
# ~
|
|
11
|
+
# webhook-url: https://zapier.com/hooks/asdf
|
|
12
|
+
# webhook-data: name > var|name, phone > $mygroup#result.variables.cell, $.csvpath.total_lines
|
|
13
|
+
#
|
|
14
|
+
#
|
|
15
|
+
# webhook-file: $.results.files.data, $mygroup#myinstance.results.files.errors
|
|
16
|
+
# $.results.
|
|
17
|
+
# $clean-invoices.results.acme/invoices/2025/Feb:0.step-three#var|cell
|
|
18
|
+
# $mygroup#myinstance.variables.cell
|
|
19
|
+
#
|
|
20
|
+
# ~
|
|
21
|
+
#
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class WebhookException(Exception):
|
|
25
|
+
...
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class WebhookListener(Listener, threading.Thread):
|
|
29
|
+
ON_ALL = "on_complete_all_webhook"
|
|
30
|
+
ON_VALID = "on_complete_valid_webhook"
|
|
31
|
+
ON_INVALID = "on_complete_invalid_webhook"
|
|
32
|
+
ON_ERRORS = "on_complete_errors_webhook"
|
|
33
|
+
|
|
34
|
+
HOOKS = None
|
|
35
|
+
URLS = None
|
|
36
|
+
|
|
37
|
+
ALL_URL = "all_webhook_url"
|
|
38
|
+
VALID_URL = "valid_webhook_url"
|
|
39
|
+
INVALID_URL = "invalid_webhook_url"
|
|
40
|
+
ERRORS_URL = "errors_webhook_url"
|
|
41
|
+
|
|
42
|
+
def __init__(self, config=None):
|
|
43
|
+
super().__init__(config)
|
|
44
|
+
self._url = None
|
|
45
|
+
self.csvpaths = None
|
|
46
|
+
self.result = None
|
|
47
|
+
self.metadata = None
|
|
48
|
+
self._timeout = -1
|
|
49
|
+
if WebhookListener.HOOKS is None:
|
|
50
|
+
WebhookListener.HOOKS = [
|
|
51
|
+
WebhookListener.ON_ALL,
|
|
52
|
+
WebhookListener.ON_VALID,
|
|
53
|
+
WebhookListener.ON_INVALID,
|
|
54
|
+
WebhookListener.ON_ERRORS,
|
|
55
|
+
]
|
|
56
|
+
if WebhookListener.URLS is None:
|
|
57
|
+
WebhookListener.URLS = {
|
|
58
|
+
WebhookListener.ON_ALL: WebhookListener.ALL_URL,
|
|
59
|
+
WebhookListener.ON_VALID: WebhookListener.VALID_URL,
|
|
60
|
+
WebhookListener.ON_INVALID: WebhookListener.INVALID_URL,
|
|
61
|
+
WebhookListener.ON_ERRORS: WebhookListener.ERRORS_URL,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def timeout(self) -> int:
|
|
66
|
+
if self._timeout == -1:
|
|
67
|
+
t = self.csvpaths.config.get(section="webhook", name="timeout", default=3)
|
|
68
|
+
t = ExpressionUtility.to_float(t)
|
|
69
|
+
if isinstance(t, float):
|
|
70
|
+
self._timeout = t
|
|
71
|
+
else:
|
|
72
|
+
self._timeout = 3
|
|
73
|
+
return self._timeout
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def csvpath(self):
|
|
77
|
+
return self.result.csvpath
|
|
78
|
+
|
|
79
|
+
def run(self):
|
|
80
|
+
self._metadata_update(self.metadata)
|
|
81
|
+
|
|
82
|
+
def metadata_update(self, mdata: Metadata) -> None:
|
|
83
|
+
self.metadata = mdata
|
|
84
|
+
self.start()
|
|
85
|
+
|
|
86
|
+
def _metadata_update(self, mdata: Metadata) -> None:
|
|
87
|
+
if mdata is None:
|
|
88
|
+
raise ValueError("Metadata cannot be None")
|
|
89
|
+
for t in WebhookListener.HOOKS:
|
|
90
|
+
try:
|
|
91
|
+
self._do_hook_if(mdata=mdata, atype=t)
|
|
92
|
+
except Exception as e:
|
|
93
|
+
if isinstance(e, WebhookException):
|
|
94
|
+
raise
|
|
95
|
+
msg = f"WebhookListener could not call {t} webhook: {type(e)}: {e}"
|
|
96
|
+
self.csvpaths.logger.error(msg)
|
|
97
|
+
if self.csvpaths.ecoms.do_i_raise():
|
|
98
|
+
raise WebhookException(msg)
|
|
99
|
+
|
|
100
|
+
def _do_hook_if(self, *, mdata: Metadata, atype: str) -> None:
|
|
101
|
+
if not self._run(mdata, atype):
|
|
102
|
+
return
|
|
103
|
+
url = self._url_for_type(mdata, WebhookListener.URLS[atype])
|
|
104
|
+
if url is None:
|
|
105
|
+
self.csvpaths.logger.debug(
|
|
106
|
+
"Nothing to do for webhook url %s", WebhookListener.URLS[atype]
|
|
107
|
+
)
|
|
108
|
+
return
|
|
109
|
+
payload = self._payload_for_type(mdata, atype)
|
|
110
|
+
#
|
|
111
|
+
# prep request
|
|
112
|
+
#
|
|
113
|
+
headers = {"Content-Type": "application/json"}
|
|
114
|
+
#
|
|
115
|
+
# send
|
|
116
|
+
#
|
|
117
|
+
x = requests.post(url, json=payload, headers=headers, timeout=self.timeout)
|
|
118
|
+
if x and x.status_code != 200:
|
|
119
|
+
if self.csvpaths is not None:
|
|
120
|
+
self.csvpaths.logger.warning(
|
|
121
|
+
"WebhookListener received status code %s from %s",
|
|
122
|
+
x.status_code,
|
|
123
|
+
"",
|
|
124
|
+
)
|
|
125
|
+
elif self.result is not None:
|
|
126
|
+
self.result.csvpath.logger.warning(
|
|
127
|
+
"WebhookListener received status code %s from %s",
|
|
128
|
+
x.status_code,
|
|
129
|
+
"",
|
|
130
|
+
)
|
|
131
|
+
else:
|
|
132
|
+
msg = f"WebhookListener received status code {x.status_code} from {self.url}"
|
|
133
|
+
self.csvpaths.logger.error(msg)
|
|
134
|
+
if self.csvpaths.ecoms.do_i_raise():
|
|
135
|
+
raise WebhookException(msg)
|