csvpath 0.0.473__tar.gz → 0.0.474__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 (207) hide show
  1. {csvpath-0.0.473 → csvpath-0.0.474}/PKG-INFO +1 -2
  2. {csvpath-0.0.473 → csvpath-0.0.474}/config/config.ini +4 -0
  3. csvpath-0.0.474/config/imports.txt +1 -0
  4. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/function_factory.py +11 -14
  5. csvpath-0.0.474/csvpath/matching/functions/function_finder.py +55 -0
  6. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/util/config.py +28 -1
  7. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/implementing_functions.md +11 -2
  8. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions.md +14 -1
  9. {csvpath-0.0.473 → csvpath-0.0.474}/pyproject.toml +1 -2
  10. csvpath-0.0.473/csvpath/matching/functions/stats/correlate.py +0 -41
  11. {csvpath-0.0.473 → csvpath-0.0.474}/LICENSE +0 -0
  12. {csvpath-0.0.473 → csvpath-0.0.474}/README.md +0 -0
  13. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/__init__.py +0 -0
  14. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/csvpath.py +0 -0
  15. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/csvpaths.py +0 -0
  16. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/managers/__init__.py +0 -0
  17. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/managers/csvpaths_manager.py +0 -0
  18. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/managers/file_manager.py +0 -0
  19. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/managers/result.py +0 -0
  20. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/managers/results_manager.py +0 -0
  21. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/__init__.py +0 -0
  22. {csvpath-0.0.473/csvpath/scanning → csvpath-0.0.474/csvpath/matching/functions}/__init__.py +0 -0
  23. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/boolean/all.py +0 -0
  24. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/boolean/andf.py +0 -0
  25. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/boolean/any.py +0 -0
  26. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/boolean/between.py +0 -0
  27. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/boolean/empty.py +0 -0
  28. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/boolean/exists.py +0 -0
  29. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/boolean/inf.py +0 -0
  30. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/boolean/no.py +0 -0
  31. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/boolean/notf.py +0 -0
  32. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/boolean/orf.py +0 -0
  33. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/boolean/yes.py +0 -0
  34. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/counting/count.py +0 -0
  35. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/counting/count_headers.py +0 -0
  36. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/counting/count_lines.py +0 -0
  37. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/counting/count_scans.py +0 -0
  38. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/counting/counter.py +0 -0
  39. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/counting/every.py +0 -0
  40. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/counting/has_matches.py +0 -0
  41. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/counting/increment.py +0 -0
  42. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/counting/tally.py +0 -0
  43. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/counting/total_lines.py +0 -0
  44. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/dates/datef.py +0 -0
  45. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/dates/now.py +0 -0
  46. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/function.py +0 -0
  47. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/function_focus.py +0 -0
  48. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/headers/collect.py +0 -0
  49. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/headers/empty_stack.py +0 -0
  50. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/headers/end.py +0 -0
  51. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/headers/header_name.py +0 -0
  52. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/headers/header_names_mismatch.py +0 -0
  53. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/headers/headers.py +0 -0
  54. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/headers/mismatch.py +0 -0
  55. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/headers/replace.py +0 -0
  56. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/headers/reset_headers.py +0 -0
  57. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/lines/advance.py +0 -0
  58. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/lines/after_blank.py +0 -0
  59. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/lines/dups.py +0 -0
  60. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/lines/first.py +0 -0
  61. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/lines/first_line.py +0 -0
  62. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/lines/last.py +0 -0
  63. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/lines/stop.py +0 -0
  64. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/math/above.py +0 -0
  65. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/math/add.py +0 -0
  66. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/math/divide.py +0 -0
  67. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/math/equals.py +0 -0
  68. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/math/mod.py +0 -0
  69. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/math/multiply.py +0 -0
  70. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/math/round.py +0 -0
  71. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/math/subtract.py +0 -0
  72. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/math/sum.py +0 -0
  73. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/misc/importf.py +0 -0
  74. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/misc/intf.py +0 -0
  75. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/misc/nonef.py +0 -0
  76. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/misc/random.py +0 -0
  77. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/print/jinjaf.py +0 -0
  78. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/print/print_line.py +0 -0
  79. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/print/print_queue.py +0 -0
  80. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/print/printf.py +0 -0
  81. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/print/table.py +0 -0
  82. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/stats/minf.py +0 -0
  83. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/stats/percent.py +0 -0
  84. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/stats/percent_unique.py +0 -0
  85. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/stats/stdev.py +0 -0
  86. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/strings/concat.py +0 -0
  87. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/strings/length.py +0 -0
  88. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/strings/lower.py +0 -0
  89. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/strings/metaphone.py +0 -0
  90. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/strings/num.py +0 -0
  91. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/strings/regex.py +0 -0
  92. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/strings/starts_with.py +0 -0
  93. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/strings/strip.py +0 -0
  94. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/strings/substring.py +0 -0
  95. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/strings/upper.py +0 -0
  96. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/testing/debug.py +0 -0
  97. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/validation.py +0 -0
  98. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/validity/fail.py +0 -0
  99. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/validity/failed.py +0 -0
  100. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/variables/get.py +0 -0
  101. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/variables/pushpop.py +0 -0
  102. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/variables/put.py +0 -0
  103. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/variables/track.py +0 -0
  104. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/functions/variables/variables.py +0 -0
  105. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/lark_parser.py +0 -0
  106. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/lark_transformer.py +0 -0
  107. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/matcher.py +0 -0
  108. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/productions/__init__.py +0 -0
  109. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/productions/equality.py +0 -0
  110. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/productions/expression.py +0 -0
  111. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/productions/header.py +0 -0
  112. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/productions/matchable.py +0 -0
  113. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/productions/qualified.py +0 -0
  114. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/productions/reference.py +0 -0
  115. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/productions/term.py +0 -0
  116. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/productions/variable.py +0 -0
  117. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/util/exceptions.py +0 -0
  118. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/util/expression_encoder.py +0 -0
  119. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/util/expression_utility.py +0 -0
  120. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/util/lark_print_parser.py +0 -0
  121. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/matching/util/print_parser.py +0 -0
  122. {csvpath-0.0.473/csvpath/matching/functions → csvpath-0.0.474/csvpath/scanning}/__init__.py +0 -0
  123. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/scanning/exceptions.py +0 -0
  124. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/scanning/parser.out +0 -0
  125. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/scanning/parsetab.py +0 -0
  126. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/scanning/scanner.py +0 -0
  127. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/scanning/scanning_lexer.py +0 -0
  128. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/util/cache.py +0 -0
  129. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/util/config_exception.py +0 -0
  130. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/util/error.py +0 -0
  131. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/util/exceptions.py +0 -0
  132. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/util/last_line_stats.py +0 -0
  133. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/util/line_counter.py +0 -0
  134. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/util/line_monitor.py +0 -0
  135. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/util/log_utility.py +0 -0
  136. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/util/metadata_parser.py +0 -0
  137. {csvpath-0.0.473 → csvpath-0.0.474}/csvpath/util/printer.py +0 -0
  138. {csvpath-0.0.473 → csvpath-0.0.474}/docs/asbool.md +0 -0
  139. {csvpath-0.0.473 → csvpath-0.0.474}/docs/assignment.md +0 -0
  140. {csvpath-0.0.473 → csvpath-0.0.474}/docs/config.md +0 -0
  141. {csvpath-0.0.473 → csvpath-0.0.474}/docs/examples.md +0 -0
  142. {csvpath-0.0.473 → csvpath-0.0.474}/docs/files.md +0 -0
  143. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/above.md +0 -0
  144. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/advance.md +0 -0
  145. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/after_blank.md +0 -0
  146. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/all.md +0 -0
  147. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/andor.md +0 -0
  148. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/any.md +0 -0
  149. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/average.md +0 -0
  150. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/between.md +0 -0
  151. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/collect.md +0 -0
  152. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/correlate.md +0 -0
  153. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/count.md +0 -0
  154. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/count_headers.md +0 -0
  155. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/counter.md +0 -0
  156. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/date.md +0 -0
  157. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/empty.md +0 -0
  158. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/empty_stack.md +0 -0
  159. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/end.md +0 -0
  160. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/every.md +0 -0
  161. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/fail.md +0 -0
  162. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/first.md +0 -0
  163. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/get.md +0 -0
  164. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/has_dups.md +0 -0
  165. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/has_matches.md +0 -0
  166. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/header.md +0 -0
  167. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/header_name.md +0 -0
  168. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/header_names_mismatch.md +0 -0
  169. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/import.md +0 -0
  170. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/in.md +0 -0
  171. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/increment.md +0 -0
  172. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/jinja.md +0 -0
  173. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/last.md +0 -0
  174. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/line_number.md +0 -0
  175. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/max.md +0 -0
  176. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/metaphone.md +0 -0
  177. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/mismatch.md +0 -0
  178. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/no.md +0 -0
  179. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/not.md +0 -0
  180. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/now.md +0 -0
  181. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/percent_unique.md +0 -0
  182. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/pop.md +0 -0
  183. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/print.md +0 -0
  184. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/print_line.md +0 -0
  185. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/print_queue.md +0 -0
  186. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/regex.md +0 -0
  187. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/replace.md +0 -0
  188. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/reset_headers.md +0 -0
  189. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/stdev.md +0 -0
  190. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/stop.md +0 -0
  191. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/string_functions.md +0 -0
  192. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/subtract.md +0 -0
  193. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/sum.md +0 -0
  194. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/tally.md +0 -0
  195. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/total_lines.md +0 -0
  196. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/track.md +0 -0
  197. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/variables.md +0 -0
  198. {csvpath-0.0.473 → csvpath-0.0.474}/docs/functions/variables_and_headers.md +0 -0
  199. {csvpath-0.0.473 → csvpath-0.0.474}/docs/grammar.md +0 -0
  200. {csvpath-0.0.473 → csvpath-0.0.474}/docs/headers.md +0 -0
  201. {csvpath-0.0.473 → csvpath-0.0.474}/docs/images/logo-wordmark-white-on-black-trimmed-padded.png +0 -0
  202. {csvpath-0.0.473 → csvpath-0.0.474}/docs/images/logo-wordmark-white-trimmed.png +0 -0
  203. {csvpath-0.0.473 → csvpath-0.0.474}/docs/paths.md +0 -0
  204. {csvpath-0.0.473 → csvpath-0.0.474}/docs/qualifiers.md +0 -0
  205. {csvpath-0.0.473 → csvpath-0.0.474}/docs/references.md +0 -0
  206. {csvpath-0.0.473 → csvpath-0.0.474}/docs/terms.md +0 -0
  207. {csvpath-0.0.473 → csvpath-0.0.474}/docs/variables.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: csvpath
