csvpath 0.0.523__tar.gz → 0.0.524__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 (370) hide show
  1. {csvpath-0.0.523 → csvpath-0.0.524}/PKG-INFO +3 -3
  2. {csvpath-0.0.523 → csvpath-0.0.524}/README.md +2 -2
  3. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/cli/cli.py +47 -38
  4. csvpath-0.0.524/csvpath/cli/const.py +26 -0
  5. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/cli/drill_down.py +19 -14
  6. csvpath-0.0.524/csvpath/cli/function_describer.py +190 -0
  7. csvpath-0.0.524/csvpath/cli/function_lister.py +30 -0
  8. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/cli/selecter.py +1 -0
  9. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/csvpath.py +1 -1
  10. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/csvpaths.py +5 -2
  11. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/args.py +5 -1
  12. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/args_helper.py +8 -1
  13. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/boolean/notf.py +8 -2
  14. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/counting/count.py +2 -1
  15. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/counting/counter.py +1 -0
  16. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/counting/increment.py +1 -0
  17. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/counting/tally.py +1 -0
  18. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/function.py +4 -0
  19. csvpath-0.0.524/csvpath/matching/functions/function_factory.py +373 -0
  20. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/headers/header_names_mismatch.py +1 -0
  21. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/headers/reset_headers.py +7 -1
  22. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/lines/dups.py +22 -8
  23. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/lines/first.py +1 -0
  24. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/lines/stop.py +1 -0
  25. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/math/intf.py +2 -0
  26. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/math/subtotal.py +1 -0
  27. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/math/sum.py +1 -0
  28. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/misc/fingerprint.py +1 -0
  29. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/misc/random.py +1 -10
  30. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/print/printf.py +12 -1
  31. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/stats/minf.py +6 -0
  32. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/stats/percent_unique.py +1 -0
  33. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/strings/regex.py +1 -0
  34. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/types/boolean.py +13 -2
  35. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/types/datef.py +12 -0
  36. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/types/decimal.py +13 -1
  37. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/types/email.py +11 -8
  38. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/types/nonef.py +15 -1
  39. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/types/string.py +14 -3
  40. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/types/url.py +8 -8
  41. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/validity/line.py +10 -1
  42. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/variables/pushpop.py +8 -1
  43. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/variables/track.py +1 -0
  44. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/productions/matchable.py +6 -0
  45. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/productions/qualified.py +1 -1
  46. {csvpath-0.0.523 → csvpath-0.0.524}/pyproject.toml +1 -1
  47. csvpath-0.0.523/csvpath/matching/functions/function_factory.py +0 -447
  48. {csvpath-0.0.523 → csvpath-0.0.524}/LICENSE +0 -0
  49. {csvpath-0.0.523 → csvpath-0.0.524}/config/config.ini +0 -0
  50. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/__init__.py +0 -0
  51. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/cli/__init__.py +0 -0
  52. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/cli/asker.py +0 -0
  53. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/cli/debug_config.py +0 -0
  54. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/__init__.py +0 -0
  55. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/errors/error.py +0 -0
  56. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/errors/error_collector.py +0 -0
  57. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/errors/error_comms.py +0 -0
  58. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/errors/error_manager.py +0 -0
  59. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/files/file_cacher.py +0 -0
  60. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/files/file_manager.py +0 -0
  61. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/files/file_metadata.py +0 -0
  62. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/files/file_registrar.py +0 -0
  63. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/files/files_listener.py +0 -0
  64. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/ckan/ckan.py +0 -0
  65. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/ckan/ckan_listener.py +0 -0
  66. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/ckan/datafile.py +0 -0
  67. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/ckan/dataset.py +0 -0
  68. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/ol/event.py +0 -0
  69. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/ol/event_result.py +0 -0
  70. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/ol/file_listener_ol.py +0 -0
  71. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/ol/job.py +0 -0
  72. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/ol/ol_listener.py +0 -0
  73. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/ol/paths_listener_ol.py +0 -0
  74. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/ol/result_listener_ol.py +0 -0
  75. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/ol/results_listener_ol.py +0 -0
  76. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/ol/run.py +0 -0
  77. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/ol/run_listener_ol.py +0 -0
  78. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/ol/run_state.py +0 -0
  79. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/ol/sender.py +0 -0
  80. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/otlp/error_metrics.py +0 -0
  81. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/otlp/metrics.py +0 -0
  82. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/otlp/otlp_error_listener.py +0 -0
  83. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/otlp/otlp_listener.py +0 -0
  84. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/otlp/otlp_result_listener.py +0 -0
  85. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/otlp/otlp_results_listener.py +0 -0
  86. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/sftp/sftp_sender.py +0 -0
  87. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/sftpplus/arrival_handler.py +0 -0
  88. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/sftpplus/rpc.py +0 -0
  89. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/sftpplus/sftpplus_listener.py +0 -0
  90. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/sftpplus/transfer_creator.py +0 -0
  91. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/sftpplus/transfers.py +0 -0
  92. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/slack/event.py +0 -0
  93. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/integrations/slack/sender.py +0 -0
  94. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/listener.py +0 -0
  95. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/metadata.py +0 -0
  96. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/paths/paths_listener.py +0 -0
  97. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/paths/paths_manager.py +0 -0
  98. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/paths/paths_metadata.py +0 -0
  99. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/paths/paths_registrar.py +0 -0
  100. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/registrar.py +0 -0
  101. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/results/readers/file_errors_reader.py +0 -0
  102. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/results/readers/file_lines_reader.py +0 -0
  103. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/results/readers/file_printouts_reader.py +0 -0
  104. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/results/readers/file_unmatched_reader.py +0 -0
  105. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/results/readers/readers.py +0 -0
  106. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/results/result.py +0 -0
  107. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/results/result_file_reader.py +0 -0
  108. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/results/result_metadata.py +0 -0
  109. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/results/result_registrar.py +0 -0
  110. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/results/result_serializer.py +0 -0
  111. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/results/results_manager.py +0 -0
  112. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/results/results_metadata.py +0 -0
  113. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/results/results_registrar.py +0 -0
  114. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/run/run_listener_stdout.py +0 -0
  115. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/run/run_metadata.py +0 -0
  116. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/managers/run/run_registrar.py +0 -0
  117. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/__init__.py +0 -0
  118. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/__init__.py +0 -0
  119. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/boolean/all.py +0 -0
  120. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/boolean/andf.py +0 -0
  121. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/boolean/any.py +0 -0
  122. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/boolean/between.py +0 -0
  123. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/boolean/empty.py +0 -0
  124. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/boolean/exists.py +0 -0
  125. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/boolean/inf.py +0 -0
  126. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/boolean/no.py +0 -0
  127. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/boolean/orf.py +0 -0
  128. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/boolean/yes.py +0 -0
  129. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/counting/count_bytes.py +0 -0
  130. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/counting/count_headers.py +0 -0
  131. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/counting/count_lines.py +0 -0
  132. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/counting/count_scans.py +0 -0
  133. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/counting/every.py +0 -0
  134. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/counting/has_matches.py +0 -0
  135. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/counting/total_lines.py +0 -0
  136. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/dates/now.py +0 -0
  137. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/function_finder.py +0 -0
  138. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/function_focus.py +0 -0
  139. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/headers/append.py +0 -0
  140. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/headers/collect.py +0 -0
  141. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/headers/empty_stack.py +0 -0
  142. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/headers/end.py +0 -0
  143. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/headers/header_name.py +0 -0
  144. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/headers/headers.py +0 -0
  145. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/headers/insert.py +0 -0
  146. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/headers/mismatch.py +0 -0
  147. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/headers/replace.py +0 -0
  148. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/lines/advance.py +0 -0
  149. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/lines/after_blank.py +0 -0
  150. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/lines/first_line.py +0 -0
  151. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/lines/last.py +0 -0
  152. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/math/above.py +0 -0
  153. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/math/add.py +0 -0
  154. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/math/divide.py +0 -0
  155. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/math/equals.py +0 -0
  156. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/math/mod.py +0 -0
  157. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/math/multiply.py +0 -0
  158. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/math/odd.py +0 -0
  159. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/math/round.py +0 -0
  160. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/math/subtract.py +0 -0
  161. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/misc/importf.py +0 -0
  162. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/print/jinjaf.py +0 -0
  163. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/print/print_line.py +0 -0
  164. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/print/print_queue.py +0 -0
  165. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/print/table.py +0 -0
  166. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/stats/percent.py +0 -0
  167. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/stats/stdev.py +0 -0
  168. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/strings/alter.py +0 -0
  169. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/strings/caps.py +0 -0
  170. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/strings/concat.py +0 -0
  171. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/strings/contains.py +0 -0
  172. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/strings/length.py +0 -0
  173. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/strings/lower.py +0 -0
  174. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/strings/metaphone.py +0 -0
  175. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/strings/starts_with.py +0 -0
  176. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/strings/strip.py +0 -0
  177. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/strings/substring.py +0 -0
  178. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/strings/upper.py +0 -0
  179. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/testing/debug.py +0 -0
  180. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/types/__init__.py +0 -0
  181. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/types/type.py +0 -0
  182. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/validity/fail.py +0 -0
  183. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/validity/failed.py +0 -0
  184. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/variables/get.py +0 -0
  185. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/variables/put.py +0 -0
  186. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/functions/variables/variables.py +0 -0
  187. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/lark_parser.py +0 -0
  188. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/lark_transformer.py +0 -0
  189. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/matcher.py +0 -0
  190. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/productions/__init__.py +0 -0
  191. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/productions/equality.py +0 -0
  192. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/productions/expression.py +0 -0
  193. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/productions/header.py +0 -0
  194. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/productions/reference.py +0 -0
  195. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/productions/term.py +0 -0
  196. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/productions/variable.py +0 -0
  197. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/util/exceptions.py +0 -0
  198. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/util/expression_encoder.py +0 -0
  199. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/util/expression_utility.py +0 -0
  200. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/util/lark_print_parser.py +0 -0
  201. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/util/print_parser.py +0 -0
  202. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/matching/util/runtime_data_collector.py +0 -0
  203. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/modes/error_mode.py +0 -0
  204. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/modes/explain_mode.py +0 -0
  205. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/modes/files_mode.py +0 -0
  206. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/modes/logic_mode.py +0 -0
  207. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/modes/mode_controller.py +0 -0
  208. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/modes/print_mode.py +0 -0
  209. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/modes/return_mode.py +0 -0
  210. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/modes/run_mode.py +0 -0
  211. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/modes/source_mode.py +0 -0
  212. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/modes/transfer_mode.py +0 -0
  213. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/modes/unmatched_mode.py +0 -0
  214. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/modes/validation_mode.py +0 -0
  215. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/scanning/__init__.py +0 -0
  216. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/scanning/exceptions.py +0 -0
  217. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/scanning/parser.out +0 -0
  218. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/scanning/parsetab.py +0 -0
  219. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/scanning/scanner.py +0 -0
  220. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/scanning/scanning_lexer.py +0 -0
  221. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/box.py +0 -0
  222. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/cache.py +0 -0
  223. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/class_loader.py +0 -0
  224. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/config.py +0 -0
  225. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/config_exception.py +0 -0
  226. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/exceptions.py +0 -0
  227. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/file_info.py +0 -0
  228. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/file_readers.py +0 -0
  229. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/file_writers.py +0 -0
  230. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/hasher.py +0 -0
  231. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/last_line_stats.py +0 -0
  232. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/line_counter.py +0 -0
  233. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/line_monitor.py +0 -0
  234. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/line_spooler.py +0 -0
  235. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/log_utility.py +0 -0
  236. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/metadata_parser.py +0 -0
  237. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/nos.py +0 -0
  238. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/pandas_data_reader.py +0 -0
  239. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/printer.py +0 -0
  240. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/reference_parser.py +0 -0
  241. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/s3/s3_data_reader.py +0 -0
  242. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/s3/s3_data_writer.py +0 -0
  243. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/s3/s3_fingerprinter.py +0 -0
  244. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/s3/s3_utils.py +0 -0
  245. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/s3/s3_xlsx_data_reader.py +0 -0
  246. {csvpath-0.0.523 → csvpath-0.0.524}/csvpath/util/var_utility.py +0 -0
  247. {csvpath-0.0.523 → csvpath-0.0.524}/docs/asbool.md +0 -0
  248. {csvpath-0.0.523 → csvpath-0.0.524}/docs/assignment.md +0 -0
  249. {csvpath-0.0.523 → csvpath-0.0.524}/docs/comments.md +0 -0
  250. {csvpath-0.0.523 → csvpath-0.0.524}/docs/config.md +0 -0
  251. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/files/file_cacher.html +0 -0
  252. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/files/file_manager.html +0 -0
  253. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/files/file_metadata.html +0 -0
  254. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/files/file_registrar.html +0 -0
  255. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/files/files_listener.html +0 -0
  256. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/files.html +0 -0
  257. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/paths/paths_listener.html +0 -0
  258. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/paths/paths_manager.html +0 -0
  259. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/paths/paths_metadata.html +0 -0
  260. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/paths/paths_registrar.html +0 -0
  261. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/paths.html +0 -0
  262. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/results/readers/file_errors_reader.html +0 -0
  263. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/results/readers/file_lines_reader.html +0 -0
  264. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/results/readers/file_printouts_reader.html +0 -0
  265. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/results/readers/file_unmatched_reader.html +0 -0
  266. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/results/readers/readers.html +0 -0
  267. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/results/readers.html +0 -0
  268. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/results/result.html +0 -0
  269. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/results/result_file_reader.html +0 -0
  270. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/results/result_metadata.html +0 -0
  271. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/results/result_registrar.html +0 -0
  272. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/results/result_serializer.html +0 -0
  273. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/results/results_manager.html +0 -0
  274. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/results/results_metadata.html +0 -0
  275. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/results/results_registrar.html +0 -0
  276. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath/managers/results.html +0 -0
  277. {csvpath-0.0.523 → csvpath-0.0.524}/docs/csvpath.html +0 -0
  278. {csvpath-0.0.523 → csvpath-0.0.524}/docs/examples.md +0 -0
  279. {csvpath-0.0.523 → csvpath-0.0.524}/docs/files.md +0 -0
  280. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/above.md +0 -0
  281. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/advance.md +0 -0
  282. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/after_blank.md +0 -0
  283. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/all.md +0 -0
  284. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/andor.md +0 -0
  285. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/any.md +0 -0
  286. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/average.md +0 -0
  287. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/between.md +0 -0
  288. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/collect.md +0 -0
  289. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/contains.md +0 -0
  290. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/correlate.md +0 -0
  291. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/count.md +0 -0
  292. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/count_bytes.md +0 -0
  293. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/count_headers.md +0 -0
  294. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/counter.md +0 -0
  295. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/date.md +0 -0
  296. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/email.md +0 -0
  297. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/empty.md +0 -0
  298. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/empty_stack.md +0 -0
  299. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/end.md +0 -0
  300. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/equal.md +0 -0
  301. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/every.md +0 -0
  302. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/fail.md +0 -0
  303. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/fingerprint.md +0 -0
  304. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/first.md +0 -0
  305. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/get.md +0 -0
  306. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/has_dups.md +0 -0
  307. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/has_matches.md +0 -0
  308. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/header.md +0 -0
  309. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/header_name.md +0 -0
  310. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/header_names_mismatch.md +0 -0
  311. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/implementing_functions.md +0 -0
  312. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/import.md +0 -0
  313. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/in.md +0 -0
  314. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/increment.md +0 -0
  315. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/intf.md +0 -0
  316. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/jinja.md +0 -0
  317. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/last.md +0 -0
  318. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/line.md +0 -0
  319. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/line_number.md +0 -0
  320. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/max.md +0 -0
  321. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/metaphone.md +0 -0
  322. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/mismatch.md +0 -0
  323. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/no.md +0 -0
  324. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/not.md +0 -0
  325. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/now.md +0 -0
  326. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/odd.md +0 -0
  327. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/percent_unique.md +0 -0
  328. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/pop.md +0 -0
  329. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/print.md +0 -0
  330. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/print_line.md +0 -0
  331. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/print_queue.md +0 -0
  332. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/random.md +0 -0
  333. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/regex.md +0 -0
  334. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/replace.md +0 -0
  335. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/reset_headers.md +0 -0
  336. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/stdev.md +0 -0
  337. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/stop.md +0 -0
  338. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/string_functions.md +0 -0
  339. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/subtotal.md +0 -0
  340. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/subtract.md +0 -0
  341. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/sum.md +0 -0
  342. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/tally.md +0 -0
  343. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/total_lines.md +0 -0
  344. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/track.md +0 -0
  345. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/types.md +0 -0
  346. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/variables.md +0 -0
  347. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions/variables_and_headers.md +0 -0
  348. {csvpath-0.0.523 → csvpath-0.0.524}/docs/functions.md +0 -0
  349. {csvpath-0.0.523 → csvpath-0.0.524}/docs/grammar.md +0 -0
  350. {csvpath-0.0.523 → csvpath-0.0.524}/docs/headers.md +0 -0
  351. {csvpath-0.0.523 → csvpath-0.0.524}/docs/images/ckan-logo-sm.png +0 -0
  352. {csvpath-0.0.523 → csvpath-0.0.524}/docs/images/csvpath-icon-sm.png +0 -0
  353. {csvpath-0.0.523 → csvpath-0.0.524}/docs/images/csvpath-logo-wordmark-tight-2.svg +0 -0
  354. {csvpath-0.0.523 → csvpath-0.0.524}/docs/images/logo-wordmark-3.svg +0 -0
  355. {csvpath-0.0.523 → csvpath-0.0.524}/docs/images/logo-wordmark-4.svg +0 -0
  356. {csvpath-0.0.523 → csvpath-0.0.524}/docs/images/logo-wordmark-white-on-black-trimmed-padded.png +0 -0
  357. {csvpath-0.0.523 → csvpath-0.0.524}/docs/images/logo-wordmark-white-trimmed.png +0 -0
  358. {csvpath-0.0.523 → csvpath-0.0.524}/docs/images/marquez-logo-sm.png +0 -0
  359. {csvpath-0.0.523 → csvpath-0.0.524}/docs/images/openlineage-logo-sm.png +0 -0
  360. {csvpath-0.0.523 → csvpath-0.0.524}/docs/images/opentelemetry.png +0 -0
  361. {csvpath-0.0.523 → csvpath-0.0.524}/docs/images/sftpplus-logo2.png +0 -0
  362. {csvpath-0.0.523 → csvpath-0.0.524}/docs/images/sftpplus-logo3.png +0 -0
  363. {csvpath-0.0.523 → csvpath-0.0.524}/docs/index.html +0 -0
  364. {csvpath-0.0.523 → csvpath-0.0.524}/docs/paths.md +0 -0
  365. {csvpath-0.0.523 → csvpath-0.0.524}/docs/printing.md +0 -0
  366. {csvpath-0.0.523 → csvpath-0.0.524}/docs/qualifiers.md +0 -0
  367. {csvpath-0.0.523 → csvpath-0.0.524}/docs/references.md +0 -0
  368. {csvpath-0.0.523 → csvpath-0.0.524}/docs/search.js +0 -0
  369. {csvpath-0.0.523 → csvpath-0.0.524}/docs/terms.md +0 -0
  370. {csvpath-0.0.523 → csvpath-0.0.524}/docs/variables.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: csvpath
