csvpath 0.0.538__tar.gz → 0.0.541__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.538 → csvpath-0.0.541}/PKG-INFO +1 -1
- {csvpath-0.0.538 → csvpath-0.0.541/assets}/config/config.ini +2 -2
- {csvpath-0.0.538/assets → csvpath-0.0.541}/config/config.ini +2 -2
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/cli/function_describer.py +5 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/csvpath.py +19 -8
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/errors/error_comms.py +9 -1
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/files/file_manager.py +11 -6
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/ol/file_listener_ol.py +1 -1
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/ol/paths_listener_ol.py +2 -2
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/ol/result_listener_ol.py +1 -1
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/ol/results_listener_ol.py +1 -1
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/ol/run_listener_ol.py +1 -1
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/paths/paths_manager.py +91 -8
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/paths/paths_registrar.py +8 -9
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/results/readers/readers.py +1 -1
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/results/results_manager.py +16 -2
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/args_helper.py +1 -1
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/boolean/all.py +18 -3
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/boolean/andf.py +15 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/boolean/any.py +28 -2
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/boolean/between.py +35 -3
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/boolean/empty.py +17 -2
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/boolean/exists.py +18 -1
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/boolean/inf.py +23 -2
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/boolean/no.py +9 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/boolean/notf.py +12 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/boolean/orf.py +17 -2
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/boolean/yes.py +9 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/counting/count.py +41 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/counting/count_bytes.py +12 -0
- csvpath-0.0.541/csvpath/matching/functions/counting/count_headers.py +44 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/counting/count_lines.py +22 -0
- csvpath-0.0.541/csvpath/matching/functions/counting/count_scans.py +32 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/counting/counter.py +7 -1
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/counting/has_matches.py +9 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/counting/increment.py +17 -2
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/counting/tally.py +24 -1
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/counting/total_lines.py +8 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/dates/now.py +23 -1
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/function.py +16 -2
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/headers/append.py +19 -2
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/headers/collect.py +26 -5
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/headers/empty_stack.py +17 -1
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/headers/end.py +15 -1
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/headers/header_name.py +37 -3
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/headers/header_names_mismatch.py +25 -9
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/headers/headers.py +17 -3
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/misc/fingerprint.py +48 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/print/printf.py +46 -8
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/stats/minf.py +33 -4
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/strings/concat.py +10 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/strings/regex.py +30 -1
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/types/nonef.py +4 -3
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/validity/fail.py +8 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/validity/failed.py +3 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/validity/line.py +14 -2
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/variables/variables.py +9 -10
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/matcher.py +6 -6
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/productions/equality.py +10 -2
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/productions/matchable.py +1 -1
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/productions/qualified.py +13 -4
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/modes/explain_mode.py +2 -2
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/config.py +106 -59
- csvpath-0.0.541/csvpath/util/date_util.py +35 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/metadata_parser.py +19 -1
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/nos.py +2 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/references/files_reference_finder.py +148 -46
- {csvpath-0.0.538 → csvpath-0.0.541}/pyproject.toml +1 -1
- csvpath-0.0.538/csvpath/matching/functions/counting/count_headers.py +0 -20
- csvpath-0.0.538/csvpath/matching/functions/counting/count_scans.py +0 -15
- {csvpath-0.0.538 → csvpath-0.0.541}/LICENSE +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/README.md +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/config/function.imports +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/config/jenkins-local-azure.ini +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/config/jenkins-local-filesystem-mysql.ini +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/config/jenkins-local-filesystem.ini +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/config/jenkins-local-gcs.ini +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/config/jenkins-local-sftp.ini +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/config/jenkins-s3.ini +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/config/jenkins-windows-azure.ini +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/config/jenkins-windows-local.ini +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/config/jenkins-windows-sftp.ini +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/config/local-localhost-sftp.ini +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/integrations/sftpplus/handle_auto_arrival.bat +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/integrations/sftpplus/handle_auto_arrival.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/integrations/sftpplus/handle_auto_arrival.sh +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/integrations/sftpplus/handle_mailbox_arrival.bat +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/integrations/sftpplus/handle_mailbox_arrival.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/integrations/sftpplus/handle_mailbox_arrival.sh +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/integrations/sqlite/csvpath +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/assets/integrations/sqlite/schema.sql +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/__init__.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/cli/__init__.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/cli/asker.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/cli/cli.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/cli/const.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/cli/debug_config.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/cli/drill_down.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/cli/function_lister.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/cli/selecter.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/csvpaths.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/__init__.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/errors/error.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/errors/error_collector.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/errors/error_manager.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/files/file_metadata.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/files/file_registrar.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/files/files_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/files/lines_and_headers_cacher.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/ckan/ckan.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/ckan/ckan_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/ckan/datafile.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/ckan/dataset.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/ol/event.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/ol/event_result.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/ol/job.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/ol/ol_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/ol/run.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/ol/run_state.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/ol/sender.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/otlp/error_metrics.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/otlp/metrics.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/otlp/otlp_error_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/otlp/otlp_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/otlp/otlp_result_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/otlp/otlp_results_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/scripts/scripts_results_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sftp/sftp_sender.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sftpplus/arrival_handler.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sftpplus/rpc.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sftpplus/sftpplus_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sftpplus/transfer_creator.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sftpplus/transfers.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/slack/event.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/slack/sender.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sql/engine.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sql/sql_file_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sql/sql_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sql/sql_paths_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sql/sql_result_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sql/sql_results_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sql/tables.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sql/updates.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sqlite/schema.sql +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sqlite/sqlite_result_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/sqlite/sqlite_results_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/webhook/webhook_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/integrations/webhook/webhook_results_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/metadata.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/paths/paths_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/paths/paths_metadata.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/registrar.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/results/readers/file_errors_reader.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/results/readers/file_lines_reader.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/results/readers/file_printouts_reader.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/results/readers/file_unmatched_reader.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/results/result.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/results/result_file_reader.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/results/result_metadata.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/results/result_registrar.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/results/result_serializer.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/results/results_metadata.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/results/results_registrar.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/run/run_listener_stdout.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/run/run_metadata.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/run/run_registrar.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/managers/test_listener.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/__init__.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/__init__.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/args.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/counting/every.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/function_factory.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/function_finder.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/function_focus.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/headers/insert.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/headers/mismatch.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/headers/replace.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/headers/reset_headers.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/lines/advance.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/lines/after_blank.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/lines/dups.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/lines/first.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/lines/first_line.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/lines/last.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/lines/stop.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/math/above.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/math/add.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/math/divide.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/math/equals.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/math/intf.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/math/mod.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/math/multiply.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/math/odd.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/math/round.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/math/subtotal.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/math/subtract.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/math/sum.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/misc/importf.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/misc/random.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/print/jinjaf.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/print/print_line.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/print/print_queue.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/print/table.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/stats/percent.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/stats/percent_unique.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/stats/stdev.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/strings/alter.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/strings/caps.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/strings/contains.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/strings/length.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/strings/lower.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/strings/metaphone.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/strings/starts_with.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/strings/strip.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/strings/substring.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/strings/upper.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/testing/debug.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/types/__init__.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/types/boolean.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/types/datef.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/types/decimal.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/types/email.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/types/string.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/types/type.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/types/url.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/variables/get.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/variables/pushpop.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/variables/put.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/functions/variables/track.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/lark_parser.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/lark_transformer.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/productions/__init__.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/productions/expression.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/productions/header.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/productions/reference.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/productions/term.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/productions/variable.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/util/exceptions.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/util/expression_encoder.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/util/expression_utility.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/util/lark_print_parser.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/util/print_parser.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/matching/util/runtime_data_collector.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/modes/error_mode.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/modes/files_mode.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/modes/logic_mode.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/modes/mode_controller.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/modes/print_mode.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/modes/return_mode.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/modes/run_mode.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/modes/source_mode.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/modes/transfer_mode.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/modes/unmatched_mode.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/modes/validation_mode.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/scanning/__init__.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/scanning/exceptions.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/scanning/parser.out +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/scanning/parsetab.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/scanning/scanner.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/scanning/scanning_lexer.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/azure/azure_data_reader.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/azure/azure_data_writer.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/azure/azure_fingerprinter.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/azure/azure_nos.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/azure/azure_utils.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/azure/azure_xlsx_data_reader.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/box.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/cache.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/caser.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/class_loader.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/code.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/config_exception.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/exceptions.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/file_info.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/file_readers.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/file_writers.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/gcs/gcs_data_reader.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/gcs/gcs_data_writer.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/gcs/gcs_fingerprinter.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/gcs/gcs_nos.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/gcs/gcs_utils.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/gcs/gcs_xlsx_data_reader.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/hasher.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/http/http_data_reader.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/intermediary.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/last_line_stats.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/line_counter.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/line_monitor.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/line_spooler.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/log_utility.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/pandas_data_reader.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/path_util.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/printer.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/references/ref_utils.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/references/reference_parser.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/references/results_reference_finder.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/run_home_maker.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/s3/s3_data_reader.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/s3/s3_data_writer.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/s3/s3_fingerprinter.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/s3/s3_nos.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/s3/s3_utils.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/s3/s3_xlsx_data_reader.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/sftp/sftp_config.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/sftp/sftp_data_reader.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/sftp/sftp_data_writer.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/sftp/sftp_fingerprinter.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/sftp/sftp_nos.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/sftp/sftp_walk.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/sftp/sftp_xlsx_data_reader.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/sqliter.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/template_util.py +0 -0
- {csvpath-0.0.538 → csvpath-0.0.541}/csvpath/util/var_utility.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: csvpath
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.541
|
|
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
|
|
@@ -57,7 +57,7 @@ groups =
|
|
|
57
57
|
#slack, marquez, ckan, sftp, sftpplus, otlp, default, sqlite
|
|
58
58
|
|
|
59
59
|
# general purpose webhook caller
|
|
60
|
-
webhook.results = from csvpath.managers.integrations.webhook.webhook_results_listener import
|
|
60
|
+
webhook.results = from csvpath.managers.integrations.webhook.webhook_results_listener import WebhookResultsListener
|
|
61
61
|
|
|
62
62
|
# add a listener to exec scripts at the end of named-paths group runs
|
|
63
63
|
scripts.results = from csvpath.managers.integrations.scripts.scripts_results_listener import ScriptsResultsListener
|
|
@@ -91,7 +91,7 @@ otlp.errors = from csvpath.managers.integrations.otlp.otlp_error_listener import
|
|
|
91
91
|
sftpplus.paths = from csvpath.managers.integrations.sftpplus.sftpplus_listener import SftpPlusListener
|
|
92
92
|
|
|
93
93
|
# add sftp to the list of groups above to push results to an sftp account
|
|
94
|
-
sftp.results = from csvpath.managers.integrations.sftp.
|
|
94
|
+
sftp.results = from csvpath.managers.integrations.sftp.sftp_sender import SftpSender
|
|
95
95
|
|
|
96
96
|
# add ckan to the list of groups above for alerts to slack webhooks
|
|
97
97
|
ckan.results = from csvpath.managers.integrations.ckan.ckan_listener import CkanListener
|
|
@@ -57,7 +57,7 @@ groups =
|
|
|
57
57
|
#slack, marquez, ckan, sftp, sftpplus, otlp, default, sqlite
|
|
58
58
|
|
|
59
59
|
# general purpose webhook caller
|
|
60
|
-
webhook.results = from csvpath.managers.integrations.webhook.webhook_results_listener import
|
|
60
|
+
webhook.results = from csvpath.managers.integrations.webhook.webhook_results_listener import WebhookResultsListener
|
|
61
61
|
|
|
62
62
|
# add a listener to exec scripts at the end of named-paths group runs
|
|
63
63
|
scripts.results = from csvpath.managers.integrations.scripts.scripts_results_listener import ScriptsResultsListener
|
|
@@ -91,7 +91,7 @@ otlp.errors = from csvpath.managers.integrations.otlp.otlp_error_listener import
|
|
|
91
91
|
sftpplus.paths = from csvpath.managers.integrations.sftpplus.sftpplus_listener import SftpPlusListener
|
|
92
92
|
|
|
93
93
|
# add sftp to the list of groups above to push results to an sftp account
|
|
94
|
-
sftp.results = from csvpath.managers.integrations.sftp.
|
|
94
|
+
sftp.results = from csvpath.managers.integrations.sftp.sftp_sender import SftpSender
|
|
95
95
|
|
|
96
96
|
# add ckan to the list of groups above for alerts to slack webhooks
|
|
97
97
|
ckan.results = from csvpath.managers.integrations.ckan.ckan_listener import CkanListener
|
|
@@ -31,6 +31,11 @@ class FunctionDescriber:
|
|
|
31
31
|
def sigs(cls, function):
|
|
32
32
|
sigs = []
|
|
33
33
|
args = function.args
|
|
34
|
+
if not args:
|
|
35
|
+
#
|
|
36
|
+
# this is possibly due to the very small number of unrefactored functions. (3?)
|
|
37
|
+
#
|
|
38
|
+
return sigs
|
|
34
39
|
argsets = args.argsets
|
|
35
40
|
for ai, a in enumerate(argsets):
|
|
36
41
|
pa = ""
|
|
@@ -19,7 +19,6 @@ from .matching.matcher import Matcher
|
|
|
19
19
|
from .scanning.scanner import Scanner
|
|
20
20
|
from .util.metadata_parser import MetadataParser
|
|
21
21
|
from .managers.errors.error import Error
|
|
22
|
-
from .managers.errors.error_collector import ErrorCollector
|
|
23
22
|
from .managers.errors.error_comms import ErrorCommunications
|
|
24
23
|
from .managers.errors.error_manager import ErrorManager
|
|
25
24
|
from .managers.metadata import Metadata
|
|
@@ -33,6 +32,7 @@ from .util.exceptions import (
|
|
|
33
32
|
CsvPathsException,
|
|
34
33
|
)
|
|
35
34
|
from .matching.util.exceptions import MatchException
|
|
35
|
+
from .managers.errors.error_collector import ErrorCollector
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
class CsvPath(ErrorCollector, Printer): # pylint: disable=R0902, R0904
|
|
@@ -584,7 +584,7 @@ class CsvPath(ErrorCollector, Printer): # pylint: disable=R0902, R0904
|
|
|
584
584
|
@property
|
|
585
585
|
def explain(self) -> bool:
|
|
586
586
|
"""@private
|
|
587
|
-
when this property is True CsvPath dumps a match
|
|
587
|
+
when this property is True CsvPath dumps a match explanation
|
|
588
588
|
to INFO. this can be expensive. a 25% performance hit wouldn't
|
|
589
589
|
be unexpected.
|
|
590
590
|
"""
|
|
@@ -672,7 +672,7 @@ class CsvPath(ErrorCollector, Printer): # pylint: disable=R0902, R0904
|
|
|
672
672
|
# - logic-mode: AND | OR
|
|
673
673
|
# - return-mode: matches | no-matches
|
|
674
674
|
# - print-mode: default | no-default
|
|
675
|
-
# - validation-mode: (no-)print | log | (no-)raise | quiet | (no-)match
|
|
675
|
+
# - validation-mode: (no-)print | log | (no-)raise | quiet | (no-)match | (no-)stop
|
|
676
676
|
# - run-mode: no-run | run
|
|
677
677
|
# - unmatched-mode: no-keep | keep
|
|
678
678
|
# - source-mode: preceding | origin
|
|
@@ -975,7 +975,8 @@ class CsvPath(ErrorCollector, Printer): # pylint: disable=R0902, R0904
|
|
|
975
975
|
def limit_collection_to(self, indexes: List[int]) -> None:
|
|
976
976
|
"""@private"""
|
|
977
977
|
self._limit_collection_to = indexes
|
|
978
|
-
self.
|
|
978
|
+
if self._limit_collection_to and self._limit_collection_to != indexes:
|
|
979
|
+
self.logger.info("Limiting headers collected: %s", indexes)
|
|
979
980
|
|
|
980
981
|
def stop(self) -> None:
|
|
981
982
|
"""@private"""
|
|
@@ -1137,7 +1138,7 @@ class CsvPath(ErrorCollector, Printer): # pylint: disable=R0902, R0904
|
|
|
1137
1138
|
#
|
|
1138
1139
|
# DataFileReader is abstract. instantiating it results in a concrete subclass.
|
|
1139
1140
|
# pylint doesn't like that just because it doesn't see what we're doing.
|
|
1140
|
-
# otoh, is this a bad way to do it?
|
|
1141
|
+
# otoh, is this a bad way to do it? it works fine.
|
|
1141
1142
|
#
|
|
1142
1143
|
reader = DataFileReader( # pylint: disable=E0110
|
|
1143
1144
|
self.scanner.filename, delimiter=self.delimiter, quotechar=self.quotechar
|
|
@@ -1264,9 +1265,13 @@ class CsvPath(ErrorCollector, Printer): # pylint: disable=R0902, R0904
|
|
|
1264
1265
|
ls = []
|
|
1265
1266
|
for k in self.limit_collection_to:
|
|
1266
1267
|
if k is None or k >= len(line):
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1268
|
+
#
|
|
1269
|
+
# FP change. didn't do do_i_raise and didn't handle w/error mgr
|
|
1270
|
+
#
|
|
1271
|
+
msg = f"[{self.identity}] Line {self.line_monitor.physical_line_number}: unknown header name: {k} of {self.limit_collection_to} in headers {self.headers}"
|
|
1272
|
+
self.error_manager.handle_error(source=self, msg=msg)
|
|
1273
|
+
if self.ecoms.do_i_raise():
|
|
1274
|
+
raise InputException(msg)
|
|
1270
1275
|
ls.append(line[k])
|
|
1271
1276
|
return ls
|
|
1272
1277
|
|
|
@@ -1321,6 +1326,12 @@ class CsvPath(ErrorCollector, Printer): # pylint: disable=R0902, R0904
|
|
|
1321
1326
|
if use_cache:
|
|
1322
1327
|
uc = self.csvpaths.config.get(section="cache", name="use_cache")
|
|
1323
1328
|
use_cache = uc is None or uc.strip().lower() != "no"
|
|
1329
|
+
#
|
|
1330
|
+
# do we really want to only use cache if we're running a named-paths group?
|
|
1331
|
+
# users may want to run one-offs repeatedly, particularly in FP. otoh, we
|
|
1332
|
+
# don't have a file_manager and its a big change for probably a small number of
|
|
1333
|
+
# bad cases and it can be worked around by simply using a CsvPaths.
|
|
1334
|
+
#
|
|
1324
1335
|
if self.csvpaths and use_cache is True:
|
|
1325
1336
|
self.line_monitor = self.csvpaths.file_manager.lines_and_headers_cacher.get_new_line_monitor(
|
|
1326
1337
|
self.scanner.filename
|
|
@@ -17,7 +17,7 @@ class ErrorCommunications:
|
|
|
17
17
|
the error policy in config/config.ini (or whereever your config is)
|
|
18
18
|
is the baseline. however, every csvpath can override the config
|
|
19
19
|
for some of the error handling using a comment with the metadata
|
|
20
|
-
field
|
|
20
|
+
field validation-mode. config
|
|
21
21
|
has two setting values not tracked in metadata: quiet and log.
|
|
22
22
|
"""
|
|
23
23
|
|
|
@@ -62,7 +62,15 @@ class ErrorCommunications:
|
|
|
62
62
|
def do_i_stop(self) -> bool:
|
|
63
63
|
mode = None
|
|
64
64
|
if self._csvpath and self._csvpath.stop_on_validation_errors is not None:
|
|
65
|
+
#
|
|
66
|
+
# looks wrong. function in FlightPath is not correct. doesn't match other do_i_...
|
|
67
|
+
#
|
|
65
68
|
mode = self._csvpath.stop_on_validation_errors
|
|
69
|
+
#
|
|
70
|
+
# this was a change made for flightpath. not sure it works. it may well work.
|
|
71
|
+
# however atm visibility isn't great. come back later.
|
|
72
|
+
#
|
|
73
|
+
# return self._csvpath.stop_on_validation_errors
|
|
66
74
|
policy = self.in_policy(OnError.STOP.value)
|
|
67
75
|
return mode is True or policy is True
|
|
68
76
|
|
|
@@ -299,7 +299,10 @@ class FileManager:
|
|
|
299
299
|
# cannot be a reference or part of a reference. has to just
|
|
300
300
|
# be the simple name of the named file.
|
|
301
301
|
#
|
|
302
|
-
|
|
302
|
+
try:
|
|
303
|
+
self.legal_name(name)
|
|
304
|
+
except Exception:
|
|
305
|
+
return False
|
|
303
306
|
#
|
|
304
307
|
# the home should exist if the named file exists.
|
|
305
308
|
#
|
|
@@ -367,13 +370,15 @@ class FileManager:
|
|
|
367
370
|
if self.csvpaths.ecoms.do_i_raise():
|
|
368
371
|
raise
|
|
369
372
|
|
|
370
|
-
def legal_name(self, name:str) -> None:
|
|
373
|
+
def legal_name(self, name: str) -> None:
|
|
371
374
|
if name is None:
|
|
372
375
|
raise ValueError("Name cannot be None")
|
|
373
376
|
if name.strip() == "":
|
|
374
377
|
raise ValueError("Name cannot be empty")
|
|
375
378
|
if name.find("/") > -1 or name.find("\\") > -1:
|
|
376
|
-
raise ValueError(
|
|
379
|
+
raise ValueError(
|
|
380
|
+
f"Not a legal name: {name}. Path seperators are not allowed."
|
|
381
|
+
)
|
|
377
382
|
if name.find(".") > -1:
|
|
378
383
|
raise ValueError(f"Not a legal name: {name}. Periods are not allowed.")
|
|
379
384
|
if name.find("$") > -1:
|
|
@@ -397,8 +402,8 @@ class FileManager:
|
|
|
397
402
|
#
|
|
398
403
|
# legal_name handled at add_named_file
|
|
399
404
|
#
|
|
400
|
-
#self.legal_name(name)
|
|
401
|
-
#if dirname is None or dirname.strip() == "":
|
|
405
|
+
# self.legal_name(name)
|
|
406
|
+
# if dirname is None or dirname.strip() == "":
|
|
402
407
|
# raise ValueError("Dirname cannot be None or empty")
|
|
403
408
|
#
|
|
404
409
|
# need to support adding all files from directory under the same name. preferably
|
|
@@ -440,7 +445,7 @@ class FileManager:
|
|
|
440
445
|
self, *, name: NamedFileName, path: str, template: str = None
|
|
441
446
|
) -> None:
|
|
442
447
|
self.legal_name(name)
|
|
443
|
-
#if name is None or name.strip() == "":
|
|
448
|
+
# if name is None or name.strip() == "":
|
|
444
449
|
# raise ValueError("Name cannot be None or empty")
|
|
445
450
|
if path is None or path.strip() == "":
|
|
446
451
|
raise ValueError("Path cannot be None or empty")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from openlineage.client import OpenLineageClient
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from .ol_listener import OpenLineageListener
|
|
3
|
+
from csvpath.managers.metadata import Metadata
|
|
4
|
+
from csvpath.managers.integrations.ol.ol_listener import OpenLineageListener
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class OpenLineagePathsListener(OpenLineageListener):
|
|
@@ -197,12 +197,20 @@ class PathsManager:
|
|
|
197
197
|
raise InputException(msg)
|
|
198
198
|
|
|
199
199
|
def add_named_paths_from_file(
|
|
200
|
-
self,
|
|
200
|
+
self,
|
|
201
|
+
*,
|
|
202
|
+
name: NamedPathsName,
|
|
203
|
+
file_path: str,
|
|
204
|
+
template=None,
|
|
205
|
+
append: bool = False,
|
|
201
206
|
) -> None:
|
|
207
|
+
#
|
|
208
|
+
# change for FP: added append as a pass-through
|
|
209
|
+
#
|
|
202
210
|
self.csvpaths.logger.debug("Reading csvpaths file at %s", file_path)
|
|
203
211
|
_ = self._get_csvpaths_from_file(file_path)
|
|
204
212
|
self.add_named_paths(
|
|
205
|
-
name=name, paths=_, source_path=file_path, template=template
|
|
213
|
+
name=name, paths=_, source_path=file_path, template=template, append=append
|
|
206
214
|
)
|
|
207
215
|
|
|
208
216
|
def add_named_paths_from_json(self, file_path: str) -> None:
|
|
@@ -248,12 +256,16 @@ class PathsManager:
|
|
|
248
256
|
from_json: str = None,
|
|
249
257
|
source_path: str = None,
|
|
250
258
|
template: str = None,
|
|
259
|
+
append: bool = False,
|
|
251
260
|
) -> None:
|
|
252
261
|
if template is not None:
|
|
253
262
|
temu.valid(template)
|
|
254
263
|
if from_file is not None:
|
|
264
|
+
#
|
|
265
|
+
# change for FP. added append as a pass-through
|
|
266
|
+
#
|
|
255
267
|
return self.add_named_paths_from_file(
|
|
256
|
-
name=name, file_path=from_file, template=template
|
|
268
|
+
name=name, file_path=from_file, template=template, append=append
|
|
257
269
|
)
|
|
258
270
|
elif from_dir is not None:
|
|
259
271
|
return self.add_named_paths_from_dir(
|
|
@@ -273,7 +285,7 @@ class PathsManager:
|
|
|
273
285
|
for _ in paths:
|
|
274
286
|
self.csvpaths.logger.debug("Adding %s to %s", _, name)
|
|
275
287
|
s = self._str_from_list(paths)
|
|
276
|
-
t = self._copy_in(name, s)
|
|
288
|
+
t = self._copy_in(name, s, append=append)
|
|
277
289
|
grp_paths = self.get_identified_paths_in(name, paths=paths)
|
|
278
290
|
ids = [t[0] for t in grp_paths]
|
|
279
291
|
for i, t in enumerate(ids):
|
|
@@ -630,9 +642,15 @@ class PathsManager:
|
|
|
630
642
|
cs = s.split("---- CSVPATH ----")
|
|
631
643
|
cs = [s for s in cs if s.strip() != ""]
|
|
632
644
|
#
|
|
633
|
-
# this update may not
|
|
634
|
-
#
|
|
635
|
-
#
|
|
645
|
+
# this update may not result in broadcasting an update event to listeners.
|
|
646
|
+
# that all depends on if group.csvpaths was changed outside the manager.
|
|
647
|
+
# if someone put a new group.csvpaths file by hand we want to capture its
|
|
648
|
+
# fingerprint for future reference. this shouldn't happen, but it probably
|
|
649
|
+
# will happen.
|
|
650
|
+
#
|
|
651
|
+
# seen 1x with FlightPath. not yet clear if FP is doing something new and
|
|
652
|
+
# desireable or if it has a bug. in principle, still don't see a reason this
|
|
653
|
+
# update should obtain, unless a user edits a file they shouldn't.
|
|
636
654
|
#
|
|
637
655
|
self.registrar.update_manifest_if(name=name, group_file_path=grp, paths=cs)
|
|
638
656
|
return cs
|
|
@@ -644,7 +662,21 @@ class PathsManager:
|
|
|
644
662
|
f = f"{f}\n\n---- CSVPATH ----\n\n{_}"
|
|
645
663
|
return f
|
|
646
664
|
|
|
647
|
-
def _copy_in(self, name: NamedPathsName, csvpathstr: Csvpath) -> None:
|
|
665
|
+
def _copy_in(self, name: NamedPathsName, csvpathstr: Csvpath, append=False) -> None:
|
|
666
|
+
#
|
|
667
|
+
# if we have a set of paths we append these new paths
|
|
668
|
+
#
|
|
669
|
+
if self.has_named_paths(name) and append is True:
|
|
670
|
+
existing = self.get_named_paths(name)
|
|
671
|
+
estr = self._str_from_list(existing)
|
|
672
|
+
if not estr.strip().endswith(
|
|
673
|
+
"---- CSVPATH ----"
|
|
674
|
+
) and not csvpathstr.strip().startswith("---- CSVPATH ----"):
|
|
675
|
+
csvpathstr = f"{estr}\n\n---- CSVPATH ----\n\n"
|
|
676
|
+
csvpathstr = f"{estr}{csvpathstr}"
|
|
677
|
+
#
|
|
678
|
+
# continue with the write
|
|
679
|
+
#
|
|
648
680
|
temp = self._group_file_path(name)
|
|
649
681
|
with DataFileWriter(path=temp, mode="w") as writer:
|
|
650
682
|
writer.append(csvpathstr)
|
|
@@ -691,6 +723,32 @@ class PathsManager:
|
|
|
691
723
|
ps.append(path[0])
|
|
692
724
|
return ps
|
|
693
725
|
|
|
726
|
+
#
|
|
727
|
+
# this version correctly picks up csvpaths that the Framework identifies by index
|
|
728
|
+
# because they don't have user assigned identities. this was seen in FlightPath
|
|
729
|
+
# but applies in general.
|
|
730
|
+
#
|
|
731
|
+
def _get_from(self, npn: NamedPathsName, identity: Identity) -> list[Csvpath]:
|
|
732
|
+
index = expu.to_int(identity)
|
|
733
|
+
ps = []
|
|
734
|
+
paths = self.get_identified_paths_in(npn)
|
|
735
|
+
for i, path in enumerate(paths):
|
|
736
|
+
#
|
|
737
|
+
# if we have the identity or the identity is the index or we are collecting
|
|
738
|
+
# after our first collection because :from collects all csvpaths coming after
|
|
739
|
+
# a starting csvpath
|
|
740
|
+
#
|
|
741
|
+
if (path[0] == identity or (path[0] is None and index == i)) or len(ps) > 0:
|
|
742
|
+
ps.append(path[1])
|
|
743
|
+
"""
|
|
744
|
+
if path[0] != identity and len(ps) == 0:
|
|
745
|
+
continue
|
|
746
|
+
ps.append(path[1])
|
|
747
|
+
"""
|
|
748
|
+
return ps
|
|
749
|
+
|
|
750
|
+
"""
|
|
751
|
+
original version
|
|
694
752
|
def _get_from(self, npn: NamedPathsName, identity: Identity) -> list[Csvpath]:
|
|
695
753
|
ps = []
|
|
696
754
|
paths = self.get_identified_paths_in(npn)
|
|
@@ -699,6 +757,7 @@ class PathsManager:
|
|
|
699
757
|
continue
|
|
700
758
|
ps.append(path[1])
|
|
701
759
|
return ps
|
|
760
|
+
"""
|
|
702
761
|
|
|
703
762
|
def get_preceeding_instance_identity(self, name, index: int) -> str:
|
|
704
763
|
if index <= 0:
|
|
@@ -735,6 +794,7 @@ class PathsManager:
|
|
|
735
794
|
idps.append((c.identity, path))
|
|
736
795
|
return idps
|
|
737
796
|
|
|
797
|
+
"""
|
|
738
798
|
def _find_one(self, npn: NamedPathsName, identity: Identity) -> Csvpath:
|
|
739
799
|
if npn is not None:
|
|
740
800
|
paths = self.get_identified_paths_in(npn)
|
|
@@ -744,6 +804,29 @@ class PathsManager:
|
|
|
744
804
|
raise InputException(
|
|
745
805
|
f"Path identified as '{identity}' must be in the group identitied as '{npn}'"
|
|
746
806
|
)
|
|
807
|
+
"""
|
|
808
|
+
|
|
809
|
+
def _find_one(self, npn: NamedPathsName, identity: Identity) -> Csvpath:
|
|
810
|
+
#
|
|
811
|
+
# this version of the method is a change for FlightPath. the change is correct for
|
|
812
|
+
# all purposes, but showed up clearly in FP. the problem is that we don't test index
|
|
813
|
+
# for unidentitied paths. luckily we do return all paths with None as the identity
|
|
814
|
+
# for those w/o user specified id. for those we just need to test the index.
|
|
815
|
+
#
|
|
816
|
+
# this version assumes that if a csvpath is identitied we do not allow using the
|
|
817
|
+
# index to point to it. this may not be the right assumption, but it is arguably a
|
|
818
|
+
# good way to go. if the writer bothered to identify, the id is more specific than
|
|
819
|
+
# the index and so less error-prone.
|
|
820
|
+
#
|
|
821
|
+
index = expu.to_int(identity)
|
|
822
|
+
if npn is not None:
|
|
823
|
+
paths = self.get_identified_paths_in(npn)
|
|
824
|
+
for i, path in enumerate(paths):
|
|
825
|
+
if path[0] == identity or (path[0] is None and index == i):
|
|
826
|
+
return path[1]
|
|
827
|
+
raise InputException(
|
|
828
|
+
f"Path identified as '{identity}' must be in the group identitied as '{npn}'"
|
|
829
|
+
)
|
|
747
830
|
|
|
748
831
|
def _name_from_name_part(self, name):
|
|
749
832
|
i = name.rfind(".")
|
|
@@ -35,7 +35,7 @@ class PathsRegistrar(Registrar, Listener):
|
|
|
35
35
|
mdata.fingerprint = self._fingerprint(name=mdata.named_paths_name)
|
|
36
36
|
self.distribute_update(mdata)
|
|
37
37
|
|
|
38
|
-
def update_manifest_if(self, *, group_file_path, name, paths
|
|
38
|
+
def update_manifest_if(self, *, group_file_path, name, paths):
|
|
39
39
|
#
|
|
40
40
|
# if we find that the current group file does not have the same
|
|
41
41
|
# fingerprint as the most recent on file, we register a new version.
|
|
@@ -47,20 +47,19 @@ class PathsRegistrar(Registrar, Listener):
|
|
|
47
47
|
mpath = self.manifest_path(name)
|
|
48
48
|
cf = self._most_recent_fingerprint(mpath)
|
|
49
49
|
if f != cf:
|
|
50
|
-
mdata = PathsMetadata()
|
|
50
|
+
mdata = PathsMetadata(self.csvpaths.config)
|
|
51
51
|
mdata.archive_name = self.csvpaths.config.archive_name
|
|
52
52
|
mdata.named_paths_name = name
|
|
53
|
-
#
|
|
54
|
-
# why two of these? :/
|
|
55
|
-
#
|
|
56
|
-
# mdata.named_paths_file = group_file_path
|
|
57
53
|
mdata.group_file_path = group_file_path
|
|
58
54
|
mdata.named_paths = paths
|
|
59
55
|
mdata.named_paths_identities = [
|
|
60
|
-
|
|
56
|
+
#
|
|
57
|
+
# if we don't pass paths to get_identified_paths_in we will infinite loop
|
|
58
|
+
#
|
|
59
|
+
t[0]
|
|
60
|
+
for t in self.manager.get_identified_paths_in(name, paths)
|
|
61
61
|
]
|
|
62
|
-
|
|
63
|
-
mdata.named_paths_count = len(paths)
|
|
62
|
+
mdata.named_paths_count = len(paths)
|
|
64
63
|
mdata.manifest_path = mpath
|
|
65
64
|
mdata.fingerprint = f
|
|
66
65
|
self.distribute_update(mdata)
|
|
@@ -63,7 +63,7 @@ class PrintoutsReader(ResultReader):
|
|
|
63
63
|
|
|
64
64
|
class ResultReadersFacade(ErrorsReader, UnmatchedReader, LinesReader, PrintoutsReader):
|
|
65
65
|
#
|
|
66
|
-
# as
|
|
66
|
+
# as soon as we get a run_dir and an instance we'll create the
|
|
67
67
|
# instance_dir and load the readers
|
|
68
68
|
#
|
|
69
69
|
def __init__(self, result):
|
|
@@ -309,7 +309,12 @@ class ResultsManager: # pylint: disable=C0115
|
|
|
309
309
|
path = self._csvpaths.config.archive_path
|
|
310
310
|
if Nos(path).dir_exists():
|
|
311
311
|
names = Nos(path).listdir()
|
|
312
|
-
|
|
312
|
+
#
|
|
313
|
+
# listing dir shouldn't return manifest.json or any file. can do better here.
|
|
314
|
+
#
|
|
315
|
+
names = [
|
|
316
|
+
n for n in names if not n.startswith(".") and not n.endswith(".json")
|
|
317
|
+
]
|
|
313
318
|
names.sort()
|
|
314
319
|
else:
|
|
315
320
|
self._csvpaths.logger.warning(
|
|
@@ -513,7 +518,14 @@ class ResultsManager: # pylint: disable=C0115
|
|
|
513
518
|
# CsvPaths instance, we would create a new one.
|
|
514
519
|
#
|
|
515
520
|
if name in self.named_results:
|
|
516
|
-
|
|
521
|
+
#
|
|
522
|
+
# exp. removed 4 May.
|
|
523
|
+
# was/is this ever a good idea?
|
|
524
|
+
#
|
|
525
|
+
# seems to be important for a handful of unit tests.
|
|
526
|
+
#
|
|
527
|
+
rs = self.named_results[name]
|
|
528
|
+
return rs
|
|
517
529
|
#
|
|
518
530
|
# find and load the result, if exists. we find results home with the name. run_home is the
|
|
519
531
|
# last run dir. the results we're looking for are the instance dirs in the run dir.
|
|
@@ -573,7 +585,9 @@ class ResultsManager: # pylint: disable=C0115
|
|
|
573
585
|
nos = Nos(path)
|
|
574
586
|
exists = nos.dir_exists()
|
|
575
587
|
nonphy = nos.physical_dirs()
|
|
588
|
+
#
|
|
576
589
|
# is not nonphy needed?
|
|
590
|
+
#
|
|
577
591
|
if exists or not nonphy:
|
|
578
592
|
runs = nos.listdir()
|
|
579
593
|
if len(runs) > 0:
|
|
@@ -26,7 +26,7 @@ class ArgumentValidationHelper:
|
|
|
26
26
|
# Validate each argument against the argset.
|
|
27
27
|
# this part gets ugly. we should instead just say:
|
|
28
28
|
# f"invalid {argset.matchable.name}. {argset.explain}"
|
|
29
|
-
# and then write the
|
|
29
|
+
# and then write the explanation into the classes. (OMG! but it would be best, imho).
|
|
30
30
|
#
|
|
31
31
|
results = []
|
|
32
32
|
for va in valid_argsets:
|
|
@@ -16,11 +16,26 @@ class All(MatchDecider):
|
|
|
16
16
|
"""checks that a number of match components return True"""
|
|
17
17
|
|
|
18
18
|
def check_valid(self) -> None: # pragma: no cover
|
|
19
|
+
self.description = [
|
|
20
|
+
self._cap_name(),
|
|
21
|
+
self.wrap(
|
|
22
|
+
"""\
|
|
23
|
+
Tests if all contained or referenced match components evaluate to True.
|
|
24
|
+
If all() has no arguments the check is if all headers have values.
|
|
25
|
+
"""
|
|
26
|
+
),
|
|
27
|
+
]
|
|
19
28
|
self.args = Args(matchable=self)
|
|
20
|
-
self.args.argset(0)
|
|
21
|
-
self.args.argset(1).arg(
|
|
29
|
+
self.args.argset(0) # what would the function of all() w/o args be?
|
|
30
|
+
self.args.argset(1).arg(
|
|
31
|
+
name="a function indicating all headers or all variables",
|
|
32
|
+
types=[None, Variables, Headers],
|
|
33
|
+
actuals=[],
|
|
34
|
+
)
|
|
22
35
|
self.args.argset().arg(
|
|
23
|
-
|
|
36
|
+
name="one of a set of match components",
|
|
37
|
+
types=[None, Function, Variable, Header],
|
|
38
|
+
actuals=[None, Any],
|
|
24
39
|
)
|
|
25
40
|
self.args.validate(self.siblings())
|
|
26
41
|
super().check_valid()
|
|
@@ -13,6 +13,21 @@ class And(MatchDecider):
|
|
|
13
13
|
need more control."""
|
|
14
14
|
|
|
15
15
|
def check_valid(self) -> None: # pragma: no cover
|
|
16
|
+
self.description = [
|
|
17
|
+
self._cap_name(),
|
|
18
|
+
self.wrap(
|
|
19
|
+
"""
|
|
20
|
+
and() tests if its contained match components evaluate to True.
|
|
21
|
+
|
|
22
|
+
Matching is ANDed by default, but it can be set to OR. And and()
|
|
23
|
+
gives you a bit more control in certain situations, such as making.
|
|
24
|
+
a when/do expression that is based on multiple match components.
|
|
25
|
+
|
|
26
|
+
The functionality of and() overlaps with all(), but all() has
|
|
27
|
+
powers that are more specific than and().
|
|
28
|
+
"""
|
|
29
|
+
),
|
|
30
|
+
]
|
|
16
31
|
self.args = Args(matchable=self)
|
|
17
32
|
a = self.args.argset()
|
|
18
33
|
a.arg(types=[Matchable], actuals=[None, Any])
|
|
@@ -20,12 +20,38 @@ class Any(MatchDecider):
|
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
22
|
def check_valid(self) -> None:
|
|
23
|
+
self.description = [
|
|
24
|
+
self._cap_name(),
|
|
25
|
+
self.wrap(
|
|
26
|
+
"""\
|
|
27
|
+
any() returns True if at least one contained match component
|
|
28
|
+
matches a given value.
|
|
29
|
+
|
|
30
|
+
With no arguments any() matches if there are values in any variable or header.
|
|
31
|
+
|
|
32
|
+
With a single headers() or variables() function any() returns True if there is
|
|
33
|
+
a match component of the the type indicated with a value.
|
|
34
|
+
|
|
35
|
+
With a second argument the test is for the specific value in any match component
|
|
36
|
+
of the indicated type.
|
|
37
|
+
|
|
38
|
+
any() is similar to or() or OR logic. While any() gives
|
|
39
|
+
you more fine-grained control, remember that you can
|
|
40
|
+
also use logic-mode to configure a csvpath to use OR as
|
|
41
|
+
the basis for matching.
|
|
42
|
+
"""
|
|
43
|
+
),
|
|
44
|
+
]
|
|
23
45
|
self.args = Args(matchable=self)
|
|
24
46
|
a = self.args.argset(0)
|
|
25
47
|
|
|
26
48
|
a = self.args.argset(2)
|
|
27
|
-
a.arg(
|
|
28
|
-
|
|
49
|
+
a.arg(
|
|
50
|
+
name="Indicates where to look",
|
|
51
|
+
types=[Variables, Headers],
|
|
52
|
+
actuals=[None, typing.Any],
|
|
53
|
+
)
|
|
54
|
+
a.arg(name="The value to find", types=[typing.Any], actuals=[None, typing.Any])
|
|
29
55
|
|
|
30
56
|
a = self.args.argset(1)
|
|
31
57
|
a.arg(types=[typing.Any, Variables, Headers], actuals=[None, typing.Any])
|