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.
Files changed (222) hide show
  1. {csvpath-0.0.485 → csvpath-0.0.486}/PKG-INFO +2 -1
  2. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/args.py +3 -10
  3. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/function.py +9 -1
  4. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/lines/dups.py +9 -5
  5. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/types/boolean.py +9 -12
  6. csvpath-0.0.486/csvpath/matching/functions/types/datef.py +130 -0
  7. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/types/decimal.py +39 -34
  8. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/types/nonef.py +24 -1
  9. csvpath-0.0.486/csvpath/matching/functions/types/string.py +65 -0
  10. csvpath-0.0.486/csvpath/matching/functions/types/type.py +14 -0
  11. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/validity/line.py +50 -23
  12. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/matcher.py +24 -20
  13. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/matchable.py +5 -2
  14. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/qualified.py +11 -0
  15. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/util/expression_utility.py +37 -2
  16. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/scanning/scanning_lexer.py +1 -1
  17. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/file_readers.py +16 -0
  18. {csvpath-0.0.485 → csvpath-0.0.486}/pyproject.toml +2 -1
  19. csvpath-0.0.485/csvpath/matching/functions/types/datef.py +0 -130
  20. csvpath-0.0.485/csvpath/matching/functions/types/string.py +0 -45
  21. {csvpath-0.0.485 → csvpath-0.0.486}/LICENSE +0 -0
  22. {csvpath-0.0.485 → csvpath-0.0.486}/README.md +0 -0
  23. {csvpath-0.0.485 → csvpath-0.0.486}/config/config.ini +0 -0
  24. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/__init__.py +0 -0
  25. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/csvpath.py +0 -0
  26. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/csvpaths.py +0 -0
  27. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/managers/__init__.py +0 -0
  28. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/managers/csvpaths_manager.py +0 -0
  29. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/managers/file_manager.py +0 -0
  30. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/managers/result.py +0 -0
  31. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/managers/results_manager.py +0 -0
  32. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/__init__.py +0 -0
  33. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/__init__.py +0 -0
  34. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/all.py +0 -0
  35. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/andf.py +0 -0
  36. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/any.py +0 -0
  37. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/between.py +0 -0
  38. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/empty.py +0 -0
  39. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/exists.py +0 -0
  40. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/inf.py +0 -0
  41. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/no.py +0 -0
  42. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/notf.py +0 -0
  43. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/orf.py +0 -0
  44. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/boolean/yes.py +0 -0
  45. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/count.py +0 -0
  46. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/count_headers.py +0 -0
  47. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/count_lines.py +0 -0
  48. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/count_scans.py +0 -0
  49. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/counter.py +0 -0
  50. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/every.py +0 -0
  51. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/has_matches.py +0 -0
  52. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/increment.py +0 -0
  53. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/tally.py +0 -0
  54. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/counting/total_lines.py +0 -0
  55. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/dates/now.py +0 -0
  56. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/function_factory.py +0 -0
  57. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/function_finder.py +0 -0
  58. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/function_focus.py +0 -0
  59. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/append.py +0 -0
  60. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/collect.py +0 -0
  61. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/empty_stack.py +0 -0
  62. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/end.py +0 -0
  63. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/header_name.py +0 -0
  64. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/header_names_mismatch.py +0 -0
  65. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/headers.py +0 -0
  66. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/mismatch.py +0 -0
  67. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/replace.py +0 -0
  68. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/headers/reset_headers.py +0 -0
  69. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/lines/advance.py +0 -0
  70. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/lines/after_blank.py +0 -0
  71. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/lines/first.py +0 -0
  72. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/lines/first_line.py +0 -0
  73. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/lines/last.py +0 -0
  74. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/lines/stop.py +0 -0
  75. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/above.py +0 -0
  76. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/add.py +0 -0
  77. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/divide.py +0 -0
  78. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/equals.py +0 -0
  79. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/intf.py +0 -0
  80. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/mod.py +0 -0
  81. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/multiply.py +0 -0
  82. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/round.py +0 -0
  83. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/subtotal.py +0 -0
  84. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/subtract.py +0 -0
  85. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/math/sum.py +0 -0
  86. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/misc/importf.py +0 -0
  87. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/misc/random.py +0 -0
  88. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/print/jinjaf.py +0 -0
  89. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/print/print_line.py +0 -0
  90. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/print/print_queue.py +0 -0
  91. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/print/printf.py +0 -0
  92. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/print/table.py +0 -0
  93. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/stats/minf.py +0 -0
  94. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/stats/percent.py +0 -0
  95. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/stats/percent_unique.py +0 -0
  96. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/stats/stdev.py +0 -0
  97. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/concat.py +0 -0
  98. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/length.py +0 -0
  99. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/lower.py +0 -0
  100. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/metaphone.py +0 -0
  101. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/regex.py +0 -0
  102. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/starts_with.py +0 -0
  103. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/strip.py +0 -0
  104. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/substring.py +0 -0
  105. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/strings/upper.py +0 -0
  106. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/testing/debug.py +0 -0
  107. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/types/__init__.py +0 -0
  108. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/validity/fail.py +0 -0
  109. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/validity/failed.py +0 -0
  110. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/variables/get.py +0 -0
  111. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/variables/pushpop.py +0 -0
  112. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/variables/put.py +0 -0
  113. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/variables/track.py +0 -0
  114. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/functions/variables/variables.py +0 -0
  115. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/lark_parser.py +0 -0
  116. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/lark_transformer.py +0 -0
  117. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/__init__.py +0 -0
  118. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/equality.py +0 -0
  119. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/expression.py +0 -0
  120. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/header.py +0 -0
  121. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/reference.py +0 -0
  122. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/term.py +0 -0
  123. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/productions/variable.py +0 -0
  124. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/util/exceptions.py +0 -0
  125. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/util/expression_encoder.py +0 -0
  126. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/util/lark_print_parser.py +0 -0
  127. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/matching/util/print_parser.py +0 -0
  128. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/scanning/__init__.py +0 -0
  129. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/scanning/exceptions.py +0 -0
  130. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/scanning/parser.out +0 -0
  131. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/scanning/parsetab.py +0 -0
  132. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/scanning/scanner.py +0 -0
  133. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/cache.py +0 -0
  134. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/config.py +0 -0
  135. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/config_exception.py +0 -0
  136. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/error.py +0 -0
  137. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/exceptions.py +0 -0
  138. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/last_line_stats.py +0 -0
  139. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/line_counter.py +0 -0
  140. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/line_monitor.py +0 -0
  141. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/log_utility.py +0 -0
  142. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/metadata_parser.py +0 -0
  143. {csvpath-0.0.485 → csvpath-0.0.486}/csvpath/util/printer.py +0 -0
  144. {csvpath-0.0.485 → csvpath-0.0.486}/docs/asbool.md +0 -0
  145. {csvpath-0.0.485 → csvpath-0.0.486}/docs/assignment.md +0 -0
  146. {csvpath-0.0.485 → csvpath-0.0.486}/docs/comments.md +0 -0
  147. {csvpath-0.0.485 → csvpath-0.0.486}/docs/config.md +0 -0
  148. {csvpath-0.0.485 → csvpath-0.0.486}/docs/examples.md +0 -0
  149. {csvpath-0.0.485 → csvpath-0.0.486}/docs/files.md +0 -0
  150. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/above.md +0 -0
  151. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/advance.md +0 -0
  152. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/after_blank.md +0 -0
  153. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/all.md +0 -0
  154. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/andor.md +0 -0
  155. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/any.md +0 -0
  156. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/average.md +0 -0
  157. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/between.md +0 -0
  158. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/collect.md +0 -0
  159. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/correlate.md +0 -0
  160. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/count.md +0 -0
  161. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/count_headers.md +0 -0
  162. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/counter.md +0 -0
  163. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/date.md +0 -0
  164. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/empty.md +0 -0
  165. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/empty_stack.md +0 -0
  166. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/end.md +0 -0
  167. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/every.md +0 -0
  168. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/fail.md +0 -0
  169. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/first.md +0 -0
  170. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/get.md +0 -0
  171. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/has_dups.md +0 -0
  172. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/has_matches.md +0 -0
  173. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/header.md +0 -0
  174. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/header_name.md +0 -0
  175. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/header_names_mismatch.md +0 -0
  176. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/implementing_functions.md +0 -0
  177. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/import.md +0 -0
  178. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/in.md +0 -0
  179. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/increment.md +0 -0
  180. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/intf.md +0 -0
  181. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/jinja.md +0 -0
  182. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/last.md +0 -0
  183. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/line.md +0 -0
  184. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/line_number.md +0 -0
  185. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/max.md +0 -0
  186. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/metaphone.md +0 -0
  187. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/mismatch.md +0 -0
  188. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/no.md +0 -0
  189. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/not.md +0 -0
  190. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/now.md +0 -0
  191. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/percent_unique.md +0 -0
  192. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/pop.md +0 -0
  193. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/print.md +0 -0
  194. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/print_line.md +0 -0
  195. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/print_queue.md +0 -0
  196. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/random.md +0 -0
  197. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/regex.md +0 -0
  198. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/replace.md +0 -0
  199. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/reset_headers.md +0 -0
  200. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/stdev.md +0 -0
  201. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/stop.md +0 -0
  202. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/string_functions.md +0 -0
  203. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/subtotal.md +0 -0
  204. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/subtract.md +0 -0
  205. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/sum.md +0 -0
  206. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/tally.md +0 -0
  207. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/total_lines.md +0 -0
  208. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/track.md +0 -0
  209. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/types.md +0 -0
  210. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/variables.md +0 -0
  211. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions/variables_and_headers.md +0 -0
  212. {csvpath-0.0.485 → csvpath-0.0.486}/docs/functions.md +0 -0
  213. {csvpath-0.0.485 → csvpath-0.0.486}/docs/grammar.md +0 -0
  214. {csvpath-0.0.485 → csvpath-0.0.486}/docs/headers.md +0 -0
  215. {csvpath-0.0.485 → csvpath-0.0.486}/docs/images/logo-wordmark-white-on-black-trimmed-padded.png +0 -0
  216. {csvpath-0.0.485 → csvpath-0.0.486}/docs/images/logo-wordmark-white-trimmed.png +0 -0
  217. {csvpath-0.0.485 → csvpath-0.0.486}/docs/paths.md +0 -0
  218. {csvpath-0.0.485 → csvpath-0.0.486}/docs/printing.md +0 -0
  219. {csvpath-0.0.485 → csvpath-0.0.486}/docs/qualifiers.md +0 -0
  220. {csvpath-0.0.485 → csvpath-0.0.486}/docs/references.md +0 -0
  221. {csvpath-0.0.485 → csvpath-0.0.486}/docs/terms.md +0 -0
  222. {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.485
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}: {mismatches}"
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(cls, mc, name: str, skip=None) -> tuple[str, list[int]]:
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(mc.children) == 1:
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 = None
26
+ self.value = CheckedUnset()
27
+ # self.value = None
27
28
  if self.notnone is True:
28
- pln = self.matcher.csvpath.line_monitor.physical_line_number
29
- self.parent.raise_if(
30
- ChildrenException(f"Line {pln}: Value cannot be empty")
31
- )
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 = None
38
- pln = self.matcher.csvpath.line_monitor.physical_line_number
39
- self.parent.raise_if(
40
- ChildrenException(f"Line {pln}: Not a boolean value: '{v}'")
41
- )
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.parent.raise_if(
23
- ChildrenException(f"Incorrect argument: {s} is not allowed")
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
- val = self._value_one(skip=skip)
32
- h = None
33
- try:
34
- h = self.matcher.get_header_value(val)
35
- if h is None or f"{h}".strip() == "":
36
- self.value = None
37
- if self.notnone is True:
38
- self.match = False
39
- # pln = self.matcher.csvpath.line_monitor.physical_line_number
40
- self.parent.raise_if(ChildrenException(f"'{val}' cannot be empty"))
41
- except (TypeError, IndexError) as e:
42
- self.match = False
43
- # pln = self.matcher.csvpath.line_monitor.physical_line_number
44
- self.parent.raise_if(
45
- ChildrenException(
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
- # pln = self.matcher.csvpath.line_monitor.physical_line_number
60
- self.parent.raise_if(
61
- ChildrenException(
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(types=[Variable, Header, Function, Reference], actuals=[None, Any])
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