3
- Version: 0.0.473
3
+ Version: 0.0.474
4
4
  Summary: A declarative language for data extraction and validation of CSV files
5
5
  Author: David Kershaw
6
6
  Author-email: dk107dk@hotmail.com
@@ -22,7 +22,6 @@ Requires-Dist: inflect (>=7.3.1,<8.0.0)
22
22
  Requires-Dist: jinja2 (>=3.1.4,<4.0.0)
23
23
  Requires-Dist: lark (>=1.2.2,<2.0.0)
24
24
  Requires-Dist: metaphone (>=0.6,<0.7)
25
- Requires-Dist: pandas (>=2.2.2,<3.0.0)
26
25
  Requires-Dist: ply (>=3.11,<4.0)
27
26
  Requires-Dist: python-dateutil (>=2.9.0.post0,<3.0.0)
28
27
  Requires-Dist: tabulate (>=0.9.0,<0.10.0)
@@ -20,3 +20,7 @@ path = config/config.ini
20
20
 
21
21
  [cache]
22
22
  path = cache
23
+
24
+ [functions]
25
+ imports =
26
+
@@ -0,0 +1 @@
1
+ from csvpath.matching.functions.boolean.yes import Yes as sure
@@ -1,6 +1,7 @@
1
1
  # pylint: disable=C0114