3
- Version: 0.0.523
3
+ Version: 0.0.524
4
4
  Summary: An edge governance framework for managing and validating CSV, Excel, and other tabular data files
5
5
  Author: David Kershaw
6
6
  Author-email: dk107dk@hotmail.com
@@ -50,7 +50,7 @@ Description-Content-Type: text/markdown
50
50
 
51
51
  # <a href='https://www.csvpath.org/'><img src='https://github.com/csvpath/csvpath/blob/main/docs/images/logo-wordmark-4.svg'/></a>
52
52
 
53
- The CsvPath Language defines a declarative syntax for inspecting and validating CSV and Excel files, and other tabular data.
53
+ The CsvPath Framework helps you close the gap between Managed File Transfer and your data lake and/or applications. CsvPath Language is the core of the Framework. It defines a declarative syntax for inspecting and validating CSV and Excel files, and other tabular data.
54
54
 
55
55
  The CsvPath Framework makes it easy to setup a <a href='https://www.atestaanalytics.com/s/The-Collect-Store-Validate-Pattern-Atesta-Analytics-88gj.pdf'>Collect, Store, Validate Pattern</a> flat-file landing zone that:
56
56
  - Registers files for **clear and durable identity**
@@ -128,7 +128,7 @@ This project tackles two needs:
128
128
  - A more robust validation language for delimited and tabular data
