pycharter 0.0.22__py3-none-any.whl → 0.0.24__py3-none-any.whl

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 (404) hide show
  1. api/main.py +27 -1
  2. api/models/docs.py +68 -0
  3. api/models/evolution.py +117 -0
  4. api/models/tracking.py +111 -0
  5. api/models/validation.py +46 -6
  6. api/routes/v1/__init__.py +14 -1
  7. api/routes/v1/docs.py +187 -0
  8. api/routes/v1/evolution.py +337 -0
  9. api/routes/v1/templates.py +211 -27
  10. api/routes/v1/tracking.py +301 -0
  11. api/routes/v1/validation.py +68 -31
  12. pycharter/__init__.py +268 -58
  13. pycharter/data/templates/contract/template_coercion_rules.yaml +57 -0
  14. pycharter/data/templates/contract/template_contract.yaml +122 -0
  15. pycharter/data/templates/contract/template_metadata.yaml +68 -0
  16. pycharter/data/templates/contract/template_schema.yaml +100 -0
  17. pycharter/data/templates/contract/template_validation_rules.yaml +75 -0
  18. pycharter/data/templates/etl/README.md +224 -0
  19. pycharter/data/templates/etl/extract_cloud_azure.yaml +24 -0
  20. pycharter/data/templates/etl/extract_cloud_gcs.yaml +25 -0
  21. pycharter/data/templates/etl/extract_cloud_s3.yaml +30 -0
  22. pycharter/data/templates/etl/extract_database.yaml +34 -0
  23. pycharter/data/templates/etl/extract_database_ssh.yaml +40 -0
  24. pycharter/data/templates/etl/extract_file_csv.yaml +21 -0
  25. pycharter/data/templates/etl/extract_file_glob.yaml +25 -0
  26. pycharter/data/templates/etl/extract_file_json.yaml +24 -0
  27. pycharter/data/templates/etl/extract_file_parquet.yaml +20 -0
  28. pycharter/data/templates/etl/extract_http_paginated.yaml +79 -0
  29. pycharter/data/templates/etl/extract_http_path_params.yaml +38 -0
  30. pycharter/data/templates/etl/extract_http_simple.yaml +62 -0
  31. pycharter/data/templates/etl/load_cloud_azure.yaml +24 -0
  32. pycharter/data/templates/etl/load_cloud_gcs.yaml +22 -0
  33. pycharter/data/templates/etl/load_cloud_s3.yaml +27 -0
  34. pycharter/data/templates/etl/load_file.yaml +34 -0
  35. pycharter/data/templates/etl/load_insert.yaml +18 -0
  36. pycharter/data/templates/etl/load_postgresql.yaml +39 -0
  37. pycharter/data/templates/etl/load_sqlite.yaml +21 -0
  38. pycharter/data/templates/etl/load_truncate_and_load.yaml +20 -0
  39. pycharter/data/templates/etl/load_upsert.yaml +25 -0
  40. pycharter/data/templates/etl/load_with_dlq.yaml +34 -0
  41. pycharter/data/templates/etl/load_with_ssh_tunnel.yaml +35 -0
  42. pycharter/data/templates/etl/pipeline_http_to_db.yaml +75 -0
  43. pycharter/data/templates/etl/transform_combined.yaml +48 -0
  44. pycharter/data/templates/etl/transform_custom_function.yaml +58 -0
  45. pycharter/data/templates/etl/transform_jsonata.yaml +51 -0
  46. pycharter/data/templates/etl/transform_simple.yaml +59 -0
  47. pycharter/db/schemas/.ipynb_checkpoints/data_contract-checkpoint.py +160 -0
  48. pycharter/docs_generator/__init__.py +43 -0
  49. pycharter/docs_generator/generator.py +465 -0
  50. pycharter/docs_generator/renderers.py +247 -0
  51. pycharter/etl_generator/__init__.py +168 -80
  52. pycharter/etl_generator/builder.py +121 -0
  53. pycharter/etl_generator/config_loader.py +394 -0
  54. pycharter/etl_generator/config_validator.py +418 -0
  55. pycharter/etl_generator/context.py +132 -0
  56. pycharter/etl_generator/expression.py +499 -0
  57. pycharter/etl_generator/extractors/__init__.py +30 -0
  58. pycharter/etl_generator/extractors/base.py +70 -0
  59. pycharter/etl_generator/extractors/cloud_storage.py +530 -0
  60. pycharter/etl_generator/extractors/database.py +221 -0
  61. pycharter/etl_generator/extractors/factory.py +185 -0
  62. pycharter/etl_generator/extractors/file.py +475 -0
  63. pycharter/etl_generator/extractors/http.py +895 -0
  64. pycharter/etl_generator/extractors/streaming.py +57 -0
  65. pycharter/etl_generator/loaders/__init__.py +41 -0
  66. pycharter/etl_generator/loaders/base.py +35 -0
  67. pycharter/etl_generator/loaders/cloud.py +87 -0
  68. pycharter/etl_generator/loaders/cloud_storage_loader.py +275 -0
  69. pycharter/etl_generator/loaders/database.py +274 -0
  70. pycharter/etl_generator/loaders/factory.py +180 -0
  71. pycharter/etl_generator/loaders/file.py +72 -0
  72. pycharter/etl_generator/loaders/file_loader.py +130 -0
  73. pycharter/etl_generator/pipeline.py +743 -0
  74. pycharter/etl_generator/protocols.py +54 -0
  75. pycharter/etl_generator/result.py +63 -0
  76. pycharter/etl_generator/schemas/__init__.py +49 -0
  77. pycharter/etl_generator/transformers/__init__.py +49 -0
  78. pycharter/etl_generator/transformers/base.py +63 -0
  79. pycharter/etl_generator/transformers/config.py +45 -0
  80. pycharter/etl_generator/transformers/custom_function.py +101 -0
  81. pycharter/etl_generator/transformers/jsonata_transformer.py +56 -0
  82. pycharter/etl_generator/transformers/operations.py +218 -0
  83. pycharter/etl_generator/transformers/pipeline.py +54 -0
  84. pycharter/etl_generator/transformers/simple_operations.py +131 -0
  85. pycharter/quality/__init__.py +25 -0
  86. pycharter/quality/tracking/__init__.py +64 -0
  87. pycharter/quality/tracking/collector.py +318 -0
  88. pycharter/quality/tracking/exporters.py +238 -0
  89. pycharter/quality/tracking/models.py +194 -0
  90. pycharter/quality/tracking/store.py +385 -0
  91. pycharter/runtime_validator/__init__.py +20 -7
  92. pycharter/runtime_validator/builder.py +328 -0
  93. pycharter/runtime_validator/validator.py +311 -7
  94. pycharter/runtime_validator/validator_core.py +61 -0
  95. pycharter/schema_evolution/__init__.py +61 -0
  96. pycharter/schema_evolution/compatibility.py +270 -0
  97. pycharter/schema_evolution/diff.py +496 -0
  98. pycharter/schema_evolution/models.py +201 -0
  99. pycharter/shared/__init__.py +56 -0
  100. pycharter/shared/errors.py +296 -0
  101. pycharter/shared/protocols.py +234 -0
  102. {pycharter-0.0.22.dist-info → pycharter-0.0.24.dist-info}/METADATA +146 -26
  103. pycharter-0.0.24.dist-info/RECORD +543 -0
  104. {pycharter-0.0.22.dist-info → pycharter-0.0.24.dist-info}/WHEEL +1 -1
  105. ui/static/404/index.html +1 -1
  106. ui/static/404.html +1 -1
  107. ui/static/__next.__PAGE__.txt +1 -1
  108. ui/static/__next._full.txt +1 -1
  109. ui/static/__next._head.txt +1 -1
  110. ui/static/__next._index.txt +1 -1
  111. ui/static/__next._tree.txt +1 -1
  112. ui/static/_next/static/chunks/26dfc590f7714c03.js +1 -0
  113. ui/static/_next/static/chunks/34d289e6db2ef551.js +1 -0
  114. ui/static/_next/static/chunks/99508d9d5869cc27.js +1 -0
  115. ui/static/_next/static/chunks/b313c35a6ba76574.js +1 -0
  116. ui/static/_not-found/__next._full.txt +1 -1
  117. ui/static/_not-found/__next._head.txt +1 -1
  118. ui/static/_not-found/__next._index.txt +1 -1
  119. ui/static/_not-found/__next._not-found.__PAGE__.txt +1 -1
  120. ui/static/_not-found/__next._not-found.txt +1 -1
  121. ui/static/_not-found/__next._tree.txt +1 -1
  122. ui/static/_not-found/index.html +1 -1
  123. ui/static/_not-found/index.txt +1 -1
  124. ui/static/contracts/__next._full.txt +2 -2
  125. ui/static/contracts/__next._head.txt +1 -1
  126. ui/static/contracts/__next._index.txt +1 -1
  127. ui/static/contracts/__next._tree.txt +1 -1
  128. ui/static/contracts/__next.contracts.__PAGE__.txt +2 -2
  129. ui/static/contracts/__next.contracts.txt +1 -1
  130. ui/static/contracts/index.html +1 -1
  131. ui/static/contracts/index.txt +2 -2
  132. ui/static/documentation/__next._full.txt +1 -1
  133. ui/static/documentation/__next._head.txt +1 -1
  134. ui/static/documentation/__next._index.txt +1 -1
  135. ui/static/documentation/__next._tree.txt +1 -1
  136. ui/static/documentation/__next.documentation.__PAGE__.txt +1 -1
  137. ui/static/documentation/__next.documentation.txt +1 -1
  138. ui/static/documentation/index.html +2 -2
  139. ui/static/documentation/index.txt +1 -1
  140. ui/static/index.html +1 -1
  141. ui/static/index.txt +1 -1
  142. ui/static/metadata/__next._full.txt +1 -1
  143. ui/static/metadata/__next._head.txt +1 -1
  144. ui/static/metadata/__next._index.txt +1 -1
  145. ui/static/metadata/__next._tree.txt +1 -1
  146. ui/static/metadata/__next.metadata.__PAGE__.txt +1 -1
  147. ui/static/metadata/__next.metadata.txt +1 -1
  148. ui/static/metadata/index.html +1 -1
  149. ui/static/metadata/index.txt +1 -1
  150. ui/static/quality/__next._full.txt +2 -2
  151. ui/static/quality/__next._head.txt +1 -1
  152. ui/static/quality/__next._index.txt +1 -1
  153. ui/static/quality/__next._tree.txt +1 -1
  154. ui/static/quality/__next.quality.__PAGE__.txt +2 -2
  155. ui/static/quality/__next.quality.txt +1 -1
  156. ui/static/quality/index.html +2 -2
  157. ui/static/quality/index.txt +2 -2
  158. ui/static/rules/__next._full.txt +1 -1
  159. ui/static/rules/__next._head.txt +1 -1
  160. ui/static/rules/__next._index.txt +1 -1
  161. ui/static/rules/__next._tree.txt +1 -1
  162. ui/static/rules/__next.rules.__PAGE__.txt +1 -1
  163. ui/static/rules/__next.rules.txt +1 -1
  164. ui/static/rules/index.html +1 -1
  165. ui/static/rules/index.txt +1 -1
  166. ui/static/schemas/__next._full.txt +1 -1
  167. ui/static/schemas/__next._head.txt +1 -1
  168. ui/static/schemas/__next._index.txt +1 -1
  169. ui/static/schemas/__next._tree.txt +1 -1
  170. ui/static/schemas/__next.schemas.__PAGE__.txt +1 -1
  171. ui/static/schemas/__next.schemas.txt +1 -1
  172. ui/static/schemas/index.html +1 -1
  173. ui/static/schemas/index.txt +1 -1
  174. ui/static/settings/__next._full.txt +1 -1
  175. ui/static/settings/__next._head.txt +1 -1
  176. ui/static/settings/__next._index.txt +1 -1
  177. ui/static/settings/__next._tree.txt +1 -1
  178. ui/static/settings/__next.settings.__PAGE__.txt +1 -1
  179. ui/static/settings/__next.settings.txt +1 -1
  180. ui/static/settings/index.html +1 -1
  181. ui/static/settings/index.txt +1 -1
  182. ui/static/static/404/index.html +1 -1
  183. ui/static/static/404.html +1 -1
  184. ui/static/static/__next.__PAGE__.txt +1 -1
  185. ui/static/static/__next._full.txt +2 -2
  186. ui/static/static/__next._head.txt +1 -1
  187. ui/static/static/__next._index.txt +2 -2
  188. ui/static/static/__next._tree.txt +2 -2
  189. ui/static/static/_next/static/chunks/13d4a0fbd74c1ee4.js +1 -0
  190. ui/static/static/_next/static/chunks/2edb43b48432ac04.js +441 -0
  191. ui/static/static/_next/static/chunks/d2363397e1b2bcab.css +1 -0
  192. ui/static/static/_next/static/chunks/f7d1a90dd75d2572.js +1 -0
  193. ui/static/static/_not-found/__next._full.txt +2 -2
  194. ui/static/static/_not-found/__next._head.txt +1 -1
  195. ui/static/static/_not-found/__next._index.txt +2 -2
  196. ui/static/static/_not-found/__next._not-found.__PAGE__.txt +1 -1
  197. ui/static/static/_not-found/__next._not-found.txt +1 -1
  198. ui/static/static/_not-found/__next._tree.txt +2 -2
  199. ui/static/static/_not-found/index.html +1 -1
  200. ui/static/static/_not-found/index.txt +2 -2
  201. ui/static/static/contracts/__next._full.txt +3 -3
  202. ui/static/static/contracts/__next._head.txt +1 -1
  203. ui/static/static/contracts/__next._index.txt +2 -2
  204. ui/static/static/contracts/__next._tree.txt +2 -2
  205. ui/static/static/contracts/__next.contracts.__PAGE__.txt +2 -2
  206. ui/static/static/contracts/__next.contracts.txt +1 -1
  207. ui/static/static/contracts/index.html +1 -1
  208. ui/static/static/contracts/index.txt +3 -3
  209. ui/static/static/documentation/__next._full.txt +3 -3
  210. ui/static/static/documentation/__next._head.txt +1 -1
  211. ui/static/static/documentation/__next._index.txt +2 -2
  212. ui/static/static/documentation/__next._tree.txt +2 -2
  213. ui/static/static/documentation/__next.documentation.__PAGE__.txt +2 -2
  214. ui/static/static/documentation/__next.documentation.txt +1 -1
  215. ui/static/static/documentation/index.html +2 -2
  216. ui/static/static/documentation/index.txt +3 -3
  217. ui/static/static/index.html +1 -1
  218. ui/static/static/index.txt +2 -2
  219. ui/static/static/metadata/__next._full.txt +2 -2
  220. ui/static/static/metadata/__next._head.txt +1 -1
  221. ui/static/static/metadata/__next._index.txt +2 -2
  222. ui/static/static/metadata/__next._tree.txt +2 -2
  223. ui/static/static/metadata/__next.metadata.__PAGE__.txt +1 -1
  224. ui/static/static/metadata/__next.metadata.txt +1 -1
  225. ui/static/static/metadata/index.html +1 -1
  226. ui/static/static/metadata/index.txt +2 -2
  227. ui/static/static/quality/__next._full.txt +2 -2
  228. ui/static/static/quality/__next._head.txt +1 -1
  229. ui/static/static/quality/__next._index.txt +2 -2
  230. ui/static/static/quality/__next._tree.txt +2 -2
  231. ui/static/static/quality/__next.quality.__PAGE__.txt +1 -1
  232. ui/static/static/quality/__next.quality.txt +1 -1
  233. ui/static/static/quality/index.html +2 -2
  234. ui/static/static/quality/index.txt +2 -2
  235. ui/static/static/rules/__next._full.txt +2 -2
  236. ui/static/static/rules/__next._head.txt +1 -1
  237. ui/static/static/rules/__next._index.txt +2 -2
  238. ui/static/static/rules/__next._tree.txt +2 -2
  239. ui/static/static/rules/__next.rules.__PAGE__.txt +1 -1
  240. ui/static/static/rules/__next.rules.txt +1 -1
  241. ui/static/static/rules/index.html +1 -1
  242. ui/static/static/rules/index.txt +2 -2
  243. ui/static/static/schemas/__next._full.txt +2 -2
  244. ui/static/static/schemas/__next._head.txt +1 -1
  245. ui/static/static/schemas/__next._index.txt +2 -2
  246. ui/static/static/schemas/__next._tree.txt +2 -2
  247. ui/static/static/schemas/__next.schemas.__PAGE__.txt +1 -1
  248. ui/static/static/schemas/__next.schemas.txt +1 -1
  249. ui/static/static/schemas/index.html +1 -1
  250. ui/static/static/schemas/index.txt +2 -2
  251. ui/static/static/settings/__next._full.txt +2 -2
  252. ui/static/static/settings/__next._head.txt +1 -1
  253. ui/static/static/settings/__next._index.txt +2 -2
  254. ui/static/static/settings/__next._tree.txt +2 -2
  255. ui/static/static/settings/__next.settings.__PAGE__.txt +1 -1
  256. ui/static/static/settings/__next.settings.txt +1 -1
  257. ui/static/static/settings/index.html +1 -1
  258. ui/static/static/settings/index.txt +2 -2
  259. ui/static/static/static/.gitkeep +0 -0
  260. ui/static/static/static/404/index.html +1 -0
  261. ui/static/static/static/404.html +1 -0
  262. ui/static/static/static/__next.__PAGE__.txt +10 -0
  263. ui/static/static/static/__next._full.txt +30 -0
  264. ui/static/static/static/__next._head.txt +7 -0
  265. ui/static/static/static/__next._index.txt +9 -0
  266. ui/static/static/static/__next._tree.txt +2 -0
  267. ui/static/static/static/_next/static/chunks/222442f6da32302a.js +1 -0
  268. ui/static/static/static/_next/static/chunks/247eb132b7f7b574.js +1 -0
  269. ui/static/static/static/_next/static/chunks/297d55555b71baba.js +1 -0
  270. ui/static/static/static/_next/static/chunks/2ab439ce003cd691.js +1 -0
  271. ui/static/static/static/_next/static/chunks/414e77373f8ff61c.js +1 -0
  272. ui/static/static/static/_next/static/chunks/49ca65abd26ae49e.js +1 -0
  273. ui/static/static/static/_next/static/chunks/652ad0aa26265c47.js +2 -0
  274. ui/static/static/static/_next/static/chunks/9667e7a3d359eb39.js +1 -0
  275. ui/static/static/static/_next/static/chunks/9c23f44fff36548a.js +1 -0
  276. ui/static/static/static/_next/static/chunks/a6dad97d9634a72d.js +1 -0
  277. ui/static/static/static/_next/static/chunks/b32a0963684b9933.js +4 -0
  278. ui/static/static/static/_next/static/chunks/c69f6cba366bd988.js +1 -0
  279. ui/static/static/static/_next/static/chunks/db913959c675cea6.js +1 -0
  280. ui/static/static/static/_next/static/chunks/f061a4be97bfc3b3.js +1 -0
  281. ui/static/static/static/_next/static/chunks/f2e7afeab1178138.js +1 -0
  282. ui/static/static/static/_next/static/chunks/ff1a16fafef87110.js +1 -0
  283. ui/static/static/static/_next/static/chunks/turbopack-ffcb7ab6794027ef.js +3 -0
  284. ui/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_buildManifest.js +11 -0
  285. ui/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_ssgManifest.js +1 -0
  286. ui/static/static/static/_not-found/__next._full.txt +17 -0
  287. ui/static/static/static/_not-found/__next._head.txt +7 -0
  288. ui/static/static/static/_not-found/__next._index.txt +9 -0
  289. ui/static/static/static/_not-found/__next._not-found.__PAGE__.txt +5 -0
  290. ui/static/static/static/_not-found/__next._not-found.txt +4 -0
  291. ui/static/static/static/_not-found/__next._tree.txt +2 -0
  292. ui/static/static/static/_not-found/index.html +1 -0
  293. ui/static/static/static/_not-found/index.txt +17 -0
  294. ui/static/static/static/contracts/__next._full.txt +21 -0
  295. ui/static/static/static/contracts/__next._head.txt +7 -0
  296. ui/static/static/static/contracts/__next._index.txt +9 -0
  297. ui/static/static/static/contracts/__next._tree.txt +2 -0
  298. ui/static/static/static/contracts/__next.contracts.__PAGE__.txt +9 -0
  299. ui/static/static/static/contracts/__next.contracts.txt +4 -0
  300. ui/static/static/static/contracts/index.html +1 -0
  301. ui/static/static/static/contracts/index.txt +21 -0
  302. ui/static/static/static/documentation/__next._full.txt +21 -0
  303. ui/static/static/static/documentation/__next._head.txt +7 -0
  304. ui/static/static/static/documentation/__next._index.txt +9 -0
  305. ui/static/static/static/documentation/__next._tree.txt +2 -0
  306. ui/static/static/static/documentation/__next.documentation.__PAGE__.txt +9 -0
  307. ui/static/static/static/documentation/__next.documentation.txt +4 -0
  308. ui/static/static/static/documentation/index.html +93 -0
  309. ui/static/static/static/documentation/index.txt +21 -0
  310. ui/static/static/static/index.html +1 -0
  311. ui/static/static/static/index.txt +30 -0
  312. ui/static/static/static/metadata/__next._full.txt +21 -0
  313. ui/static/static/static/metadata/__next._head.txt +7 -0
  314. ui/static/static/static/metadata/__next._index.txt +9 -0
  315. ui/static/static/static/metadata/__next._tree.txt +2 -0
  316. ui/static/static/static/metadata/__next.metadata.__PAGE__.txt +9 -0
  317. ui/static/static/static/metadata/__next.metadata.txt +4 -0
  318. ui/static/static/static/metadata/index.html +1 -0
  319. ui/static/static/static/metadata/index.txt +21 -0
  320. ui/static/static/static/quality/__next._full.txt +21 -0
  321. ui/static/static/static/quality/__next._head.txt +7 -0
  322. ui/static/static/static/quality/__next._index.txt +9 -0
  323. ui/static/static/static/quality/__next._tree.txt +2 -0
  324. ui/static/static/static/quality/__next.quality.__PAGE__.txt +9 -0
  325. ui/static/static/static/quality/__next.quality.txt +4 -0
  326. ui/static/static/static/quality/index.html +2 -0
  327. ui/static/static/static/quality/index.txt +21 -0
  328. ui/static/static/static/rules/__next._full.txt +21 -0
  329. ui/static/static/static/rules/__next._head.txt +7 -0
  330. ui/static/static/static/rules/__next._index.txt +9 -0
  331. ui/static/static/static/rules/__next._tree.txt +2 -0
  332. ui/static/static/static/rules/__next.rules.__PAGE__.txt +9 -0
  333. ui/static/static/static/rules/__next.rules.txt +4 -0
  334. ui/static/static/static/rules/index.html +1 -0
  335. ui/static/static/static/rules/index.txt +21 -0
  336. ui/static/static/static/schemas/__next._full.txt +21 -0
  337. ui/static/static/static/schemas/__next._head.txt +7 -0
  338. ui/static/static/static/schemas/__next._index.txt +9 -0
  339. ui/static/static/static/schemas/__next._tree.txt +2 -0
  340. ui/static/static/static/schemas/__next.schemas.__PAGE__.txt +9 -0
  341. ui/static/static/static/schemas/__next.schemas.txt +4 -0
  342. ui/static/static/static/schemas/index.html +1 -0
  343. ui/static/static/static/schemas/index.txt +21 -0
  344. ui/static/static/static/settings/__next._full.txt +21 -0
  345. ui/static/static/static/settings/__next._head.txt +7 -0
  346. ui/static/static/static/settings/__next._index.txt +9 -0
  347. ui/static/static/static/settings/__next._tree.txt +2 -0
  348. ui/static/static/static/settings/__next.settings.__PAGE__.txt +9 -0
  349. ui/static/static/static/settings/__next.settings.txt +4 -0
  350. ui/static/static/static/settings/index.html +1 -0
  351. ui/static/static/static/settings/index.txt +21 -0
  352. ui/static/static/static/validation/__next._full.txt +21 -0
  353. ui/static/static/static/validation/__next._head.txt +7 -0
  354. ui/static/static/static/validation/__next._index.txt +9 -0
  355. ui/static/static/static/validation/__next._tree.txt +2 -0
  356. ui/static/static/static/validation/__next.validation.__PAGE__.txt +9 -0
  357. ui/static/static/static/validation/__next.validation.txt +4 -0
  358. ui/static/static/static/validation/index.html +1 -0
  359. ui/static/static/static/validation/index.txt +21 -0
  360. ui/static/static/validation/__next._full.txt +2 -2
  361. ui/static/static/validation/__next._head.txt +1 -1
  362. ui/static/static/validation/__next._index.txt +2 -2
  363. ui/static/static/validation/__next._tree.txt +2 -2
  364. ui/static/static/validation/__next.validation.__PAGE__.txt +1 -1
  365. ui/static/static/validation/__next.validation.txt +1 -1
  366. ui/static/static/validation/index.html +1 -1
  367. ui/static/static/validation/index.txt +2 -2
  368. ui/static/validation/__next._full.txt +2 -2
  369. ui/static/validation/__next._head.txt +1 -1
  370. ui/static/validation/__next._index.txt +1 -1
  371. ui/static/validation/__next._tree.txt +1 -1
  372. ui/static/validation/__next.validation.__PAGE__.txt +2 -2
  373. ui/static/validation/__next.validation.txt +1 -1
  374. ui/static/validation/index.html +1 -1
  375. ui/static/validation/index.txt +2 -2
  376. pycharter/data/templates/template_coercion_rules.yaml +0 -15
  377. pycharter/data/templates/template_contract.yaml +0 -587
  378. pycharter/data/templates/template_metadata.yaml +0 -38
  379. pycharter/data/templates/template_schema.yaml +0 -22
  380. pycharter/data/templates/template_transform_advanced.yaml +0 -50
  381. pycharter/data/templates/template_transform_simple.yaml +0 -59
  382. pycharter/data/templates/template_validation_rules.yaml +0 -29
  383. pycharter/etl_generator/extraction.py +0 -916
  384. pycharter/etl_generator/factory.py +0 -174
  385. pycharter/etl_generator/orchestrator.py +0 -1650
  386. pycharter/integrations/__init__.py +0 -19
  387. pycharter/integrations/kafka.py +0 -178
  388. pycharter/integrations/streaming.py +0 -100
  389. pycharter-0.0.22.dist-info/RECORD +0 -358
  390. {pycharter-0.0.22.dist-info → pycharter-0.0.24.dist-info}/entry_points.txt +0 -0
  391. {pycharter-0.0.22.dist-info → pycharter-0.0.24.dist-info}/licenses/LICENSE +0 -0
  392. {pycharter-0.0.22.dist-info → pycharter-0.0.24.dist-info}/top_level.txt +0 -0
  393. /ui/static/_next/static/{0rYA78L88aUyD2Uh38hhX → 2gKjNv6YvE6BcIdFthBLs}/_buildManifest.js +0 -0
  394. /ui/static/_next/static/{0rYA78L88aUyD2Uh38hhX → 2gKjNv6YvE6BcIdFthBLs}/_ssgManifest.js +0 -0
  395. /ui/static/static/_next/static/{tNTkVW6puVXC4bAm4WrHl → 0rYA78L88aUyD2Uh38hhX}/_buildManifest.js +0 -0
  396. /ui/static/static/_next/static/{tNTkVW6puVXC4bAm4WrHl → 0rYA78L88aUyD2Uh38hhX}/_ssgManifest.js +0 -0
  397. /ui/static/{_next → static/_next}/static/chunks/c4fa4f4114b7c352.js +0 -0
  398. /ui/static/static/{_next → static/_next}/static/chunks/4e310fe5005770a3.css +0 -0
  399. /ui/static/{_next → static/static/_next}/static/chunks/5e04d10c4a7b58a3.js +0 -0
  400. /ui/static/static/{_next → static/_next}/static/chunks/5fc14c00a2779dc5.js +0 -0
  401. /ui/static/{_next → static/static/_next}/static/chunks/75d88a058d8ffaa6.js +0 -0
  402. /ui/static/{_next → static/static/_next}/static/chunks/8c89634cf6bad76f.js +0 -0
  403. /ui/static/static/{_next → static/_next}/static/chunks/b584574fdc8ab13e.js +0 -0
  404. /ui/static/static/{_next → static/_next}/static/chunks/d5989c94d3614b3a.js +0 -0