2
2
  from csvpath.matching.productions.expression import Matchable
3
3
  from .function import Function
4
+ from .function_finder import FunctionFinder
4
5
  from .dates.now import Now
5
6
  from .dates.datef import Date
6
7
  from .strings.lower import Lower
@@ -56,7 +57,8 @@ from .stats.percent import Percent
56
57
  from .stats.minf import Min, Max, Average
57
58
  from .stats.percent_unique import PercentUnique
58
59
  from .stats.stdev import Stdev
59
- from .stats.correlate import Correlate
60
+
61
+ # from .stats.correlate import Correlate
60
62
  from .print.printf import Print
61
63
  from .print.table import HeaderTable, RowTable, VarTable, RunTable
62
64
  from .print.print_line import PrintLine
@@ -260,8 +262,8 @@ class FunctionFactory:
260
262
  f = Strip(matcher, name, child)
261
263
  elif name == "jinja":
262
264
  f = Jinjaf(matcher, name, child)
263
- elif name == "correlate":
264
- f = Correlate(matcher, name, child)
265
+ # elif name == "correlate":
266
+ # f = Correlate(matcher, name, child)
265
267
  elif name in ["count_headers", "count_headers_in_line"]:
266
268
  f = CountHeaders(matcher, name, child)
267
269
  elif name == "percent_unique":
