pycharter 0.0.24__py3-none-any.whl → 0.0.26__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 (567) hide show
  1. pycharter/__init__.py +6 -0
  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. pycharter/api/dependencies/auth.py +158 -0
  6. {api → pycharter/api}/main.py +32 -4
  7. {api → pycharter/api}/models/__init__.py +4 -4
  8. pycharter/api/models/etl.py +66 -0
  9. {api → pycharter/api}/routes/v1/__init__.py +5 -1
  10. pycharter/api/routes/v1/auth.py +97 -0
  11. {api → pycharter/api}/routes/v1/contracts.py +14 -12
  12. {api → pycharter/api}/routes/v1/docs.py +2 -2
  13. pycharter/api/routes/v1/etl.py +131 -0
  14. {api → pycharter/api}/routes/v1/evolution.py +2 -2
  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/tracking.py +1 -1
  20. {api → pycharter/api}/routes/v1/validation.py +2 -2
  21. {api → pycharter/api}/routes/v1/validation_jobs.py +3 -3
  22. pycharter/cli.py +9 -11
  23. pycharter/config.py +69 -0
  24. pycharter/contract_builder/builder.py +32 -37
  25. pycharter/data/seed/compliance_frameworks.yaml +22 -0
  26. pycharter/data/seed/contracts.yaml +130 -0
  27. pycharter/data/seed/data_feeds.yaml +22 -0
  28. pycharter/data/seed/domains.yaml +13 -0
  29. pycharter/data/seed/environments.yaml +19 -0
  30. pycharter/data/seed/owners.yaml +21 -0
  31. pycharter/data/seed/systems.yaml +13 -0
  32. pycharter/data/seed/tags.yaml +25 -0
  33. pycharter/data/templates/contract/README.md +161 -0
  34. pycharter/data/templates/contract/template_contract.yaml +37 -0
  35. pycharter/data/templates/etl/README.md +1 -1
  36. pycharter/data/templates/etl/extract_with_validation.yaml +86 -0
  37. pycharter/data/templates/etl/load_with_validation.yaml +111 -0
  38. pycharter/data/templates/etl/settings.yaml +55 -0
  39. pycharter/db/README.md +179 -0
  40. pycharter/db/cli.py +126 -4
  41. pycharter/db/migrations/versions/20260122000000_change_artifact_unique_constraints_to_title_version.py +2 -2
  42. pycharter/db/schemas/README.md +96 -0
  43. pycharter/etl_generator/ASYNC_AND_EXECUTION.md +91 -0
  44. pycharter/etl_generator/INTERFACES.md +142 -0
  45. pycharter/etl_generator/README.md +271 -0
  46. pycharter/etl_generator/TRANSFORMATION_GUIDE.md +452 -0
  47. pycharter/etl_generator/__init__.py +47 -11
  48. pycharter/etl_generator/config_models.py +673 -0
  49. pycharter/etl_generator/config_validator.py +133 -157
  50. pycharter/etl_generator/context.py +3 -0
  51. pycharter/etl_generator/database.py +5 -1
  52. pycharter/etl_generator/extractors/__init__.py +4 -2
  53. pycharter/etl_generator/extractors/cloud_storage.py +9 -9
  54. pycharter/etl_generator/extractors/database.py +2 -2
  55. pycharter/etl_generator/extractors/factory.py +15 -33
  56. pycharter/etl_generator/extractors/file.py +2 -2
  57. pycharter/etl_generator/extractors/http.py +2 -2
  58. pycharter/etl_generator/extractors/mongodb.py +393 -0
  59. pycharter/etl_generator/extractors/streaming.py +2 -2
  60. pycharter/etl_generator/loaders/__init__.py +15 -9
  61. pycharter/etl_generator/loaders/{cloud_storage_loader.py → cloud_storage.py} +95 -2
  62. pycharter/etl_generator/loaders/factory.py +16 -29
  63. pycharter/etl_generator/loaders/file.py +135 -1
  64. pycharter/etl_generator/loaders/mongodb.py +416 -0
  65. pycharter/etl_generator/pipeline.py +283 -164
  66. pycharter/etl_generator/result.py +16 -0
  67. pycharter/etl_generator/schemas/__init__.py +71 -42
  68. pycharter/etl_generator/transformers/config.py +3 -2
  69. pycharter/etl_generator/transformers/simple_operations.py +57 -4
  70. pycharter/etl_generator/validation.py +551 -0
  71. pycharter/metadata_store/README.md +229 -0
  72. pycharter/quality/README.md +235 -0
  73. pycharter/runtime_validator/__init__.py +7 -0
  74. pycharter/runtime_validator/utils.py +33 -0
  75. pycharter/runtime_validator/validator.py +13 -10
  76. pycharter/ui/.eslintrc.json +4 -0
  77. pycharter/ui/README.md +186 -0
  78. {ui → pycharter/ui}/__init__.py +3 -3
  79. pycharter/ui/components.json +17 -0
  80. pycharter/ui/package-lock.json +6617 -0
  81. pycharter/ui/package.json +37 -0
  82. {ui → pycharter/ui}/server.py +7 -8
  83. pycharter/ui/static/404/index.html +1 -0
  84. pycharter/ui/static/404.html +1 -0
  85. pycharter/ui/static/__next.__PAGE__.txt +10 -0
  86. pycharter/ui/static/__next._full.txt +30 -0
  87. pycharter/ui/static/__next._head.txt +7 -0
  88. pycharter/ui/static/__next._index.txt +9 -0
  89. pycharter/ui/static/__next._tree.txt +2 -0
  90. pycharter/ui/static/_next/static/YCnlK66gA7FV5vvcixspB/_clientMiddlewareManifest.json +1 -0
  91. pycharter/ui/static/_next/static/chunks/0fc1f70b787b8845.js +1 -0
  92. pycharter/ui/static/_next/static/chunks/17bb8075d7b75663.css +1 -0
  93. pycharter/ui/static/_next/static/chunks/381932864dcbfdb8.js +1 -0
  94. pycharter/ui/static/_next/static/chunks/4c951b8e4507e2b3.js +1 -0
  95. pycharter/ui/static/_next/static/chunks/68b87a6f65abd3ed.js +1 -0
  96. pycharter/ui/static/_next/static/chunks/78572617b8fae189.js +1 -0
  97. pycharter/ui/static/_next/static/chunks/8b7be2803e3fe184.js +1 -0
  98. pycharter/ui/static/_next/static/chunks/a8e529fd1e67f121.js +1 -0
  99. pycharter/ui/static/_next/static/chunks/c35d998f80be3ff5.js +1 -0
  100. pycharter/ui/static/_next/static/chunks/e453aa5d01c32c17.js +1 -0
  101. pycharter/ui/static/_next/static/chunks/f2d240eb057f898a.js +970 -0
  102. pycharter/ui/static/_next/static/chunks/f7722448f6040846.js +1 -0
  103. pycharter/ui/static/_not-found/__next._full.txt +17 -0
  104. pycharter/ui/static/_not-found/__next._head.txt +7 -0
  105. pycharter/ui/static/_not-found/__next._index.txt +9 -0
  106. pycharter/ui/static/_not-found/__next._not-found.__PAGE__.txt +5 -0
  107. pycharter/ui/static/_not-found/__next._not-found.txt +4 -0
  108. pycharter/ui/static/_not-found/__next._tree.txt +2 -0
  109. pycharter/ui/static/_not-found/index.html +1 -0
  110. pycharter/ui/static/_not-found/index.txt +17 -0
  111. pycharter/ui/static/contracts/__next._full.txt +21 -0
  112. pycharter/ui/static/contracts/__next._head.txt +7 -0
  113. pycharter/ui/static/contracts/__next._index.txt +9 -0
  114. pycharter/ui/static/contracts/__next._tree.txt +2 -0
  115. pycharter/ui/static/contracts/__next.contracts.__PAGE__.txt +9 -0
  116. pycharter/ui/static/contracts/__next.contracts.txt +4 -0
  117. pycharter/ui/static/contracts/index.html +1 -0
  118. pycharter/ui/static/contracts/index.txt +21 -0
  119. pycharter/ui/static/documentation/__next._full.txt +21 -0
  120. pycharter/ui/static/documentation/__next._head.txt +7 -0
  121. pycharter/ui/static/documentation/__next._index.txt +9 -0
  122. pycharter/ui/static/documentation/__next._tree.txt +2 -0
  123. pycharter/ui/static/documentation/__next.documentation.__PAGE__.txt +9 -0
  124. pycharter/ui/static/documentation/__next.documentation.txt +4 -0
  125. pycharter/ui/static/documentation/index.html +93 -0
  126. pycharter/ui/static/documentation/index.txt +21 -0
  127. pycharter/ui/static/etl/__next._full.txt +21 -0
  128. pycharter/ui/static/etl/__next._head.txt +7 -0
  129. pycharter/ui/static/etl/__next._index.txt +9 -0
  130. pycharter/ui/static/etl/__next._tree.txt +2 -0
  131. pycharter/ui/static/etl/__next.etl.__PAGE__.txt +9 -0
  132. pycharter/ui/static/etl/__next.etl.txt +4 -0
  133. pycharter/ui/static/etl/index.html +2 -0
  134. pycharter/ui/static/etl/index.txt +21 -0
  135. pycharter/ui/static/index.html +1 -0
  136. pycharter/ui/static/index.txt +30 -0
  137. pycharter/ui/static/metadata/__next._full.txt +21 -0
  138. pycharter/ui/static/metadata/__next._head.txt +7 -0
  139. pycharter/ui/static/metadata/__next._index.txt +9 -0
  140. pycharter/ui/static/metadata/__next._tree.txt +2 -0
  141. pycharter/ui/static/metadata/__next.metadata.__PAGE__.txt +9 -0
  142. pycharter/ui/static/metadata/__next.metadata.txt +4 -0
  143. pycharter/ui/static/metadata/index.html +1 -0
  144. pycharter/ui/static/metadata/index.txt +21 -0
  145. pycharter/ui/static/quality/__next._full.txt +21 -0
  146. pycharter/ui/static/quality/__next._head.txt +7 -0
  147. pycharter/ui/static/quality/__next._index.txt +9 -0
  148. pycharter/ui/static/quality/__next._tree.txt +2 -0
  149. pycharter/ui/static/quality/__next.quality.__PAGE__.txt +9 -0
  150. pycharter/ui/static/quality/__next.quality.txt +4 -0
  151. pycharter/ui/static/quality/index.html +2 -0
  152. pycharter/ui/static/quality/index.txt +21 -0
  153. pycharter/ui/static/rules/__next._full.txt +21 -0
  154. pycharter/ui/static/rules/__next._head.txt +7 -0
  155. pycharter/ui/static/rules/__next._index.txt +9 -0
  156. pycharter/ui/static/rules/__next._tree.txt +2 -0
  157. pycharter/ui/static/rules/__next.rules.__PAGE__.txt +9 -0
  158. pycharter/ui/static/rules/__next.rules.txt +4 -0
  159. pycharter/ui/static/rules/index.html +1 -0
  160. pycharter/ui/static/rules/index.txt +21 -0
  161. pycharter/ui/static/schemas/__next._full.txt +21 -0
  162. pycharter/ui/static/schemas/__next._head.txt +7 -0
  163. pycharter/ui/static/schemas/__next._index.txt +9 -0
  164. pycharter/ui/static/schemas/__next._tree.txt +2 -0
  165. pycharter/ui/static/schemas/__next.schemas.__PAGE__.txt +9 -0
  166. pycharter/ui/static/schemas/__next.schemas.txt +4 -0
  167. pycharter/ui/static/schemas/index.html +1 -0
  168. pycharter/ui/static/schemas/index.txt +21 -0
  169. pycharter/ui/static/settings/__next._full.txt +21 -0
  170. pycharter/ui/static/settings/__next._head.txt +7 -0
  171. pycharter/ui/static/settings/__next._index.txt +9 -0
  172. pycharter/ui/static/settings/__next._tree.txt +2 -0
  173. pycharter/ui/static/settings/__next.settings.__PAGE__.txt +9 -0
  174. pycharter/ui/static/settings/__next.settings.txt +4 -0
  175. pycharter/ui/static/settings/index.html +1 -0
  176. pycharter/ui/static/settings/index.txt +21 -0
  177. pycharter/ui/static/static/_next/static/2gKjNv6YvE6BcIdFthBLs/_clientMiddlewareManifest.json +1 -0
  178. pycharter/ui/static/static/static/_next/static/0rYA78L88aUyD2Uh38hhX/_clientMiddlewareManifest.json +1 -0
  179. pycharter/ui/static/static/static/_next/static/chunks/f7d1a90dd75d2572.js +1 -0
  180. pycharter/ui/static/static/static/static/.gitkeep +0 -0
  181. pycharter/ui/static/static/static/static/_next/static/chunks/222442f6da32302a.js +1 -0
  182. pycharter/ui/static/static/static/static/_next/static/chunks/247eb132b7f7b574.js +1 -0
  183. pycharter/ui/static/static/static/static/_next/static/chunks/297d55555b71baba.js +1 -0
  184. pycharter/ui/static/static/static/static/_next/static/chunks/414e77373f8ff61c.js +1 -0
  185. pycharter/ui/static/static/static/static/_next/static/chunks/652ad0aa26265c47.js +2 -0
  186. pycharter/ui/static/static/static/static/_next/static/chunks/9c23f44fff36548a.js +1 -0
  187. pycharter/ui/static/static/static/static/_next/static/chunks/a6dad97d9634a72d.js +1 -0
  188. pycharter/ui/static/static/static/static/_next/static/chunks/b32a0963684b9933.js +4 -0
  189. pycharter/ui/static/static/static/static/_next/static/chunks/db913959c675cea6.js +1 -0
  190. pycharter/ui/static/static/static/static/_next/static/chunks/f2e7afeab1178138.js +1 -0
  191. pycharter/ui/static/static/static/static/_next/static/chunks/ff1a16fafef87110.js +1 -0
  192. pycharter/ui/static/static/static/static/_next/static/chunks/turbopack-ffcb7ab6794027ef.js +3 -0
  193. pycharter/ui/static/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_buildManifest.js +11 -0
  194. pycharter/ui/static/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_clientMiddlewareManifest.json +1 -0
  195. pycharter/ui/static/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_ssgManifest.js +1 -0
  196. pycharter/ui/static/validation/__next._full.txt +21 -0
  197. pycharter/ui/static/validation/__next._head.txt +7 -0
  198. pycharter/ui/static/validation/__next._index.txt +9 -0
  199. pycharter/ui/static/validation/__next._tree.txt +2 -0
  200. pycharter/ui/static/validation/__next.validation.__PAGE__.txt +9 -0
  201. pycharter/ui/static/validation/__next.validation.txt +4 -0
  202. pycharter/ui/static/validation/index.html +1 -0
  203. pycharter/ui/static/validation/index.txt +21 -0
  204. pycharter/ui/tsconfig.json +42 -0
  205. pycharter/worker/README.md +187 -0
  206. pycharter/worker/backends/__init__.py +8 -0
  207. pycharter/worker/backends/base.py +46 -0
  208. pycharter/worker/backends/spark.py +233 -0
  209. {worker → pycharter/worker}/cli.py +1 -1
  210. {worker → pycharter/worker}/processor.py +2 -2
  211. pycharter/worker/queue/__init__.py +8 -0
  212. pycharter/worker/queue/redis_queue.py +147 -0
  213. {pycharter-0.0.24.dist-info → pycharter-0.0.26.dist-info}/METADATA +57 -26
  214. pycharter-0.0.26.dist-info/RECORD +702 -0
  215. pycharter-0.0.26.dist-info/top_level.txt +1 -0
  216. pycharter/etl_generator/config_loader.py +0 -394
  217. pycharter/etl_generator/loaders/cloud.py +0 -87
  218. pycharter/etl_generator/loaders/file_loader.py +0 -130
  219. pycharter-0.0.24.dist-info/RECORD +0 -543
  220. pycharter-0.0.24.dist-info/top_level.txt +0 -4
  221. {api → pycharter/api}/dependencies/database.py +0 -0
  222. {api → pycharter/api}/dependencies/store.py +0 -0
  223. {api → pycharter/api}/models/contracts.py +0 -0
  224. {api → pycharter/api}/models/docs.py +0 -0
  225. {api → pycharter/api}/models/evolution.py +0 -0
  226. {api → pycharter/api}/models/metadata.py +0 -0
  227. {api → pycharter/api}/models/metadata_entities.py +0 -0
  228. {api → pycharter/api}/models/quality.py +0 -0
  229. {api → pycharter/api}/models/schemas.py +0 -0
  230. {api → pycharter/api}/models/tracking.py +0 -0
  231. {api → pycharter/api}/models/validation.py +0 -0
  232. {api → pycharter/api}/routes/__init__.py +0 -0
  233. {api → pycharter/api}/routes/v1/templates.py +0 -0
  234. {api → pycharter/api}/utils.py +0 -0
  235. {ui → pycharter/ui}/build.py +0 -0
  236. {ui → pycharter/ui}/dev.py +0 -0
  237. {ui → pycharter/ui}/static/.gitkeep +0 -0
  238. {ui/static/_next/static/2gKjNv6YvE6BcIdFthBLs → pycharter/ui/static/_next/static/YCnlK66gA7FV5vvcixspB}/_buildManifest.js +0 -0
  239. {ui/static/_next/static/2gKjNv6YvE6BcIdFthBLs → pycharter/ui/static/_next/static/YCnlK66gA7FV5vvcixspB}/_ssgManifest.js +0 -0
  240. {ui → pycharter/ui}/static/_next/static/chunks/222442f6da32302a.js +0 -0
  241. {ui → pycharter/ui}/static/_next/static/chunks/247eb132b7f7b574.js +0 -0
  242. {ui → pycharter/ui}/static/_next/static/chunks/297d55555b71baba.js +0 -0
  243. {ui → pycharter/ui}/static/_next/static/chunks/414e77373f8ff61c.js +0 -0
  244. {ui → pycharter/ui}/static/_next/static/chunks/652ad0aa26265c47.js +0 -0
  245. {ui → pycharter/ui}/static/_next/static/chunks/9c23f44fff36548a.js +0 -0
  246. {ui → pycharter/ui}/static/_next/static/chunks/a6dad97d9634a72d.js +0 -0
  247. {ui → pycharter/ui}/static/_next/static/chunks/b32a0963684b9933.js +0 -0
  248. {ui → pycharter/ui}/static/_next/static/chunks/db913959c675cea6.js +0 -0
  249. {ui → pycharter/ui}/static/_next/static/chunks/f2e7afeab1178138.js +0 -0
  250. {ui → pycharter/ui}/static/_next/static/chunks/f7d1a90dd75d2572.js +0 -0
  251. {ui → pycharter/ui}/static/_next/static/chunks/ff1a16fafef87110.js +0 -0
  252. {ui → pycharter/ui}/static/_next/static/chunks/turbopack-ffcb7ab6794027ef.js +0 -0
  253. {ui → pycharter/ui}/static/static/.gitkeep +0 -0
  254. {ui → pycharter/ui/static}/static/404/index.html +0 -0
  255. {ui → pycharter/ui/static}/static/404.html +0 -0
  256. {ui → pycharter/ui/static}/static/__next.__PAGE__.txt +0 -0
  257. {ui → pycharter/ui/static}/static/__next._full.txt +0 -0
  258. {ui → pycharter/ui/static}/static/__next._head.txt +0 -0
  259. {ui → pycharter/ui/static}/static/__next._index.txt +0 -0
  260. {ui → pycharter/ui/static}/static/__next._tree.txt +0 -0
  261. {ui/static/static/_next/static/0rYA78L88aUyD2Uh38hhX → pycharter/ui/static/static/_next/static/2gKjNv6YvE6BcIdFthBLs}/_buildManifest.js +0 -0
  262. {ui/static/static/_next/static/0rYA78L88aUyD2Uh38hhX → pycharter/ui/static/static/_next/static/2gKjNv6YvE6BcIdFthBLs}/_ssgManifest.js +0 -0
  263. {ui → pycharter/ui/static}/static/_next/static/chunks/13d4a0fbd74c1ee4.js +0 -0
  264. {ui → pycharter/ui}/static/static/_next/static/chunks/222442f6da32302a.js +0 -0
  265. {ui → pycharter/ui}/static/static/_next/static/chunks/247eb132b7f7b574.js +0 -0
  266. {ui → pycharter/ui/static}/static/_next/static/chunks/26dfc590f7714c03.js +0 -0
  267. {ui → pycharter/ui}/static/static/_next/static/chunks/297d55555b71baba.js +0 -0
  268. {ui → pycharter/ui/static}/static/_next/static/chunks/2ab439ce003cd691.js +0 -0
  269. {ui → pycharter/ui/static}/static/_next/static/chunks/2edb43b48432ac04.js +0 -0
  270. {ui → pycharter/ui/static}/static/_next/static/chunks/34d289e6db2ef551.js +0 -0
  271. {ui → pycharter/ui}/static/static/_next/static/chunks/414e77373f8ff61c.js +0 -0
  272. {ui → pycharter/ui/static}/static/_next/static/chunks/49ca65abd26ae49e.js +0 -0
  273. {ui → pycharter/ui}/static/static/_next/static/chunks/652ad0aa26265c47.js +0 -0
  274. {ui → pycharter/ui/static}/static/_next/static/chunks/9667e7a3d359eb39.js +0 -0
  275. {ui → pycharter/ui/static}/static/_next/static/chunks/99508d9d5869cc27.js +0 -0
  276. {ui → pycharter/ui}/static/static/_next/static/chunks/9c23f44fff36548a.js +0 -0
  277. {ui → pycharter/ui}/static/static/_next/static/chunks/a6dad97d9634a72d.js +0 -0
  278. {ui → pycharter/ui/static}/static/_next/static/chunks/b313c35a6ba76574.js +0 -0
  279. {ui → pycharter/ui}/static/static/_next/static/chunks/b32a0963684b9933.js +0 -0
  280. {ui → pycharter/ui/static}/static/_next/static/chunks/c69f6cba366bd988.js +0 -0
  281. {ui → pycharter/ui/static}/static/_next/static/chunks/d2363397e1b2bcab.css +0 -0
  282. {ui → pycharter/ui}/static/static/_next/static/chunks/db913959c675cea6.js +0 -0
  283. {ui → pycharter/ui/static}/static/_next/static/chunks/f061a4be97bfc3b3.js +0 -0
  284. {ui → pycharter/ui}/static/static/_next/static/chunks/f2e7afeab1178138.js +0 -0
  285. {ui → pycharter/ui}/static/static/_next/static/chunks/f7d1a90dd75d2572.js +0 -0
  286. {ui → pycharter/ui}/static/static/_next/static/chunks/ff1a16fafef87110.js +0 -0
  287. {ui → pycharter/ui}/static/static/_next/static/chunks/turbopack-ffcb7ab6794027ef.js +0 -0
  288. {ui → pycharter/ui/static}/static/_not-found/__next._full.txt +0 -0
  289. {ui → pycharter/ui/static}/static/_not-found/__next._head.txt +0 -0
  290. {ui → pycharter/ui/static}/static/_not-found/__next._index.txt +0 -0
  291. {ui → pycharter/ui/static}/static/_not-found/__next._not-found.__PAGE__.txt +0 -0
  292. {ui → pycharter/ui/static}/static/_not-found/__next._not-found.txt +0 -0
  293. {ui → pycharter/ui/static}/static/_not-found/__next._tree.txt +0 -0
  294. {ui → pycharter/ui/static}/static/_not-found/index.html +0 -0
  295. {ui → pycharter/ui/static}/static/_not-found/index.txt +0 -0
  296. {ui → pycharter/ui/static}/static/contracts/__next._full.txt +0 -0
  297. {ui → pycharter/ui/static}/static/contracts/__next._head.txt +0 -0
  298. {ui → pycharter/ui/static}/static/contracts/__next._index.txt +0 -0
  299. {ui → pycharter/ui/static}/static/contracts/__next._tree.txt +0 -0
  300. {ui → pycharter/ui/static}/static/contracts/__next.contracts.__PAGE__.txt +0 -0
  301. {ui → pycharter/ui/static}/static/contracts/__next.contracts.txt +0 -0
  302. {ui → pycharter/ui/static}/static/contracts/index.html +0 -0
  303. {ui → pycharter/ui/static}/static/contracts/index.txt +0 -0
  304. {ui → pycharter/ui/static}/static/documentation/__next._full.txt +0 -0
  305. {ui → pycharter/ui/static}/static/documentation/__next._head.txt +0 -0
  306. {ui → pycharter/ui/static}/static/documentation/__next._index.txt +0 -0
  307. {ui → pycharter/ui/static}/static/documentation/__next._tree.txt +0 -0
  308. {ui → pycharter/ui/static}/static/documentation/__next.documentation.__PAGE__.txt +0 -0
  309. {ui → pycharter/ui/static}/static/documentation/__next.documentation.txt +0 -0
  310. {ui → pycharter/ui/static}/static/documentation/index.html +0 -0
  311. {ui → pycharter/ui/static}/static/documentation/index.txt +0 -0
  312. {ui → pycharter/ui/static}/static/index.html +0 -0
  313. {ui → pycharter/ui/static}/static/index.txt +0 -0
  314. {ui → pycharter/ui/static}/static/metadata/__next._full.txt +0 -0
  315. {ui → pycharter/ui/static}/static/metadata/__next._head.txt +0 -0
  316. {ui → pycharter/ui/static}/static/metadata/__next._index.txt +0 -0
  317. {ui → pycharter/ui/static}/static/metadata/__next._tree.txt +0 -0
  318. {ui → pycharter/ui/static}/static/metadata/__next.metadata.__PAGE__.txt +0 -0
  319. {ui → pycharter/ui/static}/static/metadata/__next.metadata.txt +0 -0
  320. {ui → pycharter/ui/static}/static/metadata/index.html +0 -0
  321. {ui → pycharter/ui/static}/static/metadata/index.txt +0 -0
  322. {ui → pycharter/ui/static}/static/quality/__next._full.txt +0 -0
  323. {ui → pycharter/ui/static}/static/quality/__next._head.txt +0 -0
  324. {ui → pycharter/ui/static}/static/quality/__next._index.txt +0 -0
  325. {ui → pycharter/ui/static}/static/quality/__next._tree.txt +0 -0
  326. {ui → pycharter/ui/static}/static/quality/__next.quality.__PAGE__.txt +0 -0
  327. {ui → pycharter/ui/static}/static/quality/__next.quality.txt +0 -0
  328. {ui → pycharter/ui/static}/static/quality/index.html +0 -0
  329. {ui → pycharter/ui/static}/static/quality/index.txt +0 -0
  330. {ui → pycharter/ui/static}/static/rules/__next._full.txt +0 -0
  331. {ui → pycharter/ui/static}/static/rules/__next._head.txt +0 -0
  332. {ui → pycharter/ui/static}/static/rules/__next._index.txt +0 -0
  333. {ui → pycharter/ui/static}/static/rules/__next._tree.txt +0 -0
  334. {ui → pycharter/ui/static}/static/rules/__next.rules.__PAGE__.txt +0 -0
  335. {ui → pycharter/ui/static}/static/rules/__next.rules.txt +0 -0
  336. {ui → pycharter/ui/static}/static/rules/index.html +0 -0
  337. {ui → pycharter/ui/static}/static/rules/index.txt +0 -0
  338. {ui → pycharter/ui/static}/static/schemas/__next._full.txt +0 -0
  339. {ui → pycharter/ui/static}/static/schemas/__next._head.txt +0 -0
  340. {ui → pycharter/ui/static}/static/schemas/__next._index.txt +0 -0
  341. {ui → pycharter/ui/static}/static/schemas/__next._tree.txt +0 -0
  342. {ui → pycharter/ui/static}/static/schemas/__next.schemas.__PAGE__.txt +0 -0
  343. {ui → pycharter/ui/static}/static/schemas/__next.schemas.txt +0 -0
  344. {ui → pycharter/ui/static}/static/schemas/index.html +0 -0
  345. {ui → pycharter/ui/static}/static/schemas/index.txt +0 -0
  346. {ui → pycharter/ui/static}/static/settings/__next._full.txt +0 -0
  347. {ui → pycharter/ui/static}/static/settings/__next._head.txt +0 -0
  348. {ui → pycharter/ui/static}/static/settings/__next._index.txt +0 -0
  349. {ui → pycharter/ui/static}/static/settings/__next._tree.txt +0 -0
  350. {ui → pycharter/ui/static}/static/settings/__next.settings.__PAGE__.txt +0 -0
  351. {ui → pycharter/ui/static}/static/settings/__next.settings.txt +0 -0
  352. {ui → pycharter/ui/static}/static/settings/index.html +0 -0
  353. {ui → pycharter/ui/static}/static/settings/index.txt +0 -0
  354. {ui → pycharter/ui}/static/static/static/.gitkeep +0 -0
  355. {ui → pycharter/ui/static}/static/static/404/index.html +0 -0
  356. {ui → pycharter/ui/static}/static/static/404.html +0 -0
  357. {ui → pycharter/ui/static}/static/static/__next.__PAGE__.txt +0 -0
  358. {ui → pycharter/ui/static}/static/static/__next._full.txt +0 -0
  359. {ui → pycharter/ui/static}/static/static/__next._head.txt +0 -0
  360. {ui → pycharter/ui/static}/static/static/__next._index.txt +0 -0
  361. {ui → pycharter/ui/static}/static/static/__next._tree.txt +0 -0
  362. {ui/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl → pycharter/ui/static/static/static/_next/static/0rYA78L88aUyD2Uh38hhX}/_buildManifest.js +0 -0
  363. {ui/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl → pycharter/ui/static/static/static/_next/static/0rYA78L88aUyD2Uh38hhX}/_ssgManifest.js +0 -0
  364. {ui → pycharter/ui/static}/static/static/_next/static/chunks/13d4a0fbd74c1ee4.js +0 -0
  365. {ui → pycharter/ui}/static/static/static/_next/static/chunks/222442f6da32302a.js +0 -0
  366. {ui → pycharter/ui}/static/static/static/_next/static/chunks/247eb132b7f7b574.js +0 -0
  367. {ui → pycharter/ui}/static/static/static/_next/static/chunks/297d55555b71baba.js +0 -0
  368. {ui → pycharter/ui/static}/static/static/_next/static/chunks/2ab439ce003cd691.js +0 -0
  369. {ui → pycharter/ui/static}/static/static/_next/static/chunks/2edb43b48432ac04.js +0 -0
  370. {ui → pycharter/ui}/static/static/static/_next/static/chunks/414e77373f8ff61c.js +0 -0
  371. {ui → pycharter/ui/static}/static/static/_next/static/chunks/49ca65abd26ae49e.js +0 -0
  372. {ui → pycharter/ui/static}/static/static/_next/static/chunks/5e04d10c4a7b58a3.js +0 -0
  373. {ui → pycharter/ui}/static/static/static/_next/static/chunks/652ad0aa26265c47.js +0 -0
  374. {ui → pycharter/ui/static}/static/static/_next/static/chunks/75d88a058d8ffaa6.js +0 -0
  375. {ui → pycharter/ui/static}/static/static/_next/static/chunks/8c89634cf6bad76f.js +0 -0
  376. {ui → pycharter/ui/static}/static/static/_next/static/chunks/9667e7a3d359eb39.js +0 -0
  377. {ui → pycharter/ui}/static/static/static/_next/static/chunks/9c23f44fff36548a.js +0 -0
  378. {ui → pycharter/ui}/static/static/static/_next/static/chunks/a6dad97d9634a72d.js +0 -0
  379. {ui → pycharter/ui}/static/static/static/_next/static/chunks/b32a0963684b9933.js +0 -0
  380. {ui → pycharter/ui/static}/static/static/_next/static/chunks/c4fa4f4114b7c352.js +0 -0
  381. {ui → pycharter/ui/static}/static/static/_next/static/chunks/c69f6cba366bd988.js +0 -0
  382. {ui → pycharter/ui/static}/static/static/_next/static/chunks/d2363397e1b2bcab.css +0 -0
  383. {ui → pycharter/ui}/static/static/static/_next/static/chunks/db913959c675cea6.js +0 -0
  384. {ui → pycharter/ui/static}/static/static/_next/static/chunks/f061a4be97bfc3b3.js +0 -0
  385. {ui → pycharter/ui}/static/static/static/_next/static/chunks/f2e7afeab1178138.js +0 -0
  386. {ui → pycharter/ui}/static/static/static/_next/static/chunks/ff1a16fafef87110.js +0 -0
  387. {ui → pycharter/ui}/static/static/static/_next/static/chunks/turbopack-ffcb7ab6794027ef.js +0 -0
  388. {ui → pycharter/ui/static}/static/static/_not-found/__next._full.txt +0 -0
  389. {ui → pycharter/ui/static}/static/static/_not-found/__next._head.txt +0 -0
  390. {ui → pycharter/ui/static}/static/static/_not-found/__next._index.txt +0 -0
  391. {ui → pycharter/ui/static}/static/static/_not-found/__next._not-found.__PAGE__.txt +0 -0
  392. {ui → pycharter/ui/static}/static/static/_not-found/__next._not-found.txt +0 -0
  393. {ui → pycharter/ui/static}/static/static/_not-found/__next._tree.txt +0 -0
  394. {ui → pycharter/ui/static}/static/static/_not-found/index.html +0 -0
  395. {ui → pycharter/ui/static}/static/static/_not-found/index.txt +0 -0
  396. {ui → pycharter/ui/static}/static/static/contracts/__next._full.txt +0 -0
  397. {ui → pycharter/ui/static}/static/static/contracts/__next._head.txt +0 -0
  398. {ui → pycharter/ui/static}/static/static/contracts/__next._index.txt +0 -0
  399. {ui → pycharter/ui/static}/static/static/contracts/__next._tree.txt +0 -0
  400. {ui → pycharter/ui/static}/static/static/contracts/__next.contracts.__PAGE__.txt +0 -0
  401. {ui → pycharter/ui/static}/static/static/contracts/__next.contracts.txt +0 -0
  402. {ui → pycharter/ui/static}/static/static/contracts/index.html +0 -0
  403. {ui → pycharter/ui/static}/static/static/contracts/index.txt +0 -0
  404. {ui → pycharter/ui/static}/static/static/documentation/__next._full.txt +0 -0
  405. {ui → pycharter/ui/static}/static/static/documentation/__next._head.txt +0 -0
  406. {ui → pycharter/ui/static}/static/static/documentation/__next._index.txt +0 -0
  407. {ui → pycharter/ui/static}/static/static/documentation/__next._tree.txt +0 -0
  408. {ui → pycharter/ui/static}/static/static/documentation/__next.documentation.__PAGE__.txt +0 -0
  409. {ui → pycharter/ui/static}/static/static/documentation/__next.documentation.txt +0 -0
  410. {ui → pycharter/ui/static}/static/static/documentation/index.html +0 -0
  411. {ui → pycharter/ui/static}/static/static/documentation/index.txt +0 -0
  412. {ui → pycharter/ui/static}/static/static/index.html +0 -0
  413. {ui → pycharter/ui/static}/static/static/index.txt +0 -0
  414. {ui → pycharter/ui/static}/static/static/metadata/__next._full.txt +0 -0
  415. {ui → pycharter/ui/static}/static/static/metadata/__next._head.txt +0 -0
  416. {ui → pycharter/ui/static}/static/static/metadata/__next._index.txt +0 -0
  417. {ui → pycharter/ui/static}/static/static/metadata/__next._tree.txt +0 -0
  418. {ui → pycharter/ui/static}/static/static/metadata/__next.metadata.__PAGE__.txt +0 -0
  419. {ui → pycharter/ui/static}/static/static/metadata/__next.metadata.txt +0 -0
  420. {ui → pycharter/ui/static}/static/static/metadata/index.html +0 -0
  421. {ui → pycharter/ui/static}/static/static/metadata/index.txt +0 -0
  422. {ui → pycharter/ui/static}/static/static/quality/__next._full.txt +0 -0
  423. {ui → pycharter/ui/static}/static/static/quality/__next._head.txt +0 -0
  424. {ui → pycharter/ui/static}/static/static/quality/__next._index.txt +0 -0
  425. {ui → pycharter/ui/static}/static/static/quality/__next._tree.txt +0 -0
  426. {ui → pycharter/ui/static}/static/static/quality/__next.quality.__PAGE__.txt +0 -0
  427. {ui → pycharter/ui/static}/static/static/quality/__next.quality.txt +0 -0
  428. {ui → pycharter/ui/static}/static/static/quality/index.html +0 -0
  429. {ui → pycharter/ui/static}/static/static/quality/index.txt +0 -0
  430. {ui → pycharter/ui/static}/static/static/rules/__next._full.txt +0 -0
  431. {ui → pycharter/ui/static}/static/static/rules/__next._head.txt +0 -0
  432. {ui → pycharter/ui/static}/static/static/rules/__next._index.txt +0 -0
  433. {ui → pycharter/ui/static}/static/static/rules/__next._tree.txt +0 -0
  434. {ui → pycharter/ui/static}/static/static/rules/__next.rules.__PAGE__.txt +0 -0
  435. {ui → pycharter/ui/static}/static/static/rules/__next.rules.txt +0 -0
  436. {ui → pycharter/ui/static}/static/static/rules/index.html +0 -0
  437. {ui → pycharter/ui/static}/static/static/rules/index.txt +0 -0
  438. {ui → pycharter/ui/static}/static/static/schemas/__next._full.txt +0 -0
  439. {ui → pycharter/ui/static}/static/static/schemas/__next._head.txt +0 -0
  440. {ui → pycharter/ui/static}/static/static/schemas/__next._index.txt +0 -0
  441. {ui → pycharter/ui/static}/static/static/schemas/__next._tree.txt +0 -0
  442. {ui → pycharter/ui/static}/static/static/schemas/__next.schemas.__PAGE__.txt +0 -0
  443. {ui → pycharter/ui/static}/static/static/schemas/__next.schemas.txt +0 -0
  444. {ui → pycharter/ui/static}/static/static/schemas/index.html +0 -0
  445. {ui → pycharter/ui/static}/static/static/schemas/index.txt +0 -0
  446. {ui → pycharter/ui/static}/static/static/settings/__next._full.txt +0 -0
  447. {ui → pycharter/ui/static}/static/static/settings/__next._head.txt +0 -0
  448. {ui → pycharter/ui/static}/static/static/settings/__next._index.txt +0 -0
  449. {ui → pycharter/ui/static}/static/static/settings/__next._tree.txt +0 -0
  450. {ui → pycharter/ui/static}/static/static/settings/__next.settings.__PAGE__.txt +0 -0
  451. {ui → pycharter/ui/static}/static/static/settings/__next.settings.txt +0 -0
  452. {ui → pycharter/ui/static}/static/static/settings/index.html +0 -0
  453. {ui → pycharter/ui/static}/static/static/settings/index.txt +0 -0
  454. {ui → pycharter/ui/static}/static/static/static/404/index.html +0 -0
  455. {ui → pycharter/ui/static}/static/static/static/404.html +0 -0
  456. {ui → pycharter/ui/static}/static/static/static/__next.__PAGE__.txt +0 -0
  457. {ui → pycharter/ui/static}/static/static/static/__next._full.txt +0 -0
  458. {ui → pycharter/ui/static}/static/static/static/__next._head.txt +0 -0
  459. {ui → pycharter/ui/static}/static/static/static/__next._index.txt +0 -0
  460. {ui → pycharter/ui/static}/static/static/static/__next._tree.txt +0 -0
  461. {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/2ab439ce003cd691.js +0 -0
  462. {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/49ca65abd26ae49e.js +0 -0
  463. {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/4e310fe5005770a3.css +0 -0
  464. {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/5e04d10c4a7b58a3.js +0 -0
  465. {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/5fc14c00a2779dc5.js +0 -0
  466. {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/75d88a058d8ffaa6.js +0 -0
  467. {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/8c89634cf6bad76f.js +0 -0
  468. {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/9667e7a3d359eb39.js +0 -0
  469. {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/b584574fdc8ab13e.js +0 -0
  470. {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/c69f6cba366bd988.js +0 -0
  471. {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/d5989c94d3614b3a.js +0 -0
  472. {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/f061a4be97bfc3b3.js +0 -0
  473. {ui → pycharter/ui/static}/static/static/static/_not-found/__next._full.txt +0 -0
  474. {ui → pycharter/ui/static}/static/static/static/_not-found/__next._head.txt +0 -0
  475. {ui → pycharter/ui/static}/static/static/static/_not-found/__next._index.txt +0 -0
  476. {ui → pycharter/ui/static}/static/static/static/_not-found/__next._not-found.__PAGE__.txt +0 -0
  477. {ui → pycharter/ui/static}/static/static/static/_not-found/__next._not-found.txt +0 -0
  478. {ui → pycharter/ui/static}/static/static/static/_not-found/__next._tree.txt +0 -0
  479. {ui → pycharter/ui/static}/static/static/static/_not-found/index.html +0 -0
  480. {ui → pycharter/ui/static}/static/static/static/_not-found/index.txt +0 -0
  481. {ui → pycharter/ui/static}/static/static/static/contracts/__next._full.txt +0 -0
  482. {ui → pycharter/ui/static}/static/static/static/contracts/__next._head.txt +0 -0
  483. {ui → pycharter/ui/static}/static/static/static/contracts/__next._index.txt +0 -0
  484. {ui → pycharter/ui/static}/static/static/static/contracts/__next._tree.txt +0 -0
  485. {ui → pycharter/ui/static}/static/static/static/contracts/__next.contracts.__PAGE__.txt +0 -0
  486. {ui → pycharter/ui/static}/static/static/static/contracts/__next.contracts.txt +0 -0
  487. {ui → pycharter/ui/static}/static/static/static/contracts/index.html +0 -0
  488. {ui → pycharter/ui/static}/static/static/static/contracts/index.txt +0 -0
  489. {ui → pycharter/ui/static}/static/static/static/documentation/__next._full.txt +0 -0
  490. {ui → pycharter/ui/static}/static/static/static/documentation/__next._head.txt +0 -0
  491. {ui → pycharter/ui/static}/static/static/static/documentation/__next._index.txt +0 -0
  492. {ui → pycharter/ui/static}/static/static/static/documentation/__next._tree.txt +0 -0
  493. {ui → pycharter/ui/static}/static/static/static/documentation/__next.documentation.__PAGE__.txt +0 -0
  494. {ui → pycharter/ui/static}/static/static/static/documentation/__next.documentation.txt +0 -0
  495. {ui → pycharter/ui/static}/static/static/static/documentation/index.html +0 -0
  496. {ui → pycharter/ui/static}/static/static/static/documentation/index.txt +0 -0
  497. {ui → pycharter/ui/static}/static/static/static/index.html +0 -0
  498. {ui → pycharter/ui/static}/static/static/static/index.txt +0 -0
  499. {ui → pycharter/ui/static}/static/static/static/metadata/__next._full.txt +0 -0
  500. {ui → pycharter/ui/static}/static/static/static/metadata/__next._head.txt +0 -0
  501. {ui → pycharter/ui/static}/static/static/static/metadata/__next._index.txt +0 -0
  502. {ui → pycharter/ui/static}/static/static/static/metadata/__next._tree.txt +0 -0
  503. {ui → pycharter/ui/static}/static/static/static/metadata/__next.metadata.__PAGE__.txt +0 -0
  504. {ui → pycharter/ui/static}/static/static/static/metadata/__next.metadata.txt +0 -0
  505. {ui → pycharter/ui/static}/static/static/static/metadata/index.html +0 -0
  506. {ui → pycharter/ui/static}/static/static/static/metadata/index.txt +0 -0
  507. {ui → pycharter/ui/static}/static/static/static/quality/__next._full.txt +0 -0
  508. {ui → pycharter/ui/static}/static/static/static/quality/__next._head.txt +0 -0
  509. {ui → pycharter/ui/static}/static/static/static/quality/__next._index.txt +0 -0
  510. {ui → pycharter/ui/static}/static/static/static/quality/__next._tree.txt +0 -0
  511. {ui → pycharter/ui/static}/static/static/static/quality/__next.quality.__PAGE__.txt +0 -0
  512. {ui → pycharter/ui/static}/static/static/static/quality/__next.quality.txt +0 -0
  513. {ui → pycharter/ui/static}/static/static/static/quality/index.html +0 -0
  514. {ui → pycharter/ui/static}/static/static/static/quality/index.txt +0 -0
  515. {ui → pycharter/ui/static}/static/static/static/rules/__next._full.txt +0 -0
  516. {ui → pycharter/ui/static}/static/static/static/rules/__next._head.txt +0 -0
  517. {ui → pycharter/ui/static}/static/static/static/rules/__next._index.txt +0 -0
  518. {ui → pycharter/ui/static}/static/static/static/rules/__next._tree.txt +0 -0
  519. {ui → pycharter/ui/static}/static/static/static/rules/__next.rules.__PAGE__.txt +0 -0
  520. {ui → pycharter/ui/static}/static/static/static/rules/__next.rules.txt +0 -0
  521. {ui → pycharter/ui/static}/static/static/static/rules/index.html +0 -0
  522. {ui → pycharter/ui/static}/static/static/static/rules/index.txt +0 -0
  523. {ui → pycharter/ui/static}/static/static/static/schemas/__next._full.txt +0 -0
  524. {ui → pycharter/ui/static}/static/static/static/schemas/__next._head.txt +0 -0
  525. {ui → pycharter/ui/static}/static/static/static/schemas/__next._index.txt +0 -0
  526. {ui → pycharter/ui/static}/static/static/static/schemas/__next._tree.txt +0 -0
  527. {ui → pycharter/ui/static}/static/static/static/schemas/__next.schemas.__PAGE__.txt +0 -0
  528. {ui → pycharter/ui/static}/static/static/static/schemas/__next.schemas.txt +0 -0
  529. {ui → pycharter/ui/static}/static/static/static/schemas/index.html +0 -0
  530. {ui → pycharter/ui/static}/static/static/static/schemas/index.txt +0 -0
  531. {ui → pycharter/ui/static}/static/static/static/settings/__next._full.txt +0 -0
  532. {ui → pycharter/ui/static}/static/static/static/settings/__next._head.txt +0 -0
  533. {ui → pycharter/ui/static}/static/static/static/settings/__next._index.txt +0 -0
  534. {ui → pycharter/ui/static}/static/static/static/settings/__next._tree.txt +0 -0
  535. {ui → pycharter/ui/static}/static/static/static/settings/__next.settings.__PAGE__.txt +0 -0
  536. {ui → pycharter/ui/static}/static/static/static/settings/__next.settings.txt +0 -0
  537. {ui → pycharter/ui/static}/static/static/static/settings/index.html +0 -0
  538. {ui → pycharter/ui/static}/static/static/static/settings/index.txt +0 -0
  539. {ui → pycharter/ui/static}/static/static/static/validation/__next._full.txt +0 -0
  540. {ui → pycharter/ui/static}/static/static/static/validation/__next._head.txt +0 -0
  541. {ui → pycharter/ui/static}/static/static/static/validation/__next._index.txt +0 -0
  542. {ui → pycharter/ui/static}/static/static/static/validation/__next._tree.txt +0 -0
  543. {ui → pycharter/ui/static}/static/static/static/validation/__next.validation.__PAGE__.txt +0 -0
  544. {ui → pycharter/ui/static}/static/static/static/validation/__next.validation.txt +0 -0
  545. {ui → pycharter/ui/static}/static/static/static/validation/index.html +0 -0
  546. {ui → pycharter/ui/static}/static/static/static/validation/index.txt +0 -0
  547. {ui → pycharter/ui/static}/static/static/validation/__next._full.txt +0 -0
  548. {ui → pycharter/ui/static}/static/static/validation/__next._head.txt +0 -0
  549. {ui → pycharter/ui/static}/static/static/validation/__next._index.txt +0 -0
  550. {ui → pycharter/ui/static}/static/static/validation/__next._tree.txt +0 -0
  551. {ui → pycharter/ui/static}/static/static/validation/__next.validation.__PAGE__.txt +0 -0
  552. {ui → pycharter/ui/static}/static/static/validation/__next.validation.txt +0 -0
  553. {ui → pycharter/ui/static}/static/static/validation/index.html +0 -0
  554. {ui → pycharter/ui/static}/static/static/validation/index.txt +0 -0
  555. {ui → pycharter/ui/static}/static/validation/__next._full.txt +0 -0
  556. {ui → pycharter/ui/static}/static/validation/__next._head.txt +0 -0
  557. {ui → pycharter/ui/static}/static/validation/__next._index.txt +0 -0
  558. {ui → pycharter/ui/static}/static/validation/__next._tree.txt +0 -0
  559. {ui → pycharter/ui/static}/static/validation/__next.validation.__PAGE__.txt +0 -0
  560. {ui → pycharter/ui/static}/static/validation/__next.validation.txt +0 -0
  561. {ui → pycharter/ui/static}/static/validation/index.html +0 -0
  562. {ui → pycharter/ui/static}/static/validation/index.txt +0 -0
  563. {worker → pycharter/worker}/__init__.py +0 -0
  564. {worker → pycharter/worker}/models.py +0 -0
  565. {pycharter-0.0.24.dist-info → pycharter-0.0.26.dist-info}/WHEEL +0 -0
  566. {pycharter-0.0.24.dist-info → pycharter-0.0.26.dist-info}/entry_points.txt +0 -0
  567. {pycharter-0.0.24.dist-info → pycharter-0.0.26.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,970 @@
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,33558,e=>{"use strict";var t=e.i(43476),r=e.i(71645),a=e.i(19455),i=e.i(61246),o=e.i(75254);let n=(0,o.default)("Play",[["polygon",{points:"6 3 20 12 6 21 6 3",key:"1oa8hb"}]]),s=(0,o.default)("Copy",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]]),c=(0,o.default)("Check",[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]]);var d=e.i(78583),l=e.i(58041);let m=(0,o.default)("Code",[["polyline",{points:"16 18 22 12 16 6",key:"z7tu5w"}],["polyline",{points:"8 6 2 12 8 18",key:"1eg1df"}]]),p=(0,o.default)("ShieldCheck",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]]);var u=e.i(42009);let _=(0,o.default)("Layers",[["path",{d:"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z",key:"zw3jo"}],["path",{d:"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12",key:"1wduqc"}],["path",{d:"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17",key:"kqbvx6"}]]),h=(0,o.default)("BookOpen",[["path",{d:"M12 7v14",key:"1akyts"}],["path",{d:"M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z",key:"ruj8y"}]]),f=(0,o.default)("Activity",[["path",{d:"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2",key:"169zse"}]]),y=(0,o.default)("GitCompare",[["circle",{cx:"18",cy:"18",r:"3",key:"1xkwt0"}],["circle",{cx:"6",cy:"6",r:"3",key:"1lh9wr"}],["path",{d:"M13 6h3a2 2 0 0 1 2 2v7",key:"1yeb86"}],["path",{d:"M11 18H8a2 2 0 0 1-2-2V9",key:"19pyzm"}]]);e.i(80428);var g=e.i(50398);let v=[{id:"parse_contract",title:"Contract Parser",description:"Read and decompose data contract files",method:"parse_contract(contract_dict, validate=True)",apiEndpoint:"/api/v1/contracts/parse",apiMethod:"POST",exampleRequest:{contract:{schema:{type:"object",properties:{name:{type:"string"},age:{type:"integer"}}},metadata:{title:"User Contract",version:"1.0.0"}}},exampleCode:`from pycharter import parse_contract, parse_contract_file
2
+
3
+ parse_contract(contract_dict)
4
+ parse_contract_file(file_path)`,arguments:[{name:"contract_data",type:"Dict[str, Any]",description:"Contract data as dictionary containing schema, metadata, ownership, governance_rules, coercion_rules, and validation_rules",required:!0},{name:"validate",type:"bool",description:"If True (default), validate contract against schema before parsing",required:!1,default:"True"}],returns:{type:"ContractMetadata",description:"ContractMetadata object with decomposed components (schema, metadata, ownership, governance_rules, coercion_rules, validation_rules) and version tracking"}},{id:"parse_contract_file",title:"Contract Parser - From File",description:"Parse a data contract from an uploaded file (YAML or JSON)",method:"parse_contract_file(file_path, validate=True)",apiEndpoint:"/api/v1/contracts/parse/upload",apiMethod:"POST",exampleRequest:null,exampleCode:`from pycharter import parse_contract_file
5
+
6
+ # Parse contract from file
7
+ contract_metadata = parse_contract_file("contract.yaml")
8
+ # or
9
+ contract_metadata = parse_contract_file("contract.json", validate=True)`,arguments:[{name:"file_path",type:"str",description:"Path to contract file (YAML or JSON)",required:!0},{name:"validate",type:"bool",description:"If True (default), validate contract against schema before parsing",required:!1,default:"True"}],returns:{type:"ContractMetadata",description:"ContractMetadata object with decomposed components (schema, metadata, ownership, governance_rules, coercion_rules, validation_rules)"}},{id:"build_contract",title:"Contract Builder",description:"Construct consolidated contracts from separate artifacts",method:"build_contract(artifacts: ContractArtifacts, include_metadata=True, include_ownership=True, include_governance=True)",apiEndpoint:"/api/v1/contracts/build",apiMethod:"POST",exampleRequest:{artifacts:{schema:{type:"object",version:"1.0.0",properties:{name:{type:"string"},age:{type:"integer"}}},coercion_rules:{version:"1.0.0",age:"coerce_to_integer"},validation_rules:{version:"1.0.0",age:{greater_than_or_equal_to:{threshold:0}}},metadata:{version:"1.0.0",description:"User contract"}},include_metadata:!0,include_ownership:!0,include_governance:!0},exampleCode:`from pycharter import build_contract, ContractArtifacts
10
+
11
+ artifacts = ContractArtifacts(
12
+ schema={"type": "object", "version": "1.0.0", "properties": {...}},
13
+ coercion_rules={"version": "1.0.0", "age": "coerce_to_integer"},
14
+ validation_rules={"version": "1.0.0", "age": {...}},
15
+ metadata={"version": "1.0.0", "description": "User contract"}
16
+ )
17
+ contract = build_contract(artifacts)`,arguments:[{name:"artifacts",type:"ContractArtifacts",description:"ContractArtifacts dataclass containing schema (required), coercion_rules (optional), validation_rules (optional), and metadata (optional)",required:!0},{name:"include_metadata",type:"bool",description:"Whether to include metadata in the contract",required:!1,default:"True"},{name:"include_ownership",type:"bool",description:"Whether to include ownership information",required:!1,default:"True"},{name:"include_governance",type:"bool",description:"Whether to include governance rules",required:!1,default:"True"}],returns:{type:"Dict[str, Any]",description:"Consolidated contract dictionary ready for runtime validation, containing schema (with merged coercion/validation rules), coercion_rules, validation_rules, metadata (if included), and versions tracking dictionary"}},{id:"build_contract_from_store",title:"Contract Builder - From Store",description:"Build a consolidated contract from artifacts stored in metadata store with individual version control for each component",method:"build_contract_from_store(store, schema_title, schema_version=None, coercion_rules_title=None, coercion_rules_version=None, validation_rules_title=None, validation_rules_version=None, metadata_title=None, metadata_version=None)",apiEndpoint:"/api/v1/contracts/build",apiMethod:"POST",exampleRequest:{schema_title:"user_schema",schema_version:"1.0.0",coercion_rules_title:"user_schema",coercion_rules_version:"1.0.0",validation_rules_title:"user_schema",validation_rules_version:"1.0.0",metadata_title:"user_schema",metadata_version:"1.0.0"},exampleCode:`from pycharter import build_contract_from_store
18
+
19
+ store = PostgresMetadataStore(connection_string)
20
+ store.connect()
21
+ contract = build_contract_from_store(
22
+ store=store,
23
+ schema_title="user_schema",
24
+ schema_version="1.0.0",
25
+ coercion_rules_title="user_schema",
26
+ coercion_rules_version="1.0.0",
27
+ validation_rules_title="user_schema",
28
+ validation_rules_version="1.0.0",
29
+ metadata_title="user_schema",
30
+ metadata_version="1.0.0"
31
+ )`,arguments:[{name:"store",type:"MetadataStoreClient",description:"MetadataStoreClient instance connected to the metadata store",required:!0},{name:"schema_title",type:"str",description:"Schema title/identifier",required:!0},{name:"schema_version",type:"Optional[str]",description:"Optional schema version (if None, uses latest version)",required:!1,default:"None"},{name:"coercion_rules_title",type:"Optional[str]",description:"Optional coercion rules title/identifier (if None, uses schema_title)",required:!1,default:"None"},{name:"coercion_rules_version",type:"Optional[str]",description:"Optional coercion rules version (if None, uses latest version or schema_version)",required:!1,default:"None"},{name:"validation_rules_title",type:"Optional[str]",description:"Optional validation rules title/identifier (if None, uses schema_title)",required:!1,default:"None"},{name:"validation_rules_version",type:"Optional[str]",description:"Optional validation rules version (if None, uses latest version or schema_version)",required:!1,default:"None"},{name:"metadata_title",type:"Optional[str]",description:"Optional metadata title/identifier (if None, uses schema_title)",required:!1,default:"None"},{name:"metadata_version",type:"Optional[str]",description:"Optional metadata version (if None, uses latest version or schema_version)",required:!1,default:"None"}],returns:{type:"Dict[str, Any]",description:"Consolidated contract dictionary ready for runtime validation, containing schema (with merged coercion/validation rules), coercion_rules, validation_rules, metadata (if included), and versions tracking dictionary"}},{id:"store_schema",title:"Metadata Store - Store Schema",description:"Store a JSON Schema in the metadata store",method:"store.store_schema(schema_name, schema, version)",apiEndpoint:"/api/v1/metadata/schemas",apiMethod:"POST",exampleRequest:{schema_name:"user_schema",schema:{type:"object",properties:{name:{type:"string"},age:{type:"integer"}}},version:"1.0.0"},exampleCode:`from pycharter import MetadataStoreClient
32
+
33
+ store = MetadataStoreClient(database_url)
34
+ store.store_schema(schema_id, schema, version)
35
+ store.get_schema(schema_id, version)
36
+ store.store_metadata(schema_id, metadata, version)`,arguments:[{name:"schema_name",type:"str",description:"Name/identifier for the schema (used as data_contract name)",required:!0},{name:"schema",type:"Dict[str, Any]",description:'JSON Schema dictionary (must contain "version" field or it will be added)',required:!0},{name:"version",type:"str",description:'Required version string (must match schema["version"] if present)',required:!0}],returns:{type:"str",description:"Schema ID or identifier"}},{id:"get_schema",title:"Metadata Store - Get Schema",description:"Retrieve a schema from the metadata store",method:"store.get_schema(schema_id, version=None)",apiEndpoint:"/api/v1/metadata/schemas/{schema_id}",apiMethod:"GET",exampleRequest:null,exampleCode:`from pycharter import MetadataStoreClient
37
+
38
+ store = MetadataStoreClient(database_url)
39
+ store.get_schema(schema_id, version)`,arguments:[{name:"schema_id",type:"str",description:"Schema identifier",required:!0},{name:"version",type:"Optional[str]",description:"Optional version string (if None, returns latest version)",required:!1,default:"None"}],returns:{type:"Optional[Dict[str, Any]]",description:"Schema dictionary with version included, or None if not found"}},{id:"list_schemas",title:"Metadata Store - List Schemas",description:"Retrieve a list of all schemas stored in the metadata store",method:"store.list_schemas()",apiEndpoint:"/api/v1/metadata/schemas",apiMethod:"GET",exampleRequest:null,exampleCode:`from pycharter import PostgresMetadataStore
40
+
41
+ store = PostgresMetadataStore(connection_string)
42
+ store.connect()
43
+
44
+ # List all schemas
45
+ schemas = store.list_schemas()
46
+ for schema in schemas:
47
+ print(f"Schema: {schema.get('name')}, Version: {schema.get('version')}")`,arguments:[],returns:{type:"List[Dict[str, Any]]",description:"List of schema metadata dictionaries, each containing id, name, title, and version"}},{id:"store_metadata",title:"Metadata Store - Store Metadata",description:"Store metadata (ownership, governance rules, etc.) for a schema",method:"store.store_metadata(schema_id, metadata, version=None)",apiEndpoint:"/api/v1/metadata/metadata",apiMethod:"POST",exampleRequest:{schema_id:"user_schema",metadata:{title:"user_schema_metadata",description:"Metadata for user schema",business_owners:["owner@example.com"],team:"data-engineering",governance_rules:{data_retention:{days:2555},access_control:{level:"public"}}},version:"1.0.0"},exampleCode:`from pycharter import PostgresMetadataStore
48
+
49
+ store = PostgresMetadataStore(connection_string)
50
+ store.connect()
51
+
52
+ # Store metadata for a schema
53
+ metadata_id = store.store_metadata(
54
+ schema_id='user_schema',
55
+ metadata={
56
+ 'title': 'user_schema_metadata',
57
+ 'description': 'Metadata for user schema',
58
+ 'business_owners': ['owner@example.com'],
59
+ 'team': 'data-engineering',
60
+ 'governance_rules': {
61
+ 'data_retention': {'days': 2555},
62
+ 'access_control': {'level': 'public'}
63
+ }
64
+ },
65
+ version='1.0.0'
66
+ )`,arguments:[{name:"schema_id",type:"str",description:"Schema identifier",required:!0},{name:"metadata",type:"Dict[str, Any]",description:"Metadata dictionary containing ownership, governance_rules, and other metadata",required:!0},{name:"version",type:"Optional[str]",description:"Optional version string (if None, uses schema version)",required:!1,default:"None"}],returns:{type:"str",description:"Metadata record ID"}},{id:"get_metadata",title:"Metadata Store - Get Metadata",description:"Retrieve metadata for a schema from the metadata store",method:"store.get_metadata(schema_id, version=None)",apiEndpoint:"/api/v1/metadata/metadata/{schema_id}",apiMethod:"GET",exampleRequest:null,exampleCode:`from pycharter import PostgresMetadataStore
67
+
68
+ store = PostgresMetadataStore(connection_string)
69
+ store.connect()
70
+
71
+ # Get metadata for a schema
72
+ metadata = store.get_metadata(
73
+ schema_id='user_schema',
74
+ version='1.0.0' # Optional, defaults to latest
75
+ )`,arguments:[{name:"schema_id",type:"str",description:"Schema identifier",required:!0},{name:"version",type:"Optional[str]",description:"Optional version string (if None, uses latest version)",required:!1,default:"None"}],returns:{type:"Optional[Dict[str, Any]]",description:"Metadata dictionary or None if not found"}},{id:"get_complete_schema",title:"Metadata Store - Get Complete Schema",description:"Retrieve a complete schema with coercion and validation rules merged",method:"store.get_complete_schema(schema_id, version=None)",apiEndpoint:"/api/v1/metadata/schemas/{schema_id}/complete",apiMethod:"GET",exampleRequest:null,exampleCode:`from pycharter import PostgresMetadataStore
76
+
77
+ store = PostgresMetadataStore(connection_string)
78
+ store.connect()
79
+
80
+ # Get complete schema with rules merged
81
+ complete_schema = store.get_complete_schema(
82
+ schema_id='user_schema',
83
+ version='1.0.0' # Optional, defaults to latest
84
+ )
85
+ # The schema now includes coercion and validation rules
86
+ # merged into the properties`,arguments:[{name:"schema_id",type:"str",description:"Schema identifier",required:!0},{name:"version",type:"Optional[str]",description:"Optional version string (if None, defaults to latest)",required:!1,default:"None"}],returns:{type:"Optional[Dict[str, Any]]",description:"Complete schema dictionary with coercion and validation rules merged into the properties, or None if not found"}},{id:"store_coercion_rules",title:"Metadata Store - Store Coercion Rules",description:"Store coercion rules that define how data should be transformed before validation",method:"store.store_coercion_rules(schema_id, coercion_rules, version=None)",apiEndpoint:"/api/v1/metadata/coercion-rules",apiMethod:"POST",exampleRequest:{schema_id:"user_schema",coercion_rules:{age:"coerce_to_integer",email:"coerce_to_lowercase",price:"coerce_to_float",name:"coerce_to_stripped_string"},version:"1.0.0"},exampleCode:`from pycharter import PostgresMetadataStore
87
+
88
+ store = PostgresMetadataStore(connection_string)
89
+ store.connect()
90
+
91
+ # Store coercion rules for a schema
92
+ rule_id = store.store_coercion_rules(
93
+ schema_id='user_schema',
94
+ coercion_rules={
95
+ 'age': 'coerce_to_integer',
96
+ 'email': 'coerce_to_lowercase',
97
+ 'name': 'coerce_to_stripped_string'
98
+ },
99
+ version='1.0.0'
100
+ )`,arguments:[{name:"schema_id",type:"str",description:"Schema identifier",required:!0},{name:"coercion_rules",type:"Dict[str, Any]",description:'Dictionary mapping field names to coercion rule types (e.g., "coerce_to_integer", "coerce_to_lowercase")',required:!0},{name:"version",type:"Optional[str]",description:"Optional version string (if None, uses schema version)",required:!1,default:"None"}],returns:{type:"str",description:"Coercion rule record ID"}},{id:"get_coercion_rules",title:"Metadata Store - Get Coercion Rules",description:"Retrieve coercion rules for a schema from the metadata store",method:"store.get_coercion_rules(schema_id, version=None)",apiEndpoint:"/api/v1/metadata/coercion-rules/{schema_id}",apiMethod:"GET",exampleRequest:null,exampleCode:`from pycharter import PostgresMetadataStore
101
+
102
+ store = PostgresMetadataStore(connection_string)
103
+ store.connect()
104
+
105
+ # Get coercion rules for a schema
106
+ coercion_rules = store.get_coercion_rules(
107
+ schema_id='user_schema',
108
+ version='1.0.0' # Optional, defaults to latest
109
+ )`,arguments:[{name:"schema_id",type:"str",description:"Schema identifier",required:!0},{name:"version",type:"Optional[str]",description:"Optional version string (if None, defaults to latest)",required:!1,default:"None"}],returns:{type:"Optional[Dict[str, Any]]",description:"Coercion rules dictionary mapping field names to coercion types, or None if not found"}},{id:"store_validation_rules",title:"Metadata Store - Store Validation Rules",description:"Store validation rules that define custom validation logic beyond JSON Schema",method:"store.store_validation_rules(schema_id, validation_rules, version=None)",apiEndpoint:"/api/v1/metadata/validation-rules",apiMethod:"POST",exampleRequest:{schema_id:"user_schema",validation_rules:{age:{greater_than_or_equal_to:{threshold:0},less_than_or_equal_to:{threshold:150}},email:{min_length:{threshold:5},matches_pattern:{pattern:"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"}}},version:"1.0.0"},exampleCode:`from pycharter import PostgresMetadataStore
110
+
111
+ store = PostgresMetadataStore(connection_string)
112
+ store.connect()
113
+
114
+ # Store validation rules for a schema
115
+ rule_id = store.store_validation_rules(
116
+ schema_id='user_schema',
117
+ validation_rules={
118
+ 'age': {
119
+ 'greater_than_or_equal_to': {'threshold': 0},
120
+ 'less_than_or_equal_to': {'threshold': 150}
121
+ },
122
+ 'email': {
123
+ 'min_length': {'threshold': 5},
124
+ 'matches_pattern': {'pattern': '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$'}
125
+ }
126
+ },
127
+ version='1.0.0'
128
+ )`,arguments:[{name:"schema_id",type:"str",description:"Schema identifier",required:!0},{name:"validation_rules",type:"Dict[str, Any]",description:'Dictionary mapping field names to validation rule dictionaries (e.g., {"age": {"greater_than_or_equal_to": {"threshold": 0}}})',required:!0},{name:"version",type:"Optional[str]",description:"Optional version string (if None, uses schema version)",required:!1,default:"None"}],returns:{type:"str",description:"Validation rule record ID"}},{id:"get_validation_rules",title:"Metadata Store - Get Validation Rules",description:"Retrieve validation rules for a schema from the metadata store",method:"store.get_validation_rules(schema_id, version=None)",apiEndpoint:"/api/v1/metadata/validation-rules/{schema_id}",apiMethod:"GET",exampleRequest:null,exampleCode:`from pycharter import PostgresMetadataStore
129
+
130
+ store = PostgresMetadataStore(connection_string)
131
+ store.connect()
132
+
133
+ # Get validation rules for a schema
134
+ validation_rules = store.get_validation_rules(
135
+ schema_id='user_schema',
136
+ version='1.0.0' # Optional, defaults to latest
137
+ )`,arguments:[{name:"schema_id",type:"str",description:"Schema identifier",required:!0},{name:"version",type:"Optional[str]",description:"Optional version string (if None, defaults to latest)",required:!1,default:"None"}],returns:{type:"Optional[Dict[str, Any]]",description:"Validation rules dictionary mapping field names to validation rule dictionaries, or None if not found"}},{id:"generate_model",title:"Pydantic Generator",description:"Generate Pydantic models from JSON Schema",method:'generate_model(schema, model_name="DynamicModel")',apiEndpoint:"/api/v1/schemas/generate",apiMethod:"POST",exampleRequest:{schema:{type:"object",properties:{name:{type:"string"},age:{type:"integer"}}},model_name:"User"},exampleCode:`from pycharter import generate_model, generate_model_file, from_dict, from_file, from_json, from_url
138
+
139
+ # Advanced: More control
140
+ UserModel = generate_model(schema_dict, model_name="User")
141
+
142
+ # Quick helpers: Generate and return model
143
+ UserModel = from_dict(schema_dict) # From dictionary
144
+ UserModel = from_file("schema.json") # From file
145
+ UserModel = from_json(json_string) # From JSON string
146
+ UserModel = from_url("https://example.com/schema.json") # From URL
147
+
148
+ # Generate model and save to file
149
+ generate_model_file(schema_dict, "models.py", model_name="User")`,arguments:[{name:"schema",type:"Dict[str, Any]",description:"JSON Schema dictionary",required:!0},{name:"model_name",type:"str",description:"Name for the generated Pydantic model class",required:!1,default:'"DynamicModel"'}],returns:{type:"Type[BaseModel]",description:"A Pydantic model class generated from the schema"}},{id:"from_dict",title:"Generate Model from Dict",description:"Quick helper: Generate Pydantic model from JSON Schema dictionary",method:"from_dict(schema_dict)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import from_dict
150
+
151
+ schema = {
152
+ "type": "object",
153
+ "properties": {
154
+ "name": {"type": "string"},
155
+ "age": {"type": "integer"}
156
+ }
157
+ }
158
+
159
+ UserModel = from_dict(schema)
160
+ user = UserModel(name="Alice", age=30)`,arguments:[{name:"schema_dict",type:"Dict[str, Any]",description:"JSON Schema dictionary",required:!0}],returns:{type:"Type[BaseModel]",description:"Pydantic model class generated from the schema"}},{id:"from_file",title:"Generate Model from File",description:"Quick helper: Generate Pydantic model from JSON Schema file",method:"from_file(file_path)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import from_file
161
+
162
+ UserModel = from_file("schema.json")
163
+ # or
164
+ UserModel = from_file("schema.yaml")`,arguments:[{name:"file_path",type:"str",description:"Path to JSON Schema file (JSON or YAML)",required:!0}],returns:{type:"Type[BaseModel]",description:"Pydantic model class generated from the schema file"}},{id:"from_json",title:"Generate Model from JSON String",description:"Quick helper: Generate Pydantic model from JSON Schema JSON string",method:"from_json(json_string)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import from_json
165
+
166
+ json_schema = '{"type": "object", "properties": {"name": {"type": "string"}}}'
167
+ UserModel = from_json(json_schema)`,arguments:[{name:"json_string",type:"str",description:"JSON Schema as JSON string",required:!0}],returns:{type:"Type[BaseModel]",description:"Pydantic model class generated from the JSON string"}},{id:"from_url",title:"Generate Model from URL",description:"Quick helper: Generate Pydantic model from JSON Schema URL",method:"from_url(url)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import from_url
168
+
169
+ UserModel = from_url("https://example.com/schema.json")`,arguments:[{name:"url",type:"str",description:"URL to JSON Schema file",required:!0}],returns:{type:"Type[BaseModel]",description:"Pydantic model class generated from the URL"}},{id:"generate_model_file",title:"Generate Model File",description:"Generate Pydantic model and save to Python file",method:'generate_model_file(schema, output_file, model_name="DynamicModel")',apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import generate_model_file
170
+
171
+ schema = {
172
+ "type": "object",
173
+ "properties": {
174
+ "name": {"type": "string"},
175
+ "age": {"type": "integer"}
176
+ }
177
+ }
178
+
179
+ generate_model_file(
180
+ schema=schema,
181
+ output_file="models.py",
182
+ model_name="User"
183
+ )`,arguments:[{name:"schema",type:"Dict[str, Any]",description:"JSON Schema dictionary",required:!0},{name:"output_file",type:"str",description:"Path to output Python file",required:!0},{name:"model_name",type:"str",description:"Name for the generated Pydantic model class",required:!1,default:'"DynamicModel"'}],returns:{type:"None",description:"Saves the generated model to the specified file"}},{id:"model_to_schema",title:"JSON Schema Converter (Advanced)",description:"Convert Pydantic models to JSON Schema - core conversion function",method:"model_to_schema(model_class)",apiEndpoint:"/api/v1/schemas/convert",apiMethod:"POST",exampleRequest:{model_class:"pydantic.BaseModel"},exampleCode:`from pycharter import model_to_schema
184
+ from pydantic import BaseModel
185
+
186
+ class UserModel(BaseModel):
187
+ name: str
188
+ age: int
189
+
190
+ schema = model_to_schema(UserModel)
191
+ print(schema)`,arguments:[{name:"model_class",type:"Type[BaseModel] | str",description:'Pydantic model class or fully qualified class name (e.g., "mymodule.UserModel")',required:!0}],returns:{type:"Dict[str, Any]",description:"JSON Schema dictionary with optional title and version fields"}},{id:"to_dict",title:"Convert Model to Dict",description:"Quick helper: Convert Pydantic model to JSON Schema dictionary",method:"to_dict(model_class)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import to_dict
192
+ from pydantic import BaseModel
193
+
194
+ class UserModel(BaseModel):
195
+ name: str
196
+ age: int
197
+
198
+ schema = to_dict(UserModel)`,arguments:[{name:"model_class",type:"Type[BaseModel] | str",description:"Pydantic model class or fully qualified class name",required:!0}],returns:{type:"Dict[str, Any]",description:"JSON Schema dictionary"}},{id:"to_json",title:"Convert Model to JSON String",description:"Quick helper: Convert Pydantic model to JSON Schema JSON string",method:"to_json(model_class)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import to_json
199
+ from pydantic import BaseModel
200
+
201
+ class UserModel(BaseModel):
202
+ name: str
203
+ age: int
204
+
205
+ json_schema = to_json(UserModel)
206
+ print(json_schema)`,arguments:[{name:"model_class",type:"Type[BaseModel] | str",description:"Pydantic model class or fully qualified class name",required:!0}],returns:{type:"str",description:"JSON Schema as JSON string"}},{id:"to_file",title:"Convert Model to File",description:"Quick helper: Convert Pydantic model to JSON Schema file",method:"to_file(model_class, file_path)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import to_file
207
+ from pydantic import BaseModel
208
+
209
+ class UserModel(BaseModel):
210
+ name: str
211
+ age: int
212
+
213
+ to_file(UserModel, "schema.json")
214
+ # or
215
+ to_file(UserModel, "schema.yaml")`,arguments:[{name:"model_class",type:"Type[BaseModel] | str",description:"Pydantic model class or fully qualified class name",required:!0},{name:"file_path",type:"str",description:"Path to output file (JSON or YAML)",required:!0}],returns:{type:"None",description:"Saves the JSON Schema to the specified file"}},{id:"validator_class",title:"Validator Class (PRIMARY INTERFACE)",description:"⭐ PRIMARY: Use Validator class for all validation - best performance and flexibility",method:"Validator(contract_dir=None, contract_file=None, contract_dict=None, contract_metadata=None, store=None, schema_id=None, schema_version=None)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import Validator, ValidatorBuilder, create_validator
216
+ from pycharter.metadata_store import SQLiteMetadataStore
217
+
218
+ # From contract directory
219
+ validator = Validator(contract_dir="data/contracts/user")
220
+ result = validator.validate({"name": "Alice", "age": 30})
221
+
222
+ # From metadata store
223
+ store = SQLiteMetadataStore("metadata.db")
224
+ store.connect()
225
+ validator = Validator(store=store, schema_id="user_schema")
226
+ result = validator.validate({"name": "Alice", "age": 30})
227
+
228
+ # Using ValidatorBuilder (fluent API)
229
+ validator = (
230
+ ValidatorBuilder()
231
+ .from_directory("data/contracts/user")
232
+ .strict()
233
+ .with_quality_checks({"completeness": 0.95})
234
+ .build()
235
+ )
236
+ result = validator.validate({"name": "Alice", "age": 30})
237
+ print(result.quality.completeness) # Quality metrics included
238
+
239
+ # Batch validation
240
+ results = validator.validate_batch([
241
+ {"name": "Alice", "age": 30},
242
+ {"name": "Bob", "age": 25}
243
+ ])
244
+
245
+ # Factory function
246
+ validator = create_validator(contract_file="contract.yaml")`,arguments:[{name:"contract_dir",type:"Optional[str]",description:"Directory containing contract files (schema.yaml, coercion_rules.yaml, validation_rules.yaml)",required:!1},{name:"contract_file",type:"Optional[str]",description:"Path to complete contract file (YAML/JSON)",required:!1},{name:"contract_dict",type:"Optional[Dict[str, Any]]",description:"Contract as dictionary with schema, coercion_rules, validation_rules keys",required:!1},{name:"contract_metadata",type:"Optional[ContractMetadata]",description:"ContractMetadata object (from parse_contract)",required:!1},{name:"store",type:"Optional[MetadataStoreClient]",description:"MetadataStoreClient instance (for loading from metadata store)",required:!1},{name:"schema_id",type:"Optional[str]",description:"Schema identifier (required when using store)",required:!1},{name:"schema_version",type:"Optional[str]",description:"Optional schema version (defaults to latest when using store)",required:!1}],returns:{type:"Validator",description:"Validator instance with validate() and validate_batch() methods"}},{id:"validator_builder",title:"ValidatorBuilder (Fluent API)",description:"Fluent builder pattern for constructing validators with configuration options like strict mode and quality checks",method:"ValidatorBuilder().from_directory(path).strict().with_quality_checks(thresholds).build()",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import ValidatorBuilder
247
+
248
+ # Basic usage
249
+ validator = (
250
+ ValidatorBuilder()
251
+ .from_directory("data/contracts/user")
252
+ .build()
253
+ )
254
+
255
+ # With strict mode (raises exceptions on errors)
256
+ validator = (
257
+ ValidatorBuilder()
258
+ .from_file("contracts/user.yaml")
259
+ .strict()
260
+ .build()
261
+ )
262
+
263
+ # With quality checks
264
+ validator = (
265
+ ValidatorBuilder()
266
+ .from_dict(contract_dict)
267
+ .with_quality_checks({"completeness": 0.95, "validity_rate": 0.99})
268
+ .build()
269
+ )
270
+
271
+ # From metadata store
272
+ validator = (
273
+ ValidatorBuilder()
274
+ .from_store(store, "user_schema", version="1.0.0")
275
+ .lenient()
276
+ .with_quality_checks()
277
+ .build()
278
+ )
279
+
280
+ # Validate with quality metrics
281
+ result = validator.validate(data, include_quality=True)
282
+ if result.quality:
283
+ print(f"Completeness: {result.quality.completeness}")
284
+ print(f"Validity rate: {result.quality.validity_rate}")`,arguments:[{name:"from_directory(path)",type:"method",description:"Load contract from directory containing schema.yaml, coercion_rules.yaml, validation_rules.yaml",required:!1},{name:"from_file(path)",type:"method",description:"Load contract from a single file (YAML/JSON)",required:!1},{name:"from_dict(contract_dict)",type:"method",description:"Load contract from dictionary",required:!1},{name:"from_store(store, schema_id, version)",type:"method",description:"Load contract from metadata store",required:!1},{name:"strict()",type:"method",description:"Enable strict mode - raises exceptions on validation errors",required:!1},{name:"lenient()",type:"method",description:"Enable lenient mode (default) - returns errors in ValidationResult",required:!1},{name:"with_quality_checks(thresholds)",type:"method",description:"Enable quality metrics calculation during validation. Optional thresholds dict for pass/fail criteria.",required:!1},{name:"build()",type:"method",description:"Build and return the configured Validator instance",required:!0}],returns:{type:"Validator",description:"Configured Validator instance with the specified options"}},{id:"validation_quality_metrics",title:"ValidationResult Quality Metrics",description:"Quality metrics included in ValidationResult when quality checks are enabled",method:"result.quality (QualityMetrics)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import Validator, ValidatorBuilder
285
+
286
+ # Enable quality checks via builder
287
+ validator = (
288
+ ValidatorBuilder()
289
+ .from_directory("data/contracts/user")
290
+ .with_quality_checks()
291
+ .build()
292
+ )
293
+
294
+ # Single validation with quality
295
+ result = validator.validate(data, include_quality=True)
296
+ if result.is_valid:
297
+ print(f"Valid! Quality score: {result.quality.completeness:.2%}")
298
+ else:
299
+ print(f"Invalid. Errors: {result.errors}")
300
+
301
+ # Batch validation with quality
302
+ results = validator.validate_batch(data_list, include_quality=True)
303
+ last_result = results[-1] # Quality metrics on last result
304
+ print(f"Valid: {last_result.quality.valid_count}/{last_result.quality.record_count}")
305
+ print(f"Validity rate: {last_result.quality.validity_rate:.2%}")
306
+
307
+ # Check against thresholds
308
+ thresholds = {"completeness": 0.95, "validity_rate": 0.99}
309
+ if last_result.quality.passes_thresholds(thresholds):
310
+ print("Quality thresholds passed!")`,arguments:[{name:"completeness",type:"float",description:"Ratio of non-null fields (0.0 to 1.0)",required:!1},{name:"field_completeness",type:"Dict[str, float]",description:"Per-field completeness ratios",required:!1},{name:"record_count",type:"int",description:"Total number of records validated",required:!1},{name:"valid_count",type:"int",description:"Number of valid records",required:!1},{name:"error_count",type:"int",description:"Number of records with errors",required:!1},{name:"validity_rate",type:"float (property)",description:"Ratio of valid records (valid_count / record_count)",required:!1}],returns:{type:"QualityMetrics",description:"Quality metrics object with completeness, validity rate, and per-field metrics"}},{id:"error_handling",title:"Error Handling Modes",description:"Standardized error handling with STRICT, LENIENT, and COLLECT modes for consistent behavior across pycharter",method:"ErrorMode, StrictMode, LenientMode, set_error_mode()",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import ErrorMode, StrictMode, LenientMode, set_error_mode
311
+
312
+ # Set global error mode
313
+ set_error_mode(ErrorMode.STRICT) # Raise exceptions
314
+ set_error_mode(ErrorMode.LENIENT) # Log warnings (default)
315
+ set_error_mode(ErrorMode.COLLECT) # Collect errors
316
+
317
+ # Context manager for temporary strict mode
318
+ from pycharter import Validator
319
+
320
+ validator = Validator(contract_dir="data/contracts/user")
321
+
322
+ with StrictMode():
323
+ # Errors will raise exceptions in this block
324
+ result = validator.validate(data) # Raises on error
325
+
326
+ # Back to default lenient mode
327
+ result = validator.validate(data) # Returns ValidationResult with errors
328
+
329
+ # Context manager for lenient mode
330
+ with LenientMode():
331
+ # Errors are logged as warnings
332
+ result = validator.validate(data)
333
+
334
+ # Using ErrorContext for collecting errors
335
+ from pycharter.shared import ErrorContext, ErrorMode
336
+
337
+ ctx = ErrorContext(mode=ErrorMode.COLLECT)
338
+ ctx.handle_error("Field 'name' is missing", category="validation")
339
+ ctx.handle_error("Field 'age' must be positive", category="validation")
340
+
341
+ print(f"Has errors: {ctx.has_errors}")
342
+ print(f"Errors: {ctx.errors}")
343
+ ctx.raise_if_errors() # Raises ValueError with all errors`,arguments:[{name:"ErrorMode.STRICT",type:"enum",description:"Raise exceptions immediately on any error",required:!1},{name:"ErrorMode.LENIENT",type:"enum",description:"Log warnings and continue with best effort (default)",required:!1},{name:"ErrorMode.COLLECT",type:"enum",description:"Collect errors and return them with results",required:!1},{name:"StrictMode",type:"context manager",description:"Context manager for temporarily enabling strict mode",required:!1},{name:"LenientMode",type:"context manager",description:"Context manager for temporarily enabling lenient mode",required:!1},{name:"set_error_mode(mode)",type:"function",description:"Set the default error handling mode globally",required:!1}],returns:{type:"None / ErrorContext",description:"Context managers return None; ErrorContext for collecting errors"}},{id:"validate_with_store",title:"Validate with Store (Convenience)",description:"Quick validation using schema from metadata store",method:"validate_with_store(store, schema_id, data, version=None, strict=False)",apiEndpoint:"/api/v1/validation/validate",apiMethod:"POST",exampleRequest:{schema_id:"user_schema",data:{name:"Alice",age:30},version:"1.0.0",strict:!1},exampleCode:`from pycharter import validate_with_store
344
+ from pycharter.metadata_store import SQLiteMetadataStore
345
+
346
+ store = SQLiteMetadataStore("metadata.db")
347
+ store.connect()
348
+
349
+ result = validate_with_store(
350
+ store=store,
351
+ schema_id="user_schema",
352
+ data={"name": "Alice", "age": 30},
353
+ version="1.0.0"
354
+ )
355
+
356
+ if result.is_valid:
357
+ print("Valid data:", result.data)
358
+ else:
359
+ print("Errors:", result.errors)`,arguments:[{name:"store",type:"MetadataStoreClient",description:"MetadataStoreClient instance",required:!0},{name:"schema_id",type:"str",description:"Schema identifier",required:!0},{name:"data",type:"Dict[str, Any]",description:"Data dictionary to validate",required:!0},{name:"version",type:"Optional[str]",description:"Optional schema version (if None, uses latest)",required:!1,default:"None"},{name:"strict",type:"bool",description:"If True, raise exceptions on validation errors",required:!1,default:"False"}],returns:{type:"ValidationResult",description:"ValidationResult object with is_valid flag, validated data (if valid), and list of errors (if invalid)"}},{id:"validate_with_contract",title:"Validate with Contract (Convenience)",description:"Quick validation using contract dictionary or file",method:"validate_with_contract(contract, data, strict=False)",apiEndpoint:"/api/v1/validation/validate",apiMethod:"POST",exampleRequest:{contract:{schema:{type:"object",properties:{name:{type:"string"},age:{type:"integer"}}}},data:{name:"Alice",age:30},strict:!1},exampleCode:`from pycharter import validate_with_contract
360
+
361
+ contract = {
362
+ "schema": {
363
+ "type": "object",
364
+ "properties": {
365
+ "name": {"type": "string"},
366
+ "age": {"type": "integer"}
367
+ }
368
+ }
369
+ }
370
+
371
+ result = validate_with_contract(
372
+ contract=contract,
373
+ data={"name": "Alice", "age": 30}
374
+ )
375
+
376
+ # Or from file
377
+ result = validate_with_contract(
378
+ contract="contracts/user.yaml",
379
+ data={"name": "Alice", "age": 30}
380
+ )`,arguments:[{name:"contract",type:"Dict[str, Any] | ContractMetadata | str",description:"Contract dictionary, ContractMetadata object, or file path",required:!0},{name:"data",type:"Dict[str, Any]",description:"Data dictionary to validate",required:!0},{name:"strict",type:"bool",description:"If True, raise exceptions on validation errors",required:!1,default:"False"}],returns:{type:"ValidationResult",description:"ValidationResult object with is_valid flag, validated data (if valid), and list of errors (if invalid)"}},{id:"validate_batch_with_store",title:"Batch Validate with Store",description:"Validate multiple records using schema from metadata store",method:"validate_batch_with_store(store, schema_id, data_list, version=None, strict=False)",apiEndpoint:"/api/v1/validation/validate-batch",apiMethod:"POST",exampleRequest:{schema_id:"user_schema",data_list:[{name:"Alice",age:30},{name:"Bob",age:25}],version:"1.0.0",strict:!1},exampleCode:`from pycharter import validate_batch_with_store
381
+ from pycharter.metadata_store import SQLiteMetadataStore
382
+
383
+ store = SQLiteMetadataStore("metadata.db")
384
+ store.connect()
385
+
386
+ results = validate_batch_with_store(
387
+ store=store,
388
+ schema_id="user_schema",
389
+ data_list=[
390
+ {"name": "Alice", "age": 30},
391
+ {"name": "Bob", "age": 25}
392
+ ],
393
+ version="1.0.0"
394
+ )
395
+
396
+ print(f"Valid: {results.total_count - len(results.errors)}/{results.total_count}")`,arguments:[{name:"store",type:"MetadataStoreClient",description:"MetadataStoreClient instance",required:!0},{name:"schema_id",type:"str",description:"Schema identifier",required:!0},{name:"data_list",type:"List[Dict[str, Any]]",description:"List of data dictionaries to validate",required:!0},{name:"version",type:"Optional[str]",description:"Optional schema version (if None, uses latest)",required:!1,default:"None"},{name:"strict",type:"bool",description:"If True, raise exceptions on validation errors",required:!1,default:"False"}],returns:{type:"ValidationBatchResponse",description:"Batch validation results with total_count, valid_count, error_count, and results list"}},{id:"validate_batch_with_contract",title:"Batch Validate with Contract",description:"Validate multiple records using contract dictionary or file",method:"validate_batch_with_contract(contract, data_list, strict=False)",apiEndpoint:"/api/v1/validation/validate-batch",apiMethod:"POST",exampleRequest:{contract:{schema:{type:"object",properties:{name:{type:"string"},age:{type:"integer"}}}},data_list:[{name:"Alice",age:30},{name:"Bob",age:25}],strict:!1},exampleCode:`from pycharter import validate_batch_with_contract
397
+
398
+ contract = {
399
+ "schema": {
400
+ "type": "object",
401
+ "properties": {
402
+ "name": {"type": "string"},
403
+ "age": {"type": "integer"}
404
+ }
405
+ }
406
+ }
407
+
408
+ results = validate_batch_with_contract(
409
+ contract=contract,
410
+ data_list=[
411
+ {"name": "Alice", "age": 30},
412
+ {"name": "Bob", "age": 25}
413
+ ]
414
+ )`,arguments:[{name:"contract",type:"Dict[str, Any] | ContractMetadata | str",description:"Contract dictionary, ContractMetadata object, or file path",required:!0},{name:"data_list",type:"List[Dict[str, Any]]",description:"List of data dictionaries to validate",required:!0},{name:"strict",type:"bool",description:"If True, raise exceptions on validation errors",required:!1,default:"False"}],returns:{type:"ValidationBatchResponse",description:"Batch validation results with total_count, valid_count, error_count, and results list"}},{id:"get_model_from_store",title:"Get Model from Store",description:"Get Pydantic model class from schema stored in metadata store",method:"get_model_from_store(store, schema_id, version=None)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import get_model_from_store
415
+ from pycharter.metadata_store import SQLiteMetadataStore
416
+
417
+ store = SQLiteMetadataStore("metadata.db")
418
+ store.connect()
419
+
420
+ # Get Pydantic model class
421
+ UserModel = get_model_from_store(
422
+ store=store,
423
+ schema_id="user_schema",
424
+ version="1.0.0"
425
+ )
426
+
427
+ # Use the model directly
428
+ user = UserModel(name="Alice", age=30)
429
+ print(user.model_dump())`,arguments:[{name:"store",type:"MetadataStoreClient",description:"MetadataStoreClient instance",required:!0},{name:"schema_id",type:"str",description:"Schema identifier",required:!0},{name:"version",type:"Optional[str]",description:"Optional schema version (if None, uses latest)",required:!1,default:"None"}],returns:{type:"Type[BaseModel]",description:"Pydantic model class generated from the schema"}},{id:"get_model_from_contract",title:"Get Model from Contract",description:"Get Pydantic model class from contract dictionary or file",method:"get_model_from_contract(contract)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import get_model_from_contract
430
+
431
+ contract = {
432
+ "schema": {
433
+ "type": "object",
434
+ "properties": {
435
+ "name": {"type": "string"},
436
+ "age": {"type": "integer"}
437
+ }
438
+ }
439
+ }
440
+
441
+ # Get Pydantic model class
442
+ UserModel = get_model_from_contract(contract)
443
+
444
+ # Use the model directly
445
+ user = UserModel(name="Alice", age=30)
446
+ print(user.model_dump())
447
+
448
+ # Or from file
449
+ UserModel = get_model_from_contract("contracts/user.yaml")`,arguments:[{name:"contract",type:"Dict[str, Any] | ContractMetadata | str",description:"Contract dictionary, ContractMetadata object, or file path",required:!0}],returns:{type:"Type[BaseModel]",description:"Pydantic model class generated from the contract schema"}},{id:"validate",title:"Validate (Low-level)",description:"Low-level validation with existing Pydantic model",method:"validate(data, model, coercion_rules=None, validation_rules=None, strict=False)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import validate
450
+ from pydantic import BaseModel
451
+
452
+ # Define model manually or get from contract
453
+ class UserModel(BaseModel):
454
+ name: str
455
+ age: int
456
+
457
+ # Validate with model
458
+ result = validate(
459
+ data={"name": "Alice", "age": 30},
460
+ model=UserModel,
461
+ coercion_rules=None,
462
+ validation_rules=None
463
+ )
464
+
465
+ if result.is_valid:
466
+ print("Valid:", result.data)
467
+ else:
468
+ print("Errors:", result.errors)`,arguments:[{name:"data",type:"Dict[str, Any]",description:"Data dictionary to validate",required:!0},{name:"model",type:"Type[BaseModel]",description:"Pydantic model class",required:!0},{name:"coercion_rules",type:"Optional[Dict[str, Any]]",description:"Optional coercion rules dictionary",required:!1,default:"None"},{name:"validation_rules",type:"Optional[Dict[str, Any]]",description:"Optional validation rules dictionary",required:!1,default:"None"},{name:"strict",type:"bool",description:"If True, raise exceptions on validation errors",required:!1,default:"False"}],returns:{type:"ValidationResult",description:"ValidationResult object with is_valid flag, validated data (if valid), and list of errors (if invalid)"}},{id:"validate_batch",title:"Batch Validate (Low-level)",description:"Low-level batch validation with existing Pydantic model",method:"validate_batch(data_list, model, coercion_rules=None, validation_rules=None, strict=False)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import validate_batch
469
+ from pydantic import BaseModel
470
+
471
+ # Define model manually or get from contract
472
+ class UserModel(BaseModel):
473
+ name: str
474
+ age: int
475
+
476
+ # Batch validate with model
477
+ results = validate_batch(
478
+ data_list=[
479
+ {"name": "Alice", "age": 30},
480
+ {"name": "Bob", "age": 25}
481
+ ],
482
+ model=UserModel
483
+ )
484
+
485
+ print(f"Valid: {results.valid_count}/{results.total_count}")`,arguments:[{name:"data_list",type:"List[Dict[str, Any]]",description:"List of data dictionaries to validate",required:!0},{name:"model",type:"Type[BaseModel]",description:"Pydantic model class",required:!0},{name:"coercion_rules",type:"Optional[Dict[str, Any]]",description:"Optional coercion rules dictionary",required:!1,default:"None"},{name:"validation_rules",type:"Optional[Dict[str, Any]]",description:"Optional validation rules dictionary",required:!1,default:"None"},{name:"strict",type:"bool",description:"If True, raise exceptions on validation errors",required:!1,default:"False"}],returns:{type:"ValidationBatchResponse",description:"Batch validation results with total_count, valid_count, error_count, and results list"}},{id:"quality_check",title:"QualityCheck Class (PRIMARY INTERFACE)",description:"⭐ PRIMARY: Use QualityCheck class for quality assurance - monitor data quality, calculate metrics, and track violations",method:"QualityCheck(store=None, db_session=None).run(schema_id=None, contract=None, data=None, options=None)",apiEndpoint:"/api/v1/quality/check",apiMethod:"POST",exampleRequest:{schema_id:"user_schema",data:[{name:"Alice",age:30},{name:"Bob",age:25}],calculate_metrics:!0,record_violations:!0},exampleCode:`from pycharter import QualityCheck, QualityCheckOptions, QualityReport, QualityThresholds
486
+ from pycharter.metadata_store import SQLiteMetadataStore
487
+ from sqlalchemy.orm import Session
488
+
489
+ # Create quality check instance
490
+ store = SQLiteMetadataStore("metadata.db")
491
+ store.connect()
492
+ db_session = Session() # Your database session
493
+
494
+ check = QualityCheck(store=store, db_session=db_session)
495
+
496
+ # Configure options
497
+ options = QualityCheckOptions(
498
+ record_violations=True,
499
+ calculate_metrics=True,
500
+ check_thresholds=True,
501
+ include_field_metrics=True,
502
+ sample_size=None # Process all data
503
+ )
504
+
505
+ # Set thresholds (optional)
506
+ thresholds = QualityThresholds(
507
+ overall_score_min=80.0,
508
+ accuracy_min=95.0,
509
+ completeness_min=90.0
510
+ )
511
+
512
+ # Run quality check
513
+ report = check.run(
514
+ schema_id='user_schema',
515
+ data="data/users.json", # File path, list, or callable
516
+ options=options
517
+ )
518
+
519
+ # Access results
520
+ print(f"Quality Score: {report.quality_score.overall_score:.2f}/100")
521
+ print(f"Passed: {report.passed}")
522
+ print(f"Metrics: {report.metrics}")
523
+ print(f"Violations: {len(report.violations)}")`,arguments:[{name:"store",type:"Optional[MetadataStoreClient]",description:"Optional metadata store for retrieving contracts and storing violations",required:!1,default:"None"},{name:"db_session",type:"Optional[Session]",description:"Optional SQLAlchemy database session for persisting metrics and violations",required:!1,default:"None"},{name:"schema_id",type:"Optional[str]",description:"Schema ID (if using store-based validation)",required:!1},{name:"contract",type:"Optional[Dict[str, Any] | str]",description:"Contract dictionary or file path (if using contract-based validation)",required:!1},{name:"data",type:"List[Dict[str, Any]] | str | Callable",description:"Data to validate. Can be a list of dictionaries, file path (JSON/CSV), or callable that returns data",required:!0},{name:"options",type:"Optional[QualityCheckOptions]",description:"Quality check options including record_violations, calculate_metrics, check_thresholds, include_field_metrics, sample_size, data_source, data_version, etc.",required:!1,default:"None"}],returns:{type:"QualityReport",description:"QualityReport object containing validation results, quality score (QualityScore), field metrics (FieldQualityMetrics), violations (List[ViolationRecord]), and threshold breaches"}},{id:"quality_check_options",title:"QualityCheckOptions",description:"Configuration options for quality checks",method:"QualityCheckOptions(record_violations=True, calculate_metrics=True, check_thresholds=False, include_field_metrics=True, sample_size=None, data_source=None, data_version=None, skip_if_unchanged=False)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import QualityCheckOptions
524
+
525
+ options = QualityCheckOptions(
526
+ record_violations=True, # Record violations to database
527
+ calculate_metrics=True, # Calculate quality metrics
528
+ check_thresholds=False, # Check against quality thresholds
529
+ include_field_metrics=True, # Include field-level metrics
530
+ sample_size=1000, # Sample size for large datasets
531
+ data_source="users.csv", # Data source identifier
532
+ data_version="v1.0", # Data version identifier
533
+ skip_if_unchanged=True # Skip if data hasn't changed
534
+ )`,arguments:[{name:"record_violations",type:"bool",description:"Whether to record violations to database",required:!1,default:"True"},{name:"calculate_metrics",type:"bool",description:"Whether to calculate quality metrics",required:!1,default:"True"},{name:"check_thresholds",type:"bool",description:"Whether to check against quality thresholds",required:!1,default:"False"},{name:"include_field_metrics",type:"bool",description:"Whether to include field-level quality metrics",required:!1,default:"True"},{name:"sample_size",type:"Optional[int]",description:"Sample size for large datasets (None = process all)",required:!1,default:"None"},{name:"data_source",type:"Optional[str]",description:"Data source identifier (e.g., file name)",required:!1,default:"None"},{name:"data_version",type:"Optional[str]",description:"Data version identifier",required:!1,default:"None"},{name:"skip_if_unchanged",type:"bool",description:"Skip quality check if data fingerprint hasn't changed",required:!1,default:"False"}],returns:{type:"QualityCheckOptions",description:"QualityCheckOptions instance for configuring quality checks"}},{id:"quality_thresholds",title:"QualityThresholds",description:"Define quality thresholds for monitoring and alerting",method:"QualityThresholds(overall_score_min=None, accuracy_min=None, completeness_min=None, violation_rate_max=None, field_thresholds=None)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import QualityThresholds
535
+
536
+ thresholds = QualityThresholds(
537
+ overall_score_min=80.0, # Minimum overall quality score
538
+ accuracy_min=95.0, # Minimum accuracy percentage
539
+ completeness_min=90.0, # Minimum completeness percentage
540
+ violation_rate_max=0.05, # Maximum violation rate (5%)
541
+ field_thresholds={ # Field-specific thresholds
542
+ "email": {"completeness_min": 98.0},
543
+ "age": {"accuracy_min": 99.0}
544
+ }
545
+ )`,arguments:[{name:"overall_score_min",type:"Optional[float]",description:"Minimum overall quality score (0-100)",required:!1,default:"None"},{name:"accuracy_min",type:"Optional[float]",description:"Minimum accuracy percentage (0-100)",required:!1,default:"None"},{name:"completeness_min",type:"Optional[float]",description:"Minimum completeness percentage (0-100)",required:!1,default:"None"},{name:"violation_rate_max",type:"Optional[float]",description:"Maximum violation rate (0-1)",required:!1,default:"None"},{name:"field_thresholds",type:"Optional[Dict[str, Dict[str, float]]]",description:'Field-specific thresholds (e.g., {"email": {"completeness_min": 98.0}})',required:!1,default:"None"}],returns:{type:"QualityThresholds",description:"QualityThresholds instance for defining quality requirements"}},{id:"pipeline_class",title:"Pipeline Class (NEW - PRIMARY)",description:"⭐ NEW: Build ETL pipelines with | operator for fluent, composable pipelines. Supports both programmatic and config-driven approaches.",method:"Pipeline(extractor) | transformer | loader",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import (
546
+ Pipeline, PipelineBuilder, PipelineContext,
547
+ HTTPExtractor, PostgresLoader,
548
+ Rename, AddField, Filter, Convert, Drop
549
+ )
550
+
551
+ # Programmatic pipeline with | operator
552
+ pipeline = (
553
+ Pipeline(HTTPExtractor(url="https://api.example.com/users"))
554
+ | Rename({"userName": "name", "userAge": "age"})
555
+ | AddField("processed_at", lambda r: datetime.now().isoformat())
556
+ | Filter(lambda r: r["age"] >= 18)
557
+ | Convert({"age": int, "salary": float})
558
+ | PostgresLoader(connection_string="...", table="users")
559
+ )
560
+
561
+ # Run the pipeline
562
+ result = await pipeline.run()
563
+ print(f"Loaded {result.total_loaded} records")
564
+
565
+ # Config-driven pipeline (from YAML files)
566
+ pipeline = Pipeline.from_config("data/pipelines/users")
567
+ result = await pipeline.run()
568
+
569
+ # With context for variable substitution
570
+ context = PipelineContext(extra={"API_KEY": "secret123"})
571
+ pipeline = Pipeline.from_config("configs/api_pipeline", context=context)
572
+ result = await pipeline.run()`,arguments:[{name:"extractor",type:"Extractor",description:"Extractor instance (HTTPExtractor, FileExtractor, DatabaseExtractor, CloudStorageExtractor)",required:!0},{name:"| transformer",type:"Transformer",description:"Chain transformers using | operator (Rename, AddField, Filter, Convert, Drop, Select, Map, FlatMap)",required:!1},{name:"| loader",type:"Loader",description:"Chain loader at the end (PostgresLoader, FileLoader, CloudStorageLoader)",required:!0}],returns:{type:"PipelineResult",description:"Result with total_extracted, total_transformed, total_loaded, batches, errors, duration_seconds"}},{id:"pipeline_builder",title:"PipelineBuilder (Fluent API)",description:"Alternative fluent API for building pipelines with method chaining",method:"PipelineBuilder().extract(extractor).transform(transformer).load(loader).build()",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import PipelineBuilder, HTTPExtractor, PostgresLoader, Rename, Filter
573
+
574
+ pipeline = (
575
+ PipelineBuilder()
576
+ .extract(HTTPExtractor(url="https://api.example.com/data"))
577
+ .transform(Rename({"old_name": "new_name"}))
578
+ .transform(Filter(lambda r: r["active"]))
579
+ .load(PostgresLoader(connection_string="...", table="users"))
580
+ .build()
581
+ )
582
+
583
+ result = await pipeline.run()`,arguments:[{name:"extract(extractor)",type:"method",description:"Set the extractor for the pipeline",required:!0},{name:"transform(transformer)",type:"method",description:"Add a transformer (can be called multiple times)",required:!1},{name:"load(loader)",type:"method",description:"Set the loader for the pipeline",required:!0},{name:"build()",type:"method",description:"Build and return the Pipeline instance",required:!0}],returns:{type:"Pipeline",description:"Configured Pipeline instance ready to run"}},{id:"etl_transformers",title:"ETL Transformers",description:"Built-in transformers for data manipulation, chainable with | operator",method:"Rename, AddField, Drop, Select, Filter, Convert, Default, Map, FlatMap, CustomFunction",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import (
584
+ Rename, AddField, Drop, Select, Filter,
585
+ Convert, Default, Map, FlatMap, CustomFunction
586
+ )
587
+
588
+ # Rename fields
589
+ rename = Rename({"old_name": "new_name", "userName": "user_name"})
590
+
591
+ # Add computed fields
592
+ add = AddField("full_name", lambda r: f"{r['first']} {r['last']}")
593
+
594
+ # Drop fields
595
+ drop = Drop(["temp_field", "internal_id"])
596
+
597
+ # Select specific fields only
598
+ select = Select(["id", "name", "email"])
599
+
600
+ # Filter records
601
+ filter_active = Filter(lambda r: r.get("active", False))
602
+
603
+ # Convert types
604
+ convert = Convert({"age": int, "price": float, "active": bool})
605
+
606
+ # Set defaults for missing/null values
607
+ defaults = Default({"status": "pending", "count": 0})
608
+
609
+ # Map - transform each record
610
+ map_transform = Map(lambda r: {**r, "name": r["name"].upper()})
611
+
612
+ # FlatMap - expand records (one-to-many)
613
+ flatmap = FlatMap(lambda r: [{"item": i} for i in r.get("items", [])])
614
+
615
+ # Custom function
616
+ def my_transform(records, **kwargs):
617
+ return [r for r in records if r.get("valid")]
618
+ custom = CustomFunction(my_transform)
619
+
620
+ # Chain transformers
621
+ chain = Rename({"a": "b"}) | Filter(lambda r: r["x"] > 0) | Convert({"x": int})`,arguments:[{name:"Rename(mapping)",type:"Transformer",description:"Rename fields according to mapping dict",required:!1},{name:"AddField(name, value_or_func)",type:"Transformer",description:"Add a new field with static value or computed from record",required:!1},{name:"Drop(fields)",type:"Transformer",description:"Remove specified fields from records",required:!1},{name:"Select(fields)",type:"Transformer",description:"Keep only specified fields",required:!1},{name:"Filter(predicate)",type:"Transformer",description:"Keep only records matching predicate function",required:!1},{name:"Convert(type_mapping)",type:"Transformer",description:"Convert field types (int, float, str, bool)",required:!1},{name:"Default(defaults)",type:"Transformer",description:"Set default values for missing/null fields",required:!1},{name:"Map(func)",type:"Transformer",description:"Transform each record with function",required:!1},{name:"FlatMap(func)",type:"Transformer",description:"Expand records (one-to-many transformation)",required:!1}],returns:{type:"Transformer / TransformerChain",description:"Transformer instance, chainable with | operator"}},{id:"etl_extractors",title:"ETL Extractors",description:"Built-in extractors for different data sources",method:"HTTPExtractor, FileExtractor, DatabaseExtractor, CloudStorageExtractor",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import (
622
+ HTTPExtractor, FileExtractor,
623
+ DatabaseExtractor, CloudStorageExtractor
624
+ )
625
+
626
+ # HTTP API extraction
627
+ http = HTTPExtractor(
628
+ url="https://api.example.com/data",
629
+ method="GET",
630
+ headers={"Authorization": "Bearer token"},
631
+ params={"limit": 100}
632
+ )
633
+
634
+ # File extraction (JSON, CSV, Parquet)
635
+ file = FileExtractor(
636
+ file_path="data/input.json",
637
+ file_format="json"
638
+ )
639
+
640
+ # Database extraction
641
+ db = DatabaseExtractor(
642
+ connection_string="postgresql://user:pass@host/db",
643
+ query="SELECT * FROM users WHERE active = true"
644
+ )
645
+
646
+ # Cloud storage extraction (S3, GCS, Azure)
647
+ cloud = CloudStorageExtractor(
648
+ provider="s3",
649
+ bucket="my-bucket",
650
+ key="data/users.json",
651
+ credentials={"aws_access_key_id": "...", "aws_secret_access_key": "..."}
652
+ )
653
+
654
+ # Config-driven extraction
655
+ http_from_config = HTTPExtractor.from_config({
656
+ "base_url": "https://api.example.com",
657
+ "api_endpoint": "/v1/users",
658
+ "method": "GET"
659
+ })`,arguments:[{name:"HTTPExtractor",type:"class",description:"Extract from HTTP APIs with pagination support",required:!1},{name:"FileExtractor",type:"class",description:"Extract from local files (JSON, CSV, Parquet, JSONL)",required:!1},{name:"DatabaseExtractor",type:"class",description:"Extract from databases via SQL query",required:!1},{name:"CloudStorageExtractor",type:"class",description:"Extract from cloud storage (S3, GCS, Azure Blob)",required:!1}],returns:{type:"Extractor",description:"Extractor instance implementing the Extractor protocol"}},{id:"etl_loaders",title:"ETL Loaders",description:"Built-in loaders for different destinations",method:"PostgresLoader, DatabaseLoader, FileLoader, CloudStorageLoader",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import PostgresLoader, FileLoader, CloudStorageLoader
660
+
661
+ # PostgreSQL/Database loading
662
+ postgres = PostgresLoader(
663
+ connection_string="postgresql://user:pass@host/db",
664
+ table="users",
665
+ schema="public",
666
+ if_exists="append", # 'append', 'replace', 'fail'
667
+ )
668
+
669
+ # File loading
670
+ file = FileLoader(
671
+ file_path="output/users.json",
672
+ file_format="json",
673
+ mode="w"
674
+ )
675
+
676
+ # Cloud storage loading
677
+ cloud = CloudStorageLoader(
678
+ provider="s3",
679
+ bucket="my-bucket",
680
+ key="output/users.parquet",
681
+ file_format="parquet"
682
+ )
683
+
684
+ # Use in pipeline
685
+ pipeline = (
686
+ Pipeline(HTTPExtractor(url="..."))
687
+ | Rename({"old": "new"})
688
+ | PostgresLoader(connection_string="...", table="users")
689
+ )`,arguments:[{name:"PostgresLoader",type:"class",description:"Load to PostgreSQL database",required:!1},{name:"DatabaseLoader",type:"class",description:"Generic database loader (supports various databases)",required:!1},{name:"FileLoader",type:"class",description:"Load to local files (JSON, CSV, Parquet)",required:!1},{name:"CloudStorageLoader",type:"class",description:"Load to cloud storage (S3, GCS, Azure Blob)",required:!1}],returns:{type:"Loader",description:"Loader instance implementing the Loader protocol"}},{id:"etl_orchestrator",title:"ETL Orchestrator (Legacy)",description:"Config-driven ETL orchestration from contract directories. Use Pipeline class for new projects.",method:"ETLOrchestrator(contract_dir=None, contract_file=None, extract_config=None, transform_config=None, load_config=None, config_context=None, ...)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter.etl_generator import ETLOrchestrator
690
+
691
+ orchestrator = ETLOrchestrator(contract_dir="path/to/contract_dir")
692
+ result = await orchestrator.run()
693
+
694
+ # With config overrides
695
+ orchestrator = ETLOrchestrator(
696
+ contract_dir="contracts/user",
697
+ extract_config={"base_url": "https://api.example.com", "api_endpoint": "/v1/data"},
698
+ transform_config={"rename": {"oldName": "new_name"}},
699
+ load_config={"target_table": "users", "schema_name": "public"}
700
+ )
701
+ result = await orchestrator.run(dry_run=False)`,arguments:[{name:"contract_dir",type:"Optional[str]",description:"Directory containing schema and extract/transform/load configs",required:!1},{name:"contract_file",type:"Optional[str]",description:"Path to a complete contract file (YAML or JSON)",required:!1},{name:"extract_config",type:"Optional[Dict[str, Any]]",description:"Extract configuration dictionary (overrides extract.yaml when provided)",required:!1},{name:"transform_config",type:"Optional[Dict[str, Any]]",description:"Transform configuration dictionary (overrides transform.yaml when provided)",required:!1},{name:"load_config",type:"Optional[Dict[str, Any]]",description:"Load configuration dictionary (overrides load.yaml when provided)",required:!1},{name:"config_context",type:"Optional[Dict[str, Any]]",description:"Context for resolving ${VAR} placeholders in config files",required:!1}],returns:{type:"ETLOrchestrator",description:"Orchestrator instance; call .run(**kwargs) to execute the pipeline"}},{id:"create_orchestrator",title:"Create Orchestrator",description:"Factory helper that creates an ETLOrchestrator instance from a contract directory.",method:"create_orchestrator(contract_dir=None, **kwargs) -> ETLOrchestrator",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter.etl_generator import create_orchestrator
702
+
703
+ orchestrator = create_orchestrator(contract_dir="configs/user_pipeline")
704
+ result = await orchestrator.run()`,arguments:[{name:"contract_dir",type:"Optional[str]",description:"Directory containing ETL configs (extract.yaml, transform.yaml, load.yaml)",required:!1},{name:"**kwargs",type:"Any",description:"Additional arguments passed through to ETLOrchestrator",required:!1}],returns:{type:"ETLOrchestrator",description:"Orchestrator instance configured for the given contract directory"}},{id:"pipeline_factory",title:"Pipeline Factory",description:"Discover pipelines by scanning a config root for subdirectories that contain extract.yaml, transform.yaml, and load.yaml, and create orchestrators by pipeline name.",method:'PipelineFactory(config_root="configs", excluded_dirs=None, required_files=None)',apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter.etl_generator import PipelineFactory
705
+
706
+ factory = PipelineFactory(config_root="configs")
707
+ names = factory.get_pipeline_names()
708
+ orchestrator = factory.create_orchestrator(
709
+ pipeline_name="fmp_key_metrics",
710
+ config_context={"FMP_API_KEY": "your_key"}
711
+ )
712
+ result = await orchestrator.run(symbol="AAPL")`,arguments:[{name:"config_root",type:"Union[str, Path]",description:"Root directory to scan for pipeline config directories",required:!1,default:'"configs"'},{name:"excluded_dirs",type:"Optional[List[str]]",description:"Directory names to skip during discovery (e.g. old, templates)",required:!1},{name:"required_files",type:"Optional[List[str]]",description:"Files each pipeline directory must contain (default: extract.yaml, transform.yaml, load.yaml)",required:!1}],returns:{type:"PipelineFactory",description:"Factory with get_pipeline_names(), get_contract_dir(name), and create_orchestrator(name, ...)"}},{id:"extract_with_pagination_streaming",title:"Extract with Pagination Streaming",description:"Async generator that yields batches of records. Dispatches to the appropriate extractor by source_type (http, file, database, cloud_storage) via ExtractorFactory.",method:"extract_with_pagination_streaming(extract_config, params, headers, contract_dir=None, batch_size=1000, max_records=None, config_context=None)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter.etl_generator.extractors import extract_with_pagination_streaming
713
+
714
+ async for batch in extract_with_pagination_streaming(
715
+ extract_config={"source_type": "file", "file_path": "data.json"},
716
+ params={},
717
+ headers={},
718
+ batch_size=500
719
+ ):
720
+ print(len(batch))`,arguments:[{name:"extract_config",type:"Dict[str, Any]",description:"Extract configuration (source_type is auto-detected if omitted)",required:!0},{name:"params",type:"Dict[str, Any]",description:"Request or query parameters (e.g. for HTTP extractions)",required:!0},{name:"headers",type:"Dict[str, Any]",description:"Request headers (e.g. for HTTP extractions)",required:!0},{name:"contract_dir",type:"Optional[Any]",description:"Contract directory used for variable resolution in configs",required:!1},{name:"batch_size",type:"int",description:"Number of records to yield per batch",required:!1,default:"1000"},{name:"max_records",type:"Optional[int]",description:"Maximum total records to extract (None for no limit)",required:!1},{name:"config_context",type:"Optional[Dict[str, Any]]",description:"Context for resolving ${VAR} placeholders in configs",required:!1}],returns:{type:"AsyncIterator[List[Dict[str, Any]]]",description:"Async iterator yielding batches of record dictionaries"}},{id:"apply_transforms",title:"Apply Transforms",description:"Run the transform pipeline on a list of records. Order: simple operations (rename, convert, defaults, add, select, drop) → JSONata → custom function.",method:"apply_transforms(data, transform_config, **kwargs) -> List[Dict[str, Any]]",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter.etl_generator.transformers import apply_transforms
721
+
722
+ config = {
723
+ "transform": {"rename": {"oldName": "new_name"}, "convert": {"price": "float"}},
724
+ "jsonata": {"expression": "$.{\\"x\\": x * 2}", "mode": "record"}
725
+ }
726
+ out = apply_transforms(records, config)`,arguments:[{name:"data",type:"List[Dict[str, Any]]",description:"Input list of record dictionaries to transform",required:!0},{name:"transform_config",type:"Dict[str, Any]",description:"Transform configuration (transform, jsonata, and/or custom_function)",required:!0},{name:"**kwargs",type:"Any",description:"Additional keyword arguments passed to the custom_function step when configured",required:!1}],returns:{type:"List[Dict[str, Any]]",description:"Transformed list of record dictionaries"}},{id:"extractor_factory",title:"Extractor Factory",description:"Resolve source_type from extract config and return the appropriate extractor (HTTPExtractor, FileExtractor, DatabaseExtractor, or CloudStorageExtractor).",method:"ExtractorFactory.get_extractor(extract_config) -> BaseExtractor",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter.etl_generator.extractors import ExtractorFactory, get_extractor
727
+
728
+ extractor = get_extractor({"source_type": "http", "base_url": "https://api.example.com", "api_endpoint": "/v1/data"})
729
+ # or
730
+ extractor = ExtractorFactory.get_extractor(extract_config)
731
+ # Register a custom extractor
732
+ ExtractorFactory.register_extractor("kafka", KafkaExtractor)`,arguments:[{name:"extract_config",type:"Dict[str, Any]",description:"Extract configuration; source_type is auto-detected from config if not specified",required:!0}],returns:{type:"BaseExtractor",description:"Extractor instance (HTTPExtractor, FileExtractor, DatabaseExtractor, or CloudStorageExtractor)"}},{id:"load_to_file",title:"Load to File and Cloud Storage",description:"Write transformed data to a local file (JSON, CSV, Parquet, JSONL) or to cloud storage (S3, GCS, Azure). Used when load_config has destination_type file or cloud_storage.",method:"load_to_file(data, load_config, contract_dir=None, config_context=None)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter.etl_generator.loaders import load_to_file, load_to_cloud_storage
733
+
734
+ # Local file
735
+ result = load_to_file(
736
+ data=transformed_records,
737
+ load_config={"destination_type": "file", "file_path": "out.json", "format": "json"}
738
+ )
739
+ # Cloud (S3 / GCS / Azure)
740
+ result = load_to_cloud_storage(data, load_config, contract_dir=contract_dir)`,arguments:[{name:"data",type:"List[Dict[str, Any]]",description:"List of record dictionaries to write",required:!0},{name:"load_config",type:"Dict[str, Any]",description:"Load configuration (destination_type, file_path or storage, format, etc.)",required:!0},{name:"contract_dir",type:"Optional[Any]",description:"Contract directory used for variable resolution in load_config",required:!1},{name:"config_context",type:"Optional[Dict[str, Any]]",description:"Context for resolving ${VAR} placeholders in load_config",required:!1}],returns:{type:"Dict[str, Any]",description:"Result dictionary with keys such as written and total"}},{id:"generate_etl_config",title:"Generate ETL Config",description:"Generate ETL config dictionaries (extract, transform, load) from contract artifacts or from the metadata store. Use generate_etl_config_from_contract or generate_etl_config_from_store.",method:"generate_etl_config_from_contract(contract_dict, extraction_config=None, ...)",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter.etl_generator import generate_etl_config_from_contract, generate_etl_config_from_store
741
+
742
+ # From contract dictionary
743
+ config = generate_etl_config_from_contract(
744
+ contract_dict,
745
+ extraction_config={"provider_name": "fmp", "api_endpoint": "/api/v3/profile/AAPL"}
746
+ )
747
+ # From metadata store
748
+ config = generate_etl_config_from_store(store, schema_title="user_schema", ...)`,arguments:[{name:"contract_dict",type:"Dict[str, Any]",description:"Contract dictionary (used by generate_etl_config_from_contract)",required:!1},{name:"store",type:"MetadataStoreClient",description:"Metadata store client (used by generate_etl_config_from_store)",required:!1},{name:"schema_title",type:"str",description:"Schema or title identifier in the store",required:!1},{name:"extraction_config",type:"Optional[Dict[str, Any]]",description:"Extraction hints such as provider name and API endpoint",required:!1}],returns:{type:"Dict[str, Any]",description:"Dictionary containing extract, transform, and load configuration sections"}},{id:"docs_generator",title:"DocsGenerator Class",description:"Generate human-readable documentation from data contracts. Supports Markdown and HTML output formats.",method:"DocsGenerator(renderer=MarkdownRenderer())",apiEndpoint:"/api/v1/docs/generate",apiMethod:"POST",exampleRequest:{contract:{schema:{type:"object",title:"UserProfile",version:"1.0.0",properties:{name:{type:"string",description:"User name"},email:{type:"string",format:"email"}},required:["name"]}},format:"markdown"},exampleCode:`from pycharter import DocsGenerator, generate_docs, MarkdownRenderer, HTMLRenderer
749
+
750
+ # Quick generation
751
+ contract = parse_contract_file("contract.yaml")
752
+ markdown = generate_docs(contract)
753
+ html = generate_docs(contract, format="html")
754
+
755
+ # Custom generator
756
+ generator = DocsGenerator(renderer=MarkdownRenderer())
757
+ docs = generator.generate(contract)
758
+ schema_section = generator.generate_schema_section(contract.schema)`,arguments:[{name:"renderer",type:"DocsRenderer",description:"Renderer for output format (MarkdownRenderer or HTMLRenderer)",required:!1,default:"MarkdownRenderer()"}],returns:{type:"DocsGenerator",description:"DocsGenerator instance for generating documentation"}},{id:"generate_docs",title:"generate_docs() Function",description:"Convenience function to generate documentation from a contract in one call",method:'generate_docs(contract, format="markdown", **kwargs)',apiEndpoint:"/api/v1/docs/generate",apiMethod:"POST",exampleRequest:{contract:{schema:{type:"object",title:"Product",version:"1.0.0",properties:{id:{type:"string"},price:{type:"number",minimum:0}}},coercion_rules:{price:"to_float"}},format:"html",include_schema:!0,include_coercions:!0},exampleCode:`from pycharter import generate_docs, parse_contract_file
759
+
760
+ contract = parse_contract_file("contract.yaml")
761
+
762
+ # Generate Markdown
763
+ markdown = generate_docs(contract)
764
+
765
+ # Generate HTML
766
+ html = generate_docs(contract, format="html")
767
+
768
+ # Control sections included
769
+ docs = generate_docs(
770
+ contract,
771
+ format="markdown",
772
+ include_schema=True,
773
+ include_coercions=True,
774
+ include_validations=False,
775
+ include_metadata=True
776
+ )`,arguments:[{name:"contract",type:"ContractMetadata | Dict",description:"ContractMetadata object or contract dictionary",required:!0},{name:"format",type:"str",description:'Output format: "markdown" or "html"',required:!1,default:'"markdown"'},{name:"include_schema",type:"bool",description:"Include schema fields section",required:!1,default:"True"},{name:"include_coercions",type:"bool",description:"Include coercion rules section",required:!1,default:"True"},{name:"include_validations",type:"bool",description:"Include validation rules section",required:!1,default:"True"},{name:"include_metadata",type:"bool",description:"Include metadata/ownership section",required:!1,default:"True"}],returns:{type:"str",description:"Generated documentation as string"}},{id:"metrics_collector",title:"MetricsCollector Class",description:"Collect and query validation metrics over time. Track quality trends and aggregate statistics.",method:"MetricsCollector(store=InMemoryMetricsStore())",apiEndpoint:"/api/v1/quality/tracking",apiMethod:"GET",exampleRequest:null,exampleCode:`from pycharter import MetricsCollector, InMemoryMetricsStore, SQLiteMetricsStore
777
+
778
+ # Create collector with in-memory store (development)
779
+ store = InMemoryMetricsStore()
780
+ collector = MetricsCollector(store)
781
+
782
+ # Or use SQLite for persistence
783
+ store = SQLiteMetricsStore("metrics.db")
784
+ collector = MetricsCollector(store)
785
+
786
+ # Record validation results
787
+ result = validator.validate(data)
788
+ collector.record(result, schema_name="users", version="1.0.0", duration_ms=50.0)
789
+
790
+ # Query metrics
791
+ metrics = collector.query(schema_name="users", limit=100)
792
+
793
+ # Get aggregated summary
794
+ summary = collector.get_summary("users", window_hours=24)
795
+ print(f"Avg validity rate: {summary.avg_validity_rate}")`,arguments:[{name:"store",type:"MetricsStore",description:"Storage backend (InMemoryMetricsStore or SQLiteMetricsStore)",required:!1,default:"InMemoryMetricsStore()"}],returns:{type:"MetricsCollector",description:"MetricsCollector instance for tracking validation metrics"}},{id:"validation_metric",title:"ValidationMetric Model",description:"Data model for a single validation run metric. Contains all metrics captured from validation.",method:"ValidationMetric(schema_name, version, ...)",apiEndpoint:"/api/v1/quality/tracking",apiMethod:"POST",exampleRequest:{schema_name:"users",version:"1.0.0",record_count:100,valid_count:95,error_count:5,completeness:.98,duration_ms:150.5},exampleCode:`from pycharter import ValidationMetric
796
+ from datetime import datetime
797
+
798
+ # Metrics are typically created automatically by MetricsCollector
799
+ # but can be created manually:
800
+ metric = ValidationMetric(
801
+ schema_name="users",
802
+ version="1.0.0",
803
+ timestamp=datetime.utcnow(),
804
+ record_count=100,
805
+ valid_count=95,
806
+ error_count=5,
807
+ validity_rate=0.95,
808
+ completeness=0.98,
809
+ field_completeness={"email": 1.0, "phone": 0.85},
810
+ duration_ms=150.5,
811
+ errors_by_type={"missing_required": 3, "type_error": 2}
812
+ )
813
+
814
+ # Convert to dict for API/storage
815
+ data = metric.to_dict()`,arguments:[{name:"schema_name",type:"str",description:"Name of the schema validated against",required:!0},{name:"version",type:"str",description:"Version of the schema",required:!0},{name:"record_count",type:"int",description:"Number of records validated",required:!1,default:"0"},{name:"valid_count",type:"int",description:"Number of valid records",required:!1,default:"0"},{name:"validity_rate",type:"float",description:"Ratio of valid records (0.0 to 1.0)",required:!1,default:"1.0"},{name:"completeness",type:"float",description:"Overall data completeness (0.0 to 1.0)",required:!1,default:"1.0"},{name:"duration_ms",type:"float",description:"Validation duration in milliseconds",required:!1,default:"0.0"}],returns:{type:"ValidationMetric",description:"ValidationMetric dataclass instance"}},{id:"metrics_summary",title:"MetricsSummary Model",description:"Aggregated metrics summary for a schema over a time period. Used for trend analysis.",method:"collector.get_summary(schema_name, window_hours=24)",apiEndpoint:"/api/v1/quality/tracking/{schema_name}/summary",apiMethod:"GET",exampleRequest:null,exampleCode:`from pycharter import MetricsCollector, InMemoryMetricsStore
816
+
817
+ collector = MetricsCollector(InMemoryMetricsStore())
818
+
819
+ # Get summary for last 24 hours
820
+ summary = collector.get_summary("users", window_hours=24)
821
+
822
+ print(f"Total validations: {summary.total_validations}")
823
+ print(f"Average validity rate: {summary.avg_validity_rate:.2%}")
824
+ print(f"Min validity rate: {summary.min_validity_rate:.2%}")
825
+ print(f"Max validity rate: {summary.max_validity_rate:.2%}")
826
+ print(f"Total records: {summary.total_records}")
827
+ print(f"Top errors: {summary.top_error_types}")`,arguments:[{name:"schema_name",type:"str",description:"Name of the schema to summarize",required:!0},{name:"window_hours",type:"int",description:"Number of hours to look back",required:!1,default:"24"}],returns:{type:"MetricsSummary",description:"MetricsSummary with aggregated statistics"}},{id:"metrics_export",title:"Export Metrics",description:"Export validation metrics in various formats: JSON, Prometheus, or CSV.",method:"export_json(metrics) | export_prometheus(metrics) | export_csv(metrics)",apiEndpoint:"/api/v1/quality/tracking/export",apiMethod:"GET",exampleRequest:null,exampleCode:`from pycharter.quality.tracking import (
828
+ export_json, export_prometheus, export_csv, MetricsCollector
829
+ )
830
+
831
+ collector = MetricsCollector()
832
+ metrics = collector.query(schema_name="users")
833
+
834
+ # Export as JSON
835
+ json_data = export_json(metrics, pretty=True)
836
+
837
+ # Export as Prometheus text format (for scraping)
838
+ prom_data = export_prometheus(metrics, prefix="pycharter")
839
+
840
+ # Export as CSV
841
+ csv_data = export_csv(metrics, include_header=True)
842
+
843
+ # Via API
844
+ # GET /api/v1/quality/tracking/export?format=prometheus&schema_name=users`,arguments:[{name:"metrics",type:"List[ValidationMetric]",description:"List of metrics to export",required:!0},{name:"format",type:"str",description:'Export format: "json", "prometheus", or "csv"',required:!1,default:'"json"'}],returns:{type:"str",description:"Exported metrics as string in specified format"}},{id:"validator_with_tracking",title:"Validator with Tracking",description:"Integrate metrics tracking into validators using ValidatorBuilder.with_tracking()",method:"ValidatorBuilder().with_tracking(collector).build()",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import ValidatorBuilder
845
+ from pycharter.quality.tracking import MetricsCollector, InMemoryMetricsStore
846
+
847
+ # Create metrics collector
848
+ store = InMemoryMetricsStore()
849
+ collector = MetricsCollector(store)
850
+
851
+ # Build validator with automatic tracking
852
+ validator = (
853
+ ValidatorBuilder()
854
+ .from_directory("contracts/users")
855
+ .with_tracking(collector) # Enable tracking
856
+ .with_quality_checks()
857
+ .build()
858
+ )
859
+
860
+ # Each validation automatically records metrics
861
+ result = validator.validate({"name": "Alice", "email": "alice@example.com"})
862
+
863
+ # Batch validation also tracks
864
+ results = validator.validate_batch([...])
865
+
866
+ # Query the recorded metrics
867
+ metrics = collector.query(schema_name="users")
868
+ summary = collector.get_summary("users")`,arguments:[{name:"collector",type:"MetricsCollector",description:"MetricsCollector instance for recording metrics",required:!0}],returns:{type:"ValidatorBuilder",description:"Self for method chaining"}},{id:"check_compatibility",title:"check_compatibility() Function",description:"Check if two schemas are compatible according to the specified mode (backward, forward, or full).",method:'check_compatibility(old_schema, new_schema, mode="backward")',apiEndpoint:"/api/v1/evolution/check",apiMethod:"POST",exampleRequest:{old_schema:{type:"object",properties:{name:{type:"string"}},required:["name"]},new_schema:{type:"object",properties:{name:{type:"string"},email:{type:"string"}},required:["name"]},mode:"backward"},exampleCode:`from pycharter import check_compatibility, CompatibilityMode
869
+
870
+ old_schema = {
871
+ "type": "object",
872
+ "properties": {"name": {"type": "string"}},
873
+ "required": ["name"]
874
+ }
875
+ new_schema = {
876
+ "type": "object",
877
+ "properties": {
878
+ "name": {"type": "string"},
879
+ "email": {"type": "string"} # New optional field
880
+ },
881
+ "required": ["name"]
882
+ }
883
+
884
+ # Check backward compatibility (new consumer, old data)
885
+ result = check_compatibility(old_schema, new_schema, mode="backward")
886
+ print(f"Compatible: {result.compatible}")
887
+
888
+ if not result.compatible:
889
+ print(f"Issues: {result.issues}")
890
+
891
+ # Check forward compatibility (old consumer, new data)
892
+ result = check_compatibility(old_schema, new_schema, mode="forward")
893
+
894
+ # Check full compatibility (both directions)
895
+ result = check_compatibility(old_schema, new_schema, mode="full")`,arguments:[{name:"old_schema",type:"Dict[str, Any]",description:"The existing/original schema",required:!0},{name:"new_schema",type:"Dict[str, Any]",description:"The new schema to check",required:!0},{name:"mode",type:"str | CompatibilityMode",description:'Compatibility mode: "backward", "forward", or "full"',required:!1,default:'"backward"'}],returns:{type:"CompatibilityResult",description:"CompatibilityResult with compatible status, diff, issues, and warnings"}},{id:"compute_diff",title:"compute_diff() Function",description:"Compute detailed diff between two JSON Schema versions. Returns all changes categorized by type.",method:"compute_diff(old_schema, new_schema)",apiEndpoint:"/api/v1/evolution/diff",apiMethod:"POST",exampleRequest:{old_schema:{type:"object",properties:{name:{type:"string"},age:{type:"integer",minimum:0}}},new_schema:{type:"object",properties:{name:{type:"string"},age:{type:"integer",minimum:18},email:{type:"string"}}}},exampleCode:`from pycharter import compute_diff, ChangeType
896
+
897
+ old_schema = {
898
+ "type": "object",
899
+ "properties": {
900
+ "name": {"type": "string"},
901
+ "age": {"type": "integer", "minimum": 0}
902
+ }
903
+ }
904
+ new_schema = {
905
+ "type": "object",
906
+ "properties": {
907
+ "name": {"type": "string"},
908
+ "age": {"type": "integer", "minimum": 18}, # Changed
909
+ "email": {"type": "string"} # Added
910
+ }
911
+ }
912
+
913
+ diff = compute_diff(old_schema, new_schema)
914
+
915
+ print(f"Total changes: {len(diff.changes)}")
916
+ print(f"Breaking changes: {len(diff.breaking_changes)}")
917
+
918
+ for change in diff.changes:
919
+ status = "BREAKING" if change.breaking else "OK"
920
+ print(f"[{status}] {change.change_type.value}: {change.path}")
921
+ print(f" {change.message}")
922
+
923
+ # Access specific change types
924
+ for addition in diff.additions:
925
+ print(f"Added: {addition.path}")`,arguments:[{name:"old_schema",type:"Dict[str, Any]",description:"Original schema",required:!0},{name:"new_schema",type:"Dict[str, Any]",description:"New schema",required:!0}],returns:{type:"SchemaDiff",description:"SchemaDiff with changes, breaking_changes, additions, removals, modifications"}},{id:"compatibility_modes",title:"Compatibility Modes",description:"Understanding the three compatibility modes: backward, forward, and full.",method:"CompatibilityMode.BACKWARD | FORWARD | FULL",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import CompatibilityMode, check_compatibility
926
+
927
+ # BACKWARD: New schema can read old data
928
+ # Use when: Upgrading consumers before producers
929
+ # Safe: Add optional fields, remove fields, widen types
930
+ # Breaking: Add required fields, narrow types, remove enum values
931
+ result = check_compatibility(old, new, mode=CompatibilityMode.BACKWARD)
932
+
933
+ # FORWARD: Old schema can read new data
934
+ # Use when: Upgrading producers before consumers
935
+ # Safe: Remove optional fields, add fields
936
+ # Breaking: Remove required fields, add enum values, widen types
937
+ result = check_compatibility(old, new, mode=CompatibilityMode.FORWARD)
938
+
939
+ # FULL: Both backward and forward compatible
940
+ # Use when: No control over upgrade order
941
+ # Safe: Only metadata changes, add fields with defaults
942
+ # Breaking: Most schema changes
943
+ result = check_compatibility(old, new, mode=CompatibilityMode.FULL)`,arguments:[{name:"BACKWARD",type:"CompatibilityMode",description:"New consumers can read data from old producers",required:!1},{name:"FORWARD",type:"CompatibilityMode",description:"Old consumers can read data from new producers",required:!1},{name:"FULL",type:"CompatibilityMode",description:"Both backward and forward compatible",required:!1}],returns:{type:"CompatibilityMode",description:"Enum for specifying compatibility checking mode"}},{id:"change_types",title:"Change Types",description:"All schema change types detected by compute_diff()",method:"ChangeType enum values",apiEndpoint:null,apiMethod:"N/A",exampleRequest:null,exampleCode:`from pycharter import ChangeType, compute_diff
944
+
945
+ diff = compute_diff(old_schema, new_schema)
946
+
947
+ # Field changes
948
+ # ChangeType.FIELD_ADDED - New field added
949
+ # ChangeType.FIELD_REMOVED - Field removed
950
+
951
+ # Type changes
952
+ # ChangeType.TYPE_CHANGED - Type completely changed
953
+ # ChangeType.TYPE_WIDENED - Type widened (int -> number) - safe for backward
954
+ # ChangeType.TYPE_NARROWED - Type narrowed (number -> int) - breaking
955
+
956
+ # Constraint changes
957
+ # ChangeType.CONSTRAINT_ADDED - New constraint (min, max, pattern, etc.)
958
+ # ChangeType.CONSTRAINT_REMOVED - Constraint removed
959
+ # ChangeType.CONSTRAINT_MODIFIED - Constraint value changed
960
+
961
+ # Required/optional changes
962
+ # ChangeType.REQUIRED_ADDED - Field became required - breaking
963
+ # ChangeType.REQUIRED_REMOVED - Field became optional - safe
964
+
965
+ # Enum changes
966
+ # ChangeType.ENUM_VALUE_ADDED - New enum value
967
+ # ChangeType.ENUM_VALUE_REMOVED - Enum value removed - breaking
968
+
969
+ # Filter by type
970
+ type_changes = [c for c in diff.changes if c.change_type == ChangeType.TYPE_CHANGED]`,arguments:[],returns:{type:"ChangeType",description:"Enum with all possible schema change types"}}];function x({method:o}){let[d,l]=(0,r.useState)(o.exampleRequest?JSON.stringify(o.exampleRequest,null,2):""),[m,p]=(0,r.useState)(null),[u,_]=(0,r.useState)(null),[h,f]=(0,r.useState)(!1),[y,g]=(0,r.useState)(!1);if(!o.apiEndpoint)return null;let v=o.apiEndpoint?.includes("/upload")??!1,x=async()=>{f(!0),_(null);try{let t,r,{getApiBaseUrl:a}=await e.A(36909),i=a(),n=o.apiEndpoint;if(!n){_({success:!1,error:"This method does not have an API endpoint (Python-only)"}),f(!1);return}n.includes("{schema_id}")&&(n=n.replace("{schema_id}","user_schema"));let s=`${i}${n}`;if("GET"===o.apiMethod)t=await fetch(s);else if(v){if(!m){_({success:!1,error:"Please select a file to upload"}),f(!1);return}let e=new FormData;e.append("file",m),n.includes("/contracts/parse/upload")&&e.append("validate","true"),t=await fetch(s,{method:o.apiMethod,body:e})}else{let e=d?JSON.parse(d):{};t=await fetch(s,{method:o.apiMethod,headers:{"Content-Type":"application/json"},body:JSON.stringify(e)})}let c=t.headers.get("content-type");r=c&&c.includes("application/json")?await t.json():{message:await t.text()},t.ok?_({success:!0,data:r}):_({success:!1,error:r.detail||r.message||`HTTP ${t.status}: ${t.statusText}`})}catch(t){let e=t.message;e.includes("JSON")&&(e="Invalid JSON in request body. Please check your input."),_({success:!1,error:e||"Failed to test API"})}finally{f(!1)}};return(0,t.jsxs)("div",{className:"border rounded-lg p-4 bg-muted/30",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between mb-3",children:[(0,t.jsx)("h5",{className:"text-sm font-semibold",children:"Test API"}),o.apiEndpoint&&(0,t.jsxs)("div",{className:"flex gap-2",children:[(0,t.jsx)(a.Button,{size:"sm",variant:"outline",onClick:()=>{var e;return o.apiEndpoint&&(e=o.apiEndpoint,void(navigator.clipboard.writeText(e),g(!0),setTimeout(()=>g(!1),2e3)))},className:"h-7",disabled:!o.apiEndpoint,children:y?(0,t.jsx)(c,{className:"h-3 w-3"}):(0,t.jsx)(s,{className:"h-3 w-3"})}),(0,t.jsx)(a.Button,{size:"sm",onClick:x,disabled:h||"GET"!==o.apiMethod&&!v&&!d||v&&!m,className:"h-7",children:h?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("div",{className:"mr-1",children:(0,t.jsx)(i.default,{size:"sm"})}),"Testing..."]}):(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n,{className:"h-3 w-3 mr-1"}),"Test"]})})]})]}),o.apiEndpoint&&"GET"!==o.apiMethod&&(0,t.jsx)("div",{className:"mb-3",children:v?(0,t.jsxs)("div",{children:[(0,t.jsx)("label",{className:"block text-xs font-medium mb-1",children:"Upload File"}),(0,t.jsx)("input",{type:"file",accept:".yaml,.yml,.json",onChange:e=>p(e.target.files?.[0]||null),className:"w-full px-2 py-1 border rounded text-xs bg-background"}),m&&(0,t.jsxs)("div",{className:"mt-1 text-xs text-muted-foreground",children:["Selected: ",m.name," (",(m.size/1024).toFixed(2)," KB)"]})]}):(0,t.jsxs)("div",{children:[(0,t.jsx)("label",{className:"block text-xs font-medium mb-1",children:"Request Body (JSON)"}),(0,t.jsx)("textarea",{value:d,onChange:e=>l(e.target.value),rows:6,className:"w-full px-2 py-1 border rounded text-xs font-mono bg-background",placeholder:"Enter JSON request body..."})]})}),o.apiEndpoint&&(0,t.jsxs)("div",{className:"text-xs text-muted-foreground mb-2",children:[(0,t.jsx)("span",{className:"font-mono font-semibold",children:o.apiMethod})," ",o.apiEndpoint]}),u&&(0,t.jsx)("div",{className:"mt-3",children:u.success?(0,t.jsxs)("div",{className:"bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded p-2",children:[(0,t.jsx)("div",{className:"text-xs font-semibold text-green-800 dark:text-green-200 mb-1",children:"Success"}),(0,t.jsx)("pre",{className:"text-xs overflow-x-auto text-green-700 dark:text-green-300",children:JSON.stringify(u.data,null,2)})]}):(0,t.jsxs)("div",{className:"bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded p-2",children:[(0,t.jsx)("div",{className:"text-xs font-semibold text-red-800 dark:text-red-200 mb-1",children:"Error"}),(0,t.jsx)("div",{className:"text-xs text-red-700 dark:text-red-300",children:u.error})]})})]})}function b(){let[e,a]=(0,r.useState)("contract-management"),i={"contract-management":["parse_contract","parse_contract_file","build_contract","build_contract_from_store"],"metadata-store":["store_schema","get_schema","list_schemas","store_metadata","get_metadata","store_coercion_rules","get_coercion_rules","store_validation_rules","get_validation_rules","get_complete_schema"],"model-generator":["generate_model","generate_model_file","from_dict","from_file","from_json","from_url","model_to_schema","to_dict","to_json","to_file"],validation:["validator_class","validator_builder","validation_quality_metrics","error_handling","validate_with_store","validate_with_contract","validate_batch_with_store","validate_batch_with_contract","get_model_from_store","get_model_from_contract","validate","validate_batch"],"quality-assurance":["quality_check","quality_check_options","quality_thresholds"],"quality-tracking":["metrics_collector","validation_metric","metrics_summary","metrics_export","validator_with_tracking"],"docs-generation":["docs_generator","generate_docs"],"schema-evolution":["check_compatibility","compute_diff","compatibility_modes","change_types"],"etl-generator":["pipeline_class","pipeline_builder","etl_transformers","etl_extractors","etl_loaders","etl_orchestrator","create_orchestrator","pipeline_factory","extract_with_pagination_streaming","apply_transforms","extractor_factory","load_to_file","generate_etl_config"]},o=e=>{let t=Object.keys(i).find(t=>i[t].includes(e));if(t)a(t),setTimeout(()=>{let t=document.getElementById(`method-${e}`);t&&t.scrollIntoView({behavior:"smooth",block:"start"})},150);else{let t=document.getElementById(`method-${e}`);t&&t.scrollIntoView({behavior:"smooth",block:"start"})}},n=[{id:"contract-management",title:"Contract Management",icon:d.FileText,items:[{id:"parse_contract",label:"Parse Contract",onClick:()=>o("parse_contract")},{id:"build_contract",label:"Build Contract",onClick:()=>o("build_contract")}]},{id:"metadata-store",title:"Metadata Store Client",icon:l.Database,items:[{id:"store_schema",label:"Store Schema",onClick:()=>o("store_schema")},{id:"get_schema",label:"Get Schema",onClick:()=>o("get_schema")},{id:"list_schemas",label:"List Schemas",onClick:()=>o("list_schemas")},{id:"store_metadata",label:"Store Metadata",onClick:()=>o("store_metadata")},{id:"get_metadata",label:"Get Metadata",onClick:()=>o("get_metadata")},{id:"store_coercion_rules",label:"Store Coercion Rules",onClick:()=>o("store_coercion_rules")},{id:"get_coercion_rules",label:"Get Coercion Rules",onClick:()=>o("get_coercion_rules")},{id:"store_validation_rules",label:"Store Validation Rules",onClick:()=>o("store_validation_rules")},{id:"get_validation_rules",label:"Get Validation Rules",onClick:()=>o("get_validation_rules")},{id:"get_complete_schema",label:"Get Complete Schema",onClick:()=>o("get_complete_schema")}]},{id:"model-generator",title:"Model Generator",icon:m,items:[{id:"generate_model",label:"Generate Model",onClick:()=>o("generate_model")},{id:"generate_model_file",label:"Generate Model File",onClick:()=>o("generate_model_file")},{id:"from_dict",label:"From Dict",onClick:()=>o("from_dict")},{id:"from_file",label:"From File",onClick:()=>o("from_file")},{id:"from_json",label:"From JSON",onClick:()=>o("from_json")},{id:"from_url",label:"From URL",onClick:()=>o("from_url")},{id:"model_to_schema",label:"Model to Schema",onClick:()=>o("model_to_schema")},{id:"to_dict",label:"To Dict",onClick:()=>o("to_dict")},{id:"to_json",label:"To JSON",onClick:()=>o("to_json")},{id:"to_file",label:"To File",onClick:()=>o("to_file")}]},{id:"validation",title:"Validation",icon:p,items:[{id:"validator_class",label:"⭐ Validator Class",onClick:()=>o("validator_class")},{id:"validator_builder",label:"ValidatorBuilder",onClick:()=>o("validator_builder")},{id:"validation_quality_metrics",label:"Quality Metrics",onClick:()=>o("validation_quality_metrics")},{id:"error_handling",label:"Error Handling",onClick:()=>o("error_handling")},{id:"validate_with_store",label:"Validate with Store",onClick:()=>o("validate_with_store")},{id:"validate_with_contract",label:"Validate with Contract",onClick:()=>o("validate_with_contract")},{id:"validate_batch_with_store",label:"Batch Validate (Store)",onClick:()=>o("validate_batch_with_store")},{id:"validate_batch_with_contract",label:"Batch Validate (Contract)",onClick:()=>o("validate_batch_with_contract")},{id:"get_model_from_store",label:"Get Model (Store)",onClick:()=>o("get_model_from_store")},{id:"get_model_from_contract",label:"Get Model (Contract)",onClick:()=>o("get_model_from_contract")},{id:"validate",label:"Validate (Low-level)",onClick:()=>o("validate")},{id:"validate_batch",label:"Batch Validate (Low-level)",onClick:()=>o("validate_batch")}]},{id:"quality-assurance",title:"Quality Assurance",icon:u.Award,items:[{id:"quality_check",label:"⭐ QualityCheck Class",onClick:()=>o("quality_check")},{id:"quality_check_options",label:"QualityCheckOptions",onClick:()=>o("quality_check_options")},{id:"quality_thresholds",label:"QualityThresholds",onClick:()=>o("quality_thresholds")}]},{id:"quality-tracking",title:"Quality Tracking",icon:f,items:[{id:"metrics_collector",label:"⭐ MetricsCollector",onClick:()=>o("metrics_collector")},{id:"validation_metric",label:"ValidationMetric",onClick:()=>o("validation_metric")},{id:"metrics_summary",label:"MetricsSummary",onClick:()=>o("metrics_summary")},{id:"metrics_export",label:"Export Metrics",onClick:()=>o("metrics_export")},{id:"validator_with_tracking",label:"Validator + Tracking",onClick:()=>o("validator_with_tracking")}]},{id:"docs-generation",title:"Documentation Generation",icon:h,items:[{id:"docs_generator",label:"⭐ DocsGenerator",onClick:()=>o("docs_generator")},{id:"generate_docs",label:"generate_docs()",onClick:()=>o("generate_docs")}]},{id:"schema-evolution",title:"Schema Evolution",icon:y,items:[{id:"check_compatibility",label:"⭐ check_compatibility()",onClick:()=>o("check_compatibility")},{id:"compute_diff",label:"compute_diff()",onClick:()=>o("compute_diff")},{id:"compatibility_modes",label:"Compatibility Modes",onClick:()=>o("compatibility_modes")},{id:"change_types",label:"Change Types",onClick:()=>o("change_types")}]},{id:"etl-generator",title:"ETL Generator",icon:_,items:[{id:"pipeline_class",label:"⭐ Pipeline (NEW)",onClick:()=>o("pipeline_class")},{id:"pipeline_builder",label:"PipelineBuilder",onClick:()=>o("pipeline_builder")},{id:"etl_transformers",label:"Transformers",onClick:()=>o("etl_transformers")},{id:"etl_extractors",label:"Extractors",onClick:()=>o("etl_extractors")},{id:"etl_loaders",label:"Loaders",onClick:()=>o("etl_loaders")},{id:"etl_orchestrator",label:"ETL Orchestrator (Legacy)",onClick:()=>o("etl_orchestrator")},{id:"create_orchestrator",label:"Create Orchestrator",onClick:()=>o("create_orchestrator")},{id:"pipeline_factory",label:"Pipeline Factory",onClick:()=>o("pipeline_factory")},{id:"extract_with_pagination_streaming",label:"Extract Streaming",onClick:()=>o("extract_with_pagination_streaming")},{id:"apply_transforms",label:"Apply Transforms",onClick:()=>o("apply_transforms")},{id:"extractor_factory",label:"Extractor Factory",onClick:()=>o("extractor_factory")},{id:"load_to_file",label:"Load to File / Cloud",onClick:()=>o("load_to_file")},{id:"generate_etl_config",label:"Generate ETL Config",onClick:()=>o("generate_etl_config")}]}],s=i[e]?v.filter(t=>i[e].includes(t.id)):v;return(0,t.jsxs)("div",{className:"flex h-full bg-background",style:{height:"calc(100vh - 4rem)",overflow:"hidden"},children:[(0,t.jsx)("div",{className:"flex-shrink-0",style:{height:"100%",overflow:"hidden"},children:(0,t.jsx)(g.CollapsibleSidebar,{sections:n,defaultCollapsed:!1,headerTitle:"Documentation",selectedSection:e,onSectionClick:e=>{a(e),setTimeout(()=>{let t=document.getElementById(`section-${e}`);t&&t.scrollIntoView({behavior:"smooth",block:"start"})},100)}})}),(0,t.jsx)("div",{className:"flex-1 min-w-0",style:{height:"100%",overflowY:"auto",overflowX:"hidden"},"data-content-area":!0,children:(0,t.jsx)("div",{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8",children:(0,t.jsxs)("div",{className:"space-y-8",children:[(0,t.jsxs)("div",{id:`section-${e}`,className:"scroll-mt-4 mb-4",children:[(0,t.jsx)("h2",{className:"text-2xl font-bold text-foreground mb-1",children:n.find(t=>t.id===e)?.title||"Documentation"}),(0,t.jsxs)("p",{className:"text-sm text-muted-foreground",children:["contract-management"===e&&"Manage and work with data contracts","metadata-store"===e&&"Store and retrieve schemas, metadata, coercion rules, and validation rules","model-generator"===e&&"Generate Pydantic models from schemas","validation"===e&&"Validate data against schemas and contracts","quality-assurance"===e&&"Monitor data quality and track violations","quality-tracking"===e&&"Track validation metrics over time with trend analysis and export capabilities","docs-generation"===e&&"Generate human-readable documentation from data contracts in Markdown or HTML","schema-evolution"===e&&"Check schema compatibility and compute detailed diffs between versions","etl-generator"===e&&"Execute ETL pipelines from contract configs: extract, transform, and load"]})]}),(0,t.jsx)("div",{className:"space-y-6",children:s.map(e=>(0,t.jsx)("div",{id:`method-${e.id}`,className:"border rounded-lg overflow-hidden scroll-mt-4",children:(0,t.jsxs)("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-4 p-4",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("h4",{className:"font-semibold mb-2",children:e.title}),(0,t.jsx)("p",{className:"text-sm text-muted-foreground mb-3",children:e.description}),e.arguments&&e.arguments.length>0&&(0,t.jsxs)("div",{className:"mb-4",children:[(0,t.jsx)("h5",{className:"text-sm font-semibold mb-2",children:"Arguments"}),(0,t.jsx)("div",{className:"space-y-2",children:e.arguments.map((e,r)=>(0,t.jsxs)("div",{className:"text-xs border-l-2 border-primary/20 pl-2",children:[(0,t.jsxs)("div",{className:"font-mono font-semibold text-foreground",children:[e.name,!e.required&&(0,t.jsx)("span",{className:"text-muted-foreground ml-1",children:"(optional)"})]}),(0,t.jsxs)("div",{className:"text-muted-foreground mt-0.5",children:[(0,t.jsx)("span",{className:"font-mono",children:e.type}),e.default&&(0,t.jsxs)("span",{className:"ml-1",children:["default: ",e.default]})]}),(0,t.jsx)("div",{className:"text-muted-foreground mt-1",children:e.description})]},r))})]}),e.returns&&(0,t.jsxs)("div",{className:"mb-4",children:[(0,t.jsx)("h5",{className:"text-sm font-semibold mb-2",children:"Returns"}),(0,t.jsxs)("div",{className:"text-xs border-l-2 border-green-500/20 pl-2",children:[(0,t.jsx)("div",{className:"font-mono font-semibold text-foreground mb-0.5",children:e.returns.type}),(0,t.jsx)("div",{className:"text-muted-foreground",children:e.returns.description})]})]}),(0,t.jsx)("div",{className:"bg-muted p-3 rounded font-mono text-xs overflow-x-auto mb-3",children:(0,t.jsx)("pre",{className:"whitespace-pre-wrap",children:e.exampleCode})}),(0,t.jsxs)("div",{className:"text-xs text-muted-foreground",children:[(0,t.jsx)("span",{className:"font-semibold",children:"Method:"})," ",e.method]})]}),(0,t.jsx)("div",{children:(0,t.jsx)(x,{method:e})})]})},e.id))}),(0,t.jsxs)("div",{className:"border rounded-lg p-4 bg-primary/5",children:[(0,t.jsx)("h4",{className:"font-semibold mb-2",children:"Additional Resources"}),(0,t.jsxs)("ul",{className:"text-sm space-y-1 text-muted-foreground",children:[(0,t.jsx)("li",{children:"• Full documentation: See README.md and REFERENCE.md"}),(0,t.jsx)("li",{children:"• ETL Generator interfaces: pycharter/etl_generator/INTERFACES.md"}),(0,t.jsx)("li",{children:"• Examples: Check the examples/ directory (including examples/etl_pyoptima/)"}),(0,t.jsx)("li",{children:"• API Documentation: Available at /docs when running the API server"})]})]})]})})})]})}e.s(["default",()=>b],33558)}]);