csvpath 0.0.481__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.481 → csvpath-0.0.483}/PKG-INFO +2 -3
- {csvpath-0.0.481 → csvpath-0.0.483}/README.md +1 -2
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/csvpath.py +11 -7
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/managers/results_manager.py +5 -8
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/args.py +16 -9
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/boolean/all.py +3 -1
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/boolean/andf.py +3 -7
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/boolean/any.py +3 -3
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/boolean/empty.py +2 -26
- {csvpath-0.0.481 → 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.481 → csvpath-0.0.483}/csvpath/matching/functions/counting/count.py +2 -5
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/counting/counter.py +5 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/counting/every.py +2 -2
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/counting/increment.py +3 -3
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/counting/tally.py +1 -7
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/dates/now.py +2 -4
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/function.py +5 -3
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/function_factory.py +11 -10
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/headers/collect.py +1 -1
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/headers/end.py +1 -5
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/headers/reset_headers.py +4 -2
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/lines/advance.py +3 -2
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/math/intf.py +62 -5
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/strings/length.py +4 -1
- 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.481/csvpath/matching/functions/misc → csvpath-0.0.483/csvpath/matching/functions/types}/nonef.py +5 -3
- {csvpath-0.0.481/csvpath/matching/functions/strings → 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.481 → csvpath-0.0.483}/csvpath/matching/functions/variables/pushpop.py +2 -2
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/matcher.py +15 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/productions/matchable.py +43 -2
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/util/expression_utility.py +20 -4
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/util/error.py +5 -30
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/util/line_counter.py +3 -2
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/comments.md +2 -2
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/header_names_mismatch.md +2 -0
- csvpath-0.0.483/docs/functions/intf.md +51 -0
- csvpath-0.0.483/docs/functions/line.md +74 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/now.md +5 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/subtract.md +1 -10
- csvpath-0.0.483/docs/functions/types.md +48 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions.md +18 -6
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/variables.md +70 -2
- {csvpath-0.0.481 → csvpath-0.0.483}/pyproject.toml +1 -1
- csvpath-0.0.481/csvpath/matching/functions/boolean/boolean.py +0 -31
- csvpath-0.0.481/csvpath/matching/functions/boolean/orf.py +0 -34
- csvpath-0.0.481/csvpath/matching/functions/dates/datef.py +0 -40
- csvpath-0.0.481/csvpath/matching/functions/validity/line.py +0 -88
- {csvpath-0.0.481 → csvpath-0.0.483}/LICENSE +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/config/config.ini +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/__init__.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/csvpaths.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/managers/__init__.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/managers/csvpaths_manager.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/managers/file_manager.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/managers/result.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/__init__.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/__init__.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/boolean/between.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/boolean/exists.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/boolean/no.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/boolean/notf.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/boolean/yes.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/counting/count_headers.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/counting/count_lines.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/counting/count_scans.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/counting/has_matches.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/counting/total_lines.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/function_finder.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/function_focus.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/headers/append.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/headers/empty_stack.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/headers/header_name.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/headers/header_names_mismatch.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/headers/headers.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/headers/mismatch.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/headers/replace.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/lines/after_blank.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/lines/dups.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/lines/first.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/lines/first_line.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/lines/last.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/lines/stop.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/math/above.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/math/add.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/math/divide.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/math/equals.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/math/mod.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/math/multiply.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/math/round.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/math/subtotal.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/math/subtract.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/math/sum.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/misc/importf.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/misc/random.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/print/jinjaf.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/print/print_line.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/print/print_queue.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/print/printf.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/print/table.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/stats/minf.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/stats/percent.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/stats/percent_unique.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/stats/stdev.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/strings/concat.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/strings/lower.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/strings/metaphone.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/strings/regex.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/strings/starts_with.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/strings/strip.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/strings/substring.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/strings/upper.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/testing/debug.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/validity/fail.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/validity/failed.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/variables/get.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/variables/put.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/variables/track.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/functions/variables/variables.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/lark_parser.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/lark_transformer.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/productions/__init__.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/productions/equality.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/productions/expression.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/productions/header.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/productions/qualified.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/productions/reference.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/productions/term.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/productions/variable.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/util/exceptions.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/util/expression_encoder.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/util/lark_print_parser.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/matching/util/print_parser.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/scanning/__init__.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/scanning/exceptions.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/scanning/parser.out +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/scanning/parsetab.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/scanning/scanner.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/scanning/scanning_lexer.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/util/cache.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/util/config.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/util/config_exception.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/util/exceptions.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/util/last_line_stats.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/util/line_monitor.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/util/log_utility.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/util/metadata_parser.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/csvpath/util/printer.py +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/asbool.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/assignment.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/config.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/examples.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/files.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/above.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/advance.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/after_blank.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/all.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/andor.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/any.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/average.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/between.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/collect.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/correlate.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/count.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/count_headers.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/counter.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/date.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/empty.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/empty_stack.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/end.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/every.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/fail.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/first.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/get.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/has_dups.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/has_matches.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/header.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/header_name.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/implementing_functions.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/import.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/in.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/increment.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/jinja.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/last.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/line_number.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/max.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/metaphone.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/mismatch.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/no.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/not.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/percent_unique.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/pop.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/print.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/print_line.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/print_queue.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/random.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/regex.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/replace.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/reset_headers.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/stdev.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/stop.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/string_functions.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/subtotal.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/sum.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/tally.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/total_lines.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/track.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/variables.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/functions/variables_and_headers.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/grammar.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/headers.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/images/logo-wordmark-white-on-black-trimmed-padded.png +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/images/logo-wordmark-white-trimmed.png +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/paths.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/printing.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/qualifiers.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/references.md +0 -0
- {csvpath-0.0.481 → csvpath-0.0.483}/docs/terms.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
|
|
|
@@ -81,8 +80,8 @@ Read more about CsvPath and see realistic CSV validation examples at <a href='ht
|
|
|
81
80
|
- [More Examples](#examples)
|
|
82
81
|
- [Grammar](#grammar)
|
|
83
82
|
|
|
84
|
-
# Motivation
|
|
85
83
|
<a name="motivation"></a>
|
|
84
|
+
# Motivation
|
|
86
85
|
|
|
87
86
|
CSV files are everywhere!
|
|
88
87
|
|
|
@@ -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
|
|
|
@@ -47,8 +46,8 @@ Read more about CsvPath and see realistic CSV validation examples at <a href='ht
|
|
|
47
46
|
- [More Examples](#examples)
|
|
48
47
|
- [Grammar](#grammar)
|
|
49
48
|
|
|
50
|
-
# Motivation
|
|
51
49
|
<a name="motivation"></a>
|
|
50
|
+
# Motivation
|
|
52
51
|
|
|
53
52
|
CSV files are everywhere!
|
|
54
53
|
|
|
@@ -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:
|
|
@@ -89,7 +89,6 @@ class ResultsManager(CsvPathsResultsManager): # pylint: disable=C0115
|
|
|
89
89
|
def __init__(self, *, csvpaths=None):
|
|
90
90
|
self.named_results = {}
|
|
91
91
|
self._csvpaths = None
|
|
92
|
-
self._variables = None
|
|
93
92
|
|
|
94
93
|
# use property
|
|
95
94
|
self.csvpaths = csvpaths
|
|
@@ -137,13 +136,11 @@ class ResultsManager(CsvPathsResultsManager): # pylint: disable=C0115
|
|
|
137
136
|
return True
|
|
138
137
|
|
|
139
138
|
def get_variables(self, name: str) -> bool:
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
self._variables = vs
|
|
146
|
-
return self._variables
|
|
139
|
+
results = self.get_named_results(name)
|
|
140
|
+
vs = {}
|
|
141
|
+
for r in results:
|
|
142
|
+
vs = {**r.csvpath.variables, **vs}
|
|
143
|
+
return vs
|
|
147
144
|
|
|
148
145
|
def has_lines(self, name: str) -> bool:
|
|
149
146
|
results = self.get_named_results(name)
|
|
@@ -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
|
|
@@ -16,6 +16,11 @@ class Counter(ValueProducer):
|
|
|
16
16
|
self.args = Args(matchable=self)
|
|
17
17
|
self.args.argset(1).arg(types=[None, Any], actuals=[int])
|
|
18
18
|
self.args.validate(self.siblings())
|
|
19
|
+
name = self.first_non_term_qualifier(self.get_id())
|
|
20
|
+
# initializing the counter to 0. if we don't do this and the counter is
|
|
21
|
+
# never hit (e.g. it is behind a ->) a print returns the counter's name
|
|
22
|
+
# which is confusing.
|
|
23
|
+
self.matcher.get_variable(name, set_if_none=0)
|
|
19
24
|
super().check_valid() # pylint: disable=W0246
|
|
20
25
|
|
|
21
26
|
def _produce_value(self, skip=None) -> None:
|
|
@@ -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
|
|
@@ -3,11 +3,9 @@ from csvpath.matching.productions.expression import Matchable
|
|
|
3
3
|
from .function import Function
|
|
4
4
|
from .function_finder import FunctionFinder
|
|
5
5
|
from .dates.now import Now
|
|
6
|
-
from .dates.datef import Date
|
|
7
6
|
from .strings.lower import Lower
|
|
8
7
|
from .strings.upper import Upper
|
|
9
8
|
from .strings.substring import Substring
|
|
10
|
-
from .strings.string import String
|
|
11
9
|
from .strings.starts_with import StartsWith
|
|
12
10
|
from .strings.strip import Strip
|
|
13
11
|
from .strings.length import Length, MinMaxLength
|
|
@@ -35,11 +33,11 @@ from .headers.empty_stack import EmptyStack
|
|
|
35
33
|
from .headers.mismatch import Mismatch
|
|
36
34
|
from .headers.end import End
|
|
37
35
|
from .math.above import AboveBelow
|
|
38
|
-
from .math.intf import Int, Num, Float
|
|
39
36
|
from .math.add import Add
|
|
40
37
|
from .math.subtract import Subtract
|
|
41
38
|
from .math.multiply import Multiply
|
|
42
39
|
from .math.divide import Divide
|
|
40
|
+
from .math.intf import Int, Float # , Num
|
|
43
41
|
from .math.sum import Sum
|
|
44
42
|
from .math.subtotal import Subtotal
|
|
45
43
|
from .math.equals import Equals
|
|
@@ -47,7 +45,6 @@ from .math.round import Round
|
|
|
47
45
|
from .math.mod import Mod
|
|
48
46
|
from .boolean.notf import Not
|
|
49
47
|
from .boolean.inf import In
|
|
50
|
-
from .boolean.boolean import Boolean
|
|
51
48
|
from .boolean.orf import Or
|
|
52
49
|
from .boolean.empty import Empty
|
|
53
50
|
from .boolean.no import No
|
|
@@ -61,8 +58,6 @@ from .stats.percent import Percent
|
|
|
61
58
|
from .stats.minf import Min, Max, Average
|
|
62
59
|
from .stats.percent_unique import PercentUnique
|
|
63
60
|
from .stats.stdev import Stdev
|
|
64
|
-
|
|
65
|
-
# from .stats.correlate import Correlate
|
|
66
61
|
from .print.printf import Print
|
|
67
62
|
from .print.table import HeaderTable, RowTable, VarTable, RunTable
|
|
68
63
|
from .print.print_line import PrintLine
|
|
@@ -81,12 +76,16 @@ from .variables.get import Get
|
|
|
81
76
|
from .variables.put import Put
|
|
82
77
|
from .variables.track import Track
|
|
83
78
|
from .misc.random import Random, Shuffle
|
|
84
|
-
from .misc.nonef import Nonef, Blank
|
|
85
79
|
from .misc.importf import Import
|
|
86
80
|
from .testing.debug import Debug, BriefStackTrace, VoteStack, DoWhenStack, Log
|
|
87
81
|
from .validity.line import Line
|
|
88
82
|
from .validity.failed import Failed
|
|
89
83
|
from .validity.fail import Fail, FailAll
|
|
84
|
+
from .types.nonef import Nonef, Blank
|
|
85
|
+
from .types.decimal import Decimal
|
|
86
|
+
from .types.boolean import Boolean
|
|
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
|
#
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# pylint: disable=C0114
|
|
2
2
|
from csvpath.matching.util.exceptions import ChildrenException
|
|
3
3
|
from ..function_focus import SideEffect
|
|
4
|
-
from csvpath.matching.productions
|
|
4
|
+
from csvpath.matching.productions import Term, Variable
|
|
5
|
+
from csvpath.matching.functions.function import Function
|
|
5
6
|
from ..args import Args
|
|
6
7
|
|
|
7
8
|
|
|
@@ -11,7 +12,7 @@ class Advance(SideEffect):
|
|
|
11
12
|
def check_valid(self) -> None:
|
|
12
13
|
self.args = Args(matchable=self)
|
|
13
14
|
a = self.args.argset(1)
|
|
14
|
-
a.arg(types=[Term], actuals=[int])
|
|
15
|
+
a.arg(types=[Term, Variable, Function], actuals=[int])
|
|
15
16
|
self.args.validate(self.siblings())
|
|
16
17
|
super().check_valid()
|
|
17
18
|
|