csvpath 0.0.476__tar.gz → 0.0.478__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.
Files changed (226) hide show
  1. {csvpath-0.0.476 → csvpath-0.0.478}/PKG-INFO +37 -35
  2. {csvpath-0.0.476 → csvpath-0.0.478}/README.md +32 -33
  3. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/csvpath.py +198 -15
  4. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/csvpaths.py +22 -25
  5. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/managers/csvpaths_manager.py +14 -4
  6. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/managers/file_manager.py +8 -6
  7. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/managers/result.py +10 -6
  8. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/managers/results_manager.py +1 -10
  9. csvpath-0.0.478/csvpath/matching/functions/args.py +390 -0
  10. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/boolean/all.py +18 -1
  11. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/boolean/andf.py +12 -1
  12. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/boolean/any.py +16 -8
  13. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/boolean/between.py +50 -5
  14. csvpath-0.0.478/csvpath/matching/functions/boolean/exists.py +27 -0
  15. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/boolean/inf.py +10 -3
  16. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/boolean/no.py +5 -4
  17. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/boolean/notf.py +10 -1
  18. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/boolean/orf.py +12 -1
  19. csvpath-0.0.478/csvpath/matching/functions/boolean/yes.py +18 -0
  20. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/counting/count.py +1 -1
  21. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/counting/count_headers.py +3 -1
  22. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/counting/count_lines.py +5 -2
  23. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/counting/count_scans.py +3 -1
  24. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/counting/counter.py +6 -2
  25. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/counting/every.py +8 -2
  26. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/counting/has_matches.py +3 -1
  27. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/counting/increment.py +8 -1
  28. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/counting/tally.py +9 -2
  29. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/counting/total_lines.py +3 -1
  30. csvpath-0.0.478/csvpath/matching/functions/dates/datef.py +40 -0
  31. csvpath-0.0.478/csvpath/matching/functions/dates/now.py +47 -0
  32. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/function.py +50 -18
  33. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/function_factory.py +16 -7
  34. csvpath-0.0.478/csvpath/matching/functions/headers/append.py +31 -0
  35. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/headers/collect.py +11 -6
  36. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/headers/empty_stack.py +6 -1
  37. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/headers/end.py +6 -1
  38. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/headers/header_name.py +8 -1
  39. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/headers/header_names_mismatch.py +9 -0
  40. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/headers/headers.py +11 -2
  41. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/headers/mismatch.py +8 -2
  42. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/headers/replace.py +13 -7
  43. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/headers/reset_headers.py +9 -5
  44. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/lines/advance.py +20 -14
  45. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/lines/after_blank.py +3 -1
  46. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/lines/dups.py +16 -5
  47. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/lines/first.py +6 -1
  48. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/lines/first_line.py +5 -1
  49. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/lines/last.py +13 -1
  50. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/lines/stop.py +22 -11
  51. csvpath-0.0.478/csvpath/matching/functions/math/above.py +98 -0
  52. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/math/add.py +15 -2
  53. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/math/divide.py +9 -2
  54. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/math/equals.py +9 -1
  55. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/math/mod.py +10 -2
  56. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/math/multiply.py +12 -2
  57. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/math/round.py +9 -3
  58. csvpath-0.0.478/csvpath/matching/functions/math/subtotal.py +32 -0
  59. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/math/subtract.py +8 -3
  60. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/math/sum.py +8 -2
  61. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/misc/importf.py +17 -5
  62. csvpath-0.0.478/csvpath/matching/functions/misc/intf.py +75 -0
  63. csvpath-0.0.478/csvpath/matching/functions/misc/nonef.py +21 -0
  64. csvpath-0.0.478/csvpath/matching/functions/misc/random.py +70 -0
  65. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/print/jinjaf.py +22 -17
  66. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/print/print_line.py +12 -5
  67. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/print/print_queue.py +4 -2
  68. csvpath-0.0.478/csvpath/matching/functions/print/printf.py +55 -0
  69. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/print/table.py +21 -8
  70. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/stats/minf.py +18 -8
  71. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/stats/percent.py +7 -2
  72. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/stats/percent_unique.py +5 -1
  73. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/stats/stdev.py +8 -2
  74. csvpath-0.0.478/csvpath/matching/functions/strings/concat.py +35 -0
  75. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/strings/length.py +13 -4
  76. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/strings/lower.py +7 -3
  77. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/strings/metaphone.py +9 -3
  78. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/strings/regex.py +12 -17
  79. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/strings/starts_with.py +8 -1
  80. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/strings/strip.py +8 -2
  81. csvpath-0.0.478/csvpath/matching/functions/strings/substring.py +38 -0
  82. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/strings/upper.py +7 -1
  83. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/testing/debug.py +42 -17
  84. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/validity/fail.py +7 -4
  85. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/validity/failed.py +3 -1
  86. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/variables/get.py +6 -5
  87. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/variables/pushpop.py +36 -18
  88. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/variables/put.py +17 -2
  89. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/variables/track.py +15 -6
  90. csvpath-0.0.478/csvpath/matching/functions/variables/variables.py +29 -0
  91. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/matcher.py +20 -15
  92. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/productions/equality.py +8 -2
  93. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/productions/expression.py +5 -0
  94. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/productions/header.py +2 -2
  95. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/productions/matchable.py +41 -7
  96. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/productions/qualified.py +16 -2
  97. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/productions/reference.py +0 -44
  98. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/util/expression_utility.py +178 -21
  99. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/util/print_parser.py +69 -56
  100. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/util/line_monitor.py +1 -1
  101. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/util/log_utility.py +8 -6
  102. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/util/metadata_parser.py +1 -1
  103. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/util/printer.py +14 -4
  104. csvpath-0.0.478/docs/comments.md +121 -0
  105. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/between.md +2 -2
  106. csvpath-0.0.478/docs/functions/in.md +43 -0
  107. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/print.md +24 -2
  108. csvpath-0.0.478/docs/functions/random.md +24 -0
  109. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/regex.md +2 -2
  110. csvpath-0.0.478/docs/functions/replace.md +51 -0
  111. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/string_functions.md +2 -2
  112. csvpath-0.0.478/docs/functions/subtotal.md +30 -0
  113. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions.md +41 -37
  114. csvpath-0.0.478/docs/printing.md +101 -0
  115. {csvpath-0.0.476 → csvpath-0.0.478}/docs/qualifiers.md +4 -4
  116. {csvpath-0.0.476 → csvpath-0.0.478}/docs/terms.md +1 -1
  117. {csvpath-0.0.476 → csvpath-0.0.478}/pyproject.toml +2 -2
  118. csvpath-0.0.476/csvpath/matching/functions/boolean/exists.py +0 -31
  119. csvpath-0.0.476/csvpath/matching/functions/boolean/yes.py +0 -17
  120. csvpath-0.0.476/csvpath/matching/functions/dates/datef.py +0 -25
  121. csvpath-0.0.476/csvpath/matching/functions/dates/now.py +0 -27
  122. csvpath-0.0.476/csvpath/matching/functions/math/above.py +0 -64
  123. csvpath-0.0.476/csvpath/matching/functions/misc/intf.py +0 -20
  124. csvpath-0.0.476/csvpath/matching/functions/misc/nonef.py +0 -17
  125. csvpath-0.0.476/csvpath/matching/functions/misc/random.py +0 -28
  126. csvpath-0.0.476/csvpath/matching/functions/print/printf.py +0 -45
  127. csvpath-0.0.476/csvpath/matching/functions/strings/concat.py +0 -22
  128. csvpath-0.0.476/csvpath/matching/functions/strings/num.py +0 -28
  129. csvpath-0.0.476/csvpath/matching/functions/strings/substring.py +0 -27
  130. csvpath-0.0.476/csvpath/matching/functions/validation.py +0 -293
  131. csvpath-0.0.476/csvpath/matching/functions/variables/variables.py +0 -17
  132. csvpath-0.0.476/docs/functions/in.md +0 -25
  133. csvpath-0.0.476/docs/functions/replace.md +0 -23
  134. {csvpath-0.0.476 → csvpath-0.0.478}/LICENSE +0 -0
  135. {csvpath-0.0.476 → csvpath-0.0.478}/config/config.ini +0 -0
  136. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/__init__.py +0 -0
  137. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/managers/__init__.py +0 -0
  138. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/__init__.py +0 -0
  139. {csvpath-0.0.476/csvpath/scanning → csvpath-0.0.478/csvpath/matching/functions}/__init__.py +0 -0
  140. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/boolean/empty.py +0 -0
  141. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/function_finder.py +0 -0
  142. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/functions/function_focus.py +0 -0
  143. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/lark_parser.py +0 -0
  144. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/lark_transformer.py +0 -0
  145. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/productions/__init__.py +0 -0
  146. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/productions/term.py +0 -0
  147. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/productions/variable.py +0 -0
  148. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/util/exceptions.py +0 -0
  149. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/util/expression_encoder.py +0 -0
  150. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/matching/util/lark_print_parser.py +0 -0
  151. {csvpath-0.0.476/csvpath/matching/functions → csvpath-0.0.478/csvpath/scanning}/__init__.py +0 -0
  152. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/scanning/exceptions.py +0 -0
  153. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/scanning/parser.out +0 -0
  154. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/scanning/parsetab.py +0 -0
  155. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/scanning/scanner.py +0 -0
  156. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/scanning/scanning_lexer.py +0 -0
  157. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/util/cache.py +0 -0
  158. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/util/config.py +0 -0
  159. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/util/config_exception.py +0 -0
  160. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/util/error.py +0 -0
  161. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/util/exceptions.py +0 -0
  162. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/util/last_line_stats.py +0 -0
  163. {csvpath-0.0.476 → csvpath-0.0.478}/csvpath/util/line_counter.py +0 -0
  164. {csvpath-0.0.476 → csvpath-0.0.478}/docs/asbool.md +0 -0
  165. {csvpath-0.0.476 → csvpath-0.0.478}/docs/assignment.md +0 -0
  166. {csvpath-0.0.476 → csvpath-0.0.478}/docs/config.md +0 -0
  167. {csvpath-0.0.476 → csvpath-0.0.478}/docs/examples.md +0 -0
  168. {csvpath-0.0.476 → csvpath-0.0.478}/docs/files.md +0 -0
  169. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/above.md +0 -0
  170. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/advance.md +0 -0
  171. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/after_blank.md +0 -0
  172. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/all.md +0 -0
  173. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/andor.md +0 -0
  174. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/any.md +0 -0
  175. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/average.md +0 -0
  176. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/collect.md +0 -0
  177. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/correlate.md +0 -0
  178. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/count.md +0 -0
  179. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/count_headers.md +0 -0
  180. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/counter.md +0 -0
  181. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/date.md +0 -0
  182. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/empty.md +0 -0
  183. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/empty_stack.md +0 -0
  184. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/end.md +0 -0
  185. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/every.md +0 -0
  186. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/fail.md +0 -0
  187. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/first.md +0 -0
  188. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/get.md +0 -0
  189. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/has_dups.md +0 -0
  190. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/has_matches.md +0 -0
  191. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/header.md +0 -0
  192. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/header_name.md +0 -0
  193. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/header_names_mismatch.md +0 -0
  194. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/implementing_functions.md +0 -0
  195. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/import.md +0 -0
  196. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/increment.md +0 -0
  197. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/jinja.md +0 -0
  198. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/last.md +0 -0
  199. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/line_number.md +0 -0
  200. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/max.md +0 -0
  201. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/metaphone.md +0 -0
  202. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/mismatch.md +0 -0
  203. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/no.md +0 -0
  204. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/not.md +0 -0
  205. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/now.md +0 -0
  206. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/percent_unique.md +0 -0
  207. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/pop.md +0 -0
  208. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/print_line.md +0 -0
  209. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/print_queue.md +0 -0
  210. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/reset_headers.md +0 -0
  211. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/stdev.md +0 -0
  212. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/stop.md +0 -0
  213. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/subtract.md +0 -0
  214. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/sum.md +0 -0
  215. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/tally.md +0 -0
  216. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/total_lines.md +0 -0
  217. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/track.md +0 -0
  218. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/variables.md +0 -0
  219. {csvpath-0.0.476 → csvpath-0.0.478}/docs/functions/variables_and_headers.md +0 -0
  220. {csvpath-0.0.476 → csvpath-0.0.478}/docs/grammar.md +0 -0
  221. {csvpath-0.0.476 → csvpath-0.0.478}/docs/headers.md +0 -0
  222. {csvpath-0.0.476 → csvpath-0.0.478}/docs/images/logo-wordmark-white-on-black-trimmed-padded.png +0 -0
  223. {csvpath-0.0.476 → csvpath-0.0.478}/docs/images/logo-wordmark-white-trimmed.png +0 -0
  224. {csvpath-0.0.476 → csvpath-0.0.478}/docs/paths.md +0 -0
  225. {csvpath-0.0.476 → csvpath-0.0.478}/docs/references.md +0 -0
  226. {csvpath-0.0.476 → csvpath-0.0.478}/docs/variables.md +0 -0