129
129
  - A systems integration framework for flat-file landing and staging
130
130
 
131
- CsvPath Language is first and foremost a validation language. It supports both schema definitions and rules-based validation. CsvPath Language describes data so you can easily tell if a file is valid. CsvPath can also extract and shape data and create reports. Overall the goal is to automate human judgement out of the processing loop and instead move it to the process definition stage.
131
+ CsvPath Language is the core of the CsvPath Framework. It is a simple validation language for delimited data. It supports both schema definitions and rules-based validation. CsvPath Language describes data so you can easily tell if a file is valid. CsvPath can also extract and shape data and create reports. Overall the goal is to automate human judgement out of the processing loop and instead move it to the process definition stage.
132
132
 
133
133
  The CsvPath Framework implements CsvPath Language, but goes far beyond it to provide a full <a href='https://www.atestaanalytics.com/s/The-Collect-Store-Validate-Pattern-Atesta-Analytics-88gj.pdf'>Collect, Store, Validate Pattern</a> framework for landing flat files, registering them, validating them, shaping them to a consistent and comparable form, and staging them for a data lake. In that way, CsvPath fills the gap commonly found between an organization's MFT (managed file transfer) and a typical data lake architecture.
134
134
 
@@ -1,7 +1,7 @@
1
1
 
2
2
  # <a href='https://www.csvpath.org/'><img src='https://github.com/csvpath/csvpath/blob/main/docs/images/logo-wordmark-4.svg'/></a>