@@ -292,9 +294,6 @@ class FunctionFactory:
292
294
  f = Stack(matcher, name, child)
293
295
  elif name in ["stdev", "pstdev"]:
294
296
  f = Stdev(matcher, name, child)
295
- #
296
- # dup_lines can also decide matches
297
- #
298
297
  elif name == "has_dups":
299
298
  f = HasDups(matcher, name, child)
300
299
  elif name == "count_dups":
@@ -373,15 +372,13 @@ class FunctionFactory:
373
372
  f = Num(matcher, name, child)
374
373
  elif name == "counter":
375
374
  f = Counter(matcher, name, child)
376
-
377
375
  else:
378
- if (
379
- f is None
380
- and find_external_functions
381
- and name in FunctionFactory.NOT_MY_FUNCTION
382
- ):
383
- f = cls.NOT_MY_FUNCTION[name]
384
- f = f(matcher, name, child)
376
+ if f is None and find_external_functions:
377
+ if FunctionFinder.EXTERNALS not in FunctionFactory.NOT_MY_FUNCTION:
378
+ FunctionFinder().load(matcher, cls)
379
+ if name in FunctionFactory.NOT_MY_FUNCTION:
380
+ f = cls.NOT_MY_FUNCTION[name]
381
+ f = f(matcher, name, child)
385
382
  if not find_external_functions:
386
383
  return None
387
384
  if f is None:
@@ -0,0 +1,55 @@
1
+ # pylint: disable=C0114
2
+ import os
3
+ import importlib
4
+ from csvpath.util.config_exception import ConfigurationException
5
+ from .boolean.yes import Yes
6
+
7
+
8
+ class FunctionFinder:
9
+ EXTERNALS = "externalfunctionsloaded"
10
+
11
+ @classmethod
12
+ def load(cls, matcher, func_fact) -> None:
13
+ # any problems loading will bubble up to the nearest
14
+ # expression and be handled there.
15
+ config = matcher.csvpath.config
16
+ # find the list
17
+ path = config.function_imports
18
+ # read the list
19
+ if path is None:
20
+ matcher.csvpath.logger.error("No [functions][imports] in config.ini")
21
+ return
22
+ if not os.path.exists(path):
23
+ matcher.csvpath.logger.error(
24
+ "No [functions][imports] path from config.ini does not exist"
25
+ )
26
+ return
27
+ with open(path, "r") as file:
28
+ i = 0
29
+ for line in file:
30
+ i += 1
31
+ cls._add_function(matcher, func_fact, line)
32
+ matcher.csvpath.logger.info("Added %s external functions", i)
33
+ # add a sentinel to keep us from attempting reload.
34
+ # this instance will never be found, but the dict will
35
+ # never be empty
36
+ func_fact.add_function(cls.EXTERNALS, Yes(None, cls.EXTERNALS))
37
+
38
+ @classmethod
39
+ def _add_function(cls, matcher, func_fact, s: str) -> None:
40
+ s = s.strip()
41
+ if s != "":
42
+ instance = None
43
+ # instantiate the classes
44
+ # function_name module classname
45
+ cs = s.split(" ")
46
+ if len(cs) == 6 and cs[0] == "from" and cs[2] == "import" and cs[4] == "as":
47
+ module = importlib.import_module(cs[1])
48
+ class_ = getattr(module, cs[3])
49
+ instance = class_(matcher, cs[5])
50
+ # load to FunctionFactory.add
51
+ func_fact.add_function(cs[5], instance)
52
+ else:
53
+ raise ConfigurationException(
54
+ "Unclear external function import setup: {s}"
55
+ )
@@ -42,6 +42,7 @@ class Sections(Enum):
42
42
  CSV_FILES = "csv_files"
43
43
  ERRORS = "errors"
44
44
  LOGGING = "logging"
45
+ FUNCTIONS = "functions"
45
46
 
46
47
 
47
48
  class Config:
@@ -172,6 +173,17 @@ path =
172
173
  self.log_file_size = self._get(
173
174
  Sections.LOGGING.value, LogFile.LOG_FILE_SIZE.value
174
175
  )
176
+ #
177
+ # path to external functions list. external functions are very optional.
178
+ # not blowing up when absent seems reasonable.
179
+ #
180
+ try:
181
+ self.function_imports = self._get(Sections.FUNCTIONS.value, "imports")
182
+ except Exception:
183
+ pass
184
+ #
185
+ # reload if another config path is set
186
+ #
175
187
  path = self._get("config", "path")
176
188
  if path:
177
189
  path = path.strip().lower()
@@ -262,17 +274,32 @@ path =
262
274
 
263
275
  # ======================================
264
276
 
277
+ @property
278
+ def configpath(self) -> str:
279
+ return self._configpath
280
+
281
+ @configpath.setter
282
+ def configpath(self, path: str) -> None:
283
+ self._configpath = path
284
+
265
285
  @property
266
286
  def cache_dir_path(self) -> str:
267
287
  try:
268
288
  path = self._get("cache", "path")
269
289
  except Exception:
270
- print("No cache path in config.ini at [cache][path]. Using 'cache'.")
271
290
  path = "config"
272
291
  self._config.add_section("cache")
273
292
  self._config.set("cache", "path", path)
274
293
  return path
275
294
 
295
+ @property
296
+ def function_imports(self) -> str:
297
+ return self._function_imports
298
+
299
+ @function_imports.setter
300
+ def function_imports(self, path: str) -> None:
301
+ self._function_imports = path
302
+
276
303
  @property
277
304
  def csvpath_file_extensions(self) -> list[str]:
278
305
  return self._csvpath_file_extensions
@@ -80,17 +80,26 @@ When your function needs its arguments you can call:
80
80
  - self._value_two(skip=skip)
81
81
  - self._siblings()
82
82
 
83
- When you need to get a value or a match from a child object you use `to_value()` or `matches()`. Remember to pass the skip list as a named argument "skip".
83
+ When you need to get a value or a match from a child object you use `to_value()` or `matches()`. Remember to pass the skip list as the named argument `skip`.
84
84
 
85
85
  ## Registering
86
86
 
87
- To register your function for use, add it to the FunctionFactory like this:
87
+ To register your function for use, add it to the `FunctionFactory` like this:
88
88
 
89
89
  ```python
90
90
  from csvpath.matching.functions.function_factory import FunctionFactory
91
91
  FunctionFactory.add_function(name='iamafunction', function=my_function_instance)
92
92
  ```
