pycharter 0.0.23__py3-none-any.whl → 0.0.25__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 (495) hide show
  1. pycharter/__init__.py +268 -58
  2. pycharter/api/README.md +340 -0
  3. {api → pycharter/api}/__init__.py +1 -1
  4. {api → pycharter/api}/dependencies/__init__.py +2 -2
  5. {api → pycharter/api}/main.py +28 -2
  6. {api → pycharter/api}/models/__init__.py +4 -4
  7. pycharter/api/models/docs.py +68 -0
  8. pycharter/api/models/evolution.py +117 -0
  9. pycharter/api/models/tracking.py +111 -0
  10. {api → pycharter/api}/models/validation.py +46 -6
  11. {api → pycharter/api}/routes/v1/__init__.py +14 -1
  12. {api → pycharter/api}/routes/v1/contracts.py +4 -4
  13. pycharter/api/routes/v1/docs.py +187 -0
  14. pycharter/api/routes/v1/evolution.py +337 -0
  15. {api → pycharter/api}/routes/v1/metadata.py +5 -5
  16. {api → pycharter/api}/routes/v1/quality.py +3 -3
  17. {api → pycharter/api}/routes/v1/schemas.py +1 -1
  18. {api → pycharter/api}/routes/v1/settings.py +1 -1
  19. {api → pycharter/api}/routes/v1/templates.py +168 -3
  20. pycharter/api/routes/v1/tracking.py +301 -0
  21. {api → pycharter/api}/routes/v1/validation.py +70 -33
  22. {api → pycharter/api}/routes/v1/validation_jobs.py +3 -3
  23. pycharter/cli.py +8 -10
  24. pycharter/data/templates/contract/README.md +144 -0
  25. pycharter/data/templates/contract/template_coercion_rules.yaml +54 -12
  26. pycharter/data/templates/contract/template_contract.yaml +87 -552
  27. pycharter/data/templates/contract/template_metadata.yaml +51 -21
  28. pycharter/data/templates/contract/template_schema.yaml +83 -5
  29. pycharter/data/templates/contract/template_validation_rules.yaml +68 -22
  30. pycharter/data/templates/etl/README.md +197 -64
  31. pycharter/data/templates/etl/extract_cloud_azure.yaml +14 -13
  32. pycharter/data/templates/etl/extract_cloud_gcs.yaml +17 -14
  33. pycharter/data/templates/etl/extract_cloud_s3.yaml +21 -15
  34. pycharter/data/templates/etl/extract_database.yaml +24 -18
  35. pycharter/data/templates/etl/extract_database_ssh.yaml +36 -23
  36. pycharter/data/templates/etl/extract_file_csv.yaml +15 -11
  37. pycharter/data/templates/etl/extract_file_glob.yaml +20 -12
  38. pycharter/data/templates/etl/extract_file_json.yaml +18 -8
  39. pycharter/data/templates/etl/extract_file_parquet.yaml +15 -8
  40. pycharter/data/templates/etl/extract_http_paginated.yaml +47 -43
  41. pycharter/data/templates/etl/extract_http_path_params.yaml +20 -27
  42. pycharter/data/templates/etl/extract_http_simple.yaml +30 -20
  43. pycharter/data/templates/etl/load_cloud_azure.yaml +24 -0
  44. pycharter/data/templates/etl/load_cloud_gcs.yaml +22 -0
  45. pycharter/data/templates/etl/load_cloud_s3.yaml +27 -0
  46. pycharter/data/templates/etl/load_file.yaml +34 -0
  47. pycharter/data/templates/etl/load_insert.yaml +11 -10
  48. pycharter/data/templates/etl/load_postgresql.yaml +31 -9
  49. pycharter/data/templates/etl/load_sqlite.yaml +12 -7
  50. pycharter/data/templates/etl/load_truncate_and_load.yaml +13 -11
  51. pycharter/data/templates/etl/load_upsert.yaml +17 -20
  52. pycharter/data/templates/etl/load_with_dlq.yaml +21 -11
  53. pycharter/data/templates/etl/load_with_ssh_tunnel.yaml +28 -21
  54. pycharter/data/templates/etl/pipeline_http_to_db.yaml +62 -25
  55. pycharter/data/templates/etl/transform_combined.yaml +26 -16
  56. pycharter/data/templates/etl/transform_custom_function.yaml +54 -14
  57. pycharter/data/templates/etl/transform_jsonata.yaml +44 -13
  58. pycharter/data/templates/etl/transform_simple.yaml +35 -17
  59. pycharter/db/README.md +179 -0
  60. pycharter/db/schemas/README.md +96 -0
  61. pycharter/docs_generator/__init__.py +43 -0
  62. pycharter/docs_generator/generator.py +465 -0
  63. pycharter/docs_generator/renderers.py +247 -0
  64. pycharter/etl_generator/ASYNC_AND_EXECUTION.md +91 -0
  65. pycharter/etl_generator/INTERFACES.md +143 -0
  66. pycharter/etl_generator/README.md +271 -0
  67. pycharter/etl_generator/TRANSFORMATION_GUIDE.md +452 -0
  68. pycharter/etl_generator/__init__.py +168 -80
  69. pycharter/etl_generator/builder.py +121 -0
  70. pycharter/etl_generator/config_loader.py +394 -0
  71. pycharter/etl_generator/config_validator.py +418 -0
  72. pycharter/etl_generator/context.py +132 -0
  73. pycharter/etl_generator/expression.py +499 -0
  74. pycharter/etl_generator/extractors/__init__.py +4 -0
  75. pycharter/etl_generator/extractors/cloud_storage.py +77 -1
  76. pycharter/etl_generator/extractors/database.py +71 -1
  77. pycharter/etl_generator/extractors/factory.py +112 -68
  78. pycharter/etl_generator/extractors/file.py +58 -1
  79. pycharter/etl_generator/extractors/http.py +80 -1
  80. pycharter/etl_generator/extractors/streaming.py +57 -0
  81. pycharter/etl_generator/loaders/__init__.py +41 -0
  82. pycharter/etl_generator/loaders/base.py +35 -0
  83. pycharter/etl_generator/loaders/cloud.py +87 -0
  84. pycharter/etl_generator/loaders/cloud_storage_loader.py +275 -0
  85. pycharter/etl_generator/loaders/database.py +274 -0
  86. pycharter/etl_generator/loaders/factory.py +180 -0
  87. pycharter/etl_generator/loaders/file.py +72 -0
  88. pycharter/etl_generator/loaders/file_loader.py +130 -0
  89. pycharter/etl_generator/pipeline.py +743 -0
  90. pycharter/etl_generator/protocols.py +54 -0
  91. pycharter/etl_generator/result.py +63 -0
  92. pycharter/etl_generator/schemas/__init__.py +49 -0
  93. pycharter/etl_generator/schemas/extract.json +234 -0
  94. pycharter/etl_generator/schemas/load.json +202 -0
  95. pycharter/etl_generator/schemas/pipeline.json +94 -0
  96. pycharter/etl_generator/schemas/transform.json +171 -0
  97. pycharter/etl_generator/transformers/__init__.py +49 -0
  98. pycharter/etl_generator/transformers/base.py +63 -0
  99. pycharter/etl_generator/transformers/config.py +45 -0
  100. pycharter/etl_generator/transformers/custom_function.py +101 -0
  101. pycharter/etl_generator/transformers/jsonata_transformer.py +56 -0
  102. pycharter/etl_generator/transformers/operations.py +218 -0
  103. pycharter/etl_generator/transformers/pipeline.py +54 -0
  104. pycharter/etl_generator/transformers/simple_operations.py +131 -0
  105. pycharter/metadata_store/README.md +229 -0
  106. pycharter/quality/README.md +235 -0
  107. pycharter/quality/__init__.py +25 -0
  108. pycharter/quality/tracking/__init__.py +64 -0
  109. pycharter/quality/tracking/collector.py +318 -0
  110. pycharter/quality/tracking/exporters.py +238 -0
  111. pycharter/quality/tracking/models.py +194 -0
  112. pycharter/quality/tracking/store.py +385 -0
  113. pycharter/runtime_validator/__init__.py +20 -7
  114. pycharter/runtime_validator/builder.py +328 -0
  115. pycharter/runtime_validator/validator.py +311 -7
  116. pycharter/runtime_validator/validator_core.py +61 -0
  117. pycharter/schema_evolution/__init__.py +61 -0
  118. pycharter/schema_evolution/compatibility.py +270 -0
  119. pycharter/schema_evolution/diff.py +496 -0
  120. pycharter/schema_evolution/models.py +201 -0
  121. pycharter/shared/__init__.py +56 -0
  122. pycharter/shared/errors.py +296 -0
  123. pycharter/shared/protocols.py +234 -0
  124. pycharter/ui/.eslintrc.json +4 -0
  125. pycharter/ui/README.md +186 -0
  126. {ui → pycharter/ui}/__init__.py +3 -3
  127. pycharter/ui/components.json +17 -0
  128. pycharter/ui/package-lock.json +6608 -0
  129. pycharter/ui/package.json +36 -0
  130. {ui → pycharter/ui}/server.py +7 -8
  131. pycharter/ui/static/_next/static/2gKjNv6YvE6BcIdFthBLs/_clientMiddlewareManifest.json +1 -0
  132. pycharter/ui/static/static/_next/static/0rYA78L88aUyD2Uh38hhX/_clientMiddlewareManifest.json +1 -0
  133. pycharter/ui/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_clientMiddlewareManifest.json +1 -0
  134. pycharter/ui/tsconfig.json +42 -0
  135. pycharter/worker/README.md +187 -0
  136. pycharter/worker/backends/__init__.py +8 -0
  137. pycharter/worker/backends/base.py +46 -0
  138. pycharter/worker/backends/spark.py +233 -0
  139. {worker → pycharter/worker}/cli.py +1 -1
  140. {worker → pycharter/worker}/processor.py +2 -2
  141. pycharter/worker/queue/__init__.py +8 -0
  142. pycharter/worker/queue/redis_queue.py +147 -0
  143. {pycharter-0.0.23.dist-info → pycharter-0.0.25.dist-info}/METADATA +141 -26
  144. pycharter-0.0.25.dist-info/RECORD +572 -0
  145. pycharter-0.0.25.dist-info/top_level.txt +1 -0
  146. pycharter/etl_generator/extraction.py +0 -701
  147. pycharter/etl_generator/factory.py +0 -174
  148. pycharter/etl_generator/orchestrator.py +0 -1650
  149. pycharter/integrations/__init__.py +0 -19
  150. pycharter/integrations/kafka.py +0 -178
  151. pycharter/integrations/streaming.py +0 -100
  152. pycharter-0.0.23.dist-info/RECORD +0 -498
  153. pycharter-0.0.23.dist-info/top_level.txt +0 -4
  154. {api → pycharter/api}/dependencies/database.py +0 -0
  155. {api → pycharter/api}/dependencies/store.py +0 -0
  156. {api → pycharter/api}/models/contracts.py +0 -0
  157. {api → pycharter/api}/models/metadata.py +0 -0
  158. {api → pycharter/api}/models/metadata_entities.py +0 -0
  159. {api → pycharter/api}/models/quality.py +0 -0
  160. {api → pycharter/api}/models/schemas.py +0 -0
  161. {api → pycharter/api}/routes/__init__.py +0 -0
  162. {api → pycharter/api}/utils.py +0 -0
  163. {ui → pycharter/ui}/build.py +0 -0
  164. {ui → pycharter/ui}/dev.py +0 -0
  165. {ui → pycharter/ui}/static/.gitkeep +0 -0
  166. {ui → pycharter/ui}/static/404/index.html +0 -0
  167. {ui → pycharter/ui}/static/404.html +0 -0
  168. {ui → pycharter/ui}/static/__next.__PAGE__.txt +0 -0
  169. {ui → pycharter/ui}/static/__next._full.txt +0 -0
  170. {ui → pycharter/ui}/static/__next._head.txt +0 -0
  171. {ui → pycharter/ui}/static/__next._index.txt +0 -0
  172. {ui → pycharter/ui}/static/__next._tree.txt +0 -0
  173. {ui → pycharter/ui}/static/_next/static/2gKjNv6YvE6BcIdFthBLs/_buildManifest.js +0 -0
  174. {ui → pycharter/ui}/static/_next/static/2gKjNv6YvE6BcIdFthBLs/_ssgManifest.js +0 -0
  175. {ui → pycharter/ui}/static/_next/static/chunks/13d4a0fbd74c1ee4.js +0 -0
  176. {ui → pycharter/ui}/static/_next/static/chunks/222442f6da32302a.js +0 -0
  177. {ui → pycharter/ui}/static/_next/static/chunks/247eb132b7f7b574.js +0 -0
  178. {ui → pycharter/ui}/static/_next/static/chunks/26dfc590f7714c03.js +0 -0
  179. {ui → pycharter/ui}/static/_next/static/chunks/297d55555b71baba.js +0 -0
  180. {ui → pycharter/ui}/static/_next/static/chunks/2ab439ce003cd691.js +0 -0
  181. {ui → pycharter/ui}/static/_next/static/chunks/2edb43b48432ac04.js +0 -0
  182. {ui → pycharter/ui}/static/_next/static/chunks/34d289e6db2ef551.js +0 -0
  183. {ui → pycharter/ui}/static/_next/static/chunks/414e77373f8ff61c.js +0 -0
  184. {ui → pycharter/ui}/static/_next/static/chunks/49ca65abd26ae49e.js +0 -0
  185. {ui → pycharter/ui}/static/_next/static/chunks/652ad0aa26265c47.js +0 -0
  186. {ui → pycharter/ui}/static/_next/static/chunks/9667e7a3d359eb39.js +0 -0
  187. {ui → pycharter/ui}/static/_next/static/chunks/99508d9d5869cc27.js +0 -0
  188. {ui → pycharter/ui}/static/_next/static/chunks/9c23f44fff36548a.js +0 -0
  189. {ui → pycharter/ui}/static/_next/static/chunks/a6dad97d9634a72d.js +0 -0
  190. {ui → pycharter/ui}/static/_next/static/chunks/b313c35a6ba76574.js +0 -0
  191. {ui → pycharter/ui}/static/_next/static/chunks/b32a0963684b9933.js +0 -0
  192. {ui → pycharter/ui}/static/_next/static/chunks/c69f6cba366bd988.js +0 -0
  193. {ui → pycharter/ui}/static/_next/static/chunks/d2363397e1b2bcab.css +0 -0
  194. {ui → pycharter/ui}/static/_next/static/chunks/db913959c675cea6.js +0 -0
  195. {ui → pycharter/ui}/static/_next/static/chunks/f061a4be97bfc3b3.js +0 -0
  196. {ui → pycharter/ui}/static/_next/static/chunks/f2e7afeab1178138.js +0 -0
  197. {ui → pycharter/ui}/static/_next/static/chunks/f7d1a90dd75d2572.js +0 -0
  198. {ui → pycharter/ui}/static/_next/static/chunks/ff1a16fafef87110.js +0 -0
  199. {ui → pycharter/ui}/static/_next/static/chunks/turbopack-ffcb7ab6794027ef.js +0 -0
  200. {ui → pycharter/ui}/static/_not-found/__next._full.txt +0 -0
  201. {ui → pycharter/ui}/static/_not-found/__next._head.txt +0 -0
  202. {ui → pycharter/ui}/static/_not-found/__next._index.txt +0 -0
  203. {ui → pycharter/ui}/static/_not-found/__next._not-found.__PAGE__.txt +0 -0
  204. {ui → pycharter/ui}/static/_not-found/__next._not-found.txt +0 -0
  205. {ui → pycharter/ui}/static/_not-found/__next._tree.txt +0 -0
  206. {ui → pycharter/ui}/static/_not-found/index.html +0 -0
  207. {ui → pycharter/ui}/static/_not-found/index.txt +0 -0
  208. {ui → pycharter/ui}/static/contracts/__next._full.txt +0 -0
  209. {ui → pycharter/ui}/static/contracts/__next._head.txt +0 -0
  210. {ui → pycharter/ui}/static/contracts/__next._index.txt +0 -0
  211. {ui → pycharter/ui}/static/contracts/__next._tree.txt +0 -0
  212. {ui → pycharter/ui}/static/contracts/__next.contracts.__PAGE__.txt +0 -0
  213. {ui → pycharter/ui}/static/contracts/__next.contracts.txt +0 -0
  214. {ui → pycharter/ui}/static/contracts/index.html +0 -0
  215. {ui → pycharter/ui}/static/contracts/index.txt +0 -0
  216. {ui → pycharter/ui}/static/documentation/__next._full.txt +0 -0
  217. {ui → pycharter/ui}/static/documentation/__next._head.txt +0 -0
  218. {ui → pycharter/ui}/static/documentation/__next._index.txt +0 -0
  219. {ui → pycharter/ui}/static/documentation/__next._tree.txt +0 -0
  220. {ui → pycharter/ui}/static/documentation/__next.documentation.__PAGE__.txt +0 -0
  221. {ui → pycharter/ui}/static/documentation/__next.documentation.txt +0 -0
  222. {ui → pycharter/ui}/static/documentation/index.html +0 -0
  223. {ui → pycharter/ui}/static/documentation/index.txt +0 -0
  224. {ui → pycharter/ui}/static/index.html +0 -0
  225. {ui → pycharter/ui}/static/index.txt +0 -0
  226. {ui → pycharter/ui}/static/metadata/__next._full.txt +0 -0
  227. {ui → pycharter/ui}/static/metadata/__next._head.txt +0 -0
  228. {ui → pycharter/ui}/static/metadata/__next._index.txt +0 -0
  229. {ui → pycharter/ui}/static/metadata/__next._tree.txt +0 -0
  230. {ui → pycharter/ui}/static/metadata/__next.metadata.__PAGE__.txt +0 -0
  231. {ui → pycharter/ui}/static/metadata/__next.metadata.txt +0 -0
  232. {ui → pycharter/ui}/static/metadata/index.html +0 -0
  233. {ui → pycharter/ui}/static/metadata/index.txt +0 -0
  234. {ui → pycharter/ui}/static/quality/__next._full.txt +0 -0
  235. {ui → pycharter/ui}/static/quality/__next._head.txt +0 -0
  236. {ui → pycharter/ui}/static/quality/__next._index.txt +0 -0
  237. {ui → pycharter/ui}/static/quality/__next._tree.txt +0 -0
  238. {ui → pycharter/ui}/static/quality/__next.quality.__PAGE__.txt +0 -0
  239. {ui → pycharter/ui}/static/quality/__next.quality.txt +0 -0
  240. {ui → pycharter/ui}/static/quality/index.html +0 -0
  241. {ui → pycharter/ui}/static/quality/index.txt +0 -0
  242. {ui → pycharter/ui}/static/rules/__next._full.txt +0 -0
  243. {ui → pycharter/ui}/static/rules/__next._head.txt +0 -0
  244. {ui → pycharter/ui}/static/rules/__next._index.txt +0 -0
  245. {ui → pycharter/ui}/static/rules/__next._tree.txt +0 -0
  246. {ui → pycharter/ui}/static/rules/__next.rules.__PAGE__.txt +0 -0
  247. {ui → pycharter/ui}/static/rules/__next.rules.txt +0 -0
  248. {ui → pycharter/ui}/static/rules/index.html +0 -0
  249. {ui → pycharter/ui}/static/rules/index.txt +0 -0
  250. {ui → pycharter/ui}/static/schemas/__next._full.txt +0 -0
  251. {ui → pycharter/ui}/static/schemas/__next._head.txt +0 -0
  252. {ui → pycharter/ui}/static/schemas/__next._index.txt +0 -0
  253. {ui → pycharter/ui}/static/schemas/__next._tree.txt +0 -0
  254. {ui → pycharter/ui}/static/schemas/__next.schemas.__PAGE__.txt +0 -0
  255. {ui → pycharter/ui}/static/schemas/__next.schemas.txt +0 -0
  256. {ui → pycharter/ui}/static/schemas/index.html +0 -0
  257. {ui → pycharter/ui}/static/schemas/index.txt +0 -0
  258. {ui → pycharter/ui}/static/settings/__next._full.txt +0 -0
  259. {ui → pycharter/ui}/static/settings/__next._head.txt +0 -0
  260. {ui → pycharter/ui}/static/settings/__next._index.txt +0 -0
  261. {ui → pycharter/ui}/static/settings/__next._tree.txt +0 -0
  262. {ui → pycharter/ui}/static/settings/__next.settings.__PAGE__.txt +0 -0
  263. {ui → pycharter/ui}/static/settings/__next.settings.txt +0 -0
  264. {ui → pycharter/ui}/static/settings/index.html +0 -0
  265. {ui → pycharter/ui}/static/settings/index.txt +0 -0
  266. {ui → pycharter/ui}/static/static/.gitkeep +0 -0
  267. {ui → pycharter/ui}/static/static/404/index.html +0 -0
  268. {ui → pycharter/ui}/static/static/404.html +0 -0
  269. {ui → pycharter/ui}/static/static/__next.__PAGE__.txt +0 -0
  270. {ui → pycharter/ui}/static/static/__next._full.txt +0 -0
  271. {ui → pycharter/ui}/static/static/__next._head.txt +0 -0
  272. {ui → pycharter/ui}/static/static/__next._index.txt +0 -0
  273. {ui → pycharter/ui}/static/static/__next._tree.txt +0 -0
  274. {ui → pycharter/ui}/static/static/_next/static/0rYA78L88aUyD2Uh38hhX/_buildManifest.js +0 -0
  275. {ui → pycharter/ui}/static/static/_next/static/0rYA78L88aUyD2Uh38hhX/_ssgManifest.js +0 -0
  276. {ui → pycharter/ui}/static/static/_next/static/chunks/13d4a0fbd74c1ee4.js +0 -0
  277. {ui → pycharter/ui}/static/static/_next/static/chunks/222442f6da32302a.js +0 -0
  278. {ui → pycharter/ui}/static/static/_next/static/chunks/247eb132b7f7b574.js +0 -0
  279. {ui → pycharter/ui}/static/static/_next/static/chunks/297d55555b71baba.js +0 -0
  280. {ui → pycharter/ui}/static/static/_next/static/chunks/2ab439ce003cd691.js +0 -0
  281. {ui → pycharter/ui}/static/static/_next/static/chunks/2edb43b48432ac04.js +0 -0
  282. {ui → pycharter/ui}/static/static/_next/static/chunks/414e77373f8ff61c.js +0 -0
  283. {ui → pycharter/ui}/static/static/_next/static/chunks/49ca65abd26ae49e.js +0 -0
  284. {ui → pycharter/ui}/static/static/_next/static/chunks/5e04d10c4a7b58a3.js +0 -0
  285. {ui → pycharter/ui}/static/static/_next/static/chunks/652ad0aa26265c47.js +0 -0
  286. {ui → pycharter/ui}/static/static/_next/static/chunks/75d88a058d8ffaa6.js +0 -0
  287. {ui → pycharter/ui}/static/static/_next/static/chunks/8c89634cf6bad76f.js +0 -0
  288. {ui → pycharter/ui}/static/static/_next/static/chunks/9667e7a3d359eb39.js +0 -0
  289. {ui → pycharter/ui}/static/static/_next/static/chunks/9c23f44fff36548a.js +0 -0
  290. {ui → pycharter/ui}/static/static/_next/static/chunks/a6dad97d9634a72d.js +0 -0
  291. {ui → pycharter/ui}/static/static/_next/static/chunks/b32a0963684b9933.js +0 -0
  292. {ui → pycharter/ui}/static/static/_next/static/chunks/c4fa4f4114b7c352.js +0 -0
  293. {ui → pycharter/ui}/static/static/_next/static/chunks/c69f6cba366bd988.js +0 -0
  294. {ui → pycharter/ui}/static/static/_next/static/chunks/d2363397e1b2bcab.css +0 -0
  295. {ui → pycharter/ui}/static/static/_next/static/chunks/db913959c675cea6.js +0 -0
  296. {ui → pycharter/ui}/static/static/_next/static/chunks/f061a4be97bfc3b3.js +0 -0
  297. {ui → pycharter/ui}/static/static/_next/static/chunks/f2e7afeab1178138.js +0 -0
  298. {ui → pycharter/ui}/static/static/_next/static/chunks/f7d1a90dd75d2572.js +0 -0
  299. {ui → pycharter/ui}/static/static/_next/static/chunks/ff1a16fafef87110.js +0 -0
  300. {ui → pycharter/ui}/static/static/_next/static/chunks/turbopack-ffcb7ab6794027ef.js +0 -0
  301. {ui → pycharter/ui}/static/static/_not-found/__next._full.txt +0 -0
  302. {ui → pycharter/ui}/static/static/_not-found/__next._head.txt +0 -0
  303. {ui → pycharter/ui}/static/static/_not-found/__next._index.txt +0 -0
  304. {ui → pycharter/ui}/static/static/_not-found/__next._not-found.__PAGE__.txt +0 -0
  305. {ui → pycharter/ui}/static/static/_not-found/__next._not-found.txt +0 -0
  306. {ui → pycharter/ui}/static/static/_not-found/__next._tree.txt +0 -0
  307. {ui → pycharter/ui}/static/static/_not-found/index.html +0 -0
  308. {ui → pycharter/ui}/static/static/_not-found/index.txt +0 -0
  309. {ui → pycharter/ui}/static/static/contracts/__next._full.txt +0 -0
  310. {ui → pycharter/ui}/static/static/contracts/__next._head.txt +0 -0
  311. {ui → pycharter/ui}/static/static/contracts/__next._index.txt +0 -0
  312. {ui → pycharter/ui}/static/static/contracts/__next._tree.txt +0 -0
  313. {ui → pycharter/ui}/static/static/contracts/__next.contracts.__PAGE__.txt +0 -0
  314. {ui → pycharter/ui}/static/static/contracts/__next.contracts.txt +0 -0
  315. {ui → pycharter/ui}/static/static/contracts/index.html +0 -0
  316. {ui → pycharter/ui}/static/static/contracts/index.txt +0 -0
  317. {ui → pycharter/ui}/static/static/documentation/__next._full.txt +0 -0
  318. {ui → pycharter/ui}/static/static/documentation/__next._head.txt +0 -0
  319. {ui → pycharter/ui}/static/static/documentation/__next._index.txt +0 -0
  320. {ui → pycharter/ui}/static/static/documentation/__next._tree.txt +0 -0
  321. {ui → pycharter/ui}/static/static/documentation/__next.documentation.__PAGE__.txt +0 -0
  322. {ui → pycharter/ui}/static/static/documentation/__next.documentation.txt +0 -0
  323. {ui → pycharter/ui}/static/static/documentation/index.html +0 -0
  324. {ui → pycharter/ui}/static/static/documentation/index.txt +0 -0
  325. {ui → pycharter/ui}/static/static/index.html +0 -0
  326. {ui → pycharter/ui}/static/static/index.txt +0 -0
  327. {ui → pycharter/ui}/static/static/metadata/__next._full.txt +0 -0
  328. {ui → pycharter/ui}/static/static/metadata/__next._head.txt +0 -0
  329. {ui → pycharter/ui}/static/static/metadata/__next._index.txt +0 -0
  330. {ui → pycharter/ui}/static/static/metadata/__next._tree.txt +0 -0
  331. {ui → pycharter/ui}/static/static/metadata/__next.metadata.__PAGE__.txt +0 -0
  332. {ui → pycharter/ui}/static/static/metadata/__next.metadata.txt +0 -0
  333. {ui → pycharter/ui}/static/static/metadata/index.html +0 -0
  334. {ui → pycharter/ui}/static/static/metadata/index.txt +0 -0
  335. {ui → pycharter/ui}/static/static/quality/__next._full.txt +0 -0
  336. {ui → pycharter/ui}/static/static/quality/__next._head.txt +0 -0
  337. {ui → pycharter/ui}/static/static/quality/__next._index.txt +0 -0
  338. {ui → pycharter/ui}/static/static/quality/__next._tree.txt +0 -0
  339. {ui → pycharter/ui}/static/static/quality/__next.quality.__PAGE__.txt +0 -0
  340. {ui → pycharter/ui}/static/static/quality/__next.quality.txt +0 -0
  341. {ui → pycharter/ui}/static/static/quality/index.html +0 -0
  342. {ui → pycharter/ui}/static/static/quality/index.txt +0 -0
  343. {ui → pycharter/ui}/static/static/rules/__next._full.txt +0 -0
  344. {ui → pycharter/ui}/static/static/rules/__next._head.txt +0 -0
  345. {ui → pycharter/ui}/static/static/rules/__next._index.txt +0 -0
  346. {ui → pycharter/ui}/static/static/rules/__next._tree.txt +0 -0
  347. {ui → pycharter/ui}/static/static/rules/__next.rules.__PAGE__.txt +0 -0
  348. {ui → pycharter/ui}/static/static/rules/__next.rules.txt +0 -0
  349. {ui → pycharter/ui}/static/static/rules/index.html +0 -0
  350. {ui → pycharter/ui}/static/static/rules/index.txt +0 -0
  351. {ui → pycharter/ui}/static/static/schemas/__next._full.txt +0 -0
  352. {ui → pycharter/ui}/static/static/schemas/__next._head.txt +0 -0
  353. {ui → pycharter/ui}/static/static/schemas/__next._index.txt +0 -0
  354. {ui → pycharter/ui}/static/static/schemas/__next._tree.txt +0 -0
  355. {ui → pycharter/ui}/static/static/schemas/__next.schemas.__PAGE__.txt +0 -0
  356. {ui → pycharter/ui}/static/static/schemas/__next.schemas.txt +0 -0
  357. {ui → pycharter/ui}/static/static/schemas/index.html +0 -0
  358. {ui → pycharter/ui}/static/static/schemas/index.txt +0 -0
  359. {ui → pycharter/ui}/static/static/settings/__next._full.txt +0 -0
  360. {ui → pycharter/ui}/static/static/settings/__next._head.txt +0 -0
  361. {ui → pycharter/ui}/static/static/settings/__next._index.txt +0 -0
  362. {ui → pycharter/ui}/static/static/settings/__next._tree.txt +0 -0
  363. {ui → pycharter/ui}/static/static/settings/__next.settings.__PAGE__.txt +0 -0
  364. {ui → pycharter/ui}/static/static/settings/__next.settings.txt +0 -0
  365. {ui → pycharter/ui}/static/static/settings/index.html +0 -0
  366. {ui → pycharter/ui}/static/static/settings/index.txt +0 -0
  367. {ui → pycharter/ui}/static/static/static/.gitkeep +0 -0
  368. {ui → pycharter/ui}/static/static/static/404/index.html +0 -0
  369. {ui → pycharter/ui}/static/static/static/404.html +0 -0
  370. {ui → pycharter/ui}/static/static/static/__next.__PAGE__.txt +0 -0
  371. {ui → pycharter/ui}/static/static/static/__next._full.txt +0 -0
  372. {ui → pycharter/ui}/static/static/static/__next._head.txt +0 -0
  373. {ui → pycharter/ui}/static/static/static/__next._index.txt +0 -0
  374. {ui → pycharter/ui}/static/static/static/__next._tree.txt +0 -0
  375. {ui → pycharter/ui}/static/static/static/_next/static/chunks/222442f6da32302a.js +0 -0
  376. {ui → pycharter/ui}/static/static/static/_next/static/chunks/247eb132b7f7b574.js +0 -0
  377. {ui → pycharter/ui}/static/static/static/_next/static/chunks/297d55555b71baba.js +0 -0
  378. {ui → pycharter/ui}/static/static/static/_next/static/chunks/2ab439ce003cd691.js +0 -0
  379. {ui → pycharter/ui}/static/static/static/_next/static/chunks/414e77373f8ff61c.js +0 -0
  380. {ui → pycharter/ui}/static/static/static/_next/static/chunks/49ca65abd26ae49e.js +0 -0
  381. {ui → pycharter/ui}/static/static/static/_next/static/chunks/4e310fe5005770a3.css +0 -0
  382. {ui → pycharter/ui}/static/static/static/_next/static/chunks/5e04d10c4a7b58a3.js +0 -0
  383. {ui → pycharter/ui}/static/static/static/_next/static/chunks/5fc14c00a2779dc5.js +0 -0
  384. {ui → pycharter/ui}/static/static/static/_next/static/chunks/652ad0aa26265c47.js +0 -0
  385. {ui → pycharter/ui}/static/static/static/_next/static/chunks/75d88a058d8ffaa6.js +0 -0
  386. {ui → pycharter/ui}/static/static/static/_next/static/chunks/8c89634cf6bad76f.js +0 -0
  387. {ui → pycharter/ui}/static/static/static/_next/static/chunks/9667e7a3d359eb39.js +0 -0
  388. {ui → pycharter/ui}/static/static/static/_next/static/chunks/9c23f44fff36548a.js +0 -0
  389. {ui → pycharter/ui}/static/static/static/_next/static/chunks/a6dad97d9634a72d.js +0 -0
  390. {ui → pycharter/ui}/static/static/static/_next/static/chunks/b32a0963684b9933.js +0 -0
  391. {ui → pycharter/ui}/static/static/static/_next/static/chunks/b584574fdc8ab13e.js +0 -0
  392. {ui → pycharter/ui}/static/static/static/_next/static/chunks/c69f6cba366bd988.js +0 -0
  393. {ui → pycharter/ui}/static/static/static/_next/static/chunks/d5989c94d3614b3a.js +0 -0
  394. {ui → pycharter/ui}/static/static/static/_next/static/chunks/db913959c675cea6.js +0 -0
  395. {ui → pycharter/ui}/static/static/static/_next/static/chunks/f061a4be97bfc3b3.js +0 -0
  396. {ui → pycharter/ui}/static/static/static/_next/static/chunks/f2e7afeab1178138.js +0 -0
  397. {ui → pycharter/ui}/static/static/static/_next/static/chunks/ff1a16fafef87110.js +0 -0
  398. {ui → pycharter/ui}/static/static/static/_next/static/chunks/turbopack-ffcb7ab6794027ef.js +0 -0
  399. {ui → pycharter/ui}/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_buildManifest.js +0 -0
  400. {ui → pycharter/ui}/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_ssgManifest.js +0 -0
  401. {ui → pycharter/ui}/static/static/static/_not-found/__next._full.txt +0 -0
  402. {ui → pycharter/ui}/static/static/static/_not-found/__next._head.txt +0 -0
  403. {ui → pycharter/ui}/static/static/static/_not-found/__next._index.txt +0 -0
  404. {ui → pycharter/ui}/static/static/static/_not-found/__next._not-found.__PAGE__.txt +0 -0
  405. {ui → pycharter/ui}/static/static/static/_not-found/__next._not-found.txt +0 -0
  406. {ui → pycharter/ui}/static/static/static/_not-found/__next._tree.txt +0 -0
  407. {ui → pycharter/ui}/static/static/static/_not-found/index.html +0 -0
  408. {ui → pycharter/ui}/static/static/static/_not-found/index.txt +0 -0
  409. {ui → pycharter/ui}/static/static/static/contracts/__next._full.txt +0 -0
  410. {ui → pycharter/ui}/static/static/static/contracts/__next._head.txt +0 -0
  411. {ui → pycharter/ui}/static/static/static/contracts/__next._index.txt +0 -0
  412. {ui → pycharter/ui}/static/static/static/contracts/__next._tree.txt +0 -0
  413. {ui → pycharter/ui}/static/static/static/contracts/__next.contracts.__PAGE__.txt +0 -0
  414. {ui → pycharter/ui}/static/static/static/contracts/__next.contracts.txt +0 -0
  415. {ui → pycharter/ui}/static/static/static/contracts/index.html +0 -0
  416. {ui → pycharter/ui}/static/static/static/contracts/index.txt +0 -0
  417. {ui → pycharter/ui}/static/static/static/documentation/__next._full.txt +0 -0
  418. {ui → pycharter/ui}/static/static/static/documentation/__next._head.txt +0 -0
  419. {ui → pycharter/ui}/static/static/static/documentation/__next._index.txt +0 -0
  420. {ui → pycharter/ui}/static/static/static/documentation/__next._tree.txt +0 -0
  421. {ui → pycharter/ui}/static/static/static/documentation/__next.documentation.__PAGE__.txt +0 -0
  422. {ui → pycharter/ui}/static/static/static/documentation/__next.documentation.txt +0 -0
  423. {ui → pycharter/ui}/static/static/static/documentation/index.html +0 -0
  424. {ui → pycharter/ui}/static/static/static/documentation/index.txt +0 -0
  425. {ui → pycharter/ui}/static/static/static/index.html +0 -0
  426. {ui → pycharter/ui}/static/static/static/index.txt +0 -0
  427. {ui → pycharter/ui}/static/static/static/metadata/__next._full.txt +0 -0
  428. {ui → pycharter/ui}/static/static/static/metadata/__next._head.txt +0 -0
  429. {ui → pycharter/ui}/static/static/static/metadata/__next._index.txt +0 -0
  430. {ui → pycharter/ui}/static/static/static/metadata/__next._tree.txt +0 -0
  431. {ui → pycharter/ui}/static/static/static/metadata/__next.metadata.__PAGE__.txt +0 -0
  432. {ui → pycharter/ui}/static/static/static/metadata/__next.metadata.txt +0 -0
  433. {ui → pycharter/ui}/static/static/static/metadata/index.html +0 -0
  434. {ui → pycharter/ui}/static/static/static/metadata/index.txt +0 -0
  435. {ui → pycharter/ui}/static/static/static/quality/__next._full.txt +0 -0
  436. {ui → pycharter/ui}/static/static/static/quality/__next._head.txt +0 -0
  437. {ui → pycharter/ui}/static/static/static/quality/__next._index.txt +0 -0
  438. {ui → pycharter/ui}/static/static/static/quality/__next._tree.txt +0 -0
  439. {ui → pycharter/ui}/static/static/static/quality/__next.quality.__PAGE__.txt +0 -0
  440. {ui → pycharter/ui}/static/static/static/quality/__next.quality.txt +0 -0
  441. {ui → pycharter/ui}/static/static/static/quality/index.html +0 -0
  442. {ui → pycharter/ui}/static/static/static/quality/index.txt +0 -0
  443. {ui → pycharter/ui}/static/static/static/rules/__next._full.txt +0 -0
  444. {ui → pycharter/ui}/static/static/static/rules/__next._head.txt +0 -0
  445. {ui → pycharter/ui}/static/static/static/rules/__next._index.txt +0 -0
  446. {ui → pycharter/ui}/static/static/static/rules/__next._tree.txt +0 -0
  447. {ui → pycharter/ui}/static/static/static/rules/__next.rules.__PAGE__.txt +0 -0
  448. {ui → pycharter/ui}/static/static/static/rules/__next.rules.txt +0 -0
  449. {ui → pycharter/ui}/static/static/static/rules/index.html +0 -0
  450. {ui → pycharter/ui}/static/static/static/rules/index.txt +0 -0
  451. {ui → pycharter/ui}/static/static/static/schemas/__next._full.txt +0 -0
  452. {ui → pycharter/ui}/static/static/static/schemas/__next._head.txt +0 -0
  453. {ui → pycharter/ui}/static/static/static/schemas/__next._index.txt +0 -0
  454. {ui → pycharter/ui}/static/static/static/schemas/__next._tree.txt +0 -0
  455. {ui → pycharter/ui}/static/static/static/schemas/__next.schemas.__PAGE__.txt +0 -0
  456. {ui → pycharter/ui}/static/static/static/schemas/__next.schemas.txt +0 -0
  457. {ui → pycharter/ui}/static/static/static/schemas/index.html +0 -0
  458. {ui → pycharter/ui}/static/static/static/schemas/index.txt +0 -0
  459. {ui → pycharter/ui}/static/static/static/settings/__next._full.txt +0 -0
  460. {ui → pycharter/ui}/static/static/static/settings/__next._head.txt +0 -0
  461. {ui → pycharter/ui}/static/static/static/settings/__next._index.txt +0 -0
  462. {ui → pycharter/ui}/static/static/static/settings/__next._tree.txt +0 -0
  463. {ui → pycharter/ui}/static/static/static/settings/__next.settings.__PAGE__.txt +0 -0
  464. {ui → pycharter/ui}/static/static/static/settings/__next.settings.txt +0 -0
  465. {ui → pycharter/ui}/static/static/static/settings/index.html +0 -0
  466. {ui → pycharter/ui}/static/static/static/settings/index.txt +0 -0
  467. {ui → pycharter/ui}/static/static/static/validation/__next._full.txt +0 -0
  468. {ui → pycharter/ui}/static/static/static/validation/__next._head.txt +0 -0
  469. {ui → pycharter/ui}/static/static/static/validation/__next._index.txt +0 -0
  470. {ui → pycharter/ui}/static/static/static/validation/__next._tree.txt +0 -0
  471. {ui → pycharter/ui}/static/static/static/validation/__next.validation.__PAGE__.txt +0 -0
  472. {ui → pycharter/ui}/static/static/static/validation/__next.validation.txt +0 -0
  473. {ui → pycharter/ui}/static/static/static/validation/index.html +0 -0
  474. {ui → pycharter/ui}/static/static/static/validation/index.txt +0 -0
  475. {ui → pycharter/ui}/static/static/validation/__next._full.txt +0 -0
  476. {ui → pycharter/ui}/static/static/validation/__next._head.txt +0 -0
  477. {ui → pycharter/ui}/static/static/validation/__next._index.txt +0 -0
  478. {ui → pycharter/ui}/static/static/validation/__next._tree.txt +0 -0
  479. {ui → pycharter/ui}/static/static/validation/__next.validation.__PAGE__.txt +0 -0
  480. {ui → pycharter/ui}/static/static/validation/__next.validation.txt +0 -0
  481. {ui → pycharter/ui}/static/static/validation/index.html +0 -0
  482. {ui → pycharter/ui}/static/static/validation/index.txt +0 -0
  483. {ui → pycharter/ui}/static/validation/__next._full.txt +0 -0
  484. {ui → pycharter/ui}/static/validation/__next._head.txt +0 -0
  485. {ui → pycharter/ui}/static/validation/__next._index.txt +0 -0
  486. {ui → pycharter/ui}/static/validation/__next._tree.txt +0 -0
  487. {ui → pycharter/ui}/static/validation/__next.validation.__PAGE__.txt +0 -0
  488. {ui → pycharter/ui}/static/validation/__next.validation.txt +0 -0
  489. {ui → pycharter/ui}/static/validation/index.html +0 -0
  490. {ui → pycharter/ui}/static/validation/index.txt +0 -0
  491. {worker → pycharter/worker}/__init__.py +0 -0
  492. {worker → pycharter/worker}/models.py +0 -0
  493. {pycharter-0.0.23.dist-info → pycharter-0.0.25.dist-info}/WHEEL +0 -0
  494. {pycharter-0.0.23.dist-info → pycharter-0.0.25.dist-info}/entry_points.txt +0 -0
  495. {pycharter-0.0.23.dist-info → pycharter-0.0.25.dist-info}/licenses/LICENSE +0 -0