3
3
 
4
- The CsvPath Language defines a declarative syntax for inspecting and validating CSV and Excel files, and other tabular data.
4
+ The CsvPath Framework helps you close the gap between Managed File Transfer and your data lake and/or applications. CsvPath Language is the core of the Framework. It defines a declarative syntax for inspecting and validating CSV and Excel files, and other tabular data.
5
5
 
6
6
  The CsvPath Framework makes it easy to setup a <a href='https://www.atestaanalytics.com/s/The-Collect-Store-Validate-Pattern-Atesta-Analytics-88gj.pdf'>Collect, Store, Validate Pattern</a> flat-file landing zone that:
7
7
  - Registers files for **clear and durable identity**
@@ -79,7 +79,7 @@ This project tackles two needs:
79
79
  - A more robust validation language for delimited and tabular data
80
80
  - A systems integration framework for flat-file landing and staging
81
81
 
82
- CsvPath Language is first and foremost a validation language. It supports both schema definitions and rules-based validation. CsvPath Language describes data so you can easily tell if a file is valid. CsvPath can also extract and shape data and create reports. Overall the goal is to automate human judgement out of the processing loop and instead move it to the process definition stage.
82
+ CsvPath Language is the core of the CsvPath Framework. It is a simple validation language for delimited data. It supports both schema definitions and rules-based validation. CsvPath Language describes data so you can easily tell if a file is valid. CsvPath can also extract and shape data and create reports. Overall the goal is to automate human judgement out of the processing loop and instead move it to the process definition stage.
83
83
 
84
84
  The CsvPath Framework implements CsvPath Language, but goes far beyond it to provide a full <a href='https://www.atestaanalytics.com/s/The-Collect-Store-Validate-Pattern-Atesta-Analytics-88gj.pdf'>Collect, Store, Validate Pattern</a> framework for landing flat files, registering them, validating them, shaping them to a consistent and comparable form, and staging them for a data lake. In that way, CsvPath fills the gap commonly found between an organization's MFT (managed file transfer) and a typical data lake architecture.
85
85
 
@@ -8,13 +8,16 @@ from .selecter import Selecter
8
8
  from .debug_config import DebugConfig
9
9
  from csvpath.util.nos import Nos
10
10
  from .asker import Asker
11
+ from .function_lister import FunctionLister
12
+ from .const import Const
11
13
 
12
14
 
13
15
  class Cli:
14
16
  def __init__(self):
15
17
  self.csvpaths = CsvPaths()
16
18
  self.clear()
17
- splash = """
19
+ """
20
+ splash = ""
18
21
  *** * ****** ** **
19
22
  *** ** * ** ** **** **
20
23
  ** ** ** * ** *** ***** ** *****
@@ -26,7 +29,7 @@ CsvPath Command Line Interface
26
29
  Try tab completion and menu-by-key.