93
93
 
94
+ Alternatively, add a file path to your `config.ini` file under the key `[functions][imports]` that points to a list of functions to register. The key is like:
95
+
96
+ [functions]
97
+ imports = my_imports/functions.txt
98
+
99
+ In the file list every function on its own line using a format like that of Python imports:
100
+
101
+ from a.b.c.my_function import MyFunction as iamafunction
102
+
94
103
  To use your function do something like:
95
104
 
96
105
  ```bash
@@ -41,7 +41,20 @@ Some functions will optionally make use of an arbitrary name qualifier to better
41
41
 
42
42
  ## Custom Functions
43
43
 
44
- Creating your own function is easy. Once you create a function, you register it with the `FunctionFactory` class. You must register your functions each time you run CsvPath. Use your function in csvpaths by simply referring to it by name like any other function.
44
+ Creating your own function is easy. Once you create a function, you register it with the `FunctionFactory` class. You can register your functions either programmatically or by creating an import file listing your functions. Your import file must be referenced in your `config.ini` file at `[functions][imports]` like this:
45
+
46
+ [functions]
47
+ imports = my_project_assets/my_functions.imports
48
+
49
+ Each custom function has its own line in your imports file. The format is the same as you use for importing classes into Python files -- under the hood the mechanism is similar. E.g.
50
+
51
+ ```python
52
+ from my_function.for_stuff.me import Me as function_me
53
+ ```
54
+
55
+ In this example your class is `Me` and the name of the function you use in your csvpath is `function_me()`
56
+
57
+ Use your functions in csvpaths by simply referring to them by name like you would any built-in function.
45
58
 
46
59
  <a href='https://github.com/dk107dk/csvpath/blob/main/docs/functions/implementing_functions.md'>Read more about implementing your own functions here.</a>
47
60
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "csvpath"
3
- version = "0.0.473"
3
+ version = "0.0.474"
4
4
  description = "A declarative language for data extraction and validation of CSV files"
5
5
  authors = ["David Kershaw <dk107dk@hotmail.com>"]
6
6
  readme = "README.md"
@@ -27,7 +27,6 @@ include = ["config", "logs", "docs"]
27
27
  python = "^3.12"
28
28
  ply = "^3.11"
29
29
  python-dateutil = "^2.9.0.post0"
30
- pandas = "^2.2.2"
31
30
  jinja2 = "^3.1.4"
32
31
  inflect = "^7.3.1"
33
32
  lark = "^1.2.2"
@@ -1,41 +0,0 @@
1
- # pylint: disable=C0114
2
- import pandas as pd
3
- from ..function_focus import ValueProducer
4
-
5
-
6
- class Correlate(ValueProducer):
7
- """does a statistical correlation test on the values of two headers"""
8
-
9
- def check_valid(self) -> None:
10
- self.validate_two_args()
11
- super().check_valid()
12
-
13
- def _produce_value(self, skip=None) -> None:
14
- child = self.children[0]
15
- left = child.left
16
- right = child.right
17
- leftlist = left.to_value(skip=skip)
18
- rightlist = right.to_value(skip=skip)
19
- leftlist, rightlist = self._trim(leftlist, rightlist)
20
- ll = pd.Series(leftlist)
21
- rl = pd.Series(rightlist)
22
- corr = ll.corr(rl)
23
- f = float(corr)
24
- f = round(f, 2)
25
- self.value = f
26
-
27
- def _decide_match(self, skip=None) -> None:
28
- self.to_value(skip=skip)
29
- self.match = self._noop_match() # pragma: no cover
30
-
31
- def _trim(self, leftlist, rightlist):
32
- n = len(leftlist) if len(leftlist) < len(rightlist) else len(rightlist)
33
- ll = []
34
- rl = []
35
- for i in range(0, n):
36
- try:
37
- ll.append(float(leftlist[i]))
38
- rl.append(float(rightlist[i]))
39
- except (TypeError, ValueError):
40
- pass
41
- return ll, rl
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes