csvpath 0.0.485__tar.gz → 0.0.486__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.485 → csvpath-0.0.486}/PKG-INFO +2 -1
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/args.py +3 -10
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/function.py +9 -1
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/lines/dups.py +9 -5
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/types/boolean.py +9 -12
- csvpath-0.0.486/csvpath/matching/functions/types/datef.py +130 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/types/decimal.py +39 -34
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/types/nonef.py +24 -1
- csvpath-0.0.486/csvpath/matching/functions/types/string.py +65 -0
- csvpath-0.0.486/csvpath/matching/functions/types/type.py +14 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/validity/line.py +50 -23
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/matcher.py +24 -20
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/matchable.py +5 -2
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/qualified.py +11 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/util/expression_utility.py +37 -2
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/scanning/scanning_lexer.py +1 -1
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/file_readers.py +16 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/pyproject.toml +2 -1
- csvpath-0.0.485/csvpath/matching/functions/types/datef.py +0 -130
- csvpath-0.0.485/csvpath/matching/functions/types/string.py +0 -45
- {csvpath-0.0.485 → csvpath-0.0.486}/LICENSE +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/README.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/config/config.ini +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/__init__.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/csvpath.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/csvpaths.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/managers/__init__.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/managers/csvpaths_manager.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/managers/file_manager.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/managers/result.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/managers/results_manager.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/__init__.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/__init__.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/all.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/andf.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/any.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/between.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/empty.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/exists.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/inf.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/no.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/notf.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/orf.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/yes.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/count.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/count_headers.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/count_lines.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/count_scans.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/counter.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/every.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/has_matches.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/increment.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/tally.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/total_lines.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/dates/now.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/function_factory.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/function_finder.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/function_focus.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/append.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/collect.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/empty_stack.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/end.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/header_name.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/header_names_mismatch.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/headers.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/mismatch.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/replace.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/reset_headers.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/lines/advance.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/lines/after_blank.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/lines/first.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/lines/first_line.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/lines/last.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/lines/stop.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/above.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/add.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/divide.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/equals.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/intf.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/mod.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/multiply.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/round.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/subtotal.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/subtract.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/sum.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/misc/importf.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/misc/random.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/print/jinjaf.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/print/print_line.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/print/print_queue.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/print/printf.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/print/table.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/stats/minf.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/stats/percent.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/stats/percent_unique.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/stats/stdev.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/concat.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/length.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/lower.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/metaphone.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/regex.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/starts_with.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/strip.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/substring.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/upper.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/testing/debug.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/types/__init__.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/validity/fail.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/validity/failed.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/variables/get.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/variables/pushpop.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/variables/put.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/variables/track.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/variables/variables.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/lark_parser.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/lark_transformer.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/__init__.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/equality.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/expression.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/header.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/reference.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/term.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/variable.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/util/exceptions.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/util/expression_encoder.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/util/lark_print_parser.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/util/print_parser.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/scanning/__init__.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/scanning/exceptions.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/scanning/parser.out +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/scanning/parsetab.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/scanning/scanner.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/cache.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/config.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/config_exception.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/error.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/exceptions.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/last_line_stats.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/line_counter.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/line_monitor.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/log_utility.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/metadata_parser.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/printer.py +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/asbool.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/assignment.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/comments.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/config.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/examples.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/files.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/above.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/advance.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/after_blank.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/all.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/andor.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/any.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/average.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/between.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/collect.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/correlate.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/count.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/count_headers.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/counter.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/date.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/empty.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/empty_stack.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/end.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/every.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/fail.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/first.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/get.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/has_dups.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/has_matches.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/header.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/header_name.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/header_names_mismatch.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/implementing_functions.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/import.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/in.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/increment.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/intf.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/jinja.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/last.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/line.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/line_number.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/max.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/metaphone.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/mismatch.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/no.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/not.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/now.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/percent_unique.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/pop.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/print.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/print_line.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/print_queue.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/random.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/regex.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/replace.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/reset_headers.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/stdev.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/stop.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/string_functions.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/subtotal.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/subtract.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/sum.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/tally.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/total_lines.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/track.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/types.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/variables.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/variables_and_headers.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/grammar.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/headers.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/images/logo-wordmark-white-on-black-trimmed-padded.png +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/images/logo-wordmark-white-trimmed.png +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/paths.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/printing.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/qualifiers.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/references.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/docs/terms.md +0 -0
- {csvpath-0.0.485 → csvpath-0.0.486}/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.486
|
|
4
4
|
Summary: A declarative language for validation of CSV files
|
|
5
5
|
Author: David Kershaw
|
|
6
6
|
Author-email: dk107dk@hotmail.com
|
|
@@ -28,6 +28,7 @@ Requires-Dist: metaphone (>=0.6,<0.7)
|
|
|
28
28
|
Requires-Dist: ply (>=3.11,<4.0)
|
|
29
29
|
Requires-Dist: pylightxl (>=1.61,<2.0)
|
|
30
30
|
Requires-Dist: python-dateutil (>=2.9.0.post0,<3.0.0)
|
|
31
|
+
Requires-Dist: smart-open[s3] (>=7.0.5,<8.0.0)
|
|
31
32
|
Requires-Dist: tabulate (>=0.9.0,<0.10.0)
|
|
32
33
|
Project-URL: Csvpath.org, https://www.csvpath.org
|
|
33
34
|
Project-URL: Github, https://github.com/csvpath/csvpath.git
|
|
@@ -456,16 +456,9 @@ class Args:
|
|
|
456
456
|
def handle_errors_if(self, mismatch_count, mismatches):
|
|
457
457
|
if mismatch_count == len(self._argsets):
|
|
458
458
|
self._args_match = False
|
|
459
|
-
pm = f"mismatch in {self.matchable.my_chain}
|
|
460
|
-
# when would we not have a csvpath?
|
|
461
|
-
# pln = (
|
|
462
|
-
# self._csvpath.line_monitor.physical_line_number if self._csvpath else 0
|
|
463
|
-
# )
|
|
464
|
-
# csvpathid = f"{self._csvpath_id()} " if self._csvpath_id() else ""
|
|
465
|
-
# ei = ExpressionUtility.get_my_expressions_index(self._matchable)
|
|
466
|
-
# pm = f"{csvpathid}Wrong value in match component {ei} at line {pln}: {pm}"
|
|
467
|
-
# raise ChildrenValidationException(pm)
|
|
468
|
-
#
|
|
459
|
+
pm = f"mismatch in {self.matchable.my_chain}"
|
|
469
460
|
ei = ExpressionUtility.get_my_expressions_index(self._matchable)
|
|
470
461
|
pm = f"Wrong value in match component {ei}: {pm}"
|
|
462
|
+
lpm = f"{pm}: {mismatches}"
|
|
463
|
+
self._matchable.matcher.csvpath.logger.error(lpm)
|
|
471
464
|
self._matchable.raiseChildrenException(pm)
|
|
@@ -7,6 +7,12 @@ from ..productions.matchable import Matchable
|
|
|
7
7
|
from ..util.exceptions import ChildrenException
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
class CheckedUnset:
|
|
11
|
+
"""pass on self.checked if setting self.value=None would not be clear/effective"""
|
|
12
|
+
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
10
16
|
class Function(Matchable):
|
|
11
17
|
"""base class for all functions"""
|
|
12
18
|
|
|
@@ -15,6 +21,7 @@ class Function(Matchable):
|
|
|
15
21
|
self.matcher = matcher
|
|
16
22
|
self._function_or_equality = child
|
|
17
23
|
self.args = None
|
|
24
|
+
self.checked = None
|
|
18
25
|
if child:
|
|
19
26
|
self.add_child(child)
|
|
20
27
|
|
|
@@ -28,6 +35,7 @@ class Function(Matchable):
|
|
|
28
35
|
self.match = None
|
|
29
36
|
if self.args:
|
|
30
37
|
self.args.reset()
|
|
38
|
+
self.checked = None
|
|
31
39
|
super().reset()
|
|
32
40
|
|
|
33
41
|
def to_value(self, *, skip=None) -> bool:
|
|
@@ -55,7 +63,7 @@ class Function(Matchable):
|
|
|
55
63
|
# csvpath writer doesn't know anything about this.
|
|
56
64
|
self.matcher.csvpath.logger.debug("We're frozen in %s", self)
|
|
57
65
|
return self._noop_value()
|
|
58
|
-
if self.value is None:
|
|
66
|
+
if self.value is None and not isinstance(self.checked, CheckedUnset):
|
|
59
67
|
# count() doesn't yet use args. it is grandfathered, for now.
|
|
60
68
|
if self.args and not self.args.matched:
|
|
61
69
|
self.matcher.csvpath.logger.debug(
|
|
@@ -78,9 +78,11 @@ class DupLines(ValueProducer):
|
|
|
78
78
|
|
|
79
79
|
class FingerPrinter:
|
|
80
80
|
@classmethod
|
|
81
|
-
def _capture_line(
|
|
81
|
+
def _capture_line(
|
|
82
|
+
cls, mc, name: str, skip=None, sibs=None
|
|
83
|
+
) -> tuple[str, list[int]]:
|
|
82
84
|
values = mc.matcher.get_variable(name, set_if_none={})
|
|
83
|
-
fingerprint = FingerPrinter._fingerprint(mc, skip=skip)
|
|
85
|
+
fingerprint = FingerPrinter._fingerprint(mc, skip=skip, sibs=sibs)
|
|
84
86
|
if fingerprint not in values:
|
|
85
87
|
values[fingerprint] = []
|
|
86
88
|
pln = mc.matcher.csvpath.line_monitor.physical_line_number
|
|
@@ -90,8 +92,10 @@ class FingerPrinter:
|
|
|
90
92
|
return (fingerprint, values[fingerprint])
|
|
91
93
|
|
|
92
94
|
@classmethod
|
|
93
|
-
def _fingerprint(cls, mc, skip=None) -> str:
|
|
94
|
-
if len(
|
|
95
|
+
def _fingerprint(cls, mc, skip=None, sibs=None) -> str:
|
|
96
|
+
if sibs and len(sibs) > 0:
|
|
97
|
+
fingerprint = FingerPrinter._fingerprint_for_children(sibs, skip=skip)
|
|
98
|
+
elif len(mc.children) == 1:
|
|
95
99
|
if isinstance(mc.children[0], Equality):
|
|
96
100
|
siblings = mc.children[0].commas_to_list()
|
|
97
101
|
fingerprint = FingerPrinter._fingerprint_for_children(
|
|
@@ -109,7 +113,7 @@ class FingerPrinter:
|
|
|
109
113
|
def _fingerprint_for_children(cls, sibs, skip=None) -> str:
|
|
110
114
|
string = ""
|
|
111
115
|
for _ in sibs:
|
|
112
|
-
string += f"{_.to_value(skip=skip)}"
|
|
116
|
+
string += f"{_ if not hasattr(_, 'to_value') else _.to_value(skip=skip)}"
|
|
113
117
|
return hashlib.sha256(string.encode("utf-8")).hexdigest()
|
|
114
118
|
|
|
115
119
|
@classmethod
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
from csvpath.matching.util.expression_utility import ExpressionUtility
|
|
3
3
|
from csvpath.matching.util.exceptions import ChildrenException
|
|
4
4
|
from csvpath.matching.productions import Term, Variable, Header
|
|
5
|
-
from ..function import Function
|
|
5
|
+
from ..function import Function, CheckedUnset
|
|
6
6
|
from ..function_focus import ValueProducer
|
|
7
7
|
from ..args import Args
|
|
8
8
|
|
|
@@ -19,26 +19,23 @@ class Boolean(ValueProducer):
|
|
|
19
19
|
c = self._child_one()
|
|
20
20
|
v = None
|
|
21
21
|
if isinstance(c, Term):
|
|
22
|
-
v = self.matcher.get_header_value(c.value)
|
|
22
|
+
v = self.matcher.get_header_value(self, c.value)
|
|
23
23
|
else:
|
|
24
24
|
v = c.to_value(skip=skip)
|
|
25
25
|
if v is None or f"{v}".strip() == "":
|
|
26
|
-
self.value =
|
|
26
|
+
self.value = CheckedUnset()
|
|
27
|
+
# self.value = None
|
|
27
28
|
if self.notnone is True:
|
|
28
|
-
|
|
29
|
-
self.parent.raise_if(
|
|
30
|
-
ChildrenException(f"Line {pln}: Value cannot be empty")
|
|
31
|
-
)
|
|
29
|
+
msg = self.decorate_error_message("Value cannot be empty")
|
|
30
|
+
self.parent.raise_if(ChildrenException(msg))
|
|
32
31
|
else:
|
|
33
32
|
v = ExpressionUtility.to_bool(v)
|
|
34
33
|
if v in [True, False]:
|
|
35
34
|
self.value = v
|
|
36
35
|
else:
|
|
37
|
-
self.value =
|
|
38
|
-
|
|
39
|
-
self.parent.raise_if(
|
|
40
|
-
ChildrenException(f"Line {pln}: Not a boolean value: '{v}'")
|
|
41
|
-
)
|
|
36
|
+
self.value = CheckedUnset()
|
|
37
|
+
msg = self.decorate_error_message(f"Not a boolean value: '{v}'")
|
|
38
|
+
self.parent.raise_if(ChildrenException(msg))
|
|
42
39
|
|
|
43
40
|
def _decide_match(self, skip=None) -> None:
|
|
44
41
|
# we need to make sure a value is produced so that we see
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# pylint: disable=C0114
|
|
2
|
+
import datetime
|
|
3
|
+
from csvpath.matching.productions import Header, Variable, Reference, Term
|
|
4
|
+
from csvpath.matching.util.expression_utility import ExpressionUtility
|
|
5
|
+
from csvpath.matching.util.exceptions import ChildrenException
|
|
6
|
+
from ..function_focus import ValueProducer
|
|
7
|
+
from ..args import Args
|
|
8
|
+
from ..function import Function
|
|
9
|
+
from .type import Type
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Date(ValueProducer, Type):
|
|
13
|
+
"""parses a date from a string"""
|
|
14
|
+
|
|
15
|
+
def check_valid(self) -> None:
|
|
16
|
+
self.args = Args(matchable=self)
|
|
17
|
+
#
|
|
18
|
+
# we check if a term is a date first. if it isn't, we go to the headers.
|
|
19
|
+
#
|
|
20
|
+
a = self.args.argset(2)
|
|
21
|
+
a.arg(
|
|
22
|
+
name="date string or object",
|
|
23
|
+
types=[Term, Header, Variable, Function, Reference],
|
|
24
|
+
actuals=[datetime.datetime, datetime.date],
|
|
25
|
+
)
|
|
26
|
+
a.arg(
|
|
27
|
+
name="format",
|
|
28
|
+
types=[None, Term, Header],
|
|
29
|
+
actuals=[str],
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
a = self.args.argset(2)
|
|
33
|
+
a.arg(
|
|
34
|
+
name="header name",
|
|
35
|
+
types=[Term],
|
|
36
|
+
actuals=[str],
|
|
37
|
+
)
|
|
38
|
+
a.arg(
|
|
39
|
+
name="format",
|
|
40
|
+
types=[None, Term],
|
|
41
|
+
actuals=[str],
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
self.args.validate(self.siblings())
|
|
45
|
+
super().check_valid()
|
|
46
|
+
|
|
47
|
+
def _produce_value(self, skip=None) -> None:
|
|
48
|
+
isheader = self._is_header(skip=skip)
|
|
49
|
+
sibs = self.siblings()
|
|
50
|
+
inaline = ExpressionUtility.get_ancestor(self, "Line") is not None
|
|
51
|
+
if inaline:
|
|
52
|
+
v = self._from_header_if(skip=skip)
|
|
53
|
+
else:
|
|
54
|
+
v = self._from_header_if(skip=skip, quiet=True)
|
|
55
|
+
if not v and not isheader and len(sibs) == 1:
|
|
56
|
+
v = self._from_one()
|
|
57
|
+
if not v and not isheader and len(sibs) == 2:
|
|
58
|
+
v = self._from_two()
|
|
59
|
+
if isinstance(v, (datetime.datetime, datetime.date)):
|
|
60
|
+
if isinstance(v, datetime.datetime) and not self.name == "datetime":
|
|
61
|
+
v = v.date()
|
|
62
|
+
self.value = v
|
|
63
|
+
elif ExpressionUtility.is_none(v):
|
|
64
|
+
if self.notnone:
|
|
65
|
+
self.value = None
|
|
66
|
+
msg = self.decorate_error_message("Date cannot be empty")
|
|
67
|
+
self.parent.raise_if(ChildrenException(msg))
|
|
68
|
+
else:
|
|
69
|
+
msg = self.decorate_error_message(f"'{v}' is not a date or datetime")
|
|
70
|
+
self.parent.raise_if(ChildrenException(msg))
|
|
71
|
+
|
|
72
|
+
def _is_header(self, skip=None):
|
|
73
|
+
h = self._value_one(skip=skip)
|
|
74
|
+
h = f"{h}".strip()
|
|
75
|
+
for _ in self.matcher.csvpath.headers:
|
|
76
|
+
if _.strip() == h:
|
|
77
|
+
return True
|
|
78
|
+
return False
|
|
79
|
+
|
|
80
|
+
def _from_one(self):
|
|
81
|
+
v = self._value_one()
|
|
82
|
+
if v and isinstance(v, (datetime.datetime, datetime.date)):
|
|
83
|
+
return v
|
|
84
|
+
elif v and isinstance(v, str):
|
|
85
|
+
return ExpressionUtility.to_date(v)
|
|
86
|
+
|
|
87
|
+
def _from_two(self):
|
|
88
|
+
v = self._value_one()
|
|
89
|
+
v = f"{v}".strip()
|
|
90
|
+
fmt = self._value_two()
|
|
91
|
+
r = self._date_from_strings(v, fmt)
|
|
92
|
+
return r
|
|
93
|
+
|
|
94
|
+
def _date_from_strings(self, adate, aformat):
|
|
95
|
+
try:
|
|
96
|
+
aformat = f"{aformat}".strip()
|
|
97
|
+
return datetime.datetime.strptime(adate, aformat)
|
|
98
|
+
except Exception as e:
|
|
99
|
+
if adate == "" and not self.notnone:
|
|
100
|
+
return None
|
|
101
|
+
msg = self.decorate_error_message(
|
|
102
|
+
f"Cannot parse date '{adate}' using '{aformat}'"
|
|
103
|
+
)
|
|
104
|
+
self.parent.raise_if(ChildrenException(msg), cause=e)
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
def _from_header_if(self, skip=None, quiet=False):
|
|
108
|
+
v = self.resolve_value(skip=skip, quiet=quiet)
|
|
109
|
+
if not v:
|
|
110
|
+
return None
|
|
111
|
+
fmt = self._value_two(skip=skip)
|
|
112
|
+
ret = None
|
|
113
|
+
if fmt:
|
|
114
|
+
ret = self._date_from_strings(v, fmt)
|
|
115
|
+
else:
|
|
116
|
+
ret = ExpressionUtility.to_datetime(v)
|
|
117
|
+
return ret
|
|
118
|
+
|
|
119
|
+
def _decide_match(self, skip=None) -> None:
|
|
120
|
+
#
|
|
121
|
+
# if we're deciding a match and we have a term we'll be reffing a header
|
|
122
|
+
#
|
|
123
|
+
"""
|
|
124
|
+
t = self._child_one()
|
|
125
|
+
if isinstance(t, Term):
|
|
126
|
+
v = self._from_header(skip=skip)
|
|
127
|
+
self.match = ExpressionUtility.is_date_type(v)
|
|
128
|
+
else:
|
|
129
|
+
"""
|
|
130
|
+
self.match = self.to_value(skip=skip) is not None
|
|
@@ -6,9 +6,10 @@ from ..function import Function
|
|
|
6
6
|
from .nonef import Nonef
|
|
7
7
|
from ..function_focus import ValueProducer
|
|
8
8
|
from ..args import Args
|
|
9
|
+
from .type import Type
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
class Decimal(ValueProducer):
|
|
12
|
+
class Decimal(ValueProducer, Type):
|
|
12
13
|
def check_valid(self) -> None:
|
|
13
14
|
self.args = Args(matchable=self)
|
|
14
15
|
a = self.args.argset(5)
|
|
@@ -19,52 +20,56 @@ class Decimal(ValueProducer):
|
|
|
19
20
|
for s in self.siblings():
|
|
20
21
|
if isinstance(s, Function) and not isinstance(s, Nonef):
|
|
21
22
|
self.match = False
|
|
22
|
-
self.
|
|
23
|
-
|
|
23
|
+
msg = self.decorate_error_message(
|
|
24
|
+
f"Incorrect argument: {s} is not allowed"
|
|
24
25
|
)
|
|
26
|
+
self.parent.raise_if(ChildrenException(msg))
|
|
25
27
|
super().check_valid()
|
|
26
28
|
|
|
27
29
|
def _produce_value(self, skip=None) -> None:
|
|
28
30
|
self.value = self.matches(skip=skip)
|
|
29
31
|
|
|
30
32
|
def _decide_match(self, skip=None) -> None:
|
|
31
|
-
|
|
32
|
-
h
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
f"Argument '{val}' does not identify a valid header value on this line"
|
|
47
|
-
),
|
|
48
|
-
cause=e,
|
|
49
|
-
)
|
|
50
|
-
return
|
|
51
|
-
#
|
|
52
|
-
# we know this value can be a float because Args checked it.
|
|
53
|
-
# but would a user know from looking at it that it was a float?
|
|
54
|
-
#
|
|
33
|
+
h = self.resolve_value()
|
|
34
|
+
if h is None:
|
|
35
|
+
#
|
|
36
|
+
# Matcher via Type will take care of mismatches and Nones
|
|
37
|
+
#
|
|
38
|
+
if self.notnone is True:
|
|
39
|
+
self.match = False
|
|
40
|
+
msg = self.decorate_error_message(
|
|
41
|
+
f"'{self._value_one(skip=skip)}' cannot be empty"
|
|
42
|
+
)
|
|
43
|
+
self.parent.raise_if(ChildrenException(msg))
|
|
44
|
+
return
|
|
45
|
+
else:
|
|
46
|
+
self.match = True
|
|
47
|
+
return
|
|
55
48
|
if self.name == "decimal":
|
|
49
|
+
#
|
|
50
|
+
# we know this value is a number because Args checked it.
|
|
51
|
+
# but would a user know from looking at it that it was a float?
|
|
52
|
+
#
|
|
56
53
|
if self.has_qualifier("strict"):
|
|
57
|
-
if h.find(".") == -1:
|
|
54
|
+
if f"{h}".strip().find(".") == -1:
|
|
58
55
|
self.match = False
|
|
59
|
-
|
|
60
|
-
self.
|
|
61
|
-
|
|
62
|
-
f"Argument '{val}' has 'strict' but value does not have a '.'"
|
|
63
|
-
)
|
|
56
|
+
n = self._value_one()
|
|
57
|
+
msg = self.decorate_error_message(
|
|
58
|
+
f"'{n}' has 'strict' but value does not have a '.'"
|
|
64
59
|
)
|
|
60
|
+
self.parent.raise_if(ChildrenException(msg))
|
|
65
61
|
return
|
|
62
|
+
else:
|
|
63
|
+
self.match = True
|
|
64
|
+
elif self.has_qualifier("weak"):
|
|
65
|
+
self.match = True
|
|
66
|
+
elif f"{h}".strip().find(".") == -1:
|
|
67
|
+
self.match = False
|
|
68
|
+
return
|
|
69
|
+
else:
|
|
70
|
+
self.match = True
|
|
66
71
|
else:
|
|
67
|
-
if h.find(".") > -1:
|
|
72
|
+
if f"{h}".find(".") > -1:
|
|
68
73
|
self.match = False
|
|
69
74
|
return
|
|
70
75
|
#
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
from typing import Any
|
|
3
3
|
from ..function_focus import ValueProducer
|
|
4
4
|
from csvpath.matching.util.expression_utility import ExpressionUtility
|
|
5
|
+
from csvpath.matching.util.exceptions import ChildrenException
|
|
5
6
|
from csvpath.matching.productions import Variable, Header, Reference, Term
|
|
6
7
|
from csvpath.matching.functions.function import Function
|
|
7
8
|
from ..args import Args
|
|
@@ -14,7 +15,13 @@ class Nonef(ValueProducer):
|
|
|
14
15
|
self.args = Args(matchable=self)
|
|
15
16
|
self.args.argset(0)
|
|
16
17
|
a = self.args.argset(1)
|
|
17
|
-
a.arg(
|
|
18
|
+
a.arg(
|
|
19
|
+
name="null check",
|
|
20
|
+
types=[Variable, Header, Function, Reference],
|
|
21
|
+
actuals=[None],
|
|
22
|
+
)
|
|
23
|
+
a = self.args.argset(1)
|
|
24
|
+
a.arg(name="header reference", types=[Term], actuals=[str])
|
|
18
25
|
self.args.validate(self.siblings())
|
|
19
26
|
super().check_valid()
|
|
20
27
|
|
|
@@ -25,9 +32,19 @@ class Nonef(ValueProducer):
|
|
|
25
32
|
def _decide_match(self, *, skip=None) -> None: # pragma: no cover
|
|
26
33
|
if len(self.children) == 0:
|
|
27
34
|
self.match = True
|
|
35
|
+
if isinstance(self._child_one(), Term):
|
|
36
|
+
v = self._value_one(skip=skip)
|
|
37
|
+
h = self.matcher.get_header_value(self, v)
|
|
38
|
+
self.match = ExpressionUtility.is_none(h)
|
|
39
|
+
if self.match is False:
|
|
40
|
+
msg = self.decorate_error_message(f"'{v}' must be empty")
|
|
41
|
+
self.parent.raise_if(ChildrenException(msg))
|
|
28
42
|
else:
|
|
29
43
|
self.match = ExpressionUtility.is_none(self._value_one(skip=skip))
|
|
30
44
|
|
|
45
|
+
def resolve_value(self, skip=None) -> str | None:
|
|
46
|
+
return None
|
|
47
|
+
|
|
31
48
|
|
|
32
49
|
class Blank(ValueProducer):
|
|
33
50
|
"""returns True to match, returns its child's value or None. represents any value"""
|
|
@@ -48,6 +65,9 @@ class Blank(ValueProducer):
|
|
|
48
65
|
# contained Term, if any, matches.
|
|
49
66
|
self.match = self.default_match()
|
|
50
67
|
|
|
68
|
+
def resolve_value(self, skip=None) -> str | None:
|
|
69
|
+
return None
|
|
70
|
+
|
|
51
71
|
|
|
52
72
|
class Wildcard(ValueProducer):
|
|
53
73
|
"""returns True to match, return value: the arg: 1-9+ or '*', or None.
|
|
@@ -70,3 +90,6 @@ class Wildcard(ValueProducer):
|
|
|
70
90
|
# if we're in line, line will check that our
|
|
71
91
|
# contained Term, if any, matches.
|
|
72
92
|
self.match = self.default_match()
|
|
93
|
+
|
|
94
|
+
def resolve_value(self, skip=None) -> str | None:
|
|
95
|
+
return None
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# pylint: disable=C0114
|
|
2
|
+
from csvpath.matching.util.exceptions import ChildrenException
|
|
3
|
+
from ..function_focus import ValueProducer
|
|
4
|
+
from csvpath.matching.productions import Term, Variable, Header, Reference
|
|
5
|
+
from csvpath.matching.util.expression_utility import ExpressionUtility
|
|
6
|
+
from ..function import Function
|
|
7
|
+
from ..args import Args
|
|
8
|
+
from .type import Type
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class String(Type):
|
|
12
|
+
def check_valid(self) -> None:
|
|
13
|
+
self.args = Args(matchable=self)
|
|
14
|
+
a = self.args.argset(1)
|
|
15
|
+
a.arg(
|
|
16
|
+
name="header name",
|
|
17
|
+
types=[Term],
|
|
18
|
+
actuals=[str, int],
|
|
19
|
+
)
|
|
20
|
+
# why self.args.EMPTY_STRING? we'll never have an empty string
|
|
21
|
+
# term. if we only allow terms we're only ever pointing to a
|
|
22
|
+
# header. If we allow other types we'll resolve them potentially
|
|
23
|
+
# to the empty string, but that's not what we're doing today.
|
|
24
|
+
a = self.args.argset(3)
|
|
25
|
+
a.arg(
|
|
26
|
+
name="header name",
|
|
27
|
+
types=[Term],
|
|
28
|
+
actuals=[str, int],
|
|
29
|
+
)
|
|
30
|
+
a.arg(name="max value", types=[None, Term], actuals=[int])
|
|
31
|
+
a.arg(name="min value", types=[None, Term], actuals=[int])
|
|
32
|
+
self.args.validate(self.siblings())
|
|
33
|
+
super().check_valid()
|
|
34
|
+
|
|
35
|
+
def _produce_value(self, skip=None) -> None:
|
|
36
|
+
self.matches(skip=skip)
|
|
37
|
+
self.value = f"{self._value_one()}" if self.match else None
|
|
38
|
+
|
|
39
|
+
def _decide_match(self, skip=None) -> None:
|
|
40
|
+
value = self._value_one(skip=skip)
|
|
41
|
+
value = f"{value}" if value is not None else None
|
|
42
|
+
# resolve the value of the header that our value names
|
|
43
|
+
val = self.resolve_value(skip=skip)
|
|
44
|
+
# our to_value cannot be none because Args
|
|
45
|
+
# our resolved value can be none or '' and
|
|
46
|
+
# we might not accept that
|
|
47
|
+
if val is None and self.notnone:
|
|
48
|
+
self.match = False
|
|
49
|
+
elif val is None:
|
|
50
|
+
self.match = True
|
|
51
|
+
else:
|
|
52
|
+
self._check_length_if(val)
|
|
53
|
+
|
|
54
|
+
def _check_length_if(self, value, skip=None) -> None:
|
|
55
|
+
maxlen = self._value_two(skip=skip)
|
|
56
|
+
minlen = self._value_three(skip=skip)
|
|
57
|
+
if minlen is None:
|
|
58
|
+
minlen = 0
|
|
59
|
+
if maxlen is None:
|
|
60
|
+
maxlen = len(value)
|
|
61
|
+
if maxlen < minlen:
|
|
62
|
+
self.raiseChildrenException(
|
|
63
|
+
"Max length ({maxlen}) cannot be less than min length ({minlen})"
|
|
64
|
+
)
|
|
65
|
+
self.match = minlen <= len(value) <= maxlen
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# pylint: disable=C0114
|
|
2
|
+
from ..function_focus import MatchDecider
|
|
3
|
+
from csvpath.matching.productions import Term
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Type(MatchDecider):
|
|
7
|
+
def resolve_value(self, skip=None, quiet=False) -> str | None:
|
|
8
|
+
# Args should have already checked Term
|
|
9
|
+
t = self._child_one()
|
|
10
|
+
if isinstance(t, Term):
|
|
11
|
+
name = self._value_one(skip=skip)
|
|
12
|
+
ret = self.matcher.get_header_value(self, name, quiet=quiet)
|
|
13
|
+
return ret
|
|
14
|
+
return None
|