csvpath 0.0.490__tar.gz → 0.0.492__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.490 → csvpath-0.0.492}/PKG-INFO +2 -1
- csvpath-0.0.492/csvpath/cli/__init__.py +5 -0
- csvpath-0.0.492/csvpath/cli/cli.py +197 -0
- csvpath-0.0.492/csvpath/cli/drill_down.py +185 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/managers/csvpaths_manager.py +68 -73
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/managers/file_manager.py +10 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/managers/file_registrar.py +0 -1
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/managers/paths_registrar.py +19 -2
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/managers/results_manager.py +7 -1
- {csvpath-0.0.490 → csvpath-0.0.492}/pyproject.toml +6 -1
- {csvpath-0.0.490 → csvpath-0.0.492}/LICENSE +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/README.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/config/config.ini +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/__init__.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/csvpath.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/csvpaths.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/managers/__init__.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/managers/result.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/managers/result_serializer.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/__init__.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/__init__.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/args.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/boolean/all.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/boolean/andf.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/boolean/any.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/boolean/between.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/boolean/empty.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/boolean/exists.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/boolean/inf.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/boolean/no.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/boolean/notf.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/boolean/orf.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/boolean/yes.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/counting/count.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/counting/count_headers.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/counting/count_lines.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/counting/count_scans.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/counting/counter.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/counting/every.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/counting/has_matches.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/counting/increment.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/counting/tally.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/counting/total_lines.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/dates/now.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/function.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/function_factory.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/function_finder.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/function_focus.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/headers/append.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/headers/collect.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/headers/empty_stack.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/headers/end.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/headers/header_name.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/headers/header_names_mismatch.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/headers/headers.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/headers/mismatch.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/headers/replace.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/headers/reset_headers.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/lines/advance.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/lines/after_blank.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/lines/dups.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/lines/first.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/lines/first_line.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/lines/last.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/lines/stop.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/math/above.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/math/add.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/math/divide.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/math/equals.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/math/intf.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/math/mod.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/math/multiply.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/math/round.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/math/subtotal.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/math/subtract.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/math/sum.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/misc/fingerprint.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/misc/importf.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/misc/random.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/print/jinjaf.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/print/print_line.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/print/print_queue.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/print/printf.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/print/table.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/stats/minf.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/stats/percent.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/stats/percent_unique.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/stats/stdev.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/strings/concat.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/strings/length.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/strings/lower.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/strings/metaphone.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/strings/regex.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/strings/starts_with.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/strings/strip.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/strings/substring.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/strings/upper.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/testing/debug.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/types/__init__.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/types/boolean.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/types/datef.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/types/decimal.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/types/nonef.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/types/string.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/types/type.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/validity/fail.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/validity/failed.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/validity/line.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/variables/get.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/variables/pushpop.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/variables/put.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/variables/track.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/functions/variables/variables.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/lark_parser.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/lark_transformer.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/matcher.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/productions/__init__.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/productions/equality.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/productions/expression.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/productions/header.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/productions/matchable.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/productions/qualified.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/productions/reference.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/productions/term.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/productions/variable.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/util/exceptions.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/util/expression_encoder.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/util/expression_utility.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/util/lark_print_parser.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/util/print_parser.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/matching/util/runtime_data_collector.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/scanning/__init__.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/scanning/exceptions.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/scanning/parser.out +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/scanning/parsetab.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/scanning/scanner.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/scanning/scanning_lexer.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/util/cache.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/util/config.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/util/config_exception.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/util/error.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/util/exceptions.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/util/file_readers.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/util/last_line_stats.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/util/line_counter.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/util/line_monitor.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/util/log_utility.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/util/metadata_parser.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/util/pandas_data_reader.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/util/printer.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/util/reference_parser.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/csvpath/util/s3_data_reader.py +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/asbool.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/assignment.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/comments.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/config.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/examples.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/files.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/above.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/advance.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/after_blank.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/all.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/andor.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/any.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/average.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/between.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/collect.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/correlate.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/count.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/count_headers.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/counter.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/date.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/empty.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/empty_stack.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/end.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/every.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/fail.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/fingerprint.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/first.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/get.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/has_dups.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/has_matches.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/header.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/header_name.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/header_names_mismatch.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/implementing_functions.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/import.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/in.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/increment.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/intf.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/jinja.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/last.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/line.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/line_number.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/max.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/metaphone.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/mismatch.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/no.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/not.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/now.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/percent_unique.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/pop.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/print.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/print_line.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/print_queue.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/random.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/regex.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/replace.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/reset_headers.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/stdev.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/stop.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/string_functions.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/subtotal.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/subtract.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/sum.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/tally.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/total_lines.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/track.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/types.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/variables.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions/variables_and_headers.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/functions.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/grammar.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/headers.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/images/logo-wordmark-white-on-black-trimmed-padded.png +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/images/logo-wordmark-white-trimmed.png +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/paths.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/printing.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/qualifiers.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/references.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/terms.md +0 -0
- {csvpath-0.0.490 → csvpath-0.0.492}/docs/variables.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: csvpath
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.492
|
|
4
4
|
Summary: A declarative language for validating CSV, Excel, and other tabular data files
|
|
5
5
|
Author: David Kershaw
|
|
6
6
|
Author-email: dk107dk@hotmail.com
|
|
@@ -23,6 +23,7 @@ Classifier: Topic :: Text Processing
|
|
|
23
23
|
Classifier: Topic :: Utilities
|
|
24
24
|
Provides-Extra: pandas
|
|
25
25
|
Provides-Extra: smartopen
|
|
26
|
+
Requires-Dist: bullet (>=2.2.0,<3.0.0)
|
|
26
27
|
Requires-Dist: inflect (>=7.3.1,<8.0.0)
|
|
27
28
|
Requires-Dist: jinja2 (>=3.1.4,<4.0.0)
|
|
28
29
|
Requires-Dist: lark (>=1.2.2,<2.0.0)
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
from csvpath import CsvPath, CsvPaths
|
|
2
|
+
import sys
|
|
3
|
+
import os
|
|
4
|
+
import time
|
|
5
|
+
from bullet import Bullet
|
|
6
|
+
from .drill_down import DrillDown
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Cli:
|
|
10
|
+
def __init__(self):
|
|
11
|
+
self._csvpaths = CsvPaths()
|
|
12
|
+
|
|
13
|
+
def clear(self):
|
|
14
|
+
print(chr(27) + "[2J")
|
|
15
|
+
|
|
16
|
+
def pause(self):
|
|
17
|
+
time.sleep(1.2)
|
|
18
|
+
|
|
19
|
+
def short_pause(self):
|
|
20
|
+
time.sleep(0.5)
|
|
21
|
+
|
|
22
|
+
ITALIC = "\033[3m"
|
|
23
|
+
SIDEBAR_COLOR = "\033[36m"
|
|
24
|
+
REVERT = "\033[0m"
|
|
25
|
+
STOP_HERE = f"{SIDEBAR_COLOR}{ITALIC}... done picking dir{REVERT}"
|
|
26
|
+
CANCEL = f"{SIDEBAR_COLOR}{ITALIC}... cancel{REVERT}"
|
|
27
|
+
|
|
28
|
+
def _return_to_cont(self):
|
|
29
|
+
print(
|
|
30
|
+
f"\n{Cli.SIDEBAR_COLOR}{Cli.ITALIC}... Hit return to continue{Cli.REVERT}\n"
|
|
31
|
+
)
|
|
32
|
+
self._input("")
|
|
33
|
+
|
|
34
|
+
def _response(self, text: str) -> None:
|
|
35
|
+
sys.stdout.write(f"\u001b[30;1m{text}{Cli.REVERT}\n")
|
|
36
|
+
|
|
37
|
+
def _action(self, text: str) -> None:
|
|
38
|
+
sys.stdout.write(f"\033[36m{text}{Cli.REVERT}\n")
|
|
39
|
+
|
|
40
|
+
def _input(self, prompt: str) -> str:
|
|
41
|
+
try:
|
|
42
|
+
response = input(f"{prompt}\033[93m")
|
|
43
|
+
sys.stdout.write(Cli.REVERT)
|
|
44
|
+
return response.strip()
|
|
45
|
+
except KeyboardInterrupt:
|
|
46
|
+
return "cancel"
|
|
47
|
+
|
|
48
|
+
def end(self) -> None:
|
|
49
|
+
print(chr(27) + "[2J")
|
|
50
|
+
|
|
51
|
+
def ask(self, choices: list[str]) -> str:
|
|
52
|
+
self.clear()
|
|
53
|
+
b = Bullet(bullet=" > ", choices=choices)
|
|
54
|
+
t = b.launch()
|
|
55
|
+
return t
|
|
56
|
+
|
|
57
|
+
def loop(self):
|
|
58
|
+
while True:
|
|
59
|
+
t = None
|
|
60
|
+
try:
|
|
61
|
+
self.clear()
|
|
62
|
+
b = Bullet(
|
|
63
|
+
bullet=" > ",
|
|
64
|
+
choices=[
|
|
65
|
+
"named-files",
|
|
66
|
+
"named-paths",
|
|
67
|
+
"named-results",
|
|
68
|
+
"run",
|
|
69
|
+
"quit",
|
|
70
|
+
],
|
|
71
|
+
)
|
|
72
|
+
t = b.launch()
|
|
73
|
+
except KeyboardInterrupt:
|
|
74
|
+
self.end()
|
|
75
|
+
return
|
|
76
|
+
t = self._do(t)
|
|
77
|
+
if t == "quit":
|
|
78
|
+
self.end()
|
|
79
|
+
return
|
|
80
|
+
|
|
81
|
+
def _do(self, t: str) -> str | None:
|
|
82
|
+
try:
|
|
83
|
+
if t == "quit":
|
|
84
|
+
return t
|
|
85
|
+
if t == "run":
|
|
86
|
+
self.run()
|
|
87
|
+
if t == "named-files":
|
|
88
|
+
self._files()
|
|
89
|
+
if t == "named-paths":
|
|
90
|
+
self._paths()
|
|
91
|
+
if t == "named-results":
|
|
92
|
+
self._results()
|
|
93
|
+
except KeyboardInterrupt:
|
|
94
|
+
return "quit"
|
|
95
|
+
except Exception as e:
|
|
96
|
+
print(f"Error: {e}")
|
|
97
|
+
self._return_to_cont()
|
|
98
|
+
|
|
99
|
+
def _files(self) -> None:
|
|
100
|
+
choices = ["add named-file", "list named-files", "cancel"]
|
|
101
|
+
t = self.ask(choices)
|
|
102
|
+
if t == "add named-file":
|
|
103
|
+
DrillDown(self).name_file()
|
|
104
|
+
if t == "list named-files":
|
|
105
|
+
self.list_named_files()
|
|
106
|
+
|
|
107
|
+
def _paths(self) -> None:
|
|
108
|
+
choices = ["add named-paths", "list named-paths", "cancel"]
|
|
109
|
+
t = self.ask(choices)
|
|
110
|
+
if t == "add named-paths":
|
|
111
|
+
DrillDown(self).name_paths()
|
|
112
|
+
if t == "list named-paths":
|
|
113
|
+
self.list_named_paths()
|
|
114
|
+
if t == "cancel":
|
|
115
|
+
return
|
|
116
|
+
|
|
117
|
+
def _results(self) -> None:
|
|
118
|
+
choices = ["open named-result", "list named-results", "cancel"]
|
|
119
|
+
t = self.ask(choices)
|
|
120
|
+
if t == "open named-result":
|
|
121
|
+
self.open_named_result()
|
|
122
|
+
if t == "list named-results":
|
|
123
|
+
self.list_named_results()
|
|
124
|
+
|
|
125
|
+
def list_named_results(self):
|
|
126
|
+
self.clear()
|
|
127
|
+
names = self._csvpaths.results_manager.list_named_results()
|
|
128
|
+
print(f"{len(names)} named-results names:")
|
|
129
|
+
for n in names:
|
|
130
|
+
self._response(f" {n}")
|
|
131
|
+
self._return_to_cont()
|
|
132
|
+
|
|
133
|
+
def open_named_result(self):
|
|
134
|
+
self.clear()
|
|
135
|
+
try:
|
|
136
|
+
names = self._csvpaths.results_manager.list_named_results()
|
|
137
|
+
print(f"{len(names)} named-results names:")
|
|
138
|
+
for n in names:
|
|
139
|
+
self._response(f" {n}")
|
|
140
|
+
t = self._input("Open which? ")
|
|
141
|
+
t = f"{self._csvpaths.config.archive_path}{os.sep}{t}"
|
|
142
|
+
self._action(f"Opening results at {t}...")
|
|
143
|
+
self.short_pause()
|
|
144
|
+
c = f"open {t}"
|
|
145
|
+
os.system(c)
|
|
146
|
+
except Exception as e:
|
|
147
|
+
print(e)
|
|
148
|
+
|
|
149
|
+
def list_named_paths(self):
|
|
150
|
+
self.clear()
|
|
151
|
+
names = self._csvpaths.paths_manager.named_paths_names
|
|
152
|
+
names.sort()
|
|
153
|
+
print(f"{len(names)} named-paths names:")
|
|
154
|
+
for n in names:
|
|
155
|
+
self._response(f" {n}")
|
|
156
|
+
self._return_to_cont()
|
|
157
|
+
|
|
158
|
+
def list_named_files(self):
|
|
159
|
+
self.clear()
|
|
160
|
+
names = self._csvpaths.file_manager.named_file_names
|
|
161
|
+
names.sort()
|
|
162
|
+
print(f"{len(names)} named-file names:")
|
|
163
|
+
for n in names:
|
|
164
|
+
self._response(f" {n}")
|
|
165
|
+
self._return_to_cont()
|
|
166
|
+
|
|
167
|
+
def run(self):
|
|
168
|
+
self.clear()
|
|
169
|
+
print("What named-file? ")
|
|
170
|
+
files = self._csvpaths.file_manager.named_file_names
|
|
171
|
+
cli = Bullet(bullet=" > ", choices=files)
|
|
172
|
+
file = cli.launch()
|
|
173
|
+
self.clear()
|
|
174
|
+
print("What named-paths? ")
|
|
175
|
+
allpaths = self._csvpaths.paths_manager.named_paths_names
|
|
176
|
+
cli = Bullet(bullet=" > ", choices=allpaths)
|
|
177
|
+
paths = cli.launch()
|
|
178
|
+
self.clear()
|
|
179
|
+
print("What method? ")
|
|
180
|
+
cli = Bullet(bullet=" > ", choices=["collect", "fast forward"])
|
|
181
|
+
method = cli.launch()
|
|
182
|
+
self.clear()
|
|
183
|
+
self._action(f"Running {paths} against {file} using {method}\n")
|
|
184
|
+
self.pause()
|
|
185
|
+
if method == "collect":
|
|
186
|
+
self._csvpaths.collect_paths(filename=file, pathsname=paths)
|
|
187
|
+
else:
|
|
188
|
+
self._csvpaths.fast_forward_paths(filename=file, pathsname=paths)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def run():
|
|
192
|
+
cli = Cli()
|
|
193
|
+
cli.loop()
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
if __name__ == "__main__":
|
|
197
|
+
run()
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
from csvpath import CsvPath, CsvPaths
|
|
2
|
+
import sys
|
|
3
|
+
import os
|
|
4
|
+
from bullet import Bullet
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class DrillDown:
|
|
8
|
+
def __init__(self, cli):
|
|
9
|
+
self._cli = cli
|
|
10
|
+
|
|
11
|
+
# ============================
|
|
12
|
+
# File
|
|
13
|
+
# ============================
|
|
14
|
+
|
|
15
|
+
def name_file(self):
|
|
16
|
+
#
|
|
17
|
+
# get name
|
|
18
|
+
#
|
|
19
|
+
self._cli.clear()
|
|
20
|
+
name = self._cli._input("Named-file name? ")
|
|
21
|
+
#
|
|
22
|
+
# get path
|
|
23
|
+
#
|
|
24
|
+
t = self._get_add_type()
|
|
25
|
+
p = self._get_path(t, self._cli._csvpaths.config.csv_file_extensions)
|
|
26
|
+
if p is False:
|
|
27
|
+
return
|
|
28
|
+
#
|
|
29
|
+
# do the add
|
|
30
|
+
#
|
|
31
|
+
self._cli.clear()
|
|
32
|
+
self._cli._action(f"Adding: {p}\n")
|
|
33
|
+
self._cli.pause()
|
|
34
|
+
if t == "file":
|
|
35
|
+
self._cli._csvpaths.file_manager.add_named_file(name=name, path=p)
|
|
36
|
+
elif t == "dir":
|
|
37
|
+
self._cli._csvpaths.file_manager.add_named_files_from_dir(dirname=p)
|
|
38
|
+
else:
|
|
39
|
+
self._cli._csvpaths.file_manager.set_named_files_from_json(
|
|
40
|
+
name=name, filename=p
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# ============================
|
|
44
|
+
# Paths
|
|
45
|
+
# ============================
|
|
46
|
+
|
|
47
|
+
def name_paths(self):
|
|
48
|
+
#
|
|
49
|
+
# get name
|
|
50
|
+
#
|
|
51
|
+
self._cli.clear()
|
|
52
|
+
name = self._cli._input("Named-paths name? ")
|
|
53
|
+
#
|
|
54
|
+
# get path
|
|
55
|
+
#
|
|
56
|
+
t = self._get_add_type()
|
|
57
|
+
exts = self._cli._csvpaths.config.csvpath_file_extensions
|
|
58
|
+
p = self._get_path(t, exts)
|
|
59
|
+
if p is False:
|
|
60
|
+
return
|
|
61
|
+
#
|
|
62
|
+
# do the add
|
|
63
|
+
#
|
|
64
|
+
self._cli.clear()
|
|
65
|
+
self._cli._action(f"Adding: {p}\n")
|
|
66
|
+
self._cli.pause()
|
|
67
|
+
if t == "file":
|
|
68
|
+
self._cli._csvpaths.paths_manager.add_named_paths(name=name, from_file=p)
|
|
69
|
+
elif t == "dir":
|
|
70
|
+
self._cli._csvpaths.paths_manager.add_named_paths(name=name, from_dir=p)
|
|
71
|
+
else:
|
|
72
|
+
self._cli._csvpaths.paths_manager.add_named_paths(name=name, from_json=p)
|
|
73
|
+
|
|
74
|
+
# ============================
|
|
75
|
+
# Utilities
|
|
76
|
+
# ============================
|
|
77
|
+
|
|
78
|
+
def _get_path(self, t: str, extensions: list[str]) -> str:
|
|
79
|
+
dir_only = t == "dir"
|
|
80
|
+
p = "."
|
|
81
|
+
if t == "json":
|
|
82
|
+
extensions.append("")
|
|
83
|
+
extensions.append("json")
|
|
84
|
+
elif t == "file":
|
|
85
|
+
extensions.append("")
|
|
86
|
+
while p is not None and p != "" and not os.path.isfile(p):
|
|
87
|
+
self._cli.clear()
|
|
88
|
+
self._cli._action(f"{p}\n")
|
|
89
|
+
p = self._drill_down(
|
|
90
|
+
path=p,
|
|
91
|
+
json=True if t == "json" else False,
|
|
92
|
+
extensions=extensions,
|
|
93
|
+
dir_only=dir_only,
|
|
94
|
+
)
|
|
95
|
+
if isinstance(p, tuple) and p[1] is True:
|
|
96
|
+
p = p[0]
|
|
97
|
+
break
|
|
98
|
+
if isinstance(p, tuple) and p[1] is False:
|
|
99
|
+
p = False
|
|
100
|
+
break
|
|
101
|
+
return p
|
|
102
|
+
|
|
103
|
+
def _get_add_type(self) -> str:
|
|
104
|
+
self._cli.clear()
|
|
105
|
+
t = None
|
|
106
|
+
cli = Bullet(bullet=" > ", choices=["dir", "file", "json"])
|
|
107
|
+
t = cli.launch()
|
|
108
|
+
return t
|
|
109
|
+
|
|
110
|
+
def _drill_down(self, *, path, extensions, json=False, dir_only=False) -> str:
|
|
111
|
+
names = os.listdir(path)
|
|
112
|
+
names = self._filter_hidden(names)
|
|
113
|
+
if dir_only:
|
|
114
|
+
names = self._filter_dirs_only(path, names)
|
|
115
|
+
names.sort()
|
|
116
|
+
else:
|
|
117
|
+
names = self._filter_extensions(path, names, extensions)
|
|
118
|
+
names.sort()
|
|
119
|
+
names = self._decorate(path, names)
|
|
120
|
+
cli = Bullet(bullet=" > ", choices=names)
|
|
121
|
+
t = cli.launch()
|
|
122
|
+
if t == self._cli.STOP_HERE:
|
|
123
|
+
return (path, True)
|
|
124
|
+
if t == self._cli.CANCEL:
|
|
125
|
+
return (path, False)
|
|
126
|
+
if t.startswith("📂 ") or t.startswith("📄 "):
|
|
127
|
+
t = t[2:]
|
|
128
|
+
return os.path.join(path, t)
|
|
129
|
+
|
|
130
|
+
def _decorate(self, path, names) -> list[str]:
|
|
131
|
+
ns = []
|
|
132
|
+
for n in names:
|
|
133
|
+
if n == self._cli.STOP_HERE:
|
|
134
|
+
pass
|
|
135
|
+
elif os.path.isfile(os.path.join(path, n)):
|
|
136
|
+
n = f"📄 {n}"
|
|
137
|
+
else:
|
|
138
|
+
n = f"📂 {n}"
|
|
139
|
+
ns.append(n)
|
|
140
|
+
ns.append(self._cli.STOP_HERE)
|
|
141
|
+
ns.append(self._cli.CANCEL)
|
|
142
|
+
return ns
|
|
143
|
+
|
|
144
|
+
def _filter_hidden(self, names) -> list[str]:
|
|
145
|
+
if len(names) == 0:
|
|
146
|
+
return []
|
|
147
|
+
names = [n for n in names if not n[0] == "."]
|
|
148
|
+
return names
|
|
149
|
+
|
|
150
|
+
def _filter_files_only(self, path, names) -> list[str]:
|
|
151
|
+
if len(names) == 0:
|
|
152
|
+
return []
|
|
153
|
+
ns = []
|
|
154
|
+
for n in names:
|
|
155
|
+
if os.path.isfile(os.path.join(path, n)):
|
|
156
|
+
ns.append(n)
|
|
157
|
+
return ns
|
|
158
|
+
|
|
159
|
+
def _filter_dirs_only(self, path, names) -> list[str]:
|
|
160
|
+
if len(names) == 0:
|
|
161
|
+
return []
|
|
162
|
+
ns = []
|
|
163
|
+
for n in names:
|
|
164
|
+
if not os.path.isfile(os.path.join(path, n)):
|
|
165
|
+
ns.append(n)
|
|
166
|
+
return ns
|
|
167
|
+
|
|
168
|
+
def _filter_extensions(self, path, names, extensions) -> list[str]:
|
|
169
|
+
if len(names) == 0:
|
|
170
|
+
return []
|
|
171
|
+
if len(extensions) == 0:
|
|
172
|
+
return []
|
|
173
|
+
ns = []
|
|
174
|
+
for n in names:
|
|
175
|
+
ext = self._ext_if(n)
|
|
176
|
+
if ext in extensions:
|
|
177
|
+
ns.append(n)
|
|
178
|
+
return ns
|
|
179
|
+
|
|
180
|
+
def _ext_if(self, name) -> str:
|
|
181
|
+
i = name.rfind(".")
|
|
182
|
+
if i == -1:
|
|
183
|
+
return ""
|
|
184
|
+
ext = name[i + 1 :]
|
|
185
|
+
return ext
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
from typing import Dict, List
|
|
3
3
|
import os
|
|
4
4
|
import json
|
|
5
|
+
import shutil
|
|
5
6
|
from typing import NewType
|
|
6
7
|
from json import JSONDecodeError
|
|
7
8
|
from abc import ABC, abstractmethod
|
|
@@ -82,17 +83,23 @@ class CsvPathsManager(ABC):
|
|
|
82
83
|
pass # pragma: no cover
|
|
83
84
|
|
|
84
85
|
@abstractmethod
|
|
85
|
-
def
|
|
86
|
-
pass
|
|
86
|
+
def total_named_paths(self) -> int:
|
|
87
|
+
pass
|
|
88
|
+
|
|
89
|
+
@abstractmethod
|
|
90
|
+
def number_of_named_paths(self, name: str) -> int:
|
|
91
|
+
pass
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
@abstractmethod
|
|
95
|
+
def named_paths_names(self) -> list[str]:
|
|
96
|
+
pass
|
|
87
97
|
|
|
88
98
|
|
|
89
99
|
class PathsManager(CsvPathsManager): # pylint: disable=C0115, C0116
|
|
90
100
|
MARKER: str = "---- CSVPATH ----"
|
|
91
101
|
|
|
92
102
|
def __init__(self, *, csvpaths, named_paths=None):
|
|
93
|
-
if named_paths is None:
|
|
94
|
-
named_paths = {}
|
|
95
|
-
self.named_paths = named_paths
|
|
96
103
|
self.csvpaths = csvpaths
|
|
97
104
|
self._registrar = PathsRegistrar(self.csvpaths.config)
|
|
98
105
|
|
|
@@ -103,10 +110,11 @@ class PathsManager(CsvPathsManager): # pylint: disable=C0115, C0116
|
|
|
103
110
|
def set_named_paths(self, np: Dict[str, List[str]]) -> None:
|
|
104
111
|
for name in np:
|
|
105
112
|
if not isinstance(np[name], list):
|
|
106
|
-
ie = InputException(
|
|
113
|
+
ie = InputException(
|
|
114
|
+
f"Named-paths name {name} must key a list of csvpath"
|
|
115
|
+
)
|
|
107
116
|
ErrorHandler(csvpaths=self.csvpaths).handle_error(ie)
|
|
108
117
|
return
|
|
109
|
-
self.named_paths = np
|
|
110
118
|
for k, v in np.items():
|
|
111
119
|
self.add_named_paths(name=k, paths=v)
|
|
112
120
|
self.csvpaths.logger.info(
|
|
@@ -139,6 +147,10 @@ class PathsManager(CsvPathsManager): # pylint: disable=C0115, C0116
|
|
|
139
147
|
|
|
140
148
|
def add_named_paths_from_file(self, *, name: str, file_path: str) -> None:
|
|
141
149
|
self.csvpaths.logger.debug("Reading csvpaths file at %s", file_path)
|
|
150
|
+
_ = self._get_csvpaths_from_file(file_path)
|
|
151
|
+
self.add_named_paths(name=name, paths=_)
|
|
152
|
+
|
|
153
|
+
def _get_csvpaths_from_file(self, file_path: str) -> list[str]:
|
|
142
154
|
with open(file_path, "r", encoding="utf-8") as f:
|
|
143
155
|
cp = f.read()
|
|
144
156
|
_ = [
|
|
@@ -147,7 +159,7 @@ class PathsManager(CsvPathsManager): # pylint: disable=C0115, C0116
|
|
|
147
159
|
if apath.strip() != ""
|
|
148
160
|
]
|
|
149
161
|
self.csvpaths.logger.debug("Found %s csvpaths in file", len(_))
|
|
150
|
-
|
|
162
|
+
return _
|
|
151
163
|
|
|
152
164
|
def add_named_paths_from_json(self, file_path: str) -> None:
|
|
153
165
|
try:
|
|
@@ -158,8 +170,12 @@ class PathsManager(CsvPathsManager): # pylint: disable=C0115, C0116
|
|
|
158
170
|
for k in j:
|
|
159
171
|
self.registrar.store_json_paths_file(k, file_path)
|
|
160
172
|
v = j[k]
|
|
173
|
+
paths = []
|
|
161
174
|
for f in v:
|
|
162
|
-
self.
|
|
175
|
+
_ = self._get_csvpaths_from_file(f)
|
|
176
|
+
paths += _
|
|
177
|
+
self.add_named_paths(name=k, paths=paths)
|
|
178
|
+
|
|
163
179
|
except (OSError, ValueError, TypeError, JSONDecodeError) as ex:
|
|
164
180
|
self.csvpaths.logger.error(f"Error: cannot load {file_path}: {ex}")
|
|
165
181
|
ErrorHandler(csvpaths=self.csvpaths).handle_error(ex)
|
|
@@ -188,34 +204,10 @@ class PathsManager(CsvPathsManager): # pylint: disable=C0115, C0116
|
|
|
188
204
|
)
|
|
189
205
|
ErrorHandler(csvpaths=self.csvpaths).handle_error(ie)
|
|
190
206
|
self.csvpaths.logger.debug("Adding csvpaths to named-paths group %s", name)
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
# assure a manifest
|
|
195
|
-
# write the fingerprint and timestamp in manifest
|
|
196
|
-
# return path to all-in-one file
|
|
197
|
-
#
|
|
198
|
-
if name in self.named_paths:
|
|
199
|
-
for p in paths:
|
|
200
|
-
if p in self.named_paths[name]:
|
|
201
|
-
self.csvpaths.logger.debug(
|
|
202
|
-
"csvpaths %s already exists in named-paths group %s", p, name
|
|
203
|
-
)
|
|
204
|
-
pass
|
|
205
|
-
else:
|
|
206
|
-
self.csvpaths.logger.debug("Adding %s to %s", p, name)
|
|
207
|
-
self.named_paths[name].append(p)
|
|
208
|
-
self.registrar.register_named_paths(
|
|
209
|
-
name=name, paths=self.named_paths[name]
|
|
210
|
-
)
|
|
211
|
-
else:
|
|
212
|
-
for _ in paths:
|
|
213
|
-
self.csvpaths.logger.debug("Adding %s to %s", _, name)
|
|
214
|
-
self.registrar.register_named_paths(name=name, paths=paths)
|
|
215
|
-
self.named_paths[name] = paths
|
|
207
|
+
for _ in paths:
|
|
208
|
+
self.csvpaths.logger.debug("Adding %s to %s", _, name)
|
|
209
|
+
self.registrar.register_named_paths(name=name, paths=paths)
|
|
216
210
|
|
|
217
|
-
#
|
|
218
|
-
# ========================
|
|
219
211
|
#
|
|
220
212
|
# adding ref handling for the form: $many.csvpaths.food
|
|
221
213
|
# which is equiv to: many#food
|
|
@@ -234,16 +226,15 @@ class PathsManager(CsvPathsManager): # pylint: disable=C0115, C0116
|
|
|
234
226
|
identity = ref.name_one
|
|
235
227
|
else:
|
|
236
228
|
npn, identity = self._paths_name_path(name)
|
|
237
|
-
self.
|
|
229
|
+
if identity is None and self.has_named_paths(npn):
|
|
230
|
+
ret = self._get_named_paths(npn)
|
|
231
|
+
elif identity is not None and identity.find(":") == -1:
|
|
232
|
+
ret = [self._find_one(npn, identity)]
|
|
238
233
|
#
|
|
239
234
|
# we need to be able to grab paths up to and starting from like this:
|
|
240
235
|
# $many.csvpaths.food:to
|
|
241
236
|
# $many.csvpaths.food:from
|
|
242
237
|
#
|
|
243
|
-
if identity is None and npn in self.named_paths:
|
|
244
|
-
ret = self.named_paths[npn]
|
|
245
|
-
elif identity is not None and identity.find(":") == -1:
|
|
246
|
-
ret = [self._find_one(npn, identity)]
|
|
247
238
|
elif identity is not None:
|
|
248
239
|
i = identity.find(":")
|
|
249
240
|
directive = identity[i:]
|
|
@@ -256,28 +247,23 @@ class PathsManager(CsvPathsManager): # pylint: disable=C0115, C0116
|
|
|
256
247
|
raise InputException(
|
|
257
248
|
f"Reference directive must be :to or :from, not {directive}"
|
|
258
249
|
)
|
|
259
|
-
#
|
|
260
|
-
# if not in self.named_paths we would return None here
|
|
261
|
-
# need to instead look to the named_paths dir to see what
|
|
262
|
-
# has been registered
|
|
263
|
-
#
|
|
264
250
|
return ret
|
|
265
251
|
|
|
266
|
-
def
|
|
267
|
-
if
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
252
|
+
def _get_named_paths(self, name: str) -> None:
|
|
253
|
+
if not self.has_named_paths(name):
|
|
254
|
+
return None
|
|
255
|
+
s = ""
|
|
256
|
+
path = self.registrar.named_paths_home(name)
|
|
257
|
+
grp = os.path.join(path, "group.csvpaths")
|
|
258
|
+
if os.path.exists(grp):
|
|
259
|
+
with open(grp, "r", encoding="utf-8") as file:
|
|
260
|
+
s = file.read()
|
|
261
|
+
cs = s.split("---- CSVPATH ----")
|
|
262
|
+
cs = [s for s in cs if s.strip() != ""]
|
|
263
|
+
# if someone put a new group.csvpaths file by hand we want to
|
|
264
|
+
# capture its fingerprint for future reference.
|
|
265
|
+
self.registrar.update_manifest_if(name=name)
|
|
266
|
+
return cs
|
|
281
267
|
|
|
282
268
|
def _paths_name_path(self, pathsname) -> tuple[NamedPathsName, Identity]:
|
|
283
269
|
specificpath = None
|
|
@@ -326,23 +312,32 @@ class PathsManager(CsvPathsManager): # pylint: disable=C0115, C0116
|
|
|
326
312
|
f"Path identified as '{identity}' must be in the group identitied as '{npn}'"
|
|
327
313
|
)
|
|
328
314
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
315
|
+
@property
|
|
316
|
+
def named_paths_names(self) -> list[str]:
|
|
317
|
+
path = self.registrar.named_paths_dir
|
|
318
|
+
names = [n for n in os.listdir(path) if not n.startswith(".")]
|
|
319
|
+
return names
|
|
334
320
|
|
|
335
321
|
def remove_named_paths(self, name: str) -> None:
|
|
336
|
-
if
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
322
|
+
if not self.has_named_paths(name):
|
|
323
|
+
raise InputException(f"Named-paths name {name} not found")
|
|
324
|
+
home = self.registrar.named_paths_home(name)
|
|
325
|
+
shutil.rmtree(home)
|
|
326
|
+
|
|
327
|
+
def remove_all_named_paths(self) -> None:
|
|
328
|
+
names = self.named_paths_names
|
|
329
|
+
for name in names:
|
|
330
|
+
self.remove_named_paths(name)
|
|
340
331
|
|
|
341
332
|
def has_named_paths(self, name: str) -> bool:
|
|
342
|
-
|
|
333
|
+
path = os.path.join(self.registrar.named_paths_dir, name)
|
|
334
|
+
return os.path.exists(path)
|
|
335
|
+
|
|
336
|
+
def number_of_named_paths(self, name: str) -> int:
|
|
337
|
+
return len(self._get_named_paths(name))
|
|
343
338
|
|
|
344
|
-
def
|
|
345
|
-
return len(self.
|
|
339
|
+
def total_named_paths(self) -> bool:
|
|
340
|
+
return len(self.named_paths_names) # pragma: no cover
|
|
346
341
|
|
|
347
342
|
def _name_from_name_part(self, name):
|
|
348
343
|
i = name.rfind(".")
|
|
@@ -56,6 +56,16 @@ class CsvPathsFileManager(ABC):
|
|
|
56
56
|
def get_original_headers(self, filename: str) -> List[str]:
|
|
57
57
|
"""gets the cached headers"""
|
|
58
58
|
|
|
59
|
+
@property
|
|
60
|
+
@abstractmethod
|
|
61
|
+
def named_files_count(self) -> int:
|
|
62
|
+
pass
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
@abstractmethod
|
|
66
|
+
def named_file_names(self) -> list:
|
|
67
|
+
pass
|
|
68
|
+
|
|
59
69
|
|
|
60
70
|
class FileManager(CsvPathsFileManager): # pylint: disable=C0115
|
|
61
71
|
def __init__(self, *, named_files: Dict[str, str] = None, csvpaths=None):
|