@@ -0,0 +1,238 @@
1
+ """
2
+ Quality Tracking Exporters - Export metrics in various formats.
3
+
4
+ Provides functions to export validation metrics in different
5
+ formats for external consumption.
6
+ """
7
+
8
+ import json
9
+ from datetime import datetime
10
+ from typing import List, Optional
11
+
12
+ from pycharter.quality.tracking.models import MetricsSummary, ValidationMetric
13
+
14
+
15
+ def export_json(
16
+ metrics: List[ValidationMetric],
17
+ pretty: bool = True,
18
+ include_metadata: bool = True,
19
+ ) -> str:
20
+ """
21
+ Export metrics as JSON.
22
+
23
+ Args:
24
+ metrics: List of ValidationMetrics to export
25
+ pretty: If True, format with indentation
26
+ include_metadata: If True, include metric metadata
27
+
28
+ Returns:
29
+ JSON string representation of metrics
30
+ """
31
+ data = []
32
+ for m in metrics:
33
+ metric_dict = m.to_dict()
34
+ if not include_metadata:
35
+ metric_dict.pop("metadata", None)
36
+ data.append(metric_dict)
37
+
38
+ if pretty:
39
+ return json.dumps(data, indent=2, default=str)
40
+ return json.dumps(data, default=str)
41
+
42
+
43
+ def export_prometheus(
44
+ metrics: List[ValidationMetric],
45
+ summaries: Optional[List[MetricsSummary]] = None,
46
+ prefix: str = "pycharter",
47
+ ) -> str:
48
+ """
49
+ Export metrics in Prometheus text format.
50
+
51
+ Generates Prometheus-compatible metrics that can be scraped
52
+ by a Prometheus server or used with pushgateway.
53
+
54
+ Args:
55
+ metrics: List of ValidationMetrics to export
56
+ summaries: Optional list of MetricsSummaries to export
57
+ prefix: Metric name prefix
58
+
59
+ Returns:
60
+ Prometheus text format string
61
+
62
+ Example output:
63
+ # HELP pycharter_validation_total Total validation runs
64
+ # TYPE pycharter_validation_total counter
65
+ pycharter_validation_total{schema="users",version="1.0.0"} 100
66
+ """
67
+ lines = []
68
+ timestamp_ms = int(datetime.utcnow().timestamp() * 1000)
69
+
70
+ # Helper to format labels
71
+ def format_labels(labels: dict) -> str:
72
+ parts = [f'{k}="{v}"' for k, v in labels.items()]
73
+ return "{" + ",".join(parts) + "}"
74
+
75
+ # Aggregate metrics by schema for summary metrics
76
+ schema_metrics: dict = {}
77
+ for m in metrics:
78
+ key = (m.schema_name, m.version)
79
+ if key not in schema_metrics:
80
+ schema_metrics[key] = {
81
+ "record_count": 0,
82
+ "valid_count": 0,
83
+ "error_count": 0,
84
+ "validity_rates": [],
85
+ "completeness_values": [],
86
+ "durations": [],
87
+ "latest": m,
88
+ }
89
+ data = schema_metrics[key]
90
+ data["record_count"] += m.record_count
91
+ data["valid_count"] += m.valid_count
92
+ data["error_count"] += m.error_count
93
+ data["validity_rates"].append(m.validity_rate)
94
+ data["completeness_values"].append(m.completeness)
95
+ data["durations"].append(m.duration_ms)
96
+ if m.timestamp > data["latest"].timestamp:
97
+ data["latest"] = m
98
+
99
+ # Total validations counter
100
+ lines.append(f"# HELP {prefix}_validations_total Total number of validation runs")
101
+ lines.append(f"# TYPE {prefix}_validations_total counter")
102
+ for (schema, version), data in schema_metrics.items():
103
+ labels = format_labels({"schema": schema, "version": version})
104
+ lines.append(f"{prefix}_validations_total{labels} {len(data['validity_rates'])}")
105
+
106
+ lines.append("")
107
+
108
+ # Total records processed
109
+ lines.append(f"# HELP {prefix}_records_total Total number of records processed")
110
+ lines.append(f"# TYPE {prefix}_records_total counter")
111
+ for (schema, version), data in schema_metrics.items():
112
+ labels = format_labels({"schema": schema, "version": version})
113
+ lines.append(f"{prefix}_records_total{labels} {data['record_count']}")
114
+
115
+ lines.append("")
116
+
117
+ # Valid records counter
118
+ lines.append(f"# HELP {prefix}_valid_records_total Total number of valid records")
119
+ lines.append(f"# TYPE {prefix}_valid_records_total counter")
120
+ for (schema, version), data in schema_metrics.items():
121
+ labels = format_labels({"schema": schema, "version": version})
122
+ lines.append(f"{prefix}_valid_records_total{labels} {data['valid_count']}")
123
+
124
+ lines.append("")
125
+
126
+ # Error records counter
127
+ lines.append(f"# HELP {prefix}_error_records_total Total number of records with errors")
128
+ lines.append(f"# TYPE {prefix}_error_records_total counter")
129
+ for (schema, version), data in schema_metrics.items():
130
+ labels = format_labels({"schema": schema, "version": version})
131
+ lines.append(f"{prefix}_error_records_total{labels} {data['error_count']}")
132
+
133
+ lines.append("")
134
+
135
+ # Validity rate gauge (latest value)
136
+ lines.append(f"# HELP {prefix}_validity_rate Current validity rate")
137
+ lines.append(f"# TYPE {prefix}_validity_rate gauge")
138
+ for (schema, version), data in schema_metrics.items():
139
+ labels = format_labels({"schema": schema, "version": version})
140
+ latest_rate = data["latest"].validity_rate
141
+ lines.append(f"{prefix}_validity_rate{labels} {latest_rate:.6f}")
142
+
143
+ lines.append("")
144
+
145
+ # Completeness gauge (latest value)
146
+ lines.append(f"# HELP {prefix}_completeness Current data completeness")
147
+ lines.append(f"# TYPE {prefix}_completeness gauge")
148
+ for (schema, version), data in schema_metrics.items():
149
+ labels = format_labels({"schema": schema, "version": version})
150
+ latest_completeness = data["latest"].completeness
151
+ lines.append(f"{prefix}_completeness{labels} {latest_completeness:.6f}")
152
+
153
+ lines.append("")
154
+
155
+ # Validation duration (latest value)
156
+ lines.append(f"# HELP {prefix}_validation_duration_ms Validation duration in milliseconds")
157
+ lines.append(f"# TYPE {prefix}_validation_duration_ms gauge")
158
+ for (schema, version), data in schema_metrics.items():
159
+ labels = format_labels({"schema": schema, "version": version})
160
+ latest_duration = data["latest"].duration_ms
161
+ lines.append(f"{prefix}_validation_duration_ms{labels} {latest_duration:.3f}")
162
+
163
+ lines.append("")
164
+
165
+ # Average validity rate
166
+ lines.append(f"# HELP {prefix}_validity_rate_avg Average validity rate")
167
+ lines.append(f"# TYPE {prefix}_validity_rate_avg gauge")
168
+ for (schema, version), data in schema_metrics.items():
169
+ labels = format_labels({"schema": schema, "version": version})
170
+ avg_rate = sum(data["validity_rates"]) / len(data["validity_rates"])
171
+ lines.append(f"{prefix}_validity_rate_avg{labels} {avg_rate:.6f}")
172
+
173
+ # Include summary metrics if provided
174
+ if summaries:
175
+ lines.append("")
176
+ lines.append(f"# HELP {prefix}_summary_total_validations Total validations in summary period")
177
+ lines.append(f"# TYPE {prefix}_summary_total_validations gauge")
178
+ for s in summaries:
179
+ labels = format_labels({"schema": s.schema_name})
180
+ lines.append(f"{prefix}_summary_total_validations{labels} {s.total_validations}")
181
+
182
+ lines.append("")
183
+ lines.append(f"# HELP {prefix}_summary_avg_validity_rate Average validity rate in summary period")
184
+ lines.append(f"# TYPE {prefix}_summary_avg_validity_rate gauge")
185
+ for s in summaries:
186
+ labels = format_labels({"schema": s.schema_name})
187
+ lines.append(f"{prefix}_summary_avg_validity_rate{labels} {s.avg_validity_rate:.6f}")
188
+
189
+ return "\n".join(lines) + "\n"
190
+
191
+
192
+ def export_csv(
193
+ metrics: List[ValidationMetric],
194
+ include_header: bool = True,
195
+ ) -> str:
196
+ """
197
+ Export metrics as CSV.
198
+
199
+ Args:
200
+ metrics: List of ValidationMetrics to export
201
+ include_header: If True, include header row
202
+
203
+ Returns:
204
+ CSV string representation of metrics
205
+ """
206
+ columns = [
207
+ "id",
208
+ "schema_name",
209
+ "version",
210
+ "timestamp",
211
+ "record_count",
212
+ "valid_count",
213
+ "error_count",
214
+ "validity_rate",
215
+ "completeness",
216
+ "duration_ms",
217
+ ]
218
+
219
+ lines = []
220
+ if include_header:
221
+ lines.append(",".join(columns))
222
+
223
+ for m in metrics:
224
+ row = [
225
+ m.id,
226
+ m.schema_name,
227
+ m.version,
228
+ m.timestamp.isoformat(),
229
+ str(m.record_count),
230
+ str(m.valid_count),
231
+ str(m.error_count),
232
+ f"{m.validity_rate:.6f}",
233
+ f"{m.completeness:.6f}",
234
+ f"{m.duration_ms:.3f}",
235
+ ]
236
+ lines.append(",".join(row))
237
+
238
+ return "\n".join(lines) + "\n"
@@ -0,0 +1,194 @@
1
+ """
2
+ Quality Tracking Models - Data models for metrics tracking.
3
+
4
+ Defines the core data structures for validation metrics
5
+ and aggregated summaries.
6
+ """
7
+
8
+ import uuid
9
+ from dataclasses import dataclass, field
10
+ from datetime import datetime
11
+ from typing import Any, Dict, List, Optional
12
+
13
+
14
+ @dataclass
15
+ class ValidationMetric:
16
+ """
17
+ Single validation run metric.
18
+
19
+ Captures all relevant metrics from a single validation operation
20
+ for time-series tracking and analysis.
21
+
22
+ Attributes:
23
+ id: Unique identifier for this metric
24
+ schema_name: Name of the schema validated against
25
+ version: Version of the schema
26
+ timestamp: When the validation occurred
27
+ record_count: Number of records validated
28
+ valid_count: Number of valid records
29
+ error_count: Number of records with errors
30
+ validity_rate: Ratio of valid records (0.0 to 1.0)
31
+ completeness: Overall data completeness (0.0 to 1.0)
32
+ field_completeness: Per-field completeness ratios
33
+ duration_ms: Validation duration in milliseconds
34
+ errors_by_type: Count of errors by error type
35
+ metadata: Additional custom metadata
36
+ """
37
+
38
+ schema_name: str
39
+ version: str
40
+ timestamp: datetime = field(default_factory=datetime.utcnow)
41
+ record_count: int = 0
42
+ valid_count: int = 0
43
+ error_count: int = 0
44
+ validity_rate: float = 1.0
45
+ completeness: float = 1.0
46
+ field_completeness: Dict[str, float] = field(default_factory=dict)
47
+ duration_ms: float = 0.0
48
+ errors_by_type: Dict[str, int] = field(default_factory=dict)
49
+ metadata: Dict[str, Any] = field(default_factory=dict)
50
+ id: str = field(default_factory=lambda: str(uuid.uuid4()))
51
+
52
+ def to_dict(self) -> Dict[str, Any]:
53
+ """Convert to dictionary."""
54
+ return {
55
+ "id": self.id,
56
+ "schema_name": self.schema_name,
57
+ "version": self.version,
58
+ "timestamp": self.timestamp.isoformat(),
59
+ "record_count": self.record_count,
60
+ "valid_count": self.valid_count,
61
+ "error_count": self.error_count,
62
+ "validity_rate": self.validity_rate,
63
+ "completeness": self.completeness,
64
+ "field_completeness": self.field_completeness,
65
+ "duration_ms": self.duration_ms,
66
+ "errors_by_type": self.errors_by_type,
67
+ "metadata": self.metadata,
68
+ }
69
+
70
+ @classmethod
71
+ def from_dict(cls, data: Dict[str, Any]) -> "ValidationMetric":
72
+ """Create from dictionary."""
73
+ timestamp = data.get("timestamp")
74
+ if isinstance(timestamp, str):
75
+ timestamp = datetime.fromisoformat(timestamp)
76
+ elif timestamp is None:
77
+ timestamp = datetime.utcnow()
78
+
79
+ return cls(
80
+ id=data.get("id", str(uuid.uuid4())),
81
+ schema_name=data["schema_name"],
82
+ version=data["version"],
83
+ timestamp=timestamp,
84
+ record_count=data.get("record_count", 0),
85
+ valid_count=data.get("valid_count", 0),
86
+ error_count=data.get("error_count", 0),
87
+ validity_rate=data.get("validity_rate", 1.0),
88
+ completeness=data.get("completeness", 1.0),
89
+ field_completeness=data.get("field_completeness", {}),
90
+ duration_ms=data.get("duration_ms", 0.0),
91
+ errors_by_type=data.get("errors_by_type", {}),
92
+ metadata=data.get("metadata", {}),
93
+ )
94
+
95
+
96
+ @dataclass
97
+ class MetricsSummary:
98
+ """
99
+ Aggregated metrics summary for a schema over a time period.
100
+
101
+ Provides statistical aggregations of validation metrics
102
+ for trend analysis and monitoring.
103
+
104
+ Attributes:
105
+ schema_name: Name of the schema
106
+ period_start: Start of the summary period
107
+ period_end: End of the summary period
108
+ total_validations: Total number of validation runs
109
+ total_records: Total number of records validated
110
+ total_valid: Total number of valid records
111
+ total_errors: Total number of errors
112
+ avg_validity_rate: Average validity rate
113
+ min_validity_rate: Minimum validity rate
114
+ max_validity_rate: Maximum validity rate
115
+ avg_completeness: Average completeness
116
+ avg_duration_ms: Average validation duration
117
+ top_error_types: Most common error types with counts
118
+ """
119
+
120
+ schema_name: str
121
+ period_start: datetime
122
+ period_end: datetime
123
+ total_validations: int = 0
124
+ total_records: int = 0
125
+ total_valid: int = 0
126
+ total_errors: int = 0
127
+ avg_validity_rate: float = 0.0
128
+ min_validity_rate: float = 1.0
129
+ max_validity_rate: float = 0.0
130
+ avg_completeness: float = 0.0
131
+ avg_duration_ms: float = 0.0
132
+ top_error_types: Dict[str, int] = field(default_factory=dict)
133
+
134
+ @property
135
+ def overall_validity_rate(self) -> float:
136
+ """Calculate overall validity rate from totals."""
137
+ if self.total_records == 0:
138
+ return 1.0
139
+ return self.total_valid / self.total_records
140
+
141
+ def to_dict(self) -> Dict[str, Any]:
142
+ """Convert to dictionary."""
143
+ return {
144
+ "schema_name": self.schema_name,
145
+ "period_start": self.period_start.isoformat(),
146
+ "period_end": self.period_end.isoformat(),
147
+ "total_validations": self.total_validations,
148
+ "total_records": self.total_records,
149
+ "total_valid": self.total_valid,
150
+ "total_errors": self.total_errors,
151
+ "avg_validity_rate": self.avg_validity_rate,
152
+ "min_validity_rate": self.min_validity_rate,
153
+ "max_validity_rate": self.max_validity_rate,
154
+ "avg_completeness": self.avg_completeness,
155
+ "avg_duration_ms": self.avg_duration_ms,
156
+ "overall_validity_rate": self.overall_validity_rate,
157
+ "top_error_types": self.top_error_types,
158
+ }
159
+
160
+
161
+ @dataclass
162
+ class MetricsFilter:
163
+ """
164
+ Filter criteria for querying metrics.
165
+
166
+ Attributes:
167
+ schema_name: Filter by schema name
168
+ version: Filter by schema version
169
+ since: Filter metrics after this time
170
+ until: Filter metrics before this time
171
+ min_validity_rate: Filter by minimum validity rate
172
+ limit: Maximum number of results
173
+ offset: Offset for pagination
174
+ """
175
+
176
+ schema_name: Optional[str] = None
177
+ version: Optional[str] = None
178
+ since: Optional[datetime] = None
179
+ until: Optional[datetime] = None
180
+ min_validity_rate: Optional[float] = None
181
+ limit: int = 100
182
+ offset: int = 0
183
+
184
+ def to_dict(self) -> Dict[str, Any]:
185
+ """Convert to dictionary (for serialization)."""
186
+ return {
187
+ "schema_name": self.schema_name,
188
+ "version": self.version,
189
+ "since": self.since.isoformat() if self.since else None,
190
+ "until": self.until.isoformat() if self.until else None,
191
+ "min_validity_rate": self.min_validity_rate,
192
+ "limit": self.limit,
193
+ "offset": self.offset,
194
+ }