@@ -1,15 +1,18 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: csvpath
3
- Version: 0.0.476
3
+ Version: 0.0.478
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
7
- Requires-Python: >=3.12,<4.0
7
+ Requires-Python: >=3.9,<4.0
8
8
  Classifier: Development Status :: 3 - Alpha
9
9
  Classifier: Environment :: Console
10
10
  Classifier: Intended Audience :: Developers
11
11
  Classifier: Programming Language :: Python
12
12
  Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
13
16
  Classifier: Programming Language :: Python :: 3.12
14
17
  Classifier: Topic :: File Formats
15
18
  Classifier: Topic :: Office/Business :: Financial :: Spreadsheet
@@ -177,12 +180,11 @@ This is a very basic programmatic use of CsvPath.
177
180
  ```python
178
181
  path = CsvPath()
179
182
  path.parse("""
180
- $test.csv[5-25]
181
- [
182
- #0=="Frog"
183
- @lastname.onmatch="Bats"
184
- count()==2
185
- ]
183
+ $test.csv[5-25][
184
+ #firstname == "Frog"
185
+ @lastname.onmatch = "Bat"
186
+ count() == 2
187
+ ]
186
188
  """)
187
189
 
188
190
  for i, line in enumerate( path.next() ):
@@ -193,17 +195,16 @@ This is a very basic programmatic use of CsvPath.
193
195
  The csvpath says:
194
196
  - Open test.csv
195
197
  - Scan lines 5 through 25
196
- - Match the second time we see a line where the first header equals `Frog` and set the variable called `lastname` to "Bats"
198
+ - Match the second time we see a line where the first header equals `Frog` and set the variable called `lastname` to "Bat"
197
199
 
198
200
  Another path that does the same thing a bit more simply might look like:
199
201
 
200
202
  ```bash
