csvpath 0.0.480__tar.gz → 0.0.481__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.480 → csvpath-0.0.481}/PKG-INFO +1 -1
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/csvpath.py +76 -28
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/args.py +61 -16
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/boolean/all.py +0 -2
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/boolean/any.py +1 -0
- csvpath-0.0.481/csvpath/matching/functions/boolean/boolean.py +31 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/boolean/empty.py +21 -14
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/boolean/inf.py +5 -3
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/boolean/yes.py +2 -1
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/counting/count.py +13 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/counting/increment.py +3 -3
- csvpath-0.0.481/csvpath/matching/functions/function.py +207 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/function_factory.py +10 -2
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/headers/end.py +3 -2
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/headers/header_name.py +4 -1
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/lines/dups.py +7 -7
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/lines/first_line.py +4 -2
- {csvpath-0.0.480/csvpath/matching/functions/misc → csvpath-0.0.481/csvpath/matching/functions/math}/intf.py +17 -8
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/misc/importf.py +2 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/misc/nonef.py +18 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/misc/random.py +5 -3
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/stats/minf.py +2 -2
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/stats/percent.py +2 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/stats/stdev.py +5 -2
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/strings/regex.py +1 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/strings/string.py +2 -2
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/strings/substring.py +5 -3
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/validity/failed.py +1 -0
- csvpath-0.0.481/csvpath/matching/functions/validity/line.py +88 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/matcher.py +9 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/productions/expression.py +26 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/productions/header.py +2 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/productions/matchable.py +30 -1
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/productions/qualified.py +1 -1
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/productions/term.py +8 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/util/exceptions.py +8 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/util/expression_utility.py +23 -3
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/util/error.py +97 -9
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/comments.md +10 -5
- {csvpath-0.0.480 → csvpath-0.0.481}/pyproject.toml +1 -1
- csvpath-0.0.480/csvpath/matching/functions/function.py +0 -145
- {csvpath-0.0.480 → csvpath-0.0.481}/LICENSE +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/README.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/config/config.ini +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/__init__.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/csvpaths.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/managers/__init__.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/managers/csvpaths_manager.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/managers/file_manager.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/managers/result.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/managers/results_manager.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/__init__.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/__init__.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/boolean/andf.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/boolean/between.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/boolean/exists.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/boolean/no.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/boolean/notf.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/boolean/orf.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/counting/count_headers.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/counting/count_lines.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/counting/count_scans.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/counting/counter.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/counting/every.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/counting/has_matches.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/counting/tally.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/counting/total_lines.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/dates/datef.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/dates/now.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/function_finder.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/function_focus.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/headers/append.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/headers/collect.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/headers/empty_stack.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/headers/header_names_mismatch.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/headers/headers.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/headers/mismatch.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/headers/replace.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/headers/reset_headers.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/lines/advance.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/lines/after_blank.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/lines/first.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/lines/last.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/lines/stop.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/math/above.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/math/add.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/math/divide.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/math/equals.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/math/mod.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/math/multiply.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/math/round.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/math/subtotal.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/math/subtract.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/math/sum.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/print/jinjaf.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/print/print_line.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/print/print_queue.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/print/printf.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/print/table.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/stats/percent_unique.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/strings/concat.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/strings/length.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/strings/lower.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/strings/metaphone.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/strings/starts_with.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/strings/strip.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/strings/upper.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/testing/debug.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/validity/fail.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/variables/get.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/variables/pushpop.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/variables/put.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/variables/track.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/functions/variables/variables.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/lark_parser.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/lark_transformer.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/productions/__init__.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/productions/equality.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/productions/reference.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/productions/variable.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/util/expression_encoder.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/util/lark_print_parser.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/matching/util/print_parser.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/scanning/__init__.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/scanning/exceptions.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/scanning/parser.out +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/scanning/parsetab.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/scanning/scanner.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/scanning/scanning_lexer.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/util/cache.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/util/config.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/util/config_exception.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/util/exceptions.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/util/last_line_stats.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/util/line_counter.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/util/line_monitor.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/util/log_utility.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/util/metadata_parser.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/csvpath/util/printer.py +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/asbool.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/assignment.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/config.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/examples.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/files.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/above.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/advance.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/after_blank.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/all.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/andor.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/any.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/average.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/between.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/collect.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/correlate.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/count.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/count_headers.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/counter.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/date.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/empty.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/empty_stack.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/end.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/every.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/fail.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/first.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/get.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/has_dups.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/has_matches.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/header.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/header_name.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/header_names_mismatch.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/implementing_functions.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/import.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/in.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/increment.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/jinja.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/last.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/line_number.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/max.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/metaphone.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/mismatch.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/no.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/not.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/now.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/percent_unique.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/pop.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/print.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/print_line.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/print_queue.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/random.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/regex.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/replace.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/reset_headers.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/stdev.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/stop.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/string_functions.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/subtotal.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/subtract.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/sum.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/tally.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/total_lines.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/track.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/variables.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions/variables_and_headers.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/functions.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/grammar.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/headers.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/images/logo-wordmark-white-on-black-trimmed-padded.png +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/images/logo-wordmark-white-trimmed.png +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/paths.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/printing.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/qualifiers.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/references.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/terms.md +0 -0
- {csvpath-0.0.480 → csvpath-0.0.481}/docs/variables.md +0 -0
|
@@ -172,7 +172,6 @@ class CsvPath(CsvPathPublic, ErrorCollector, Printer): # pylint: disable=R0902,
|
|
|
172
172
|
#
|
|
173
173
|
self.stopped = False
|
|
174
174
|
self._advance = 0
|
|
175
|
-
|
|
176
175
|
#
|
|
177
176
|
# set by fail()
|
|
178
177
|
#
|
|
@@ -249,9 +248,12 @@ class CsvPath(CsvPathPublic, ErrorCollector, Printer): # pylint: disable=R0902,
|
|
|
249
248
|
# use match component rules and exceptions to generate validation
|
|
250
249
|
# info. but long term this capability may go away.
|
|
251
250
|
#
|
|
252
|
-
self._log_validation_errors =
|
|
251
|
+
self._log_validation_errors = True
|
|
253
252
|
self._print_validation_errors = True
|
|
254
|
-
self._raise_validation_errors =
|
|
253
|
+
self._raise_validation_errors = None
|
|
254
|
+
self._match_validation_errors = None
|
|
255
|
+
self._stop_on_validation_errors = None
|
|
256
|
+
self._fail_on_validation_errors = None
|
|
255
257
|
#
|
|
256
258
|
# there are two logger components one for CsvPath and one for CsvPaths.
|
|
257
259
|
# the default levels are set in config.ini. to change the levels pass LogUtility
|
|
@@ -372,28 +374,70 @@ class CsvPath(CsvPathPublic, ErrorCollector, Printer): # pylint: disable=R0902,
|
|
|
372
374
|
self._errors = []
|
|
373
375
|
self._errors.append(error)
|
|
374
376
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
377
|
+
#
|
|
378
|
+
# validation error handling overrides the error policy in config. this
|
|
379
|
+
# is because the validation handling is:
|
|
380
|
+
# - different. it is built-in. it deals with programmatic decisions
|
|
381
|
+
# about how functions work and is the basis for structural (schema)
|
|
382
|
+
# validation.
|
|
383
|
+
# - set on a per csvpath basis in comments
|
|
384
|
+
#
|
|
385
|
+
# by default, validation errors do not impact matching. they are print
|
|
386
|
+
# and raise only. however, you can set them to raise or match/not-match
|
|
387
|
+
# and/or suppress printing.
|
|
388
|
+
#
|
|
384
389
|
def set_validation_error_handling(self, veh) -> None:
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
390
|
+
# print prints to the Printer(s), not std.out. atm, no
|
|
391
|
+
# customization of messages is possible, so there is likely
|
|
392
|
+
# to be stylistic mismatch with other output.
|
|
393
|
+
if veh and veh.find("no-print") > -1:
|
|
388
394
|
self._print_validation_errors = False
|
|
389
|
-
|
|
390
|
-
self.
|
|
395
|
+
elif veh and veh.find("print") > -1:
|
|
396
|
+
self._print_validation_errors = True
|
|
391
397
|
else:
|
|
392
|
-
self.
|
|
393
|
-
|
|
398
|
+
self._print_validation_errors = None
|
|
399
|
+
#
|
|
400
|
+
if veh and veh.find("no-raise") > -1:
|
|
401
|
+
self._raise_validation_errors = False
|
|
402
|
+
elif veh and veh.find("raise") > -1:
|
|
394
403
|
self._raise_validation_errors = True
|
|
395
404
|
else:
|
|
396
|
-
self._raise_validation_errors =
|
|
405
|
+
self._raise_validation_errors = None
|
|
406
|
+
#
|
|
407
|
+
# match, no-match, and None do:
|
|
408
|
+
# match: return True on error
|
|
409
|
+
# no-match: return False on error
|
|
410
|
+
# None: default behavior: default_match() or result of matches()
|
|
411
|
+
if veh and veh.find("no-match") > -1:
|
|
412
|
+
self._match_validation_errors = False
|
|
413
|
+
elif veh and veh.find("match") > -1:
|
|
414
|
+
self._match_validation_errors = True
|
|
415
|
+
else:
|
|
416
|
+
self._match_validation_errors = None
|
|
417
|
+
#
|
|
418
|
+
# also stop and fail to match the config
|
|
419
|
+
#
|
|
420
|
+
if veh and veh.find("no-stop") > -1:
|
|
421
|
+
self._stop_on_validation_errors = False
|
|
422
|
+
elif veh and veh.find("stop") > -1:
|
|
423
|
+
self._stop_on_validation_errors = True
|
|
424
|
+
else:
|
|
425
|
+
self._stop_on_validation_errors = None
|
|
426
|
+
#
|
|
427
|
+
if veh and veh.find("no-fail") > -1:
|
|
428
|
+
self._fail_on_validation_errors = False
|
|
429
|
+
elif veh and veh.find("fail") > -1:
|
|
430
|
+
self._fail_on_validation_errors = True
|
|
431
|
+
else:
|
|
432
|
+
self._fail_on_validation_errors = None
|
|
433
|
+
|
|
434
|
+
@property
|
|
435
|
+
def stop_on_validation_errors(self) -> bool:
|
|
436
|
+
return self._stop_on_validation_errors
|
|
437
|
+
|
|
438
|
+
@property
|
|
439
|
+
def fail_on_validation_errors(self) -> bool:
|
|
440
|
+
return self._fail_on_validation_errors
|
|
397
441
|
|
|
398
442
|
@property
|
|
399
443
|
def print_validation_errors(self) -> bool:
|
|
@@ -407,6 +451,10 @@ class CsvPath(CsvPathPublic, ErrorCollector, Printer): # pylint: disable=R0902,
|
|
|
407
451
|
def raise_validation_errors(self) -> bool:
|
|
408
452
|
return self._raise_validation_errors
|
|
409
453
|
|
|
454
|
+
@property
|
|
455
|
+
def match_validation_errors(self) -> bool:
|
|
456
|
+
return self._match_validation_errors
|
|
457
|
+
|
|
410
458
|
def add_printer(self, printer) -> None: # pylint: disable=C0116
|
|
411
459
|
if printer not in self.printers:
|
|
412
460
|
self.printers.append(printer)
|
|
@@ -522,8 +570,8 @@ class CsvPath(CsvPathPublic, ErrorCollector, Printer): # pylint: disable=R0902,
|
|
|
522
570
|
# settings:
|
|
523
571
|
# - logic-mode: AND | OR
|
|
524
572
|
# - match-mode: matches | no-matches
|
|
525
|
-
# - print-mode: default
|
|
526
|
-
# -
|
|
573
|
+
# - print-mode: default | no-default
|
|
574
|
+
# - validation-mode: (no-)print | log | (no-)raise | quiet | (no-)match
|
|
527
575
|
#
|
|
528
576
|
self.update_logic_mode_if()
|
|
529
577
|
self.update_match_mode_if()
|
|
@@ -531,18 +579,18 @@ class CsvPath(CsvPathPublic, ErrorCollector, Printer): # pylint: disable=R0902,
|
|
|
531
579
|
self.update_arg_validation_mode_if()
|
|
532
580
|
|
|
533
581
|
def update_arg_validation_mode_if(self) -> None:
|
|
534
|
-
if self.metadata and "
|
|
582
|
+
if self.metadata and "validation-mode" in self.metadata:
|
|
535
583
|
# sets arg validation reporting. one or more or none of:
|
|
536
584
|
# - print
|
|
537
585
|
# - log
|
|
538
586
|
# - raise
|
|
539
587
|
#
|
|
540
|
-
validation_mode = f"{self.metadata['
|
|
588
|
+
validation_mode = f"{self.metadata['validation-mode']}".strip()
|
|
541
589
|
if validation_mode:
|
|
542
590
|
self.set_validation_error_handling(validation_mode)
|
|
543
591
|
self.logger.info(
|
|
544
|
-
"Setting '
|
|
545
|
-
self.metadata["
|
|
592
|
+
"Setting 'validation-mode': %s",
|
|
593
|
+
self.metadata["validation-mode"],
|
|
546
594
|
)
|
|
547
595
|
|
|
548
596
|
def update_logic_mode_if(self) -> None:
|
|
@@ -571,7 +619,7 @@ class CsvPath(CsvPathPublic, ErrorCollector, Printer): # pylint: disable=R0902,
|
|
|
571
619
|
|
|
572
620
|
def update_print_mode_if(self) -> None:
|
|
573
621
|
if "print-mode" in self.metadata:
|
|
574
|
-
if f"{self.metadata['print-mode']}".strip() == "default
|
|
622
|
+
if f"{self.metadata['print-mode']}".strip() == "no-default":
|
|
575
623
|
remove = -1
|
|
576
624
|
for i, p in enumerate(self.printers):
|
|
577
625
|
if isinstance(p, StdOutPrinter):
|
|
@@ -579,7 +627,7 @@ class CsvPath(CsvPathPublic, ErrorCollector, Printer): # pylint: disable=R0902,
|
|
|
579
627
|
break
|
|
580
628
|
if remove >= 0:
|
|
581
629
|
del self.printers[remove]
|
|
582
|
-
elif f"{self.metadata['print-mode']}".strip() == "default
|
|
630
|
+
elif f"{self.metadata['print-mode']}".strip() == "default":
|
|
583
631
|
done = False
|
|
584
632
|
for i, p in enumerate(self.printers):
|
|
585
633
|
if isinstance(p, StdOutPrinter):
|
|
@@ -8,7 +8,7 @@ from csvpath.matching.functions.function import Function
|
|
|
8
8
|
from csvpath.matching.productions.reference import Reference
|
|
9
9
|
from csvpath.matching.productions.equality import Equality
|
|
10
10
|
from csvpath.matching.util.expression_utility import ExpressionUtility
|
|
11
|
-
from ..util.exceptions import ChildrenException
|
|
11
|
+
from ..util.exceptions import ChildrenException, ChildrenValidationException
|
|
12
12
|
from csvpath.util.config_exception import ConfigurationException
|
|
13
13
|
|
|
14
14
|
# from csvpath.util.log_utility import LogUtility
|
|
@@ -194,7 +194,7 @@ class ArgSet:
|
|
|
194
194
|
self._args = args
|
|
195
195
|
self.max_length = len(self._args)
|
|
196
196
|
|
|
197
|
-
def
|
|
197
|
+
def validate_structure(self, siblings: List[Matchable]) -> None:
|
|
198
198
|
b = self._validate_length(siblings)
|
|
199
199
|
if b is False:
|
|
200
200
|
return False
|
|
@@ -235,11 +235,44 @@ class ArgSet:
|
|
|
235
235
|
break
|
|
236
236
|
arg = self._args[i]
|
|
237
237
|
#
|
|
238
|
+
# in principle we would want to avoid any case where we don't have an arg
|
|
239
|
+
# or the arg's actuals are none
|
|
240
|
+
# -- and ---
|
|
241
|
+
# if the arg exists but has [] elements treat it as a requirement that no
|
|
242
|
+
# optional values should be passed in on that arg in that particular use
|
|
243
|
+
# case.
|
|
244
|
+
#
|
|
245
|
+
# however, that approach a) breaks stuff i'd like to not break atm, and b)
|
|
246
|
+
# the only use case today (in empty()) is obviated by a second arg set
|
|
247
|
+
# that would in essence override the [] actuals in the first argset. so
|
|
248
|
+
# we have no case. given that, letting this idea go until it resurfaces
|
|
249
|
+
# in a more practical way.
|
|
250
|
+
#
|
|
251
|
+
# exp!
|
|
252
|
+
self._parent._csvpath.logger.debug("Checking arg[%i]: %s", i, arg)
|
|
253
|
+
"""
|
|
254
|
+
if ( not arg or arg.actuals is None ):
|
|
255
|
+
if self._parent and self._parent._csvpath:
|
|
256
|
+
self._parent._csvpath.logger.debug(
|
|
257
|
+
"No expectations to validate actual values against in argset {self.argset_number}"
|
|
258
|
+
)
|
|
259
|
+
found = True
|
|
260
|
+
break
|
|
261
|
+
if len(arg.actuals) == 0 and len(actuals) > 0:
|
|
262
|
+
if self._parent and self._parent._csvpath:
|
|
263
|
+
self._parent._csvpath.logger.debug(
|
|
264
|
+
"No optional args should be presented in {self.argset_number}"
|
|
265
|
+
)
|
|
266
|
+
found = False
|
|
267
|
+
break
|
|
268
|
+
"""
|
|
269
|
+
# end exp
|
|
270
|
+
#
|
|
271
|
+
# start orig w/orig comment:
|
|
238
272
|
# we can't validate arg if we have no actuals expectations.
|
|
239
273
|
# this is a way to disable line-by-line validation -- just
|
|
240
274
|
# remove the expectations from the args
|
|
241
275
|
#
|
|
242
|
-
self._parent._csvpath.logger.debug("Checking arg[%i]: %s", i, arg)
|
|
243
276
|
if not arg or not arg.actuals or len(arg.actuals) == 0:
|
|
244
277
|
if self._parent and self._parent._csvpath:
|
|
245
278
|
self._parent._csvpath.logger.debug(
|
|
@@ -247,6 +280,9 @@ class ArgSet:
|
|
|
247
280
|
)
|
|
248
281
|
found = True
|
|
249
282
|
break
|
|
283
|
+
#
|
|
284
|
+
# end orig
|
|
285
|
+
#
|
|
250
286
|
if Any in arg.actuals:
|
|
251
287
|
self._parent._csvpath.logger.debug("Found Any so we're done")
|
|
252
288
|
found = True
|
|
@@ -309,6 +345,21 @@ class Args:
|
|
|
309
345
|
# child.to_value(skips=skips) to result in an int, did it?
|
|
310
346
|
#
|
|
311
347
|
self.matched = False
|
|
348
|
+
self._args_match = True
|
|
349
|
+
|
|
350
|
+
def reset(self) -> None:
|
|
351
|
+
self._args_match = True
|
|
352
|
+
self.matched = False
|
|
353
|
+
|
|
354
|
+
@property
|
|
355
|
+
def args_match(self) -> bool | None:
|
|
356
|
+
"""Only used in the runtime actuals matching. speaks
|
|
357
|
+
to if the line should be considered matched or not.
|
|
358
|
+
None is default
|
|
359
|
+
True means matching succeeded
|
|
360
|
+
False means matching failed
|
|
361
|
+
"""
|
|
362
|
+
return self._args_match
|
|
312
363
|
|
|
313
364
|
def argset(self, maxlength: int = -1) -> ArgSet:
|
|
314
365
|
a = ArgSet(maxlength, parent=self)
|
|
@@ -339,10 +390,10 @@ class Args:
|
|
|
339
390
|
#
|
|
340
391
|
good = False
|
|
341
392
|
for aset in self._argsets:
|
|
342
|
-
if aset.
|
|
393
|
+
if aset.validate_structure(siblings):
|
|
343
394
|
good = True
|
|
344
395
|
if not good:
|
|
345
|
-
_ = " at {self.matchable.my_chain}" if self.matchable else ""
|
|
396
|
+
_ = f" at {self.matchable.my_chain}" if self.matchable else ""
|
|
346
397
|
msg = f"{self._csvpath_id()} Incorrectly written{_}. Wrong type or number of args."
|
|
347
398
|
raise ChildrenException(msg)
|
|
348
399
|
self.validated = True
|
|
@@ -390,19 +441,13 @@ class Args:
|
|
|
390
441
|
|
|
391
442
|
def handle_errors_if(self, mismatch_count, mismatches):
|
|
392
443
|
if mismatch_count == len(self._argsets):
|
|
444
|
+
self._args_match = False
|
|
393
445
|
pm = f"mismatch in {self.matchable.my_chain}: {mismatches}"
|
|
394
446
|
# when would we not have a csvpath?
|
|
395
447
|
pln = (
|
|
396
448
|
self._csvpath.line_monitor.physical_line_number if self._csvpath else 0
|
|
397
449
|
)
|
|
398
|
-
csvpathid = self._csvpath_id()
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
raise ChildrenException(pm)
|
|
403
|
-
# we print in-run validation errors as part of the raise handle,
|
|
404
|
-
# so this is a bit extra. We can suppress the exceptions completely
|
|
405
|
-
# but still print args validation errors. not sure that is anything
|
|
406
|
-
# more than a deep corner case. defering removing it.
|
|
407
|
-
if self._csvpath and self._csvpath.print_validation_errors:
|
|
408
|
-
self._csvpath.report_validation_errors(pm)
|
|
450
|
+
csvpathid = f"{self._csvpath_id()} " if self._csvpath_id() else ""
|
|
451
|
+
ei = ExpressionUtility.get_my_expressions_index(self._matchable)
|
|
452
|
+
pm = f"{csvpathid}Wrong value in match component {ei} at line {pln}: {pm}"
|
|
453
|
+
raise ChildrenValidationException(pm)
|
|
@@ -50,8 +50,6 @@ class All(MatchDecider):
|
|
|
50
50
|
self.all_exist()
|
|
51
51
|
elif isinstance(child, Variables):
|
|
52
52
|
self.all_variables()
|
|
53
|
-
else:
|
|
54
|
-
raise ChildrenException("Child cannot be {child}")
|
|
55
53
|
|
|
56
54
|
def all_variables(self) -> None: # pylint: disable=C0116
|
|
57
55
|
# default is True in case no vars
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# pylint: disable=C0114
|
|
2
|
+
from csvpath.matching.util.expression_utility import ExpressionUtility
|
|
3
|
+
from csvpath.matching.util.exceptions import DataException
|
|
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])
|
|
15
|
+
self.args.validate(self.siblings())
|
|
16
|
+
super().check_valid()
|
|
17
|
+
|
|
18
|
+
def _produce_value(self, skip=None) -> None:
|
|
19
|
+
i = self._value_one(skip=skip)
|
|
20
|
+
if i is None:
|
|
21
|
+
self.value = None
|
|
22
|
+
else:
|
|
23
|
+
self.value = ExpressionUtility.to_bool(i)
|
|
24
|
+
|
|
25
|
+
def _decide_match(self, skip=None) -> None:
|
|
26
|
+
# we need to make sure a value is produced so that we see
|
|
27
|
+
# any errors. when we stand alone we're just checking our
|
|
28
|
+
# boolean-iness. when we're producing a value we're checking
|
|
29
|
+
# boolean-iness and casting and raising errors.
|
|
30
|
+
self.to_value(skip=skip)
|
|
31
|
+
self.match = self.default_match() # pragma: no cover
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# pylint: disable=C0114
|
|
2
|
+
from typing import Any
|
|
2
3
|
from ..function_focus import MatchDecider
|
|
3
4
|
from csvpath.matching.productions import Header, Variable, Equality, Term
|
|
4
5
|
from csvpath.matching.util.exceptions import ChildrenException
|
|
5
6
|
from ..headers.headers import Headers
|
|
6
7
|
from csvpath.matching.util.expression_utility import ExpressionUtility
|
|
8
|
+
from csvpath.matching.functions.args import Args
|
|
9
|
+
from csvpath.matching.functions.function import Function
|
|
7
10
|
|
|
8
11
|
|
|
9
12
|
class Empty(MatchDecider):
|
|
@@ -12,22 +15,26 @@ class Empty(MatchDecider):
|
|
|
12
15
|
if you pass it headers() it checks for all headers being empty."""
|
|
13
16
|
|
|
14
17
|
def check_valid(self) -> None:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
self.
|
|
18
|
+
self.args = Args(matchable=self)
|
|
19
|
+
#
|
|
20
|
+
# we'd like to disallow headers from taking a value in this case, but we
|
|
21
|
+
# cannot because headers is a function and will be covered by the second
|
|
22
|
+
# argset, so we handle that in a helper validation function.
|
|
23
|
+
#
|
|
24
|
+
a = self.args.argset(1)
|
|
25
|
+
a.arg(types=[Headers])
|
|
26
|
+
a = self.args.argset()
|
|
27
|
+
a.arg(types=[Variable, Function, Header], actuals=[None, Any])
|
|
28
|
+
self.args.validate(self.siblings())
|
|
29
|
+
#
|
|
30
|
+
self._validate()
|
|
26
31
|
super().check_valid() # pragma: no cover
|
|
27
32
|
|
|
28
|
-
def _validate(self
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
def _validate(self):
|
|
34
|
+
sibs = self.siblings()
|
|
35
|
+
for s in sibs:
|
|
36
|
+
# both definitely structure / children exceptions
|
|
37
|
+
if isinstance(s, Headers) and len(sibs) > 1:
|
|
31
38
|
raise ChildrenException(
|
|
32
39
|
"If empty() has a headers() argument it can only have 1 argument"
|
|
33
40
|
)
|
|
@@ -28,8 +28,9 @@ class In(MatchDecider):
|
|
|
28
28
|
for s in siblings[1:]:
|
|
29
29
|
v = s.to_value(skip=skip)
|
|
30
30
|
if isinstance(s, Term):
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
v = f"{v}".strip()
|
|
32
|
+
nvs = [_.strip() for _ in v.split("|")]
|
|
33
|
+
inf += nvs
|
|
33
34
|
else:
|
|
34
35
|
# tuple would mean vars were frozen. this would not be
|
|
35
36
|
# surprising from a reference
|
|
@@ -41,4 +42,5 @@ class In(MatchDecider):
|
|
|
41
42
|
inf.append(k)
|
|
42
43
|
else:
|
|
43
44
|
inf.append(v)
|
|
44
|
-
|
|
45
|
+
ret = t in inf
|
|
46
|
+
self.match = ret
|
|
@@ -8,7 +8,8 @@ class Yes(ValueProducer):
|
|
|
8
8
|
"""returns True"""
|
|
9
9
|
|
|
10
10
|
def check_valid(self) -> None:
|
|
11
|
-
Args(
|
|
11
|
+
self.args = Args(matchable=self)
|
|
12
|
+
self.args.validate(self.siblings())
|
|
12
13
|
super().check_valid()
|
|
13
14
|
|
|
14
15
|
def _produce_value(self, skip=None) -> None:
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# pylint: disable=C0114
|
|
2
2
|
from typing import Any
|
|
3
3
|
from ..function_focus import ValueProducer
|
|
4
|
+
from ..function import Function
|
|
5
|
+
from ..args import Args
|
|
6
|
+
from csvpath.matching.productions import Equality, Variable, Header, Term
|
|
4
7
|
|
|
5
8
|
|
|
6
9
|
class Count(ValueProducer):
|
|
@@ -9,6 +12,16 @@ class Count(ValueProducer):
|
|
|
9
12
|
|
|
10
13
|
def check_valid(self) -> None: # pylint: disable=W0246
|
|
11
14
|
# note to self: no specific validity checks from way back
|
|
15
|
+
# these args may need work
|
|
16
|
+
self.args = Args(matchable=self)
|
|
17
|
+
a = self.args.argset(0)
|
|
18
|
+
a = self.args.argset()
|
|
19
|
+
a.arg(
|
|
20
|
+
types=[None, Variable, Function, Header, Term, Equality],
|
|
21
|
+
actuals=[None, Any],
|
|
22
|
+
)
|
|
23
|
+
self.args.validate(self.siblings())
|
|
24
|
+
#
|
|
12
25
|
super().check_valid() # pylint: disable=W0246
|
|
13
26
|
# re: W0246: Matchable handles this class's children
|
|
14
27
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pylint: disable=C0114
|
|
2
2
|
from typing import Any
|
|
3
|
-
from csvpath.matching.util.exceptions import
|
|
3
|
+
from csvpath.matching.util.exceptions import DataException
|
|
4
4
|
from ..function_focus import ValueProducer
|
|
5
5
|
from csvpath.matching.productions import Term, Header, Variable, Equality
|
|
6
6
|
from ..function import Function
|
|
@@ -26,12 +26,12 @@ class Increment(ValueProducer):
|
|
|
26
26
|
return self._noop_value()
|
|
27
27
|
tv = self.children[0].right.to_value()
|
|
28
28
|
if not isinstance(tv, int):
|
|
29
|
-
raise
|
|
29
|
+
raise DataException(
|
|
30
30
|
"increment value must be a positive int"
|
|
31
31
|
) # pragma: no cover
|
|
32
32
|
tv = int(tv)
|
|
33
33
|
if tv <= 0:
|
|
34
|
-
raise
|
|
34
|
+
raise DataException(
|
|
35
35
|
"increment value must be a positive int"
|
|
36
36
|
) # pragma: no cover
|
|
37
37
|
if not self.value:
|