csvpath 0.0.474__tar.gz → 0.0.476__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 (206) hide show
  1. {csvpath-0.0.474 → csvpath-0.0.476}/PKG-INFO +1 -1
  2. {csvpath-0.0.474 → csvpath-0.0.476}/config/config.ini +1 -1
  3. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/csvpath.py +5 -4
  4. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/csvpaths.py +13 -2
  5. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/function_factory.py +3 -1
  6. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/function_finder.py +1 -1
  7. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/testing/debug.py +26 -0
  8. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/util/config.py +90 -38
  9. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/util/printer.py +26 -0
  10. {csvpath-0.0.474 → csvpath-0.0.476}/pyproject.toml +1 -1
  11. csvpath-0.0.474/config/imports.txt +0 -1
  12. {csvpath-0.0.474 → csvpath-0.0.476}/LICENSE +0 -0
  13. {csvpath-0.0.474 → csvpath-0.0.476}/README.md +0 -0
  14. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/__init__.py +0 -0
  15. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/managers/__init__.py +0 -0
  16. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/managers/csvpaths_manager.py +0 -0
  17. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/managers/file_manager.py +0 -0
  18. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/managers/result.py +0 -0
  19. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/managers/results_manager.py +0 -0
  20. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/__init__.py +0 -0
  21. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/__init__.py +0 -0
  22. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/boolean/all.py +0 -0
  23. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/boolean/andf.py +0 -0
  24. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/boolean/any.py +0 -0
  25. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/boolean/between.py +0 -0
  26. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/boolean/empty.py +0 -0
  27. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/boolean/exists.py +0 -0
  28. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/boolean/inf.py +0 -0
  29. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/boolean/no.py +0 -0
  30. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/boolean/notf.py +0 -0
  31. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/boolean/orf.py +0 -0
  32. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/boolean/yes.py +0 -0
  33. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/counting/count.py +0 -0
  34. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/counting/count_headers.py +0 -0
  35. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/counting/count_lines.py +0 -0
  36. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/counting/count_scans.py +0 -0
  37. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/counting/counter.py +0 -0
  38. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/counting/every.py +0 -0
  39. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/counting/has_matches.py +0 -0
  40. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/counting/increment.py +0 -0
  41. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/counting/tally.py +0 -0
  42. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/counting/total_lines.py +0 -0
  43. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/dates/datef.py +0 -0
  44. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/dates/now.py +0 -0
  45. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/function.py +0 -0
  46. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/function_focus.py +0 -0
  47. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/headers/collect.py +0 -0
  48. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/headers/empty_stack.py +0 -0
  49. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/headers/end.py +0 -0
  50. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/headers/header_name.py +0 -0
  51. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/headers/header_names_mismatch.py +0 -0
  52. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/headers/headers.py +0 -0
  53. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/headers/mismatch.py +0 -0
  54. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/headers/replace.py +0 -0
  55. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/headers/reset_headers.py +0 -0
  56. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/lines/advance.py +0 -0
  57. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/lines/after_blank.py +0 -0
  58. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/lines/dups.py +0 -0
  59. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/lines/first.py +0 -0
  60. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/lines/first_line.py +0 -0
  61. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/lines/last.py +0 -0
  62. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/lines/stop.py +0 -0
  63. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/math/above.py +0 -0
  64. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/math/add.py +0 -0
  65. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/math/divide.py +0 -0
  66. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/math/equals.py +0 -0
  67. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/math/mod.py +0 -0
  68. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/math/multiply.py +0 -0
  69. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/math/round.py +0 -0
  70. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/math/subtract.py +0 -0
  71. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/math/sum.py +0 -0
  72. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/misc/importf.py +0 -0
  73. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/misc/intf.py +0 -0
  74. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/misc/nonef.py +0 -0
  75. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/misc/random.py +0 -0
  76. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/print/jinjaf.py +0 -0
  77. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/print/print_line.py +0 -0
  78. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/print/print_queue.py +0 -0
  79. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/print/printf.py +0 -0
  80. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/print/table.py +0 -0
  81. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/stats/minf.py +0 -0
  82. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/stats/percent.py +0 -0
  83. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/stats/percent_unique.py +0 -0
  84. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/stats/stdev.py +0 -0
  85. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/strings/concat.py +0 -0
  86. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/strings/length.py +0 -0
  87. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/strings/lower.py +0 -0
  88. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/strings/metaphone.py +0 -0
  89. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/strings/num.py +0 -0
  90. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/strings/regex.py +0 -0
  91. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/strings/starts_with.py +0 -0
  92. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/strings/strip.py +0 -0
  93. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/strings/substring.py +0 -0
  94. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/strings/upper.py +0 -0
  95. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/validation.py +0 -0
  96. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/validity/fail.py +0 -0
  97. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/validity/failed.py +0 -0
  98. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/variables/get.py +0 -0
  99. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/variables/pushpop.py +0 -0
  100. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/variables/put.py +0 -0
  101. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/variables/track.py +0 -0
  102. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/functions/variables/variables.py +0 -0
  103. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/lark_parser.py +0 -0
  104. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/lark_transformer.py +0 -0
  105. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/matcher.py +0 -0
  106. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/productions/__init__.py +0 -0
  107. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/productions/equality.py +0 -0
  108. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/productions/expression.py +0 -0
  109. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/productions/header.py +0 -0
  110. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/productions/matchable.py +0 -0
  111. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/productions/qualified.py +0 -0
  112. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/productions/reference.py +0 -0
  113. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/productions/term.py +0 -0
  114. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/productions/variable.py +0 -0
  115. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/util/exceptions.py +0 -0
  116. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/util/expression_encoder.py +0 -0
  117. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/util/expression_utility.py +0 -0
  118. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/util/lark_print_parser.py +0 -0
  119. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/matching/util/print_parser.py +0 -0
  120. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/scanning/__init__.py +0 -0
  121. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/scanning/exceptions.py +0 -0
  122. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/scanning/parser.out +0 -0
  123. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/scanning/parsetab.py +0 -0
  124. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/scanning/scanner.py +0 -0
  125. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/scanning/scanning_lexer.py +0 -0
  126. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/util/cache.py +0 -0
  127. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/util/config_exception.py +0 -0
  128. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/util/error.py +0 -0
  129. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/util/exceptions.py +0 -0
  130. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/util/last_line_stats.py +0 -0
  131. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/util/line_counter.py +0 -0
  132. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/util/line_monitor.py +0 -0
  133. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/util/log_utility.py +0 -0
  134. {csvpath-0.0.474 → csvpath-0.0.476}/csvpath/util/metadata_parser.py +0 -0
  135. {csvpath-0.0.474 → csvpath-0.0.476}/docs/asbool.md +0 -0
  136. {csvpath-0.0.474 → csvpath-0.0.476}/docs/assignment.md +0 -0
  137. {csvpath-0.0.474 → csvpath-0.0.476}/docs/config.md +0 -0
  138. {csvpath-0.0.474 → csvpath-0.0.476}/docs/examples.md +0 -0
  139. {csvpath-0.0.474 → csvpath-0.0.476}/docs/files.md +0 -0
  140. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/above.md +0 -0
  141. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/advance.md +0 -0
  142. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/after_blank.md +0 -0
  143. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/all.md +0 -0
  144. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/andor.md +0 -0
  145. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/any.md +0 -0
  146. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/average.md +0 -0
  147. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/between.md +0 -0
  148. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/collect.md +0 -0
  149. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/correlate.md +0 -0
  150. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/count.md +0 -0
  151. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/count_headers.md +0 -0
  152. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/counter.md +0 -0
  153. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/date.md +0 -0
  154. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/empty.md +0 -0
  155. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/empty_stack.md +0 -0
  156. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/end.md +0 -0
  157. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/every.md +0 -0
  158. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/fail.md +0 -0
  159. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/first.md +0 -0
  160. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/get.md +0 -0
  161. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/has_dups.md +0 -0
  162. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/has_matches.md +0 -0
  163. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/header.md +0 -0
  164. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/header_name.md +0 -0
  165. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/header_names_mismatch.md +0 -0
  166. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/implementing_functions.md +0 -0
  167. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/import.md +0 -0
  168. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/in.md +0 -0
  169. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/increment.md +0 -0
  170. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/jinja.md +0 -0
  171. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/last.md +0 -0
  172. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/line_number.md +0 -0
  173. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/max.md +0 -0
  174. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/metaphone.md +0 -0
  175. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/mismatch.md +0 -0
  176. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/no.md +0 -0
  177. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/not.md +0 -0
  178. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/now.md +0 -0
  179. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/percent_unique.md +0 -0
  180. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/pop.md +0 -0
  181. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/print.md +0 -0
  182. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/print_line.md +0 -0
  183. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/print_queue.md +0 -0
  184. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/regex.md +0 -0
  185. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/replace.md +0 -0
  186. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/reset_headers.md +0 -0
  187. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/stdev.md +0 -0
  188. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/stop.md +0 -0
  189. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/string_functions.md +0 -0
  190. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/subtract.md +0 -0
  191. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/sum.md +0 -0
  192. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/tally.md +0 -0
  193. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/total_lines.md +0 -0
  194. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/track.md +0 -0
  195. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/variables.md +0 -0
  196. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions/variables_and_headers.md +0 -0
  197. {csvpath-0.0.474 → csvpath-0.0.476}/docs/functions.md +0 -0
  198. {csvpath-0.0.474 → csvpath-0.0.476}/docs/grammar.md +0 -0
  199. {csvpath-0.0.474 → csvpath-0.0.476}/docs/headers.md +0 -0
  200. {csvpath-0.0.474 → csvpath-0.0.476}/docs/images/logo-wordmark-white-on-black-trimmed-padded.png +0 -0
  201. {csvpath-0.0.474 → csvpath-0.0.476}/docs/images/logo-wordmark-white-trimmed.png +0 -0
  202. {csvpath-0.0.474 → csvpath-0.0.476}/docs/paths.md +0 -0
  203. {csvpath-0.0.474 → csvpath-0.0.476}/docs/qualifiers.md +0 -0
  204. {csvpath-0.0.474 → csvpath-0.0.476}/docs/references.md +0 -0
  205. {csvpath-0.0.474 → csvpath-0.0.476}/docs/terms.md +0 -0
  206. {csvpath-0.0.474 → csvpath-0.0.476}/docs/variables.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: csvpath