201
- $test[5-25]
202
- [
203
- #0=="Frog"
204
- @lastname.onmatch="Bats"
205
- count()==2 -> print( "$.csvpath.match_count: $.csvpath.line")
206
- ]
203
+ $test[5-25][
204
+ #firstname == "Frog"
205
+ @lastname.onmatch = "Bat"
206
+ count()==2 -> print( "$.csvpath.match_count: $.csvpath.line")
207
+ ]
207
208
  ```
208
209
 
209
210
  In this case, we're using the "when" operator, `->`, to determine when to print.
@@ -214,12 +215,14 @@ There are a small number of configuration options. Read <a href='https://github.
214
215
 
215
216
  ## The print function
216
217
 
217
- Before we get into the details of the scanning and matching parts of paths, including all the functions, let's look at print. The `print` function has several important uses, including:
218
+ Before we get into the details of scanning and matching, let's look at what CsvPath can print. The `print` function has several important uses, including:
218
219
 
219
- - Debugging csvpaths
220
220
  - Validating CSV files
221
+ - Debugging csvpaths
221
222
  - Creating new CSV files based on an existing file
222
223
 
224
+ You can <a href='https://github.com/dk107dk/csvpath/blob/main/docs/printing.md'>read more about the mechanics of printing here</a>.
225
+
223
226
  <a name="validating"></a>
224
227
  ### Validating CSV
225
228
 
@@ -250,7 +253,12 @@ This csvpath reorders the headers of the test file at `tests/test_resources/test
250
253
  # Comments