pycharter/__init__.py CHANGED
@@ -1,22 +1,97 @@
1
1
  """
2
- PyCharter - Data Contract Management and Validation
2
+ PyCharter - Data Contract Management, ETL Pipelines, and Validation
3
3
 
4
4
  Core Services:
5
- 1. Contract Parser - Reads and decomposes data contract files
6
- 2. Contract Builder - Constructs consolidated contracts from separate artifacts
7
- 3. Metadata Store - Database operations for metadata storage
8
- 4. Pydantic Generator - Generates Pydantic models from JSON Schema
9
- 5. JSON Schema Converter - Converts Pydantic models to JSON Schema
10
- 6. Runtime Validator - Validation utilities
11
- 7. Quality Assurance - Data quality checking and monitoring
12
-
13
- API Organization:
14
- - Tier 1: Primary Interfaces (Classes - Use these for best performance)
15
- - Tier 2: Convenience Functions (Quick start - one-off use cases)
16
- - Tier 3: Low-Level Utilities (When you already have models/schemas)
5
+ 1. ETL Pipelines - Build and run ETL pipelines with | operator
6
+ 2. Contract Parser - Reads and decomposes data contract files
7
+ 3. Contract Builder - Constructs consolidated contracts from separate artifacts
8
+ 4. Metadata Store - Database operations for metadata storage
9
+ 5. Pydantic Generator - Generates Pydantic models from JSON Schema
10
+ 6. JSON Schema Converter - Converts Pydantic models to JSON Schema
11
+ 7. Runtime Validator - Validation utilities
12
+ 8. Quality Assurance - Data quality checking and monitoring
13
+
14
+ ETL API:
15
+ >>> from pycharter import Pipeline, HTTPExtractor, PostgresLoader, Rename, AddField
16
+ >>>
17
+ >>> # Programmatic pipeline with | operator
18
+ >>> pipeline = (
19
+ ... Pipeline(HTTPExtractor(url="https://api.example.com/data"))
20
+ ... | Rename({"old": "new"})
21
+ ... | AddField("processed_at", "now()")
22
+ ... | PostgresLoader(connection_string="...", table="users")
23
+ ... )
24
+ >>> result = await pipeline.run() # run() is async; use asyncio.run() from scripts
25
+ >>>
26
+ >>> # Config-driven (explicit files)
27
+ >>> pipeline = Pipeline.from_config_files(
28
+ ... extract="configs/extract.yaml",
29
+ ... load="configs/load.yaml",
30
+ ... variables={"API_KEY": "secret"}
31
+ ... )
32
+ >>>
33
+ >>> # Config-driven (directory with extract.yaml, transform.yaml, load.yaml)
34
+ >>> pipeline = Pipeline.from_config_dir("pipelines/users/")
35
+ >>>
36
+ >>> # Config-driven (single file)
37
+ >>> pipeline = Pipeline.from_config_file("pipelines/users/pipeline.yaml")
38
+
39
+ Validator API:
40
+ >>> from pycharter import Validator
41
+ >>>
42
+ >>> # From explicit files
43
+ >>> validator = Validator.from_files(schema="schema.yaml")
44
+ >>>
45
+ >>> # From directory
46
+ >>> validator = Validator.from_dir("contracts/users/")
47
+ >>>
48
+ >>> result = validator.validate({"name": "Alice", "age": 30})
17
49
  """
18
50
 
19
- __version__ = "0.0.22"
51
+ __version__ = "0.1.0"
52
+
53
+ # ============================================================================
54
+ # ETL PIPELINES
55
+ # ============================================================================
56
+
57
+ from pycharter.etl_generator import (
58
+ # Core
59
+ Pipeline,
60
+ PipelineBuilder,
61
+ PipelineContext,
62
+ PipelineResult,
63
+ BatchResult,
64
+ LoadResult,
65
+ # Protocols
66
+ Extractor,
67
+ Transformer,
68
+ Loader,
69
+ # Extractors
70
+ BaseExtractor,
71
+ HTTPExtractor,
72
+ FileExtractor,
73
+ DatabaseExtractor,
74
+ CloudStorageExtractor,
75
+ # Transformers
76
+ BaseTransformer,
77
+ TransformerChain,
78
+ Rename,
79
+ AddField,
80
+ Drop,
81
+ Select,
82
+ Filter,
83
+ Convert,
84
+ Default,
85
+ Map,
86
+ FlatMap,
87
+ CustomFunction,
88
+ # Loaders
89
+ BaseLoader,
90
+ PostgresLoader,
91
+ DatabaseLoader,
92
+ FileLoader,
93
+ CloudStorageLoader,
94
+ )
20
95
 