27
30
  For help see https://www.csvpath.org
28
31
  """
29
- print(splash)
32
+ print(Const.SPLASH)
30
33
  self._return_to_cont()
31
34
  self.clear()
32
35
 
@@ -40,33 +43,33 @@ For help see https://www.csvpath.org
40
43
  time.sleep(0.5)
41
44
 
42
45
  ITALIC = "\033[3m"
43
- SIDEBAR_COLOR = "\033[36m"
44
- REVERT = "\033[0m"
45
- STOP_HERE = f"{SIDEBAR_COLOR}{ITALIC}... done picking dir{REVERT}"
46
- STOP_HERE2 = "👍 pick this dir"
47
- CANCEL = f"{SIDEBAR_COLOR}{ITALIC}... cancel{REVERT}"
48
- CANCEL2 = "← cancel"
49
- QUIT = "← quit"
50
- NAMED_FILES = "register data"
51
- NAMED_PATHS = "load csvpaths"
52
- ARCHIVE = "access the archive"
46
+ # SIDEBAR_COLOR = "\033[36m"
47
+ # REVERT = "\033[0m"
48
+ # STOP_HERE = f"{Const.SIDEBAR_COLOR}{ITALIC}... done picking dir{Const.REVERT}"
49
+ # STOP_HERE2 = "👍 pick this dir"
50
+ # CANCEL = f"{Const.SIDEBAR_COLOR}{ITALIC}... cancel{Const.REVERT}"
51
+ # CANCEL2 = "← cancel"
52
+ # QUIT = "← quit"
53
+ # NAMED_FILES = "register data"
54
+ # NAMED_PATHS = "load csvpaths"
55
+ # ARCHIVE = "access the archive"
53
56
 
54
57
  def _return_to_cont(self):
55
58
  print(
56
- f"\n{Cli.SIDEBAR_COLOR}{Cli.ITALIC}... Hit return to continue{Cli.REVERT}\n"
59
+ f"\n{Const.SIDEBAR_COLOR}{Cli.ITALIC}... Hit return to continue{Const.REVERT}\n"
57
60
  )
58
61
  self._input("")
59
62
 
60
63
  def _response(self, text: str) -> None:
61
- sys.stdout.write(f"\u001b[30;1m{text}{Cli.REVERT}\n")
64
+ sys.stdout.write(f"\u001b[30;1m{text}{Const.REVERT}\n")
62
65
 
63
66
  def action(self, text: str) -> None:
64
- sys.stdout.write(f"\033[36m{text}{Cli.REVERT}\n")
67
+ sys.stdout.write(f"\033[36m{text}{Const.REVERT}\n")
65
68
 
66
69
  def _input(self, prompt: str) -> str:
67
70
  try:
68
71
  response = input(f"{prompt}\033[93m")
69
- sys.stdout.write(Cli.REVERT)
72
+ sys.stdout.write(Const.REVERT)
70
73
  return response.strip()
71
74
  except KeyboardInterrupt:
72
75
  return "cancel"
@@ -80,12 +83,12 @@ For help see https://www.csvpath.org
80
83
  return
81
84
  if q is not None:
82
85
  print(q)
83
- if choices[len(choices) - 1] == Cli.CANCEL:
84
- choices[len(choices) - 1] = Cli.CANCEL2
85
- if choices[len(choices) - 2] == Cli.STOP_HERE:
86
- choices[len(choices) - 2] = Cli.STOP_HERE2
86
+ if choices[len(choices) - 1] == Const.CANCEL:
87
+ choices[len(choices) - 1] = Const.CANCEL2
88
+ if choices[len(choices) - 2] == Const.STOP_HERE:
89
+ choices[len(choices) - 2] = Const.STOP_HERE2
87
90
  cs = [(s, s) for s in choices]
88
- t = Selecter().ask(title="", values=cs, cancel_value="CANCEL")
91
+ t = Selecter().ask(title="", values=cs, cancel_value=Const.CANCEL)
89
92
  self.clear()
90
93
  return t
91
94
 
@@ -94,47 +97,53 @@ For help see https://www.csvpath.org
94
97
  t = None
95
98
  try:
96
99
  choices = [
97
- Cli.NAMED_FILES,
98
- Cli.NAMED_PATHS,
99
- Cli.ARCHIVE,
100
+ Const.NAMED_FILES,
101
+ Const.NAMED_PATHS,
102
+ Const.ARCHIVE,
100
103
  "run",
101
104
  "config",
102
- self.QUIT,
105
+ "functions",
106
+ Const.QUIT,
103
107
  ]
104
108
  t = self.ask(choices)
105
109
  except KeyboardInterrupt:
106
110
  self.end()
107
111
  return
108
112
  t = self._do(t)
109
- if t == Cli.QUIT:
113
+ if t == Const.QUIT:
110
114
  self.end()
111
115
  return
112
116
 
113
117
  def _do(self, t: str) -> str | None:
114
- if t == Cli.QUIT:
118
+ if t == Const.QUIT:
115
119
  return t
116
120
  try:
117
121
  if t == "run":
118
122
  self.run()
119
- if t == Cli.NAMED_FILES:
123
+ if t == Const.NAMED_FILES:
120
124
  self._files()
121
- if t == Cli.NAMED_PATHS:
125
+ if t == Const.NAMED_PATHS:
122
126
  self._paths()
123
- if t == Cli.ARCHIVE:
127
+ if t == Const.ARCHIVE:
124
128
  self._results()
125
129
  if t == "config":
126
130
  self._config()
131
+ if t == "functions":
132
+ self._functions()
127
133
  except KeyboardInterrupt:
128
- return Cli.QUIT
134
+ return Const.QUIT
129
135
  except Exception:
130
136
  print(traceback.format_exc())
131
137
  self._return_to_cont()
132
138
 
139
+ def _functions(self) -> None:
140
+ FunctionLister(self).list_functions()
141
+
133
142
  def _config(self) -> None:
134
143
  DebugConfig(self).show()
135
144
 
136
145
  def _files(self) -> None:
137
- choices = ["add named-file", "list named-files", self.CANCEL2]
146
+ choices = ["add named-file", "list named-files", Const.CANCEL2]
138
147
  t = self.ask(choices)
139
148
  if t == "add named-file":
140
149
  DrillDown(self).name_file()
@@ -142,7 +151,7 @@ For help see https://www.csvpath.org
142
151
  self.list_named_files()
143
152
 
144
153
  def _paths(self) -> None:
145
- choices = ["add named-paths", "list named-paths", self.CANCEL2]
154
+ choices = ["add named-paths", "list named-paths", Const.CANCEL2]
146
155
  t = self.ask(choices)
147
156
  if t == "add named-paths":
148
157
  DrillDown(self).name_paths()
@@ -150,7 +159,7 @@ For help see https://www.csvpath.org
150
159
  self.list_named_paths()
151
160
 
152
161
  def _results(self) -> None:
153
- choices = ["open named-result", "list named-results", self.CANCEL2]
162
+ choices = ["open named-result", "list named-results", Const.CANCEL2]
154
163
  t = self.ask(choices)
155
164
  if t == "open named-result":
156
165
  self.open_named_result()
@@ -173,9 +182,9 @@ For help see https://www.csvpath.org
173
182
  names = self.csvpaths.results_manager.list_named_results()
174
183
  names = [n for n in names if n.find(".") == -1]
175
184
  print(f"{len(names)} named-results names:")
176
- names.append(self.CANCEL)
185
+ names.append(Const.CANCEL)
177
186
  t = self.ask(names)
178
- if t == self.CANCEL:
187
+ if t == Const.CANCEL:
179
188
  return
180
189
  t = f"{self.csvpaths.config.archive_path}{os.sep}{t}"
181
190
  self.action(f"Opening results at {t}...")
@@ -245,10 +254,10 @@ For help see https://www.csvpath.org
245
254
  paths = self.complete_paths_reference(paths)
246
255
 
247
256
  self.clear()
248
- choices = ["collect", "fast-forward", Cli.CANCEL2]
257
+ choices = ["collect", "fast-forward", Const.CANCEL2]
249
258
  method = self.ask(choices, q="What method? ")
250
259
  self.clear()
251
- if method == Cli.CANCEL2:
260
+ if method == Const.CANCEL2:
252
261
  return
253
262
  self.action(f"Running {paths} against {file} using {method}\n")
254
263
  self.pause()
@@ -0,0 +1,26 @@
1
+ class Const:
2
+
3
+ SPLASH = """
4
+ *** * ****** ** **
5
+ *** ** * ** ** **** **
6
+ ** ** ** * ** *** ***** ** *****
7
+ ** * **** **** ***** *** ** ** ** **
8
+ ** **** ****** ** ** ** *** ** ** **
9
+ *** **** * ** *** ** **** **
10
+ ***************************
11
+ CsvPath Command Line Interface
12
+ Try tab completion and menu-by-key.
13
+ For help see https://www.csvpath.org
14
+ """
15
+
16
+ ITALIC = "\033[3m"
17
+ SIDEBAR_COLOR = "\033[36m"
18
+ REVERT = "\033[0m"
19
+ STOP_HERE = f"{SIDEBAR_COLOR}{ITALIC}... done picking dir{REVERT}"
20
+ STOP_HERE2 = "👍 pick this dir"
21
+ CANCEL = f"{SIDEBAR_COLOR}{ITALIC}... cancel{REVERT}"
22
+ CANCEL2 = "← cancel"
23
+ QUIT = "← quit"
24
+ NAMED_FILES = "register data"
25
+ NAMED_PATHS = "load csvpaths"
26
+ ARCHIVE = "access the archive"
@@ -2,6 +2,7 @@ import os
2
2
  import traceback
3
3
  from .debug_config import DebugConfig
4
4
  from .asker import Asker
5
+ from .const import Const
5
6
 
6
7
 
7
8
  class DrillDown:
@@ -16,14 +17,16 @@ class DrillDown:
16
17
  #
17
18
  # get name
18
19
  #
20
+ t = self._get_add_type()
21
+ if t == Const.CANCEL2:
22
+ return
19
23
  self._cli.clear()
20
- name = Asker(self._cli, name_type="files").ask()
24
+ name = None
25
+ if t == "file":
26
+ name = Asker(self._cli, name_type="files").ask()
21
27
  #
22
28
  # get path
23
29
  #
24
- t = self._get_add_type()
25
- if t == self._cli.CANCEL2:
26
- return
27
30
  p = self._get_path(t, self._cli.csvpaths.config.csv_file_extensions)
28
31
  if p is False:
29
32
  return
@@ -63,17 +66,19 @@ class DrillDown:
63
66
  # ============================
64
67
 
65
68
  def name_paths(self):
69
+ t = self._get_add_type()
70
+ if t == Const.CANCEL2:
71
+ return
66
72
  #
67
73
  # get name
68
74
  #
69
75
  self._cli.clear()
70
- name = Asker(self._cli, name_type="paths").ask()
76
+ name = None
77
+ if t == "file":
78
+ name = Asker(self._cli, name_type="paths").ask()
71
79
  #
72
80
  # get path
73
81
  #
74
- t = self._get_add_type()
75
- if t == self._cli.CANCEL2:
76
- return
77
82
  exts = self._cli.csvpaths.config.csvpath_file_extensions
78
83
  p = self._get_path(t, exts)
79
84
  if p is False:
@@ -145,7 +150,7 @@ class DrillDown:
145
150
 
146
151
  def _get_add_type(self) -> str:
147
152
  self._cli.clear()
148
- choices = ["dir", "file", "json", self._cli.CANCEL2]
153
+ choices = ["dir", "file", "json", Const.CANCEL2]
149
154
  t = None
150
155
  t = self._cli.ask(choices)
151
156
  return t
@@ -160,9 +165,9 @@ class DrillDown:
160
165
  names.sort()
161
166
  names = self._decorate(path, names, select_dir=dir_only)
162
167
  t = self._cli.ask(names)
163
- if t in [self._cli.STOP_HERE, self._cli.STOP_HERE2]:
168
+ if t in [Const.STOP_HERE, Const.STOP_HERE2]:
164
169
  return (path, True)
165
- if t in [self._cli.CANCEL, self._cli.CANCEL2]:
170
+ if t in [Const.CANCEL, Const.CANCEL2]:
166
171
  return (path, False)
167
172
  if t.startswith("📂 ") or t.startswith("📄 "):
168
173
  t = t[2:]
@@ -171,7 +176,7 @@ class DrillDown:
171
176
  def _decorate(self, path, names, select_dir=False) -> list[str]:
172
177
  ns = []
173
178
  for n in names:
174
- if n in [self._cli.STOP_HERE, self._cli.STOP_HERE2]:
179
+ if n in [Const.STOP_HERE, Const.STOP_HERE2]:
175
180
  pass
176
181
  elif os.path.isfile(os.path.join(path, n)):
177
182
  n = f"📄 {n}"
@@ -179,8 +184,8 @@ class DrillDown:
179
184
  n = f"📂 {n}"
180
185
  ns.append(n)
181
186
  if select_dir is True:
182
- ns.append(self._cli.STOP_HERE)
183
- ns.append(self._cli.CANCEL)
187
+ ns.append(Const.STOP_HERE)
188
+ ns.append(Const.CANCEL)
184
189
  return ns
185
190
 
186
191
  def _filter_hidden(self, names) -> list[str]:
@@ -0,0 +1,190 @@
1
+ # pylint: disable=C0114
2
+ import textwrap
3
+ from tabulate import tabulate
4
+ from csvpath.matching.functions.function import Function
5
+ from csvpath.matching.functions.types.type import Type
6
+ from csvpath.matching.functions.function_focus import ValueProducer, MatchDecider
7
+ from .const import Const
8
+
9
+
10
+ class FunctionDescriber:
11
+ @classmethod
12
+ def describe(cls, function: Function) -> None:
13
+ if not function.args:
14
+ #
15
+ # today this will most of the time blow up because we're
16
+ # doing a structural validation of a function that is not
17
+ # part of a structure. this should be refactored at some
18
+ # point, but it's not hurting anything.
19
+ #
20
+ try:
21
+ function.check_valid()
22
+ except Exception:
23
+ ...
24
+ if function.description and len(function.description) > 0:
25
+ for i, _ in enumerate(function.description):
26
+ print(_)
27
+ print()
28
+ cls.print_tables(function)
29
+
30
+ @classmethod
31
+ def sigs(cls, function):
32
+ sigs = []
33
+ args = function.args
34
+ argsets = args.argsets
35
+ for ai, a in enumerate(argsets):
36
+ pa = ""
37
+ for i, _ in enumerate(a.args):
38
+ t = ""
39
+ if _.name is not None:
40
+ t += f"{_.name}: "
41
+ for j, act in enumerate(_.actuals):
42
+ an = cls._actual_name(act)
43
+ if an == "":
44
+ an = "''"
45
+ t += f"{Const.SIDEBAR_COLOR}{Const.ITALIC}{an}{Const.REVERT}"
46
+ if j < len(_.actuals) - 1:
47
+ t += "|"
48
+ if _.is_noneable:
49
+ pa += f"[{t}]"
50
+ else:
51
+ pa += t
52
+ if i < len(a.args) - 1:
53
+ pa += ", "
54
+ if a.max_length == -1:
55
+ pa += ", ..."
56
+ pa = pa.strip()
57
+ if pa != "":
58
+ pa = f" {pa} "
59
+ sigs.append(f"{function.name}({pa})")
60
+ return sigs
61
+
62
+ @classmethod
63
+ def funcs(cls, function):
64
+ sigs = []
65
+ args = function.args
66
+ argsets = args.argsets
67
+ for ai, a in enumerate(argsets):
68
+ pa = ""
69
+ for i, _ in enumerate(a.args):
70
+ t = ""
71
+ if _.name is not None:
72
+ t += f"{_.name}: "
73
+ for j, act in enumerate(_.types):
74
+ an = cls._actual_name(act)
75
+ if an == "":
76
+ an = "''"
77
+ t += f"{Const.SIDEBAR_COLOR}{Const.ITALIC}{an}{Const.REVERT}"
78
+ if j < len(_.types) - 1:
79
+ t += "|"
80
+ if _.is_noneable:
81
+ pa += f"[{t}]"
82
+ else:
83
+ pa += t
84
+ if i < len(a.args) - 1:
85
+ pa += ", "
86
+ if a.max_length == -1:
87
+ pa += ", ..."
88
+ pa = pa.strip()
89
+ if pa != "":
90
+ pa = f" {pa} "
91
+ sigs.append(f"{function.name}({pa})")
92
+ return sigs
93
+
94
+ @classmethod
95
+ def focus_stmt(cls, function):
96
+ stmts = []
97
+ vp = isinstance(function, ValueProducer)
98
+ md = isinstance(function, MatchDecider)
99
+ if vp and md:
100
+ stmts.append(
101
+ f"{function.name}() produces a calculated value and decides matches"
102
+ )
103
+ elif vp:
104
+ stmts.append(f"{function.name}() produces a calculated value")
105
+ elif md:
106
+ stmts.append(f"{function.name}() determines if lines match")
107
+ else:
108
+ stmts.append(f"{function.name}() is a side-effect")
109
+ return stmts
110
+
111
+ @classmethod
112
+ def type_stmt(cls, function):
113
+ stmts = []
114
+ if isinstance(function, Type):
115
+ t = f"{function.name[0].upper()}{function.name[1:]}"
116
+ stmts.append(f"{t} is a line() schema type")
117
+ return stmts
118
+
119
+ @classmethod
120
+ def print_tables(cls, function):
121
+ #
122
+ # data sigs
123
+ #
124
+ headers = ["Data signatures"]
125
+ rows = []
126
+ sigs = cls.sigs(function)
127
+ for v in sigs:
128
+ v = str(v)
129
+ rows.append([v])
130
+ if len(rows) > 0:
131
+ print(tabulate(rows, headers=headers, tablefmt="simple_grid"))
132
+ #
133
+ # call sigs
134
+ #
135
+ headers = ["Call signatures"]
136
+ rows = []
137
+ sigs = cls.funcs(function)
138
+ for v in sigs:
139
+ v = str(v)
140
+ rows.append([v])
141
+ if len(rows) > 0:
142
+ print(tabulate(rows, headers=headers, tablefmt="simple_grid"))
143
+ #
144
+ # type and focus
145
+ #
146
+ rows = []
147
+ headers = []
148
+ stmts = cls.focus_stmt(function)
149
+ for v in stmts:
150
+ v = str(v)
151
+ rows.append(["Focus", v])
152
+ stmts = cls.type_stmt(function)
153
+ for v in stmts:
154
+ v = str(v)
155
+ rows.append(["Type", v])
156
+ if len(rows) > 0:
157
+ print(tabulate(rows, headers=headers, tablefmt="simple_grid"))
158
+ #
159
+ # qualifiers
160
+ #
161
+ rows = []
162
+ headers = []
163
+ stmts = function.match_qualifiers
164
+ stmts = [f"{Const.SIDEBAR_COLOR}{Const.ITALIC}{s}{Const.REVERT}" for s in stmts]
165
+ if len(stmts) > 0:
166
+ rows.append(["Match qualifiers", ", ".join(stmts)])
167
+ stmts = function.value_qualifiers
168
+ stmts = [f"{Const.SIDEBAR_COLOR}{Const.ITALIC}{s}{Const.REVERT}" for s in stmts]
169
+ if len(stmts) > 0:
170
+ rows.append(["Value qualifiers", ", ".join(stmts)])
171
+ if function.name_qualifier:
172
+ rows.append(
173
+ [
174
+ "Name qualifier",
175
+ f"{Const.SIDEBAR_COLOR}{Const.ITALIC}optionally expected{Const.REVERT}",
176
+ ]
177
+ )
178
+ if len(rows) > 0:
179
+ print(tabulate(rows, headers=headers, tablefmt="simple_grid"))
180
+
181
+ @classmethod
182
+ def _actual_name(cls, a) -> str:
183
+ an = f"{a}"
184
+ if an.rfind("'>") > -1:
185
+ an = an[0 : an.rfind("'>")]
186
+ if an.rfind(".") > -1:
187
+ an = an[an.rfind(".") + 1 :]
188
+ if an.rfind("'") > -1:
189
+ an = an[an.rfind("'") + 1 :]
190
+ return an
@@ -0,0 +1,30 @@
1
+ import os
2
+ import traceback
3
+ from csvpath.matching.functions.function_factory import FunctionFactory
4
+ from .function_describer import FunctionDescriber
5
+ from .selecter import Selecter
6
+ from .const import Const
7
+
8
+
9
+ class FunctionLister:
10
+ def __init__(self, cli):
11
+ self._cli = cli
12
+
13
+ def list_functions(self) -> None:
14
+ FunctionFactory.load()
15
+ names = list(FunctionFactory.MY_FUNCTIONS.keys())
16
+ names.sort()
17
+ if None in names:
18
+ raise ValueError("None cannot be a key in functions")
19
+
20
+ cs = [(n, n) for n in names]
21
+
22
+ t = Selecter().ask(title="", values=cs, cancel_value="CANCEL")
23
+ self._cli.clear()
24
+ if t in [Const.CANCEL, Const.CANCEL2]:
25
+ return
26
+ f = FunctionFactory.get_function(
27
+ None, name=t, child=None, find_external_functions=False
28
+ )
29
+ FunctionDescriber.describe(f)
30
+ self._cli._return_to_cont()
@@ -11,6 +11,7 @@ from prompt_toolkit.formatted_text import AnyFormattedText
11
11
  from prompt_toolkit.styles import BaseStyle
12
12
  from prompt_toolkit.mouse_events import MouseEvent, MouseEventType
13
13
  from prompt_toolkit.formatted_text.base import StyleAndTextTuples, to_formatted_text
14
+ from .const import Const
14
15
 
15
16
  T = TypeVar("T")
16
17
 
@@ -1252,7 +1252,7 @@ class CsvPath(ErrorCollector, Printer): # pylint: disable=R0902, R0904
1252
1252
  for k in self.limit_collection_to:
1253
1253
  if k is None or k >= len(line):
1254
1254
  raise InputException(
1255
- f"[{self.identity}] Line {self.line_monitor.physical_line_number}: unknown header name: {k}"
1255
+ f"[{self.identity}] Line {self.line_monitor.physical_line_number}: unknown header name: {k} of {self.limit_collection_to} in headers {self.headers}"
1256
1256
  )
1257
1257
  ls.append(line[k])
1258
1258
  return ls
@@ -290,9 +290,12 @@ class CsvPaths(CsvPathsCoordinator, ErrorCollector):
290
290
  """@private
