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