21
96
  # ============================================================================
22
97
  # TIER 1: PRIMARY INTERFACES (Classes - Use these for best performance)
@@ -25,7 +100,9 @@ __version__ = "0.0.22"
25
100
  # Runtime Validator (PRIMARY INTERFACE)
26
101
  from pycharter.runtime_validator import (
27
102
  Validator, # ⭐ PRIMARY: Use this for validation
103
+ ValidatorBuilder, # Fluent API for building validators
28
104
  create_validator,
105
+ QualityMetrics as ValidationQualityMetrics, # Quality metrics from validation
29
106
  )
30
107
 
31
108
  # Quality Assurance (PRIMARY INTERFACE)
@@ -140,22 +217,145 @@ from pycharter.quality import (
140
217
  ViolationTracker,
141
218
  ViolationRecord,
142
219
  DataProfiler,
220
+ # Tracking submodule
221
+ MetricsCollector,
222
+ ValidationMetric,
223
+ MetricsSummary,
224
+ InMemoryMetricsStore,
225
+ SQLiteMetricsStore,
226
+ )
227
+
228
+ # ============================================================================
229
+ # DOCUMENTATION GENERATION
230
+ # ============================================================================
231
+
232
+ from pycharter.docs_generator import (
233
+ DocsGenerator,
234
+ generate_docs,
235
+ MarkdownRenderer,
236
+ HTMLRenderer,
237
+ )
238
+
239
+ # ============================================================================
240
+ # SCHEMA EVOLUTION
241
+ # ============================================================================
242
+
243
+ from pycharter.schema_evolution import (
244
+ check_compatibility,
245
+ compute_diff,
246
+ CompatibilityResult,
247
+ SchemaDiff,
248
+ SchemaChange,
249
+ ChangeType,
250
+ CompatibilityMode,
251
+ )
252
+
253
+ # ============================================================================
254
+ # PROTOCOLS AND ERROR HANDLING
255
+ # ============================================================================
256
+
257
+ from pycharter.shared import (
258
+ # Protocols for extensibility
259
+ MetadataStore,
260
+ CoercionRegistry,
261
+ ValidationRegistry,
262
+ DataValidator,
263
+ # Exception hierarchy (catch PyCharterError for any pycharter failure)
264
+ PyCharterError,
265
+ ConfigError,
266
+ ConfigValidationError,
267
+ ConfigLoadError,
268
+ ExpressionError,
269
+ # Error handling
270
+ ErrorMode,
271
+ ErrorContext,
272
+ StrictMode,
273
+ LenientMode,
274
+ set_error_mode,
143
275
  )