3
- Version: 0.0.474
3
+ Version: 0.0.476
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,5 +22,5 @@ path = config/config.ini
22
22
  path = cache
23
23
 
24
24
  [functions]
25
- imports =
25
+ imports = config/functions.imports
26
26
 
@@ -232,11 +232,12 @@ class CsvPath(CsvPathPublic, ErrorCollector): # pylint: disable=R0902, R0904
232
232
  #
233
233
  # the config.ini file loaded as a ConfigParser instance
234
234
  #
235
- # we're moving this to a property can set up there. we
236
235
  # definitely do not want this coming from CsvPaths because
237
236
  # we want to be able to override config.ini specifically for
238
- # this instance, if needed.
239
- self._config = None
237
+ # this instance, if needed; however, we do want to be able
238
+ # to pass in a config object that has been configured in some
239
+ # way.
240
+ self._config = config
240
241
  #
241
242
  # there are two logger components one for CsvPath and one for CsvPaths.
242
243
  # the default levels are set in config.ini. to change the levels pass LogUtility
@@ -318,7 +319,7 @@ class CsvPath(CsvPathPublic, ErrorCollector): # pylint: disable=R0902, R0904
318
319
  @property
319
320
  def config(self) -> Config: # pylint: disable=C0116
320
321
  if not self._config:
321
- self._config = Config(self)
322
+ self._config = Config()
322
323
  return self._config
323
324
 
324
325
  def has_errors(self) -> bool: # pylint: disable=C0116
@@ -122,7 +122,13 @@ class CsvPaths(CsvPathsPublic, CsvPathsCoordinator):
122
122
  # pylint: disable=too-many-instance-attributes
123
123
 
124
124
  def __init__(
125
- self, *, delimiter=",", quotechar='"', skip_blank_lines=True, print_default=True
125
+ self,
126
+ *,
127
+ delimiter=",",
128
+ quotechar='"',
129
+ skip_blank_lines=True,
130
+ print_default=True,
131
+ config: Config = None,
126
132
  ):
127
133
  self.paths_manager = PathsManager(csvpaths=self)
128
134
  self.file_manager = FileManager(csvpaths=self)
@@ -132,7 +138,7 @@ class CsvPaths(CsvPathsPublic, CsvPathsCoordinator):
132
138
  self.quotechar = quotechar
133
139
  self.skip_blank_lines = skip_blank_lines
134
140
  self.current_matcher: CsvPath = None
135
- self._config = Config(self)
141
+ self._config = Config() if config is None else config
136
142
  self.logger = LogUtility.logger(self)
137
143
  self.logger.info("initialized CsvPaths")
