csvpath 0.0.482__tar.gz → 0.0.483__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.482 → csvpath-0.0.483}/PKG-INFO +1 -2
- {csvpath-0.0.482 → csvpath-0.0.483}/README.md +0 -1
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/csvpath.py +11 -7
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/args.py +16 -9
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/boolean/all.py +3 -1
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/boolean/andf.py +3 -7
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/boolean/any.py +3 -3
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/boolean/empty.py +2 -26
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/boolean/inf.py +2 -2
- csvpath-0.0.483/csvpath/matching/functions/boolean/orf.py +57 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/counting/count.py +2 -5
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/counting/every.py +2 -2
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/counting/increment.py +3 -3
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/counting/tally.py +1 -7
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/dates/now.py +2 -4
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/function.py +5 -3
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/function_factory.py +8 -7
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/headers/collect.py +1 -1
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/headers/end.py +1 -5
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/headers/reset_headers.py +4 -2
- {csvpath-0.0.482/csvpath/matching/functions/types → csvpath-0.0.483/csvpath/matching/functions/math}/intf.py +6 -4
- csvpath-0.0.483/csvpath/matching/functions/types/__init__.py +7 -0
- csvpath-0.0.483/csvpath/matching/functions/types/boolean.py +49 -0
- csvpath-0.0.483/csvpath/matching/functions/types/datef.py +138 -0
- csvpath-0.0.483/csvpath/matching/functions/types/decimal.py +92 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/types/nonef.py +5 -3
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/types/string.py +6 -6
- csvpath-0.0.483/csvpath/matching/functions/validity/line.py +109 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/variables/pushpop.py +1 -1
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/matcher.py +15 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/productions/matchable.py +14 -1
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/util/expression_utility.py +20 -4
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/util/error.py +5 -30
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/util/line_counter.py +3 -2
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/comments.md +2 -2
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/header_names_mismatch.md +2 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/line.md +2 -2
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/now.md +5 -0
- csvpath-0.0.483/docs/functions/types.md +48 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/pyproject.toml +1 -1
- csvpath-0.0.482/csvpath/matching/functions/boolean/orf.py +0 -37
- csvpath-0.0.482/csvpath/matching/functions/types/boolean.py +0 -31
- csvpath-0.0.482/csvpath/matching/functions/types/datef.py +0 -40
- csvpath-0.0.482/csvpath/matching/functions/validity/line.py +0 -92
- {csvpath-0.0.482 → csvpath-0.0.483}/LICENSE +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/config/config.ini +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/__init__.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/csvpaths.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/managers/__init__.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/managers/csvpaths_manager.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/managers/file_manager.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/managers/result.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/managers/results_manager.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/__init__.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/__init__.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/boolean/between.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/boolean/exists.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/boolean/no.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/boolean/notf.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/boolean/yes.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/counting/count_headers.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/counting/count_lines.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/counting/count_scans.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/counting/counter.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/counting/has_matches.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/counting/total_lines.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/function_finder.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/function_focus.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/headers/append.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/headers/empty_stack.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/headers/header_name.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/headers/header_names_mismatch.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/headers/headers.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/headers/mismatch.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/headers/replace.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/lines/advance.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/lines/after_blank.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/lines/dups.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/lines/first.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/lines/first_line.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/lines/last.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/lines/stop.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/math/above.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/math/add.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/math/divide.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/math/equals.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/math/mod.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/math/multiply.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/math/round.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/math/subtotal.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/math/subtract.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/math/sum.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/misc/importf.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/misc/random.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/print/jinjaf.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/print/print_line.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/print/print_queue.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/print/printf.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/print/table.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/stats/minf.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/stats/percent.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/stats/percent_unique.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/stats/stdev.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/strings/concat.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/strings/length.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/strings/lower.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/strings/metaphone.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/strings/regex.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/strings/starts_with.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/strings/strip.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/strings/substring.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/strings/upper.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/testing/debug.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/validity/fail.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/validity/failed.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/variables/get.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/variables/put.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/variables/track.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/functions/variables/variables.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/lark_parser.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/lark_transformer.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/productions/__init__.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/productions/equality.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/productions/expression.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/productions/header.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/productions/qualified.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/productions/reference.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/productions/term.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/productions/variable.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/util/exceptions.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/util/expression_encoder.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/util/lark_print_parser.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/matching/util/print_parser.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/scanning/__init__.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/scanning/exceptions.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/scanning/parser.out +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/scanning/parsetab.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/scanning/scanner.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/scanning/scanning_lexer.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/util/cache.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/util/config.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/util/config_exception.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/util/exceptions.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/util/last_line_stats.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/util/line_monitor.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/util/log_utility.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/util/metadata_parser.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/csvpath/util/printer.py +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/asbool.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/assignment.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/config.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/examples.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/files.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/above.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/advance.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/after_blank.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/all.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/andor.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/any.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/average.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/between.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/collect.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/correlate.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/count.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/count_headers.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/counter.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/date.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/empty.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/empty_stack.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/end.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/every.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/fail.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/first.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/get.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/has_dups.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/has_matches.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/header.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/header_name.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/implementing_functions.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/import.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/in.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/increment.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/intf.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/jinja.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/last.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/line_number.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/max.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/metaphone.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/mismatch.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/no.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/not.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/percent_unique.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/pop.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/print.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/print_line.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/print_queue.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/random.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/regex.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/replace.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/reset_headers.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/stdev.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/stop.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/string_functions.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/subtotal.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/subtract.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/sum.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/tally.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/total_lines.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/track.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/variables.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions/variables_and_headers.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/functions.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/grammar.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/headers.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/images/logo-wordmark-white-on-black-trimmed-padded.png +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/images/logo-wordmark-white-trimmed.png +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/paths.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/printing.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/qualifiers.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/references.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/docs/terms.md +0 -0
- {csvpath-0.0.482 → csvpath-0.0.483}/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.483
|
|
4
4
|
Summary: A declarative language for data extraction and validation of CSV files
|
|
5
5
|
Author: David Kershaw
|
|
6
6
|
Author-email: dk107dk@hotmail.com
|
|
@@ -48,7 +48,6 @@ And do it all in an automation-friendly way.
|
|
|
48
48
|
Though much simpler, it is inspired by:
|
|
49
49
|
- XPath. CsvPath is to CSV files like XPath is to XML files.
|
|
50
50
|
- Validation of XML using <a href='https://schematron.com/'>Schematron rules</a>
|
|
51
|
-
- The way CSS selectors pick out HTML structures
|
|
52
51
|
|
|
53
52
|
CsvPath is intended to fit with other DataOps and data quality tools. Files are streamed. The interface is simple. New functions are easy to create.
|
|
54
53
|
|
|
@@ -14,7 +14,6 @@ And do it all in an automation-friendly way.
|
|
|
14
14
|
Though much simpler, it is inspired by:
|
|
15
15
|
- XPath. CsvPath is to CSV files like XPath is to XML files.
|
|
16
16
|
- Validation of XML using <a href='https://schematron.com/'>Schematron rules</a>
|
|
17
|
-
- The way CSS selectors pick out HTML structures
|
|
18
17
|
|
|
19
18
|
CsvPath is intended to fit with other DataOps and data quality tools. Files are streamed. The interface is simple. New functions are easy to create.
|
|
20
19
|
|
|
@@ -14,7 +14,7 @@ from csvpath.util.log_utility import LogUtility
|
|
|
14
14
|
from .matching.matcher import Matcher
|
|
15
15
|
from .scanning.scanner import Scanner
|
|
16
16
|
from .util.metadata_parser import MetadataParser
|
|
17
|
-
from .util.error import Error, ErrorCollector
|
|
17
|
+
from .util.error import Error, ErrorCollector, ErrorCommsManager
|
|
18
18
|
from .util.printer import StdOutPrinter
|
|
19
19
|
from .util.line_counter import LineCounter
|
|
20
20
|
from .util.exceptions import VariableException, InputException, ParsingException
|
|
@@ -262,6 +262,10 @@ class CsvPath(CsvPathPublic, ErrorCollector, Printer): # pylint: disable=R0902,
|
|
|
262
262
|
#
|
|
263
263
|
self.logger = LogUtility.logger(self)
|
|
264
264
|
self.logger.info("initialized CsvPath")
|
|
265
|
+
self._ecoms = ErrorCommsManager(csvpath=self)
|
|
266
|
+
|
|
267
|
+
def do_i_raise(self) -> bool:
|
|
268
|
+
return self._ecoms.do_i_raise()
|
|
265
269
|
|
|
266
270
|
@property
|
|
267
271
|
def advance_count(self) -> int: # pragma: no cover
|
|
@@ -569,7 +573,7 @@ class CsvPath(CsvPathPublic, ErrorCollector, Printer): # pylint: disable=R0902,
|
|
|
569
573
|
#
|
|
570
574
|
# settings:
|
|
571
575
|
# - logic-mode: AND | OR
|
|
572
|
-
# -
|
|
576
|
+
# - return-mode: matches | no-matches
|
|
573
577
|
# - print-mode: default | no-default
|
|
574
578
|
# - validation-mode: (no-)print | log | (no-)raise | quiet | (no-)match
|
|
575
579
|
#
|
|
@@ -606,15 +610,15 @@ class CsvPath(CsvPathPublic, ErrorCollector, Printer): # pylint: disable=R0902,
|
|
|
606
610
|
)
|
|
607
611
|
|
|
608
612
|
def update_match_mode_if(self) -> None:
|
|
609
|
-
if "
|
|
610
|
-
if f"{self.metadata['
|
|
613
|
+
if "return-mode" in self.metadata:
|
|
614
|
+
if f"{self.metadata['return-mode']}".strip() == "matches":
|
|
611
615
|
self.collect_when_not_matched = False
|
|
612
|
-
elif f"{self.metadata['
|
|
616
|
+
elif f"{self.metadata['return-mode']}".strip() == "no-matches":
|
|
613
617
|
self.collect_when_not_matched = True
|
|
614
618
|
else:
|
|
615
619
|
self.logger.warning(
|
|
616
|
-
"Incorrect metadata field value '
|
|
617
|
-
self.metadata["
|
|
620
|
+
"Incorrect metadata field value 'return-mode': %s",
|
|
621
|
+
self.metadata["return-mode"],
|
|
618
622
|
)
|
|
619
623
|
|
|
620
624
|
def update_print_mode_if(self) -> None:
|
|
@@ -16,9 +16,12 @@ from csvpath.util.config_exception import ConfigurationException
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class Arg:
|
|
19
|
-
def __init__(
|
|
19
|
+
def __init__(
|
|
20
|
+
self, *, name: str = None, types: list[Type] = None, actuals: list[Type] = None
|
|
21
|
+
):
|
|
20
22
|
self.is_noneable = False
|
|
21
23
|
self._types = None
|
|
24
|
+
self._name = name
|
|
22
25
|
self._x_actuals = None
|
|
23
26
|
self.types: list[Type] = types or [None]
|
|
24
27
|
self.actuals: list[Type] = actuals or []
|
|
@@ -100,8 +103,10 @@ class ArgSet:
|
|
|
100
103
|
# setup time
|
|
101
104
|
# ----------------------------
|
|
102
105
|
|
|
103
|
-
def arg(
|
|
104
|
-
|
|
106
|
+
def arg(
|
|
107
|
+
self, *, name: str = None, types: list[Type] = None, actuals: list[Type] = None
|
|
108
|
+
) -> Arg:
|
|
109
|
+
arg = Arg(name=name, types=types, actuals=actuals)
|
|
105
110
|
self._args.append(arg)
|
|
106
111
|
if len(self._args) > self.max_length and self.max_length != -1:
|
|
107
112
|
self.max_length = len(self._args)
|
|
@@ -194,16 +199,17 @@ class ArgSet:
|
|
|
194
199
|
self._args = args
|
|
195
200
|
self.max_length = len(self._args)
|
|
196
201
|
|
|
197
|
-
def validate_structure(self, siblings: List[Matchable]) -> None:
|
|
202
|
+
def validate_structure(self, siblings: List[Matchable]) -> None | str:
|
|
198
203
|
b = self._validate_length(siblings)
|
|
199
204
|
if b is False:
|
|
200
|
-
return
|
|
205
|
+
return "incorrect number of args"
|
|
201
206
|
self._pad_or_shrink(siblings)
|
|
202
207
|
for i, s in enumerate(siblings):
|
|
203
208
|
t = tuple(self._args[i].types)
|
|
204
209
|
if not isinstance(s, t):
|
|
205
|
-
|
|
206
|
-
|
|
210
|
+
ii = i + 1
|
|
211
|
+
return f"type mismatch at arg {ii}"
|
|
212
|
+
return None
|
|
207
213
|
|
|
208
214
|
# ----------------------------
|
|
209
215
|
# match actuals line-by-line
|
|
@@ -390,11 +396,12 @@ class Args:
|
|
|
390
396
|
#
|
|
391
397
|
good = False
|
|
392
398
|
for aset in self._argsets:
|
|
393
|
-
|
|
399
|
+
_m = aset.validate_structure(siblings)
|
|
400
|
+
if _m is None:
|
|
394
401
|
good = True
|
|
395
402
|
if not good:
|
|
396
403
|
_ = f" at {self.matchable.my_chain}" if self.matchable else ""
|
|
397
|
-
msg = f"{self._csvpath_id()} Incorrectly written{_}. Wrong type or number of args."
|
|
404
|
+
msg = f"{self._csvpath_id()} Incorrectly written{_}. Wrong type or number of args: {_m}."
|
|
398
405
|
raise ChildrenException(msg)
|
|
399
406
|
self.validated = True
|
|
400
407
|
|
|
@@ -19,7 +19,9 @@ class All(MatchDecider):
|
|
|
19
19
|
self.args = Args(matchable=self)
|
|
20
20
|
self.args.argset(0)
|
|
21
21
|
self.args.argset(1).arg(types=[None, Variables, Headers], actuals=[])
|
|
22
|
-
self.args.argset().arg(
|
|
22
|
+
self.args.argset().arg(
|
|
23
|
+
types=[None, Function, Variable, Header], actuals=[None, Any]
|
|
24
|
+
)
|
|
23
25
|
self.args.validate(self.siblings())
|
|
24
26
|
super().check_valid()
|
|
25
27
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from typing import Any
|
|
4
4
|
from ..function_focus import MatchDecider
|
|
5
|
-
from csvpath.matching.productions import
|
|
5
|
+
from csvpath.matching.productions import Matchable
|
|
6
6
|
from ..function import Function
|
|
7
7
|
from ..args import Args
|
|
8
8
|
|
|
@@ -15,12 +15,8 @@ class And(MatchDecider):
|
|
|
15
15
|
def check_valid(self) -> None: # pragma: no cover
|
|
16
16
|
self.args = Args(matchable=self)
|
|
17
17
|
a = self.args.argset()
|
|
18
|
-
a.arg(
|
|
19
|
-
|
|
20
|
-
)
|
|
21
|
-
a.arg(
|
|
22
|
-
types=[Term, Variable, Header, Function, Reference, Equality], actuals=[Any]
|
|
23
|
-
)
|
|
18
|
+
a.arg(types=[Matchable], actuals=[None, Any])
|
|
19
|
+
a.arg(types=[Matchable], actuals=[None, Any])
|
|
24
20
|
self.args.validate(self.siblings_or_equality())
|
|
25
21
|
super().check_valid()
|
|
26
22
|
|
|
@@ -24,11 +24,11 @@ class Any(MatchDecider):
|
|
|
24
24
|
a = self.args.argset(0)
|
|
25
25
|
|
|
26
26
|
a = self.args.argset(2)
|
|
27
|
-
a.arg(types=[Variables, Headers], actuals=[Any])
|
|
28
|
-
a.arg(types=[typing.Any], actuals=[typing.Any])
|
|
27
|
+
a.arg(types=[Variables, Headers], actuals=[None, typing.Any])
|
|
28
|
+
a.arg(types=[typing.Any], actuals=[None, typing.Any])
|
|
29
29
|
|
|
30
30
|
a = self.args.argset(1)
|
|
31
|
-
a.arg(types=[typing.Any, Variables, Headers], actuals=[typing.Any])
|
|
31
|
+
a.arg(types=[typing.Any, Variables, Headers], actuals=[None, typing.Any])
|
|
32
32
|
|
|
33
33
|
self.args.validate(self.siblings())
|
|
34
34
|
super().check_valid()
|
|
@@ -33,7 +33,7 @@ class Empty(MatchDecider):
|
|
|
33
33
|
def _validate(self):
|
|
34
34
|
sibs = self.siblings()
|
|
35
35
|
for s in sibs:
|
|
36
|
-
# both
|
|
36
|
+
# both structure / children exceptions
|
|
37
37
|
if isinstance(s, Headers) and len(sibs) > 1:
|
|
38
38
|
raise ChildrenException(
|
|
39
39
|
"If empty() has a headers() argument it can only have 1 argument"
|
|
@@ -73,12 +73,7 @@ class Empty(MatchDecider):
|
|
|
73
73
|
self.match = ret
|
|
74
74
|
|
|
75
75
|
def _do_many(self, skip=None):
|
|
76
|
-
siblings =
|
|
77
|
-
if isinstance(self.children[0], Equality):
|
|
78
|
-
siblings = self.children[0].commas_to_list()
|
|
79
|
-
else:
|
|
80
|
-
siblings = self.children[0]
|
|
81
|
-
|
|
76
|
+
siblings = self.siblings()
|
|
82
77
|
for s in siblings:
|
|
83
78
|
self._do_one(s)
|
|
84
79
|
if self.match is False:
|
|
@@ -87,22 +82,3 @@ class Empty(MatchDecider):
|
|
|
87
82
|
def _do_one(self, child, skip=None):
|
|
88
83
|
v = child.to_value(skip=skip)
|
|
89
84
|
self.match = ExpressionUtility.is_empty(v)
|
|
90
|
-
|
|
91
|
-
"""
|
|
92
|
-
def _is_empty(self, v):
|
|
93
|
-
ret = True
|
|
94
|
-
if v is None:
|
|
95
|
-
ret = True
|
|
96
|
-
elif f"{v}".strip() == "":
|
|
97
|
-
ret = True
|
|
98
|
-
elif isinstance(v, list) or isinstance(v, tuple):
|
|
99
|
-
for item in v:
|
|
100
|
-
ret = self._is_empty(item)
|
|
101
|
-
if not ret:
|
|
102
|
-
break
|
|
103
|
-
elif isinstance(v, dict):
|
|
104
|
-
ret = len(v) > 0
|
|
105
|
-
else:
|
|
106
|
-
ret = False
|
|
107
|
-
return ret
|
|
108
|
-
"""
|
|
@@ -13,8 +13,8 @@ class In(MatchDecider):
|
|
|
13
13
|
def check_valid(self) -> None:
|
|
14
14
|
self.args = Args(matchable=self)
|
|
15
15
|
a = self.args.argset()
|
|
16
|
-
a.arg(types=[Term, Variable, Header, Function, Reference], actuals=[Any])
|
|
17
|
-
a.arg(types=[Term, Variable, Header, Function, Reference], actuals=[Any])
|
|
16
|
+
a.arg(types=[Term, Variable, Header, Function, Reference], actuals=[None, Any])
|
|
17
|
+
a.arg(types=[Term, Variable, Header, Function, Reference], actuals=[None, Any])
|
|
18
18
|
self.args.validate(self.siblings())
|
|
19
19
|
super().check_valid()
|
|
20
20
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# pylint: disable=C0114
|
|
2
|
+
from typing import Any
|
|
3
|
+
from ..function_focus import MatchDecider
|
|
4
|
+
from csvpath.matching.productions import (
|
|
5
|
+
Term,
|
|
6
|
+
Variable,
|
|
7
|
+
Header,
|
|
8
|
+
Reference,
|
|
9
|
+
Equality,
|
|
10
|
+
Matchable,
|
|
11
|
+
)
|
|
12
|
+
from ..function import Function
|
|
13
|
+
from ..args import Args
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Or(MatchDecider):
|
|
17
|
+
"""does a logical OR of match components"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, matcher: Any, name: str, child: Matchable = None) -> None:
|
|
20
|
+
super().__init__(matcher, name=name, child=child)
|
|
21
|
+
self.hold = []
|
|
22
|
+
|
|
23
|
+
def reset(self) -> None:
|
|
24
|
+
self.hold = []
|
|
25
|
+
super().reset()
|
|
26
|
+
|
|
27
|
+
def check_valid(self) -> None:
|
|
28
|
+
self.args = Args(matchable=self)
|
|
29
|
+
a = self.args.argset()
|
|
30
|
+
a.arg(types=[Matchable], actuals=[None, Any])
|
|
31
|
+
a.arg(types=[Matchable], actuals=[None, Any])
|
|
32
|
+
self.args.validate(self.siblings_or_equality())
|
|
33
|
+
super().check_valid()
|
|
34
|
+
|
|
35
|
+
def raise_if(self, e, *, cause=None) -> None:
|
|
36
|
+
# not bubbling up until we know we don't have a
|
|
37
|
+
# match on all options
|
|
38
|
+
self.hold.append((e, cause))
|
|
39
|
+
|
|
40
|
+
def _produce_value(self, skip=None) -> None:
|
|
41
|
+
self.value = self.matches(skip=skip)
|
|
42
|
+
|
|
43
|
+
def _decide_match(self, skip=None) -> None:
|
|
44
|
+
child = self.children[0]
|
|
45
|
+
siblings = child.commas_to_list()
|
|
46
|
+
for sib in siblings:
|
|
47
|
+
b = sib.matches(skip=skip)
|
|
48
|
+
if b:
|
|
49
|
+
self.match = True
|
|
50
|
+
# if we find a True we succeed and dump any errors
|
|
51
|
+
self.hold = []
|
|
52
|
+
return
|
|
53
|
+
self.match = False
|
|
54
|
+
# if we fail we progress any errors up the stack
|
|
55
|
+
for err in self.hold:
|
|
56
|
+
super().raise_if(err[0], cause=err[1])
|
|
57
|
+
self.hold = []
|
|
@@ -3,7 +3,7 @@ from typing import Any
|
|
|
3
3
|
from ..function_focus import ValueProducer
|
|
4
4
|
from ..function import Function
|
|
5
5
|
from ..args import Args
|
|
6
|
-
from csvpath.matching.productions import
|
|
6
|
+
from csvpath.matching.productions import Matchable
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class Count(ValueProducer):
|
|
@@ -16,10 +16,7 @@ class Count(ValueProducer):
|
|
|
16
16
|
self.args = Args(matchable=self)
|
|
17
17
|
a = self.args.argset(0)
|
|
18
18
|
a = self.args.argset()
|
|
19
|
-
a.arg(
|
|
20
|
-
types=[None, Variable, Function, Header, Term, Equality],
|
|
21
|
-
actuals=[None, Any],
|
|
22
|
-
)
|
|
19
|
+
a.arg(types=[None, Matchable], actuals=[None, Any])
|
|
23
20
|
self.args.validate(self.siblings())
|
|
24
21
|
#
|
|
25
22
|
super().check_valid() # pylint: disable=W0246
|
|
@@ -3,7 +3,7 @@ from typing import Any
|
|
|
3
3
|
from csvpath.matching.util.exceptions import ChildrenException
|
|
4
4
|
from csvpath.matching.util.expression_utility import ExpressionUtility
|
|
5
5
|
from ..function_focus import ValueProducer
|
|
6
|
-
from csvpath.matching.productions import Term,
|
|
6
|
+
from csvpath.matching.productions import Term, Matchable
|
|
7
7
|
from ..function import Function
|
|
8
8
|
from ..args import Args
|
|
9
9
|
|
|
@@ -19,7 +19,7 @@ class Every(ValueProducer):
|
|
|
19
19
|
def check_valid(self) -> None:
|
|
20
20
|
self.args = Args(matchable=self)
|
|
21
21
|
a = self.args.argset(2)
|
|
22
|
-
a.arg(types=[
|
|
22
|
+
a.arg(types=[Matchable], actuals=[None, Any])
|
|
23
23
|
a.arg(types=[Term], actuals=[int])
|
|
24
24
|
self.args.validate(self.siblings())
|
|
25
25
|
super().check_valid()
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
from typing import Any
|
|
3
3
|
from csvpath.matching.util.exceptions import DataException
|
|
4
4
|
from ..function_focus import ValueProducer
|
|
5
|
-
from csvpath.matching.productions import Term,
|
|
5
|
+
from csvpath.matching.productions import Term, Matchable
|
|
6
6
|
from ..function import Function
|
|
7
7
|
from ..args import Args
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class Increment(ValueProducer):
|
|
11
|
-
"""increments a var every n-times
|
|
11
|
+
"""increments a var every n-times each different value is seen"""
|
|
12
12
|
|
|
13
13
|
def check_valid(self) -> None:
|
|
14
14
|
self.args = Args(matchable=self)
|
|
15
15
|
a = self.args.argset(2)
|
|
16
|
-
a.arg(types=[
|
|
16
|
+
a.arg(types=[Matchable], actuals=[Any])
|
|
17
17
|
a.arg(types=[Term], actuals=[int])
|
|
18
18
|
self.args.validate(self.siblings())
|
|
19
19
|
super().check_valid()
|
|
@@ -18,14 +18,8 @@ class Tally(ValueProducer):
|
|
|
18
18
|
super().check_valid()
|
|
19
19
|
|
|
20
20
|
def _produce_value(self, skip=None) -> None:
|
|
21
|
-
|
|
22
|
-
siblings = None
|
|
23
|
-
if isinstance(child, Equality):
|
|
24
|
-
siblings = child.commas_to_list()
|
|
25
|
-
else:
|
|
26
|
-
siblings = [child]
|
|
21
|
+
siblings = self.siblings()
|
|
27
22
|
tally = ""
|
|
28
|
-
|
|
29
23
|
for _ in siblings:
|
|
30
24
|
tally += f"{_.to_value(skip=skip)}|"
|
|
31
25
|
value = f"{_.to_value(skip=skip)}"
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
# pylint: disable=C0114
|
|
2
2
|
import datetime
|
|
3
3
|
from ..function_focus import ValueProducer
|
|
4
|
-
from csvpath.matching.productions
|
|
5
|
-
from csvpath.matching.productions.variable import Variable
|
|
6
|
-
from csvpath.matching.productions.header import Header
|
|
4
|
+
from csvpath.matching.productions import Term, Variable, Header
|
|
7
5
|
from csvpath.matching.functions.function import Function
|
|
8
6
|
from csvpath.matching.util.exceptions import ChildrenException
|
|
9
7
|
from ..args import Args
|
|
@@ -19,7 +17,7 @@ class Now(ValueProducer):
|
|
|
19
17
|
self.args.validate(self.siblings())
|
|
20
18
|
else:
|
|
21
19
|
self.args.argset(1).arg(
|
|
22
|
-
types=[None, Term, Function, Header, Variable], actuals=[str]
|
|
20
|
+
types=[None, Term, Function, Header, Variable], actuals=[None, str]
|
|
23
21
|
)
|
|
24
22
|
self.args.validate(self.siblings())
|
|
25
23
|
super().check_valid()
|
|
@@ -138,7 +138,7 @@ class Function(Matchable):
|
|
|
138
138
|
if Matchable.FAILED_VALUE in sibs:
|
|
139
139
|
pln = self.matcher.csvpath.line_monitor.physical_line_number
|
|
140
140
|
raise ChildrenException(
|
|
141
|
-
f"Cannot continue with {self.my_chain}
|
|
141
|
+
f"Line {pln}: Cannot continue with {self.my_chain} due to an invalid child"
|
|
142
142
|
)
|
|
143
143
|
#
|
|
144
144
|
# ready to run the match!
|
|
@@ -162,12 +162,14 @@ class Function(Matchable):
|
|
|
162
162
|
):
|
|
163
163
|
self.matcher.csvpath.stop()
|
|
164
164
|
if (
|
|
165
|
-
self.args
|
|
165
|
+
self.args
|
|
166
|
+
and self.args.args_match is False
|
|
166
167
|
and self.matcher.csvpath.fail_on_validation_errors
|
|
167
168
|
):
|
|
168
169
|
self.matcher.csvpath.is_valid = False
|
|
169
170
|
if (
|
|
170
|
-
self.args
|
|
171
|
+
self.args
|
|
172
|
+
and self.args.args_match is False
|
|
171
173
|
and self.matcher.csvpath._match_validation_errors is not None
|
|
172
174
|
):
|
|
173
175
|
self.match = self.matcher.csvpath._match_validation_errors
|
|
@@ -37,6 +37,7 @@ from .math.add import Add
|
|
|
37
37
|
from .math.subtract import Subtract
|
|
38
38
|
from .math.multiply import Multiply
|
|
39
39
|
from .math.divide import Divide
|
|
40
|
+
from .math.intf import Int, Float # , Num
|
|
40
41
|
from .math.sum import Sum
|
|
41
42
|
from .math.subtotal import Subtotal
|
|
42
43
|
from .math.equals import Equals
|
|
@@ -57,8 +58,6 @@ from .stats.percent import Percent
|
|
|
57
58
|
from .stats.minf import Min, Max, Average
|
|
58
59
|
from .stats.percent_unique import PercentUnique
|
|
59
60
|
from .stats.stdev import Stdev
|
|
60
|
-
|
|
61
|
-
# from .stats.correlate import Correlate
|
|
62
61
|
from .print.printf import Print
|
|
63
62
|
from .print.table import HeaderTable, RowTable, VarTable, RunTable
|
|
64
63
|
from .print.print_line import PrintLine
|
|
@@ -83,10 +82,10 @@ from .validity.line import Line
|
|
|
83
82
|
from .validity.failed import Failed
|
|
84
83
|
from .validity.fail import Fail, FailAll
|
|
85
84
|
from .types.nonef import Nonef, Blank
|
|
85
|
+
from .types.decimal import Decimal
|
|
86
86
|
from .types.boolean import Boolean
|
|
87
|
-
from .types.intf import Int, Num, Float
|
|
88
|
-
from .types.string import String
|
|
89
87
|
from .types.datef import Date
|
|
88
|
+
from .types.string import String
|
|
90
89
|
|
|
91
90
|
|
|
92
91
|
class UnknownFunctionException(Exception):
|
|
@@ -218,6 +217,8 @@ class FunctionFactory:
|
|
|
218
217
|
f = Random(matcher, name, child)
|
|
219
218
|
elif name == "shuffle":
|
|
220
219
|
f = Shuffle(matcher, name, child)
|
|
220
|
+
elif name in ["decimal", "integer"]:
|
|
221
|
+
f = Decimal(matcher, name, child)
|
|
221
222
|
elif name == "end":
|
|
222
223
|
f = End(matcher, name, child)
|
|
223
224
|
elif name == "length":
|
|
@@ -260,7 +261,7 @@ class FunctionFactory:
|
|
|
260
261
|
f = Any(matcher, name, child)
|
|
261
262
|
elif name == "none":
|
|
262
263
|
f = Nonef(matcher, name, child)
|
|
263
|
-
elif name in ["blank", "
|
|
264
|
+
elif name in ["blank", "nonspecific"]:
|
|
264
265
|
f = Blank(matcher, name, child)
|
|
265
266
|
elif name == "line":
|
|
266
267
|
f = Line(matcher, name, child)
|
|
@@ -390,8 +391,8 @@ class FunctionFactory:
|
|
|
390
391
|
f = RunTable(matcher, name, child)
|
|
391
392
|
elif name == "empty_stack":
|
|
392
393
|
f = EmptyStack(matcher, name, child)
|
|
393
|
-
elif name == "num":
|
|
394
|
-
|
|
394
|
+
# elif name == "num":
|
|
395
|
+
# f = Num(matcher, name, child)
|
|
395
396
|
elif name == "counter":
|
|
396
397
|
f = Counter(matcher, name, child)
|
|
397
398
|
else:
|
|
@@ -12,7 +12,7 @@ class Collect(SideEffect):
|
|
|
12
12
|
def check_valid(self) -> None:
|
|
13
13
|
self.args = Args(matchable=self)
|
|
14
14
|
a = self.args.argset()
|
|
15
|
-
a.arg(types=[Term], actuals=[
|
|
15
|
+
a.arg(types=[Term], actuals=[int, str])
|
|
16
16
|
self.args.validate(self.siblings())
|
|
17
17
|
super().check_valid()
|
|
18
18
|
|
|
@@ -24,11 +24,7 @@ class End(ValueProducer):
|
|
|
24
24
|
else:
|
|
25
25
|
if len(self.children) > 0:
|
|
26
26
|
v = self.children[0].to_value()
|
|
27
|
-
|
|
28
|
-
i = i - int(v)
|
|
29
|
-
else:
|
|
30
|
-
# this is an Args-style / data exception
|
|
31
|
-
raise DataException("end()'s term must be a positive int")
|
|
27
|
+
i = i - abs(int(v))
|
|
32
28
|
if 0 <= i < len(self.matcher.line):
|
|
33
29
|
self.value = self.matcher.line[i]
|
|
34
30
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# pylint: disable=C0114
|
|
2
2
|
from ..function_focus import SideEffect
|
|
3
3
|
from csvpath.matching.functions.function import Function
|
|
4
|
+
from csvpath.util.line_counter import LineCounter
|
|
4
5
|
from ..args import Args
|
|
5
6
|
|
|
6
7
|
|
|
@@ -9,7 +10,7 @@ class ResetHeaders(SideEffect):
|
|
|
9
10
|
|
|
10
11
|
def check_valid(self) -> None:
|
|
11
12
|
self.args = Args(matchable=self)
|
|
12
|
-
self.args.argset(1).arg(types=[None, Function], actuals=[
|
|
13
|
+
self.args.argset(1).arg(types=[None, Function], actuals=[])
|
|
13
14
|
self.args.validate(self.siblings())
|
|
14
15
|
super().check_valid()
|
|
15
16
|
|
|
@@ -17,7 +18,8 @@ class ResetHeaders(SideEffect):
|
|
|
17
18
|
self._apply_default_value()
|
|
18
19
|
|
|
19
20
|
def _decide_match(self, skip=None) -> None:
|
|
20
|
-
|
|
21
|
+
hs = LineCounter.clean_headers(self.matcher.line[:])
|
|
22
|
+
self.matcher.csvpath.headers = hs
|
|
21
23
|
self.matcher.header_dict = None
|
|
22
24
|
for key in self.matcher.csvpath.variables.keys():
|
|
23
25
|
#
|
|
@@ -54,9 +54,10 @@ class Float(ValueProducer):
|
|
|
54
54
|
self.match = self.default_match() # pragma: no cover
|
|
55
55
|
|
|
56
56
|
|
|
57
|
+
"""
|
|
57
58
|
class Num(ValueProducer):
|
|
58
|
-
""
|
|
59
|
-
ints and bools stay ints""
|
|
59
|
+
""parses a string or stringified object to a float, if possible,
|
|
60
|
+
ints and bools stay ints""
|
|
60
61
|
|
|
61
62
|
def check_valid(self) -> None:
|
|
62
63
|
self.args = Args(matchable=self)
|
|
@@ -86,12 +87,12 @@ class Num(ValueProducer):
|
|
|
86
87
|
self.my_expression.handle_error(e)
|
|
87
88
|
|
|
88
89
|
def _decide_match(self, skip=None) -> None:
|
|
89
|
-
""
|
|
90
|
+
""
|
|
90
91
|
(value, max digits before decimal, min digits before decimal, max places, min places)
|
|
91
92
|
max of -1 means we don't care
|
|
92
93
|
min of -1 means 0, or use -1, we don't care
|
|
93
94
|
|
|
94
|
-
""
|
|
95
|
+
""
|
|
95
96
|
val = self._value_one()
|
|
96
97
|
if not ExpressionUtility.is_one_of(val, (int, float)):
|
|
97
98
|
self.match = False
|
|
@@ -137,3 +138,4 @@ class Num(ValueProducer):
|
|
|
137
138
|
self.match = 0 <= len(d) <= dplaces_max
|
|
138
139
|
elif self.match and dplaces_max == -1 and dplaces_min > -1:
|
|
139
140
|
self.match = len(d) >= dplaces_min
|
|
141
|
+
"""
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
""" this module implements the match part of a csvpath string """
|
|
2
|
+
|
|
3
|
+
from csvpath.matching.functions.types.boolean import Boolean
|
|
4
|
+
from csvpath.matching.functions.types.string import String
|
|
5
|
+
from csvpath.matching.functions.types.decimal import Decimal
|
|
6
|
+
from csvpath.matching.functions.types.nonef import Nonef, Blank
|
|
7
|
+
from csvpath.matching.functions.types.datef import Date
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# pylint: disable=C0114
|
|
2
|
+
from csvpath.matching.util.expression_utility import ExpressionUtility
|
|
3
|
+
from csvpath.matching.util.exceptions import ChildrenException
|
|
4
|
+
from csvpath.matching.productions import Term, Variable, Header
|
|
5
|
+
from ..function import Function
|
|
6
|
+
from ..function_focus import ValueProducer
|
|
7
|
+
from ..args import Args
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Boolean(ValueProducer):
|
|
11
|
+
def check_valid(self) -> None:
|
|
12
|
+
self.args = Args(matchable=self)
|
|
13
|
+
a = self.args.argset(1)
|
|
14
|
+
a.arg(types=[Term, Variable, Header, Function], actuals=[None, bool, str])
|
|
15
|
+
self.args.validate(self.siblings())
|
|
16
|
+
super().check_valid()
|
|
17
|
+
|
|
18
|
+
def _produce_value(self, skip=None) -> None:
|
|
19
|
+
c = self._child_one()
|
|
20
|
+
v = None
|
|
21
|
+
if isinstance(c, Term):
|
|
22
|
+
v = self.matcher.get_header_value(c.value)
|
|
23
|
+
else:
|
|
24
|
+
v = c.to_value(skip=skip)
|
|
25
|
+
if v is None or f"{v}".strip() == "":
|
|
26
|
+
self.value = None
|
|
27
|
+
if self.notnone is True:
|
|
28
|
+
pln = self.matcher.csvpath.line_monitor.physical_line_number
|
|
29
|
+
self.parent.raise_if(
|
|
30
|
+
ChildrenException(f"Line {pln}: Value cannot be empty")
|
|
31
|
+
)
|
|
32
|
+
else:
|
|
33
|
+
v = ExpressionUtility.to_bool(v)
|
|
34
|
+
if v in [True, False]:
|
|
35
|
+
self.value = v
|
|
36
|
+
else:
|
|
37
|
+
self.value = None
|
|
38
|
+
pln = self.matcher.csvpath.line_monitor.physical_line_number
|
|
39
|
+
self.parent.raise_if(
|
|
40
|
+
ChildrenException(f"Line {pln}: Not a boolean value: '{v}'")
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def _decide_match(self, skip=None) -> None:
|
|
44
|
+
# we need to make sure a value is produced so that we see
|
|
45
|
+
# any errors. when we stand alone we're just checking our
|
|
46
|
+
# boolean-iness. when we're producing a value we're checking
|
|
47
|
+
# boolean-iness and casting and raising errors.
|
|
48
|
+
v = self.to_value(skip=skip)
|
|
49
|
+
self.match = v in [True, False] # pragma: no cover
|