144
276
 
145
277
  __all__ = [
146
278
  # ========================================================================
147
- # TIER 1: PRIMARY INTERFACES
279
+ # ETL PIPELINES
280
+ # ========================================================================
281
+ # Core
282
+ "Pipeline",
283
+ "PipelineBuilder",
284
+ "PipelineContext",
285
+ "PipelineResult",
286
+ "BatchResult",
287
+ "LoadResult",
288
+ # Protocols
289
+ "Extractor",
290
+ "Transformer",
291
+ "Loader",
292
+ # Extractors
293
+ "BaseExtractor",
294
+ "HTTPExtractor",
295
+ "FileExtractor",
296
+ "DatabaseExtractor",
297
+ "CloudStorageExtractor",
298
+ # Transformers
299
+ "BaseTransformer",
300
+ "TransformerChain",
301
+ "Rename",
302
+ "AddField",
303
+ "Drop",
304
+ "Select",
305
+ "Filter",
306
+ "Convert",
307
+ "Default",
308
+ "Map",
309
+ "FlatMap",
310
+ "CustomFunction",
311
+ # Loaders
312
+ "BaseLoader",
313
+ "PostgresLoader",
314
+ "DatabaseLoader",
315
+ "FileLoader",
316
+ "CloudStorageLoader",
317
+ # Exceptions and error handling
318
+ "PyCharterError",
319
+ "ConfigError",
320
+ "ConfigValidationError",
321
+ "ConfigLoadError",
322
+ "ExpressionError",
323
+ "ErrorMode",
324
+ "ErrorContext",
325
+ "StrictMode",
326
+ "LenientMode",
327
+ "set_error_mode",
148
328
  # ========================================================================
149
- "Validator", # PRIMARY: Use for validation
329
+ # DATA CONTRACT SERVICES
330
+ # ========================================================================
331
+ # Validation
332
+ "Validator",
333
+ "ValidatorBuilder",
150
334
  "create_validator",
151
- "QualityCheck", # ⭐ PRIMARY: Use for quality checks
335
+ "ValidationResult",
336
+ "ValidationQualityMetrics",
337
+ "validate_with_store",
338
+ "validate_batch_with_store",
339
+ "validate_with_contract",
340
+ "validate_batch_with_contract",
341
+ "get_model_from_store",
342
+ "get_model_from_contract",
343
+ "validate",
344
+ "validate_batch",
345
+ "validate_input",
346
+ "validate_output",
347
+ "validate_with_contract_decorator",
348
+ # Quality
349
+ "QualityCheck",
152
350
  "QualityCheckOptions",
153
351
  "QualityReport",
154
352
  "QualityThresholds",
155
- "MetadataStoreClient",
156
- # ========================================================================
157
- # TIER 2: CONVENIENCE FUNCTIONS
158
- # ========================================================================
353
+ "QualityMetrics",
354
+ "QualityScore",
355
+ "FieldQualityMetrics",
356
+ "ViolationTracker",
357
+ "ViolationRecord",
358
+ "DataProfiler",
159
359
  # Contract Management
160
360
  "parse_contract",
161
361
  "parse_contract_file",
@@ -163,49 +363,59 @@ __all__ = [
163
363
  "build_contract",
164
364
  "build_contract_from_store",
165
365
  "ContractArtifacts",
166
- # Pydantic Generator (input type helpers)
167
- "from_dict", # Quick: dict → model
168
- "from_file", # Quick: file → model
169
- "from_json", # Quick: JSON string → model
170
- "from_url", # Quick: URL → model
171
- "generate_model", # Advanced: more control
366
+ # Pydantic Generator
367
+ "from_dict",
368
+ "from_file",
369
+ "from_json",
370
+ "from_url",
371
+ "generate_model",
172
372
  "generate_model_file",
173
- # JSON Schema Converter (output type helpers)
174
- "to_dict", # Quick: model → dict
175
- "to_file", # Quick: model → file
176
- "to_json", # Quick: model → JSON string
177
- "model_to_schema", # Advanced: core conversion
178
- # Runtime Validator (data source helpers)
179
- "ValidationResult",
180
- "validate_with_store", # Quick: store → validate
181
- "validate_batch_with_store", # Quick: batch validate with store
182
- "validate_with_contract", # Quick: contract → validate
183
- "validate_batch_with_contract", # Quick: batch validate with contract
184
- "get_model_from_store", # Quick: store → model
185
- "get_model_from_contract", # Quick: contract → model
186
- "validate_input", # Decorator
187
- "validate_output", # Decorator
188
- "validate_with_contract_decorator",
189
- # ========================================================================
190
- # TIER 3: LOW-LEVEL UTILITIES
191
- # ========================================================================
192
- "validate", # Low-level: model → validate
193
- "validate_batch", # Low-level: model → batch validate
194
- # ========================================================================
195
- # METADATA STORE IMPLEMENTATIONS
196
- # ========================================================================
373
+ # JSON Schema Converter
374
+ "to_dict",
375
+ "to_file",
376
+ "to_json",
377
+ "model_to_schema",
378
+ # Metadata Store
379
+ "MetadataStoreClient",
197
380
  "InMemoryMetadataStore",
198
381
  "MongoDBMetadataStore",
199
382
  "PostgresMetadataStore",
200
383
  "RedisMetadataStore",
201
384
  "SQLiteMetadataStore",
385
+ # Protocols
386
+ "MetadataStore",
387
+ "CoercionRegistry",
388
+ "ValidationRegistry",
389
+ "DataValidator",
390
+ # Error handling
391
+ "ErrorMode",
392
+ "ErrorContext",
393
+ "StrictMode",
394
+ "LenientMode",
395
+ "set_error_mode",
202
396
  # ========================================================================
203
- # QUALITY ASSURANCE - Additional utilities
397
+ # QUALITY TRACKING
204
398
  # ========================================================================
205
- "QualityMetrics",
206
- "QualityScore",
207
- "FieldQualityMetrics",
208
- "ViolationTracker",
209
- "ViolationRecord",
210
- "DataProfiler",
399
+ "MetricsCollector",
400
+ "ValidationMetric",
401
+ "MetricsSummary",
402
+ "InMemoryMetricsStore",
403
+ "SQLiteMetricsStore",
404
+ # ========================================================================
405
+ # DOCUMENTATION GENERATION
406
+ # ========================================================================
407
+ "DocsGenerator",
408
+ "generate_docs",
409
+ "MarkdownRenderer",
410
+ "HTMLRenderer",
411
+ # ========================================================================
412
+ # SCHEMA EVOLUTION
413
+ # ========================================================================
414
+ "check_compatibility",
415
+ "compute_diff",
416
+ "CompatibilityResult",
417
+ "SchemaDiff",
418
+ "SchemaChange",
419
+ "ChangeType",
420
+ "CompatibilityMode",
211
421
  ]
@@ -0,0 +1,340 @@
1
+ # PyCharter API
2
+
3
+ REST API wrapper for PyCharter services using FastAPI.
4
+
5
+ ## Overview
6
+
7
+ The PyCharter API is located at the root level of the repository (`api/`) and provides HTTP endpoints for all core PyCharter services:
8
+ - **Contract Parsing**: Parse data contract files into components
9
+ - **Contract Building**: Reconstruct contracts from metadata store
10
+ - **Metadata Storage**: Store and retrieve schemas, metadata, and rules
11
+ - **Schema Generation**: Generate Pydantic models from JSON Schemas
12
+ - **Schema Conversion**: Convert Pydantic models to JSON Schemas
13
+ - **Runtime Validation**: Validate data against schemas
14
+ - **Quality Assurance**: Run quality checks, query metrics and violations
15
+
16
+ ## Installation
17
+
18
+ Install PyCharter with API dependencies:
19
+
20
+ ```bash
21
+ pip install pycharter[api]
22
+ ```
23
+
24
+ ## Running the API Server
25
+
26
+ ### Using the CLI command:
27
+
28
+ ```bash
29
+ pycharter api
30
+ ```
31
+
32
+ ### Using uvicorn directly:
33
+
34
+ ```bash
35
+ uvicorn api.main:app --reload
36
+ ```
37
+
38
+ ### Using Python:
39
+
40
+ ```python
41
+ from api.main import main
42
+ main()
43
+ ```
44
+
45
+ ## Configuration
46
+
47
+ The API requires a database connection for most endpoints. Configure it using environment variables:
48
+
49
+ ### Database URL Configuration
50
+
51
+ The API uses `PYCHARTER_DATABASE_URL` environment variable to connect to the database. You can set it in several ways:
52
+
53
+ #### Method 1: Export in Shell (Recommended)
54
+
55
+ ```bash
56
+ # Set the environment variable
57
+ export PYCHARTER_DATABASE_URL="postgresql://user:password@localhost:5432/pycharter"
58
+
59
+ # Then run the API
60
+ pycharter api
61
+ ```
62
+
63
+ #### Method 2: Inline with Command
64
+
65
+ ```bash
66
+ # Set and run in one line
67
+ PYCHARTER_DATABASE_URL="postgresql://user:password@localhost:5432/pycharter" pycharter api
68
+ ```
69
+
70
+ #### Method 3: Add to Shell Profile (Persistent)
71
+
72
+ Add to your `~/.bashrc`, `~/.zshrc`, or `~/.profile`:
73
+
74
+ ```bash
75
+ export PYCHARTER_DATABASE_URL="postgresql://user:password@localhost:5432/pycharter"
76
+ ```
77
+
78
+ Then reload your shell:
79
+ ```bash
80
+ source ~/.bashrc # or source ~/.zshrc
81
+ ```
82
+
83
+ #### Method 4: Using a .env File
84
+
85
+ Create a `.env` file in your project root:
86
+
87
+ ```bash
88
+ PYCHARTER_DATABASE_URL=postgresql://user:password@localhost:5432/pycharter
89
+ ```
90
+
91
+ Then load it before running (requires `python-dotenv`):
92
+ ```bash
93
+ export $(cat .env | xargs)
94
+ pycharter api
95
+ ```
96
+
97
+ Or use `dotenv-cli`:
98
+ ```bash
99
+ pip install dotenv-cli
100
+ dotenv run pycharter api
101
+ ```
102
+
103
+ ### Alternative Environment Variable
104
+
105
+ PyCharter also supports Airflow-style configuration:
106
+
107
+ ```bash
108
+ export PYCHARTER__DATABASE__SQL_ALCHEMY_CONN="postgresql://user:password@localhost:5432/pycharter"
109
+ ```
110
+
111
+ ### Metadata Store Configuration
112
+
113
+ The API can be configured to use different metadata store backends:
114
+
115
+ ```bash
116
+ # Metadata store type (in_memory, postgres, mongodb, redis)
117
+ export PYCHARTER_API_STORE_TYPE=postgres
118
+
119
+ # Connection string for database-backed stores
120
+ export PYCHARTER_API_CONNECTION_STRING=postgresql://user:pass@localhost:5432/pycharter
121
+ ```
122
+
123
+ **Note**: If `PYCHARTER_DATABASE_URL` is set, it will be used for both the database connection and metadata store (for PostgreSQL).
124
+
125
+ ## API Endpoints
126
+
127
+ ### Contract Endpoints
128
+
129
+ #### `POST /api/v1/contracts/parse`
130
+ Parse a data contract dictionary into components.
131
+
132
+ **Request Body:**
133
+ ```json
134
+ {
135
+ "contract": {
136
+ "schema": {...},
137
+ "metadata": {...},
138
+ "ownership": {...},
139
+ "governance_rules": {...}
140
+ }
141
+ }
142
+ ```
143
+
144
+ **Response:**
145
+ ```json
146
+ {
147
+ "schema": {...},
148
+ "metadata": {...},
149
+ "ownership": {...},
150
+ "governance_rules": {...},
151
+ "coercion_rules": {...},
152
+ "validation_rules": {...},
153
+ "versions": {...}
154
+ }
155
+ ```
156
+
157
+ #### `POST /api/v1/contracts/build`
158
+ Build a complete contract from metadata store.
159
+
160
+ **Request Body:**
161
+ ```json
162
+ {
163
+ "schema_id": "user_schema",
164
+ "version": "1.0.0",
165
+ "include_metadata": true,
166
+ "include_ownership": true,
167
+ "include_governance": true
168
+ }
169
+ ```
170
+
171
+ #### `GET /api/v1/contracts`
172
+ List all data contracts stored in the database.
173
+
174
+ #### `GET /api/v1/contracts/{contract_id}`
175
+ Get a specific data contract by ID.
176
+
177
+ ### Metadata Endpoints
178
+
179
+ #### `GET /api/v1/metadata/schemas`
180
+ List all schemas stored in the metadata store.
181
+
182
+ #### `GET /api/v1/metadata/schemas/{schema_id}`
183
+ Get a schema by ID (optional version parameter).
184
+
185
+ #### `GET /api/v1/metadata/schemas/{schema_id}/complete`
186
+ Get complete schema with coercion and validation rules merged.
187
+
188
+ #### `POST /api/v1/metadata/schemas`
189
+ Store a schema in the metadata store.
190
+
191
+ #### `GET /api/v1/metadata/metadata/{schema_id}`
192
+ Get metadata for a schema (optional version parameter).
193
+
194
+ #### `POST /api/v1/metadata/metadata`
195
+ Store metadata for a schema.
196
+
197
+ #### `GET /api/v1/metadata/coercion-rules/{schema_id}`
198
+ Get coercion rules for a schema (optional version parameter).
199
+
200
+ #### `POST /api/v1/metadata/coercion-rules`
201
+ Store coercion rules for a schema.
202
+
203
+ #### `GET /api/v1/metadata/validation-rules/{schema_id}`
204
+ Get validation rules for a schema (optional version parameter).
205
+
206
+ #### `POST /api/v1/metadata/validation-rules`
207
+ Store validation rules for a schema.
208
+
209
+ ### Quality Assurance Endpoints
210
+
211
+ #### `GET /api/v1/quality/metrics`
212
+ List quality metrics (optional filtering by schema_id, pagination).
213
+
214
+ #### `GET /api/v1/quality/metrics/{metric_id}`
215
+ Get a specific quality metric by ID.
216
+
217
+ #### `GET /api/v1/quality/reports/{schema_id}`
218
+ Get quality reports for a schema/data feed (optional data_source filter).
219
+
220
+ #### `POST /api/v1/quality/check`
221
+ Run a quality check against a data contract.
222
+
223
+ #### `POST /api/v1/quality/violations`
224
+ Query data quality violations.
225
+
226
+ ### Schema Endpoints
227
+
228
+ #### `POST /api/v1/schemas/generate`
229
+ Generate Pydantic model from JSON Schema.
230
+
231
+ #### `POST /api/v1/schemas/convert`
232
+ Convert Pydantic model to JSON Schema.
233
+
234
+ ### Validation Endpoints
235
+
236
+ #### `POST /api/v1/validation/validate`
237
+ Validate a single record against a schema.
238
+
239
+ #### `POST /api/v1/validation/validate-batch`
240
+ Validate a batch of records against a schema.
241
+
242
+ ## API Documentation
243
+
244
+ Once the API server is running, you can access:
245
+
246
+ - **Swagger UI**: http://localhost:8000/docs
247
+ - **ReDoc**: http://localhost:8000/redoc
248
+ - **OpenAPI JSON**: http://localhost:8000/openapi.json
249
+
250
+ ## Example Usage
251
+
252
+ ### Using curl:
253
+
254
+ ```bash
255
+ # List all contracts
256
+ curl http://localhost:8000/api/v1/contracts
257
+
258
+ # Get a specific contract
259
+ curl http://localhost:8000/api/v1/contracts/{contract_id}
260
+
261
+ # List all schemas
262
+ curl http://localhost:8000/api/v1/metadata/schemas
263
+
264
+ # Get a schema
265
+ curl http://localhost:8000/api/v1/metadata/schemas/{schema_id}
266
+
267
+ # Get quality metrics
268
+ curl http://localhost:8000/api/v1/quality/metrics
269
+
270
+ # Get quality report for a schema
271
+ curl http://localhost:8000/api/v1/quality/reports/{schema_id}
272
+ ```
273
+
274
+ ### Using Python requests:
275
+
276
+ ```python
277
+ import requests
278
+
279
+ # List contracts
280
+ response = requests.get("http://localhost:8000/api/v1/contracts")
281
+ contracts = response.json()
282
+
283
+ # Get quality metrics
284
+ response = requests.get("http://localhost:8000/api/v1/quality/metrics")
285
+ metrics = response.json()
286
+ ```
287
+
288
+ ## Troubleshooting
289
+
290
+ ### Database Connection Issues
291
+
292
+ If you see errors about database URL not being configured:
293
+
294
+ 1. **Check environment variable is set:**
295
+ ```bash
296
+ echo $PYCHARTER_DATABASE_URL
297
+ ```
298
+
299
+ 2. **Verify database is accessible:**
300
+ ```bash
301
+ psql $PYCHARTER_DATABASE_URL -c "SELECT 1;"
302
+ ```
303
+
304
+ 3. **Ensure database is initialized:**
305
+ ```bash
306
+ pycharter db init $PYCHARTER_DATABASE_URL
307
+ ```
308
+
309
+ ### API Not Starting
310
+
311
+ If the API fails to start:
312
+
313
+ 1. **Check if uvicorn is installed:**
314
+ ```bash
315
+ pip install pycharter[api]
316
+ ```
317
+
318
+ 2. **Check for port conflicts:**
319
+ ```bash
320
+ # Use a different port
321
+ pycharter api --port 8001
322
+ ```
323
+
324
+ 3. **Check logs for errors:**
325
+ The API will print error messages to stderr if there are configuration issues.
326
+
327
+ ## Production Deployment
328
+
329
+ For production, consider:
330
+
331
+ 1. **Use a process manager** (systemd, supervisor, etc.)
332
+ 2. **Set environment variables** in your deployment configuration
333
+ 3. **Use a reverse proxy** (nginx, traefik) in front of the API
334
+ 4. **Enable HTTPS** for secure connections
335
+ 5. **Configure CORS** appropriately in `api/main.py`
336
+ 6. **Use a production ASGI server** like Gunicorn with Uvicorn workers:
337
+
338
+ ```bash
339
+ gunicorn api.main:app -w 4 -k uvicorn.workers.UvicornWorker
340
+ ```