138
144
  self._errors = []
@@ -155,6 +161,11 @@ class CsvPaths(CsvPathsPublic, CsvPathsCoordinator):
155
161
  delimiter=self.delimiter,
156
162
  quotechar=self.quotechar,
157
163
  skip_blank_lines=self.skip_blank_lines,
164
+ #
165
+ # in the usual case we don't want csvpaths and its csvpath children
166
+ # to share the same config. sharing doesn't offer much. the flexibility
167
+ # of having separate configs is valuable.
168
+ #
158
169
  config=None,
159
170
  print_default=self.print_default,
160
171
  )
@@ -80,7 +80,7 @@ from .misc.random import Random
80
80
  from .misc.nonef import Nonef
81
81
  from .misc.intf import Int
82
82
  from .misc.importf import Import
83
- from .testing.debug import Debug, BriefStackTrace, VoteStack, DoWhenStack
83
+ from .testing.debug import Debug, BriefStackTrace, VoteStack, DoWhenStack, Log
84
84
  from .validity.failed import Failed
85
85
  from .validity.fail import Fail, FailAll
86
86
 
@@ -350,6 +350,8 @@ class FunctionFactory:
350
350
  f = Put(matcher, name, child)
351
351
  elif name == "debug":
352
352
  f = Debug(matcher, name, child)
353
+ elif name == "log":
354
+ f = Log(matcher, name, child)
353
355
  elif name == "brief_stack_trace":
354
356
  f = BriefStackTrace(matcher, name, child)
355
357
  elif name == "vote_stack":
@@ -21,7 +21,7 @@ class FunctionFinder:
21
21
  return
22
22
  if not os.path.exists(path):
23
23
  matcher.csvpath.logger.error(
24
- "No [functions][imports] path from config.ini does not exist"
24
+ f"[functions][imports] path in {config.configpath} does not exist"
25
25
  )
26
26
  return
27
27
  with open(path, "r") as file:
@@ -6,6 +6,32 @@ from csvpath.matching.util.expression_utility import ExpressionUtility
6
6
  from csvpath.matching.productions import Equality
7
7
 
8
8
 
9
+ class Log(SideEffect):
10
+ """logs a msg at a log level, defaulting to info"""
11
+
12
+ def check_valid(self) -> None:
13
+ self.validate_one_or_two_args()
14
+ super().check_valid()
15
+
16
+ def _produce_value(self, skip=None) -> None:
17
+ self.value = self.matches(skip=skip)
18
+
19
+ def _decide_match(self, skip=None) -> None:
20
+ msg = self._value_one(skip=skip)
21
+ level = self._value_two(skip=skip)
22
+ if level in [None, "info"]:
23
+ self.matcher.csvpath.logger.info(msg)
24
+ elif level == "debug":
25
+ self.matcher.csvpath.logger.debug(msg)
26
+ elif level in ["warn", "warning"]:
27
+ self.matcher.csvpath.logger.warning(msg)
28
+ elif level == "error":
29
+ self.matcher.csvpath.logger.error(msg)
30
+ else:
31
+ self.matcher.csvpath.logger.info(msg)
32
+ self.match = self.default_match()
33
+
34
+
9
35
  class Debug(SideEffect):
10
36
  """sets the logging level"""
11
37
 
@@ -43,6 +43,7 @@ class Sections(Enum):
43
43
  ERRORS = "errors"
44
44
  LOGGING = "logging"
45
45
  FUNCTIONS = "functions"
46
+ CACHE = "cache"
46
47
 
47
48
 
48
49
  class Config:
@@ -51,22 +52,45 @@ class Config:
51
52
  - set a CSVPATH_CONFIG_FILE env var
52
53
  - create a Config instance set its CONFIG member and call reload
53
54
  - or set Config.CONFIG and reload to reset all instances w/o own specific settings