251
254
  CsvPaths have file scanning instructions, match components, and comments. Comments exist at the top level, outside the CsvPath's brackets, as well as in the matching part of the path. Comments within the match part are covered below.
252
255
 
253
- Comments outside the csvpath can contribute to a collection of metadata fields associated with a csvpath. A comment starts and ends with a `~` character. Within the comment, any word that has a colon after it is considered a metadata key. The metadata value is anything following the key up till a new metadata key word is seen or the comment ends.
256
+ As well as documentation, comments outside the csvpath can:
257
+ - Contribute to a collection of metadata fields associated with a csvpath
258
+ - Switch on/off certain validation settings
259
+ - Set the identity of a csvpath within a group of csvpaths
260
+
261
+ A comment starts and ends with a `~` character. Within the comment, any word that has a colon after it is considered a metadata key. The metadata value is anything following the key up till a new metadata key word is seen or the comment ends.
254
262
 
255
263
  For example, this comment says that the csvpath has the name `Order Validation`:
256
264
 
@@ -263,6 +271,7 @@ For example, this comment says that the csvpath has the name `Order Validation`:
263
271
 
264
272
  The name `Order Validation` is available in CsvPath's `metadata` property along with the developer's name. You can use any metadata keys you like. All the metadata is available during and after a run, giving you an easy way to name, describe, attribute, etc. your csvpaths.
265
273
 
274
+ You can <a href='https://github.com/dk107dk/csvpath/blob/main/docs/comments.md'>read more about comments and metadata here</a>.
266
275
 
267
276
  <a name="scanning"></a>
268
277
  # Scanning
@@ -427,23 +436,14 @@ Because of this nuanced approach to errors, the library will tend to raise data
427
436
  <a name="examples"></a>
428
437
  ## More Examples
429
438
 
430
- ```bash
431
- [ exists(#common_name) #0=="field" @tail.onmatch=end() not(in(@tail, 'short|medium')) ]
432
- ```
433
-
434
- In the path above, the rules applied are:
435
- - The exists test of `#common_name` checks if the column with the header "common_name" has a value. Headers are named for whatever values are found in the 0th row. They indicate a column in the row being checked for match.
436
- - `#2` means the 3rd column, counting from 0
437
- - Functions and column references are ANDed together
438
- - `@tail` creates a variable named "tail" and sets it to the value of the last column if all else matches
439
- - Functions can contain functions, equality tests, and/or terms.
440
-
441
439
  There are more examples scattered throughout the documentation. Good places to look include:
442
440
 
441
+ - Here are a few <a href='https://github.com/dk107dk/csvpath/blob/main/docs/examples.md'>more real-looking examples</a>
442
+ - Try the Getting Started examples on <a href="https://www.csvpath.org">https://www.csvpath.org</a>
443
443
  - The individual <a href='https://github.com/dk107dk/csvpath/blob/main/docs/functions.md'>function descriptions</a>
444
- - The <a href='https://github.com/dk107dk/csvpath/tree/main/tests'>unit tests</a> _(not realistic, but a good source of ideas)_
445
- - A few <a href='https://github.com/dk107dk/csvpath/blob/main/docs/examples.md'>more real-looking examples</a>
446
- - The Getting Started examples on <a href="https://www.csvpath.org">https://www.csvpath.org</a>
444
+ - The <a href='https://github.com/dk107dk/csvpath/tree/main/tests'>unit tests</a> and <a href='https://github.com/dk107dk/csvpath/tree/main/tests/grammar/match'>their match parts</a> are not realistic, but a good source of ideas.
445
+
446
+ To create example CsvPaths from your own data, try <a href='https://autogen.csvpath.org'>CsvPath AutoGen</a>. The huge caveat is that AutoGen uses AI so your results will not be perfect. You will need to adjust, polish, and test them.
447
447
 
448
448
  <a name="grammar"></a>
449
449
  ## Grammar
@@ -457,9 +457,11 @@ Visit <a href="https://www.csvpath.org">https://www.csvpath.org</a>
457
457
 
458
458
  # Sponsors
459
459
 
460
- <a href='https://www.atestaanalytics.com/' ><img width="25%" src="https://raw.githubusercontent.com/dk107dk/csvpath/main/docs/images/logo-wordmark-white-on-black-trimmed-padded.png" alt="Atesta Analytics"/></a>
461
-
462
-
460
+ <a href='https://www.atestaanalytics.com/' >
461
+ <img width="25%" src="https://raw.githubusercontent.com/dk107dk/csvpath/main/docs/images/logo-wordmark-white-on-black-trimmed-padded.png" alt="Atesta Analytics"/></a>
462
+ <a href='https://www.datakitchen.io/'>
463
+ <img src="https://datakitchen.io/wp-content/uploads/2020/10/logo.svg"
464
+ style='width:160px; position:relative;bottom:-5px;left:15px' alt="DataKitchen" id="logo" data-height-percentage="45"></a>
463
465
 
464
466
 
465
467
 