291
291
  at this time we do not recommend reusing CsvPaths, but it is doable
292
292
  you should clean before reuse unless you want to accumulate results."""
293
- self.results_manager.clean_named_results(paths)
293
+ self._set_managers()
294
294
  self.clear_run_coordination()
295
- # self.error_manager.reset()
295
+ self._errors = []
296
+ self.named_paths_name = None
297
+ self.named_file_name = None
298
+ self.current_matcher = None
296
299
  self._errors = []
297
300
  self.named_paths_name = None
298
301
  self.named_file_name = None
@@ -38,6 +38,10 @@ class Arg:
38
38
  def is_noneable(self, n: bool) -> None:
39
39
  self._noneable = n
40
40
 
41
+ @property
42
+ def name(self) -> str:
43
+ return self._name
44
+
41
45
  @property
42
46
  def types(self) -> list[Type]:
43
47
  return self._types
@@ -410,7 +414,7 @@ class Args:
410
414
  if not good:
411
415
  msg = None
412
416
  if self.matchable:
413
- msg = f"Problem in {self.matchable.my_chain}: {_m}"
417
+ msg = f"Csvpath language problem in {self.matchable.my_chain}: {_m}"
414
418
  else:
415
419
  msg = "CsvPath Language syntax problem"
416
420
  self._matchable.matcher.csvpath.error_manager.handle_error(
@@ -12,8 +12,15 @@ class ArgumentValidationHelper:
12
12
  valid_argsets = self._find_valid_argsets(args_definition, actual_values)
13
13
  if len(valid_argsets) == 0:
14
14
  if len(args_definition.argsets) == 1:
15
+ i = 0
16
+ for a in args_definition.argsets[0].args:
17
+ if not a.is_noneable:
18
+ i += 1
15
19
  expected = len(args_definition.argsets[0].args)
16
- return f"{function_name} requires {expected} argument{'s' if expected != 1 else ''}"
20
+ if i < expected:
21
+ return f"{function_name}() requires {i} to {expected} argument{'s' if expected != 1 else ''}"
22
+ else:
23
+ return f"{function_name}() requires {expected} argument{'s' if expected != 1 else ''}"
17
24
  return self._get_argument_count_error(function_name, args_definition)
18
25
  #
19
26
  # Validate each argument against the argset.