55
+ Also, you can pass Config(load=False) to give you the opportunity to set some/all
56
+ properties programmatically.
54
57
  """
55
58
 
56
59
  CONFIG: str = "config/config.ini"
57
60
  CSVPATH_CONFIG_FILE_ENV: str = "CSVPATH_CONFIG_PATH"
58
61
 
59
- def __init__(self, holder):
60
- self._holder = holder
62
+ def __init__(self, *, load=True):
63
+ self.load = load
64
+ self._cache_dir_path = None
65
+ self._function_imports = None
66
+ self._csvpath_file_extensions = None
67
+ self._csv_file_extensions = None
68
+ self._csvpath_errors_policy = None
69
+ self._csvpaths_errors_policy = None
70
+ self._csvpath_log_level = None
71
+ self._csvpaths_log_level = None
72
+ self._log_file = None
73
+ self._log_files_to_keep = None
74
+ self._log_file_size = None
61
75
  self._config = RawConfigParser()
62
76
  self.log_file_handler = None
63
77
  self._configpath = environ.get(Config.CSVPATH_CONFIG_FILE_ENV)
64
78
  if self._configpath is None:
65
79
  self._configpath = Config.CONFIG
66
- self._load_config()
80
+ if self.load:
81
+ self._load_config()
82
+
83
+ @property
84
+ def load(self) -> bool:
85
+ return self._load
86
+
87
+ @load.setter
88
+ def load(self, lo: bool) -> None:
89
+ self._load = lo
67
90
 
68
91
  def reload(self):
69
92
  self._config = RawConfigParser()
93
+ self._load = True
70
94
  self._load_config()
71
95
 
72
96
  def set_config_path_and_reload(self, path: str) -> None:
@@ -90,15 +114,28 @@ class Config:
90
114
  ret = s
91
115
  return ret
92
116
  except KeyError:
93
- raise ConfigurationException(
94
- f"Check config at {self.config_path} for [{section}][{name}]"
117
+ print(
118
+ f"WARNING: Check config at {self.config_path} for [{section}][{name}]"
95
119
  )
96
120
 
121
+ def save_config(self) -> None:
122
+ with open(self.configpath, "w") as f:
123
+ self._config.write(f)
124
+
97
125
  def _create_default_config(self) -> None:
98
- if not path.exists("config"):
99
- os.makedirs("config")
100
- with open(Config.CONFIG, "w") as file:
101
- c = """
126
+ directory = ""
127
+ name = ""
128
+ if self._configpath is None or self._configpath.strip() == "":
129
+ raise ConfigurationException("Config path cannot be None")
130
+ if self._configpath.find(os.sep) > 0:
131
+ s = self._configpath.rfind(os.sep)
132
+ directory = self._configpath[0:s]
133
+ name = self._configpath[s + 1 :]
134
+ if directory != "":
135
+ if not path.exists(directory):
136
+ os.makedirs(directory)
137
+ with open(self._configpath, "w") as file:
138
+ c = """
102
139
  [csvpath_files]
103
140
  extensions = txt, csvpath, csvpaths
104
141
  [csv_files]
@@ -114,20 +151,25 @@ log_files_to_keep = 100
114
151
  log_file_size = 52428800
115
152
  [config]
116
153
  path =
117
- """
118
- file.write(c)
119
- print(f"Creating a default config file at {Config.CONFIG}.")
154
+ [functions]
155
+ imports =
156
+ [cache]
157
+ path =
158
+ """
159
+ file.write(c)
160
+ print(f"Created a default config file at {directory} with name {name}.")
120
161
  print("If you want your config to be somewhere else remember to")
121
162
  print("update the path in the default config.ini")
122
163
 
123
164
  def _assure_logs_path(self) -> None:
124
- filepath = self.log_file
125
- if not filepath:
126
- filepath = "logs/csvpath.log"
127
- self.log_file = filepath
128
- dirpath = self._get_dir_path(filepath)
129
- if dirpath and not path.exists(dirpath):
130
- os.makedirs(dirpath)
165
+ if self.load:
166
+ filepath = self.log_file
167
+ if not filepath or filepath.strip() == "":
168
+ filepath = "logs/csvpath.log"
169
+ self.log_file = filepath
170
+ dirpath = self._get_dir_path(filepath)
171
+ if dirpath and not path.exists(dirpath):
172
+ os.makedirs(dirpath)
131
173
 
132
174
  def _get_dir_path(self, filepath):
133
175
  if filepath.find(os.sep) > -1:
@@ -136,20 +178,25 @@ path =
136
178
  return None
137
179
 
138
180
  def _assure_cache_path(self) -> None:
139
- dirpath = self.cache_dir_path
140
- if dirpath and not path.exists(dirpath):
141
- os.makedirs(dirpath)
142
- elif not dirpath:
143
- raise ConfigurationException(
144
- "No cache path available. Check config.ini [cache][path]."
145
- )
181
+ if self.load:
182
+ if self.cache_dir_path is None or self.cache_dir_path.strip() == "":
183
+ self.cache_dir_path = "cache"
184
+ if not path.exists(self.cache_dir_path):
185
+ os.makedirs(self.cache_dir_path)
146
186
 
147
187
  def _assure_config_file_path(self) -> None:
148
- if not self._configpath or not os.path.isfile(self._configpath):
149
- self._configpath = Config.CONFIG
150
- self._create_default_config()
188
+ if self.load:
189
+ if not self._configpath or self._configpath.strip() == "":
190
+ self._configpath = Config.CONFIG
191
+ if not os.path.isfile(self._configpath):
192
+ self._create_default_config()
151
193
 
152
194
  def _load_config(self, norecurse=False):
195
+ if self._load is False:
196
+ print(
197
+ "WARNING: _load_config called on a config instance that is set to not load"
198
+ )
199
+ return
153
200
  self._assure_config_file_path()
154
201
  #
155
202
  #
@@ -173,13 +220,20 @@ path =
173
220
  self.log_file_size = self._get(
174
221
  Sections.LOGGING.value, LogFile.LOG_FILE_SIZE.value
175
222
  )
176
- #
177
223
  # path to external functions list. external functions are very optional.
178
224
  # not blowing up when absent seems reasonable.
179
- #
180
225
  try:
181
226
  self.function_imports = self._get(Sections.FUNCTIONS.value, "imports")
182
227
  except Exception:
228
+ print(
229
+ "WARNING: config cannot load [functions][imports] from {self.configpath}"
230
+ )
231
+ pass
232
+ # likewise caching.
233
+ try:
234
+ self.cache_dir_path = self._get(Sections.CACHE.value, "path")
235
+ except Exception:
236
+ print("WARNING: config cannot load [cache][path] from {self.configpath}")
183
237
  pass
184
238
  #
185
239
  # reload if another config path is set
@@ -284,13 +338,11 @@ path =
284
338
 
285
339
  @property
286
340
  def cache_dir_path(self) -> str:
287
- try:
288
- path = self._get("cache", "path")
289
- except Exception:
290
- path = "config"
291
- self._config.add_section("cache")
292
- self._config.set("cache", "path", path)
293
- return path
341
+ return self._cache_dir_path
342
+
343
+ @cache_dir_path.setter
344
+ def cache_dir_path(self, p) -> None:
345
+ self._cache_dir_path = p
294
346
 
295
347
  @property
296
348
  def function_imports(self) -> str:
@@ -1,5 +1,6 @@
1
1
  from abc import ABC, abstractmethod
2
2
  import sys
3
+ from .config_exception import ConfigurationException
3
4
 
4
5
 
5
6
  class Printer(ABC):
@@ -75,3 +76,28 @@ class TestPrinter(Printer):
75
76
 
76
77
  def print_to(self, name: str, string: str) -> None:
77
78
  self.lines.append(string)
79
+
80
+
81
+ class LogPrinter(StdOutPrinter):
82
+ """logs to info by default"""
83
+
84
+ def __init__(self, logger):
85
+ self._logger = logger
86
+ if logger is None:
87
+ raise ConfigurationException("Logger cannot be None")
88
+ super().__init__()
89
+
90
+ def print_to(self, name: str, msg: str) -> None:
91
+ self._count += 1
92
+ if name in ["info", None]:
93
+ self._logger.info(msg)
94
+ elif name == "debug":
95
+ self._logger.debug(msg)
96
+ elif name in ["warn", "warning"]:
97
+ self._logger.warning(msg)
98
+ elif name == "error":
99
+ self._logger.error(msg)
100
+ else:
101
+ self._logger.info(msg)
102
+
103
+ self._last_line = msg
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "csvpath"
3
- version = "0.0.474"
3
+ version = "0.0.476"
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"
@@ -1 +0,0 @@
1
- from csvpath.matching.functions.boolean.yes import Yes as sure
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