@@ -146,12 +146,11 @@ This is a very basic programmatic use of CsvPath.
146
146
  ```python
147
147
  path = CsvPath()
148
148
  path.parse("""
149
- $test.csv[5-25]
150
- [
151
- #0=="Frog"
152
- @lastname.onmatch="Bats"
153
- count()==2
154
- ]
149
+ $test.csv[5-25][
150
+ #firstname == "Frog"
151
+ @lastname.onmatch = "Bat"
152
+ count() == 2
153
+ ]
155
154
  """)
156
155
 
157
156
  for i, line in enumerate( path.next() ):
@@ -162,17 +161,16 @@ This is a very basic programmatic use of CsvPath.
162
161
  The csvpath says:
163
162
  - Open test.csv
164
163
  - Scan lines 5 through 25
165
- - Match the second time we see a line where the first header equals `Frog` and set the variable called `lastname` to "Bats"
164
+ - Match the second time we see a line where the first header equals `Frog` and set the variable called `lastname` to "Bat"
166
165
 
167
166
  Another path that does the same thing a bit more simply might look like:
168
167
 
169
168
  ```bash
170
- $test[5-25]
171
- [
172
- #0=="Frog"
173
- @lastname.onmatch="Bats"
174
- count()==2 -> print( "$.csvpath.match_count: $.csvpath.line")
175
- ]
169
+ $test[5-25][
170
+ #firstname == "Frog"
171
+ @lastname.onmatch = "Bat"
172
+ count()==2 -> print( "$.csvpath.match_count: $.csvpath.line")
173
+ ]
176
174
  ```
177
175
 
178
176
  In this case, we're using the "when" operator, `->`, to determine when to print.
@@ -183,12 +181,14 @@ There are a small number of configuration options. Read <a href='https://github.
183
181
 
184
182
  ## The print function
185
183
 
186
- Before we get into the details of the scanning and matching parts of paths, including all the functions, let's look at print. The `print` function has several important uses, including:
184
+ Before we get into the details of scanning and matching, let's look at what CsvPath can print. The `print` function has several important uses, including:
187
185
 
188
- - Debugging csvpaths
189
186
  - Validating CSV files
187
+ - Debugging csvpaths
190
188
  - Creating new CSV files based on an existing file
191
189
 
190
+ You can <a href='https://github.com/dk107dk/csvpath/blob/main/docs/printing.md'>read more about the mechanics of printing here</a>.
191
+
192
192
  <a name="validating"></a>
193
193
  ### Validating CSV
194
194
 
@@ -219,7 +219,12 @@ This csvpath reorders the headers of the test file at `tests/test_resources/test
219
219
  # Comments
220
220
  CsvPaths have file scanning instructions, match components, and comments. Comments exist at the top level, outside the CsvPath's brackets, as well as in the matching part of the path. Comments within the match part are covered below.
221
221
 
222
- Comments outside the csvpath can contribute to a collection of metadata fields associated with a csvpath. A comment starts and ends with a `~` character. Within the comment, any word that has a colon after it is considered a metadata key. The metadata value is anything following the key up till a new metadata key word is seen or the comment ends.
222
+ As well as documentation, comments outside the csvpath can:
223
+ - Contribute to a collection of metadata fields associated with a csvpath
224
+ - Switch on/off certain validation settings
225
+ - Set the identity of a csvpath within a group of csvpaths
226
+
227
+ A comment starts and ends with a `~` character. Within the comment, any word that has a colon after it is considered a metadata key. The metadata value is anything following the key up till a new metadata key word is seen or the comment ends.
223
228
 
224
229
  For example, this comment says that the csvpath has the name `Order Validation`:
225
230
 
@@ -232,6 +237,7 @@ For example, this comment says that the csvpath has the name `Order Validation`:
232
237
 
233
238
  The name `Order Validation` is available in CsvPath's `metadata` property along with the developer's name. You can use any metadata keys you like. All the metadata is available during and after a run, giving you an easy way to name, describe, attribute, etc. your csvpaths.
234
239
 
240
+ You can <a href='https://github.com/dk107dk/csvpath/blob/main/docs/comments.md'>read more about comments and metadata here</a>.
235
241
 
236
242
  <a name="scanning"></a>
237
243
  # Scanning
@@ -396,23 +402,14 @@ Because of this nuanced approach to errors, the library will tend to raise data
396
402
  <a name="examples"></a>
397
403
  ## More Examples
398
404
 
399
- ```bash
400
- [ exists(#common_name) #0=="field" @tail.onmatch=end() not(in(@tail, 'short|medium')) ]
401
- ```
402
-
403
- In the path above, the rules applied are:
404
- - The exists test of `#common_name` checks if the column with the header "common_name" has a value. Headers are named for whatever values are found in the 0th row. They indicate a column in the row being checked for match.
405
- - `#2` means the 3rd column, counting from 0
406
- - Functions and column references are ANDed together
407
- - `@tail` creates a variable named "tail" and sets it to the value of the last column if all else matches
408
- - Functions can contain functions, equality tests, and/or terms.
409
-
410
405
  There are more examples scattered throughout the documentation. Good places to look include:
411
406
 
407
+ - Here are a few <a href='https://github.com/dk107dk/csvpath/blob/main/docs/examples.md'>more real-looking examples</a>
408
+ - Try the Getting Started examples on <a href="https://www.csvpath.org">https://www.csvpath.org</a>
412
409
  - The individual <a href='https://github.com/dk107dk/csvpath/blob/main/docs/functions.md'>function descriptions</a>
413
- - The <a href='https://github.com/dk107dk/csvpath/tree/main/tests'>unit tests</a> _(not realistic, but a good source of ideas)_
414
- - A few <a href='https://github.com/dk107dk/csvpath/blob/main/docs/examples.md'>more real-looking examples</a>
415
- - The Getting Started examples on <a href="https://www.csvpath.org">https://www.csvpath.org</a>
410
+ - The <a href='https://github.com/dk107dk/csvpath/tree/main/tests'>unit tests</a> and <a href='https://github.com/dk107dk/csvpath/tree/main/tests/grammar/match'>their match parts</a> are not realistic, but a good source of ideas.
411
+
412
+ To create example CsvPaths from your own data, try <a href='https://autogen.csvpath.org'>CsvPath AutoGen</a>. The huge caveat is that AutoGen uses AI so your results will not be perfect. You will need to adjust, polish, and test them.
416
413
 
417
414
  <a name="grammar"></a>
418
415
  ## Grammar
@@ -426,9 +423,11 @@ Visit <a href="https://www.csvpath.org">https://www.csvpath.org</a>
426
423
 
427
424
  # Sponsors
428
425
 
429
- <a href='https://www.atestaanalytics.com/' ><img width="25%" src="https://raw.githubusercontent.com/dk107dk/csvpath/main/docs/images/logo-wordmark-white-on-black-trimmed-padded.png" alt="Atesta Analytics"/></a>
430
-
431
-
426
+ <a href='https://www.atestaanalytics.com/' >
427
+ <img width="25%" src="https://raw.githubusercontent.com/dk107dk/csvpath/main/docs/images/logo-wordmark-white-on-black-trimmed-padded.png" alt="Atesta Analytics"/></a>
428
+ <a href='https://www.datakitchen.io/'>
429
+ <img src="https://datakitchen.io/wp-content/uploads/2020/10/logo.svg"
430
+ style='width:160px; position:relative;bottom:-5px;left:15px' alt="DataKitchen" id="logo" data-height-percentage="45"></a>
432
431
 
433
432
 
434
433
 
@@ -25,6 +25,7 @@ from .util.exceptions import (
25
25
  CsvPathsException,
26
26
  )
27
27
  from .matching.util.exceptions import MatchException
28
+ from csvpath.util.printer import Printer
28
29
 
29
30
 
30
31
  class CsvPathPublic(ABC):
@@ -70,7 +71,7 @@ class CsvPathPublic(ABC):
70
71
  matching rows"""
71
72
 
72
73
 
73
- class CsvPath(CsvPathPublic, ErrorCollector): # pylint: disable=R0902, R0904
74
+ class CsvPath(CsvPathPublic, ErrorCollector, Printer): # pylint: disable=R0902, R0904
74
75
  """CsvPath represents a csvpath string that contains a reference to
75
76
  a file, scanning instructions, and rules for matching lines.
76
77
  """
@@ -121,7 +122,7 @@ class CsvPath(CsvPathPublic, ErrorCollector): # pylint: disable=R0902, R0904
121
122
  # the middle of iterating a file using next(). probably not a
122
123
  # good idea, tho.
123
124
  #
124
- self._AND = True
125
+ self._AND = True # pylint: disable=C0103
125
126
  #
126
127
  # when True the lines that do not match are returned from next()
127
128
  # and collect(). this effectively switches CsvPath from being an
@@ -239,6 +240,14 @@ class CsvPath(CsvPathPublic, ErrorCollector): # pylint: disable=R0902, R0904
239
240
  # way.
240
241
  self._config = config
241
242
  #
243
+ # these settings determine how we report function args validation
244
+ # errors. e.g. if print(True) the validation check fails because
245
+ # print() expects a string.
246
+ #
247
+ self._log_validation_errors = False
248
+ self._print_validation_errors = True
249
+ self._raise_validation_errors = True
250
+ #
242
251
  # there are two logger components one for CsvPath and one for CsvPaths.
243
252
  # the default levels are set in config.ini. to change the levels pass LogUtility
244
253
  # your component instance and the logging level. e.g.:
@@ -276,19 +285,19 @@ class CsvPath(CsvPathPublic, ErrorCollector): # pylint: disable=R0902, R0904
276
285
  self._line_monitor = lm
277
286
 
278
287
  @property
279
- def AND(self) -> bool:
288
+ def AND(self) -> bool: # pylint: disable=C0103
280
289
  return self._AND
281
290
 
282
291
  @AND.setter
283
- def AND(self, a: bool) -> bool:
292
+ def AND(self, a: bool) -> bool: # pylint: disable=C0103
284
293
  self._AND = a
285
294
 
286
295
  @property
287
- def OR(self) -> bool:
296
+ def OR(self) -> bool: # pylint: disable=C0103
288
297
  return not self._AND
289
298
 
290
299
  @OR.setter
291
- def OR(self, a: bool) -> bool:
300
+ def OR(self, a: bool) -> bool: # pylint: disable=C0103
292
301
  self._AND = not a
293
302
 
294
303
  @property
@@ -345,18 +354,53 @@ class CsvPath(CsvPathPublic, ErrorCollector): # pylint: disable=R0902, R0904
345
354
  def error_collector(self, error_collector) -> None:
346
355
  self._error_collector = error_collector
347
356
 
348
- def collect_error(self, e: Error) -> None: # pylint: disable=C0116
357
+ def collect_error(self, error: Error) -> None: # pylint: disable=C0116
349
358
  #
350
359
  # errors must be built and handled in ErrorHandler.
351
360
  # here we're just collecting them if collect is
352
361
  # selected by our configuration
353
362
  #
354
363
  if self._error_collector is not None:
355
- self._error_collector.collect_error(e)
364
+ self._error_collector.collect_error(error)
356
365
  else:
357
366
  if self._errors is None:
358
367
  self._errors = []
359
- self._errors.append(e)
368
+ self._errors.append(error)
369
+
370
+ def report_validation_errors(self, msg: str) -> None:
371
+ if self.print_validation_errors:
372
+ self.print(msg)
373
+ elif self.log_validation_errors:
374
+ self.logger.warning(msg)
375
+ #
376
+ # the args class will do the raise if it is told to by the prop
377
+ #
378
+
379
+ def set_validation_error_handling(self, veh) -> None:
380
+ if veh and veh.find("print") > -1:
381
+ self._print_validation_errors = True
382
+ else:
383
+ self._print_validation_errors = False
384
+ if veh and veh.find("log") > -1:
385
+ self._log_validation_errors = True
386
+ else:
387
+ self._log_validation_errors = False
388
+ if veh and veh.find("raise") > -1:
389
+ self._raise_validation_errors = True
390
+ else:
391
+ self._raise_validation_errors = False
392
+
393
+ @property
394
+ def print_validation_errors(self) -> bool:
395
+ return self._print_validation_errors
396
+
397
+ @property
398
+ def log_validation_errors(self) -> bool:
399
+ return self._log_validation_errors
400
+
401
+ @property
402
+ def raise_validation_errors(self) -> bool:
403
+ return self._raise_validation_errors
360
404
 
361
405
  def add_printer(self, printer) -> None: # pylint: disable=C0116
362
406
  if printer not in self.printers:
@@ -365,12 +409,40 @@ class CsvPath(CsvPathPublic, ErrorCollector): # pylint: disable=R0902, R0904
365
409
  def set_printers(self, printers: List) -> None: # pylint: disable=C0116
366
410
  self.printers = printers
367
411
 
412
+ @property
413
+ def has_default_printer(self) -> bool:
414
+ if not self.printers:
415
+ self.printers = []
416
+ for i, p in enumerate(self.printers):
417
+ if isinstance(p, StdOutPrinter):
418
+ return True
419
+ return False
420
+
368
421
  def print(self, string: str) -> None: # pylint: disable=C0116
369
422
  for p in self.printers:
370
423
  p.print(string)
371
424
 
425
+ def print_to(self, name: str, string: str) -> None:
426
+ for p in self.printers:
427
+ p.print_to(name, string)
428
+
429
+ @property
430
+ def last_line(self):
431
+ if not self.printers or len(self.printers) == 0:
432
+ return None
433
+ return self.printers[0].last_line
434
+
435
+ @property
436
+ def lines_printed(self) -> int:
437
+ if not self.printers or len(self.printers) == 0:
438
+ return -1
439
+ self.printers[0].lines_printed
440
+
372
441
  @property
373
442
  def is_frozen(self) -> bool:
443
+ """True if the instance is matching on its last row only to
444
+ allow last()s to run; in which case, no variable updates
445
+ are allowed, along with other limitations."""
374
446
  return self._freeze_path
375
447
 
376
448
  @is_frozen.setter
@@ -404,6 +476,7 @@ class CsvPath(CsvPathPublic, ErrorCollector): # pylint: disable=R0902, R0904
404
476
  # the comments so we won't find them again
405
477
  #
406
478
  csvpath = MetadataParser(self).extract_metadata(instance=self, csvpath=csvpath)
479
+ self.update_settings_from_metadata()
407
480
  #
408
481
  #
409
482
  #
@@ -425,10 +498,10 @@ class CsvPath(CsvPathPublic, ErrorCollector): # pylint: disable=R0902, R0904
425
498
  # atm, tho, just create a dry-run copy. in some possible
426
499
  # unit tests we may not have a parsable match part.
427
500
  #
428
- matcher = None
429
- if mat:
430
- matcher = Matcher(csvpath=self, data=mat, line=None, headers=None)
431
501
  if disposably:
502
+ matcher = None
503
+ if mat:
504
+ matcher = Matcher(csvpath=self, data=mat, line=None, headers=None)
432
505
  #
433
506
  # if the matcher was requested for some reason beyond our own needs
434
507
  # we just return it and forget it existed.
@@ -437,7 +510,83 @@ class CsvPath(CsvPathPublic, ErrorCollector): # pylint: disable=R0902, R0904
437
510
  if self.scanner.filename is None:
438
511
  raise FileException("Cannot proceed without a filename")
439
512
  self.get_total_lines_and_headers()
440
- return self.scanner
513
+ return self
514
+
515
+ def update_settings_from_metadata(self) -> None:
516
+ #
517
+ # settings:
518
+ # - logic-mode: AND | OR
519
+ # - match-mode: matches | no-matches
520
+ # - print-mode: default-off | default-on
521
+ # - arg-validation-mode: print | log | raise | quiet
522
+ #
523
+ self.update_logic_mode_if()
524
+ self.update_match_mode_if()
525
+ self.update_print_mode_if()
526
+ self.update_arg_validation_mode_if()
527
+
528
+ def update_arg_validation_mode_if(self) -> None:
529
+ if self.metadata and "arg-validation-mode" in self.metadata:
530
+ # sets arg validation reporting. one or more or none of:
531
+ # - print
532
+ # - log
533
+ # - raise
534
+ #
535
+ validation_mode = f"{self.metadata['arg-validation-mode']}".strip()
536
+ if validation_mode:
537
+ self.set_validation_error_handling(validation_mode)
538
+ self.logger.info(
539
+ "Setting 'arg-validation-mode': %s",
540
+ self.metadata["arg-validation-mode"],
541
+ )
542
+
543
+ def update_logic_mode_if(self) -> None:
544
+ if self.metadata and "logic-mode" in self.metadata:
545
+ if f"{self.metadata['logic-mode']}".strip() == "AND":
546
+ self.AND = True
547
+ elif f"{self.metadata['logic-mode']}".strip() == "OR":
548
+ self.AND = False
549
+ else:
550
+ self.logger.warning(
551
+ "Incorrect metadata field value 'logic-mode': %s",
552
+ self.metadata["logic-mode"],
553
+ )
554
+
555
+ def update_match_mode_if(self) -> None:
556
+ if "match-mode" in self.metadata:
557
+ if f"{self.metadata['match-mode']}".strip() == "matches":
558
+ self.collect_when_not_matched = False
559
+ elif f"{self.metadata['match-mode']}".strip() == "no-matches":
560
+ self.collect_when_not_matched = True
561
+ else:
562
+ self.logger.warning(
563
+ "Incorrect metadata field value 'match-mode': %s",
564
+ self.metadata["match-mode"],
565
+ )
566
+
567
+ def update_print_mode_if(self) -> None:
568
+ if "print-mode" in self.metadata:
569
+ if f"{self.metadata['print-mode']}".strip() == "default-off":
570
+ remove = -1
571
+ for i, p in enumerate(self.printers):
572
+ if isinstance(p, StdOutPrinter):
573
+ remove = i
574
+ break
575
+ if remove >= 0:
576
+ del self.printers[remove]
577
+ elif f"{self.metadata['print-mode']}".strip() == "default-on":
578
+ done = False
579
+ for i, p in enumerate(self.printers):
580
+ if isinstance(p, StdOutPrinter):
581
+ done = True
582
+ break
583
+ if not done:
584
+ self.printers.append(StdOutPrinter())
585
+ else:
586
+ self.logger.warning(
587
+ "Incorrect metadata field value 'print-mode': %s",
588
+ self.metadata["print-mode"],
589
+ )
441
590
 
442
591
  def parse_named_path(self, name, disposably=False):
443
592
  """disposably is True when a Matcher is needed for some purpose other than
@@ -653,7 +802,7 @@ class CsvPath(CsvPathPublic, ErrorCollector): # pylint: disable=R0902, R0904
653
802
  msg = "Line cannot be None"
654
803
  self.logger.error(msg)
655
804
  raise MatchException(msg)
656
- elif len(line) == 0:
805
+ if len(line) == 0:
657
806
  msg = "Line cannot be len() == 0"
658
807
  self.logger.error(msg)
659
808
  raise MatchException(msg)
@@ -684,6 +833,9 @@ class CsvPath(CsvPathPublic, ErrorCollector): # pylint: disable=R0902, R0904
684
833
  # this exception will blow up a standalone CsvPath but should be
685
834
  # caught and handled if there is a CsvPaths.
686
835
  #
836
+ # but when would it happen? shouldn't we just let Python's exception
837
+ # handle it should it really occur?
838
+ #
687
839
  if self.scanner.filename is None:
688
840
  raise FileException("There is no filename")
689
841
  with open(self.scanner.filename, "r", encoding="utf-8") as file:
@@ -695,6 +847,35 @@ class CsvPath(CsvPathPublic, ErrorCollector): # pylint: disable=R0902, R0904
695
847
  yield line
696
848
  self.finalize()
697
849
 
850
+ """
851
+ # potential replacement for method above
852
+ # this is a proposal for having the results of one csvpath feed into another
853
+ # in memory. the goal being to both shape the data chain-of-responsibility-style
854
+ # and also to narrow the data for performance gains.
855
+ #
856
+ # we would need:
857
+ # - csvpaths.chain_result_data
858
+ # - named-path added to csvpath metadata early-on
859
+ #
860
+ # caching this here for now. jury is out on if it should be added.
861
+ #
862
+ def _next_line_new(self) -> List[Any]:
863
+ self.logger.info("beginning to scan file: %s", self.scanner.filename)
864
+ if self.csvpath and self.csvpaths.chain_result_data:
865
+ rs = csvpath.result_manager.get_named_results(self.metadata["named-paths"])
866
+ for line in rs[len(rs)-1].lines:
867
+ yield line
868
+ elif:
869
+ with open(self.scanner.filename, "r", encoding="utf-8") as file:
870
+ reader = csv.reader(
871
+ file, delimiter=self.delimiter, quotechar=self.quotechar
872
+ )
873
+ for line in reader:
874
+ self.track_line(line=line)
875
+ yield line
876
+ self.finalize()
877
+ """
878
+
698
879
  def finalize(self) -> None:
699
880
  """clears caches, etc. this is an internal method, but not _ because
700
881
  it is part of the lifecycle and we might find a reason to call it
@@ -788,6 +969,8 @@ class CsvPath(CsvPathPublic, ErrorCollector): # pylint: disable=R0902, R0904
788
969
  return False
789
970
 
790
971
  def raise_match_count_if(self):
972
+ """if the match count has already been raised earlier in the matching
973
+ process than the caller we don't raise it; otherwise, we raise."""
791
974
  if self._current_match_count == self.match_count:
792
975
  self.match_count += 1
793
976
  else:
@@ -880,7 +1063,7 @@ class CsvPath(CsvPathPublic, ErrorCollector): # pylint: disable=R0902, R0904
880
1063
  self.matcher = Matcher(
881
1064
  csvpath=self, data=self.match, line=line, headers=self.headers, myid=h
882
1065
  )
883
- self.matcher._AND = self._AND
1066
+ self.matcher.AND = self._AND
884
1067
  else:
885
1068
  self.logger.debug("Resetting and reloading matcher")
886
1069
  self.matcher.reset()