memframe 0.2.2__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (331) hide show
  1. {memframe-0.2.2 → memframe-0.4.0}/.env.test.example +3 -0
  2. memframe-0.4.0/CHANGELOG.md +183 -0
  3. {memframe-0.2.2 → memframe-0.4.0}/CONTRIBUTING.md +7 -4
  4. {memframe-0.2.2 → memframe-0.4.0}/PKG-INFO +42 -8
  5. {memframe-0.2.2 → memframe-0.4.0}/README.md +34 -5
  6. {memframe-0.2.2 → memframe-0.4.0}/docs/CONTRIBUTING.md +2 -2
  7. {memframe-0.2.2 → memframe-0.4.0}/docs/api/caching.md +16 -15
  8. {memframe-0.2.2 → memframe-0.4.0}/docs/api/cleaning.md +1 -1
  9. {memframe-0.2.2 → memframe-0.4.0}/docs/api/database.md +12 -8
  10. memframe-0.4.0/docs/api/datetime.md +840 -0
  11. {memframe-0.2.2 → memframe-0.4.0}/docs/api/inspect.md +9 -27
  12. {memframe-0.2.2 → memframe-0.4.0}/docs/api/selection.md +1 -1
  13. memframe-0.4.0/docs/api/syncdb.md +40 -0
  14. {memframe-0.2.2 → memframe-0.4.0}/docs/api/upload-manager.md +2 -2
  15. memframe-0.4.0/docs/architecture.md +62 -0
  16. memframe-0.4.0/docs/assets/memframe-arch.png +0 -0
  17. {memframe-0.2.2 → memframe-0.4.0}/docs/getting-started.md +23 -2
  18. {memframe-0.2.2 → memframe-0.4.0}/docs/index.md +6 -5
  19. memframe-0.4.0/docs/memframe-ai/agent.md +251 -0
  20. memframe-0.4.0/docs/memframe-ai/dashboard.md +114 -0
  21. memframe-0.4.0/docs/memframe-ai/observability.md +60 -0
  22. {memframe-0.2.2 → memframe-0.4.0}/mkdocs.yml +12 -2
  23. {memframe-0.2.2 → memframe-0.4.0}/pyproject.toml +14 -3
  24. {memframe-0.2.2 → memframe-0.4.0}/scripts/release.sh +2 -2
  25. {memframe-0.2.2 → memframe-0.4.0}/scripts/run-commit-checks.sh +15 -0
  26. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/__init__.py +2 -1
  27. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/cache/cache_manager.py +19 -6
  28. memframe-0.4.0/src/memframe/core/analytix/arithmetic/__init__.py +15 -0
  29. memframe-0.2.2/src/memframe/core/analytix/arithmetic.py → memframe-0.4.0/src/memframe/core/analytix/arithmetic/base.py +296 -429
  30. memframe-0.4.0/src/memframe/core/analytix/arithmetic/clickhouse.py +36 -0
  31. memframe-0.4.0/src/memframe/core/analytix/arithmetic/duckdb.py +5 -0
  32. memframe-0.4.0/src/memframe/core/analytix/arithmetic/factory.py +23 -0
  33. memframe-0.4.0/src/memframe/core/analytix/arithmetic/postgres.py +24 -0
  34. memframe-0.4.0/src/memframe/core/analytix/cleaning/__init__.py +21 -0
  35. memframe-0.2.2/src/memframe/core/analytix/cleaning.py → memframe-0.4.0/src/memframe/core/analytix/cleaning/base.py +1146 -1934
  36. memframe-0.4.0/src/memframe/core/analytix/cleaning/clickhouse.py +1064 -0
  37. memframe-0.4.0/src/memframe/core/analytix/cleaning/duckdb.py +13 -0
  38. memframe-0.4.0/src/memframe/core/analytix/cleaning/factory.py +23 -0
  39. memframe-0.4.0/src/memframe/core/analytix/cleaning/postgres.py +409 -0
  40. memframe-0.4.0/src/memframe/core/analytix/datetime/__init__.py +14 -0
  41. memframe-0.4.0/src/memframe/core/analytix/datetime/base.py +1524 -0
  42. memframe-0.4.0/src/memframe/core/analytix/datetime/clickhouse.py +1230 -0
  43. memframe-0.4.0/src/memframe/core/analytix/datetime/duckdb.py +5 -0
  44. memframe-0.4.0/src/memframe/core/analytix/datetime/factory.py +25 -0
  45. memframe-0.4.0/src/memframe/core/analytix/datetime/postgres.py +54 -0
  46. memframe-0.4.0/src/memframe/core/analytix/inspection/__init__.py +13 -0
  47. memframe-0.4.0/src/memframe/core/analytix/inspection/base.py +1507 -0
  48. memframe-0.4.0/src/memframe/core/analytix/inspection/clickhouse.py +254 -0
  49. memframe-0.4.0/src/memframe/core/analytix/inspection/duckdb.py +5 -0
  50. memframe-0.4.0/src/memframe/core/analytix/inspection/factory.py +21 -0
  51. memframe-0.4.0/src/memframe/core/analytix/inspection/postgres.py +35 -0
  52. memframe-0.4.0/src/memframe/core/analytix/selection/__init__.py +22 -0
  53. memframe-0.4.0/src/memframe/core/analytix/selection/base.py +713 -0
  54. memframe-0.4.0/src/memframe/core/analytix/selection/clickhouse.py +44 -0
  55. memframe-0.4.0/src/memframe/core/analytix/selection/duckdb.py +5 -0
  56. memframe-0.4.0/src/memframe/core/analytix/selection/factory.py +23 -0
  57. memframe-0.4.0/src/memframe/core/analytix/selection/postgres.py +40 -0
  58. memframe-0.4.0/src/memframe/core/analytix/stats/__init__.py +15 -0
  59. memframe-0.4.0/src/memframe/core/analytix/stats/base.py +729 -0
  60. memframe-0.4.0/src/memframe/core/analytix/stats/clickhouse.py +214 -0
  61. memframe-0.4.0/src/memframe/core/analytix/stats/duckdb.py +13 -0
  62. memframe-0.4.0/src/memframe/core/analytix/stats/factory.py +23 -0
  63. memframe-0.4.0/src/memframe/core/analytix/stats/postgres.py +104 -0
  64. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/ingestion/datatype_detector.py +7 -20
  65. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/ingestion/upload/__init__.py +7 -7
  66. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/ingestion/upload/base.py +11 -282
  67. memframe-0.2.2/src/memframe/core/ingestion/upload/clickhouse.py → memframe-0.4.0/src/memframe/core/ingestion/upload/clickhouse_impl.py +64 -87
  68. memframe-0.2.2/src/memframe/core/ingestion/upload/duckdb.py → memframe-0.4.0/src/memframe/core/ingestion/upload/duckdb_impl.py +22 -50
  69. memframe-0.4.0/src/memframe/core/ingestion/upload/postgres_impl.py +142 -0
  70. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/ingestion/upload/strategies/base.py +3 -2
  71. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/ingestion/upload/strategies/csv.py +12 -1
  72. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/analytix/arithmetic.py +2 -2
  73. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/analytix/cleaning.py +47 -2
  74. memframe-0.4.0/src/memframe/core/orchestrator/analytix/datetime.py +396 -0
  75. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/analytix/inspection.py +5 -21
  76. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/analytix/selection.py +2 -2
  77. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/analytix/stats.py +47 -2
  78. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/plots/bar.py +5 -1
  79. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/plots/bar_polar.py +5 -1
  80. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/plots/line.py +5 -1
  81. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/plots/pie.py +5 -1
  82. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/plots/scatter.py +5 -1
  83. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/plots/scatter_3d.py +5 -1
  84. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/plots/bar.py +4 -2
  85. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/plots/bar_polar.py +4 -2
  86. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/plots/line.py +4 -2
  87. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/plots/pie.py +4 -2
  88. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/plots/scatter.py +4 -2
  89. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/plots/scatter_3d.py +4 -2
  90. memframe-0.4.0/src/memframe/dashboard/__init__.py +27 -0
  91. memframe-0.4.0/src/memframe/dashboard/manager.py +141 -0
  92. memframe-0.4.0/src/memframe/dashboard/models.py +68 -0
  93. memframe-0.4.0/src/memframe/dashboard/render.py +416 -0
  94. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/adapters/clickhouse.py +181 -48
  95. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/adapters/duckdb.py +5 -2
  96. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/adapters/postgresql.py +8 -4
  97. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/connection/connector.py +27 -9
  98. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/connection/pool.py +75 -22
  99. memframe-0.4.0/src/memframe/db_manager/context.py +297 -0
  100. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/context.pyi +2 -0
  101. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/ops.py +87 -7
  102. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/setup/base.py +49 -4
  103. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/setup/clickhouse.py +32 -10
  104. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/setup/duckdb.py +29 -11
  105. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/setup/postgres.py +29 -11
  106. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/main.py +3 -0
  107. memframe-0.4.0/src/memframe/utils/async_sync.py +55 -0
  108. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/utils/helper.py +9 -83
  109. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/utils/plot_renderer.py +63 -11
  110. memframe-0.4.0/src/memframe/wrappers/analytix/datetime.py +587 -0
  111. memframe-0.4.0/src/memframe/wrappers/analytix/datetime.pyi +262 -0
  112. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/inspection.py +3 -45
  113. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/inspection.pyi +2 -22
  114. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/agents/__init__.py +2 -0
  115. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/agents/analytics.py +104 -31
  116. memframe-0.4.0/src/memframe_ai/agents/dashboard.py +80 -0
  117. memframe-0.4.0/src/memframe_ai/agents/guardrail.py +87 -0
  118. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/agents/planning.py +70 -4
  119. memframe-0.4.0/src/memframe_ai/config.py +31 -0
  120. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/gateway.py +19 -4
  121. memframe-0.4.0/src/memframe_ai/instrument.py +101 -0
  122. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/observe.py +7 -2
  123. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/sessions.py +28 -17
  124. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/_helpers.py +1 -0
  125. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/inspect.py +6 -4
  126. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/plot.py +5 -9
  127. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/wrappers.py +2 -0
  128. memframe-0.4.0/tests/integration/ops/_plot_pdf.py +74 -0
  129. {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_arithmetic.py +9 -1
  130. {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_bar.py +3 -35
  131. {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_bar_polar.py +3 -35
  132. {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_cleaning.py +9 -1
  133. memframe-0.4.0/tests/integration/ops/test_datetime.py +1659 -0
  134. {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_inspect.py +6 -34
  135. {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_line.py +3 -35
  136. {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_pie.py +3 -35
  137. {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_scatter.py +3 -35
  138. {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_scatter3d.py +3 -35
  139. {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_upload.py +1 -3
  140. memframe-0.4.0/tests/integration/test_dashboard_convenience.py +61 -0
  141. {memframe-0.2.2 → memframe-0.4.0}/tests/integration/test_lifecycle.py +5 -1
  142. memframe-0.4.0/tests/integration/test_syncdb.py +204 -0
  143. {memframe-0.2.2 → memframe-0.4.0}/tests/run_tests.py +1 -1
  144. memframe-0.4.0/tests/unit/ai/test_agents.py +44 -0
  145. memframe-0.4.0/tests/unit/ai/test_ai_settings.py +17 -0
  146. memframe-0.4.0/tests/unit/ai/test_datetime_binding.py +84 -0
  147. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_domain.py +24 -2
  148. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_entrypoints.py +2 -2
  149. memframe-0.4.0/tests/unit/ai/test_gateway.py +89 -0
  150. memframe-0.4.0/tests/unit/ai/test_guardrail.py +141 -0
  151. memframe-0.4.0/tests/unit/ai/test_logfire.py +73 -0
  152. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_sessions.py +1 -1
  153. memframe-0.4.0/tests/unit/fixtures/arithmetic_sql_fingerprint.json +5942 -0
  154. memframe-0.4.0/tests/unit/fixtures/cleaning_sql_fingerprint.json +3316 -0
  155. memframe-0.4.0/tests/unit/fixtures/datetime_sql_fingerprint.json +2694 -0
  156. memframe-0.4.0/tests/unit/fixtures/selection_sql_fingerprint.json +972 -0
  157. memframe-0.4.0/tests/unit/fixtures/stats_sql_fingerprint.json +1712 -0
  158. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_arithmetic_response.py +2 -2
  159. memframe-0.4.0/tests/unit/test_arithmetic_sql_fingerprint.py +146 -0
  160. memframe-0.4.0/tests/unit/test_cleaning_sql_fingerprint.py +152 -0
  161. memframe-0.4.0/tests/unit/test_concurrency_lifecycle.py +141 -0
  162. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_context.py +28 -4
  163. memframe-0.4.0/tests/unit/test_dashboard.py +428 -0
  164. memframe-0.4.0/tests/unit/test_data_path_fixes.py +96 -0
  165. memframe-0.4.0/tests/unit/test_datetime_response.py +452 -0
  166. memframe-0.4.0/tests/unit/test_datetime_sql_fingerprint.py +204 -0
  167. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_helper.py +0 -15
  168. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_ops_mixin.py +52 -2
  169. memframe-0.4.0/tests/unit/test_plot_renderer.py +76 -0
  170. memframe-0.4.0/tests/unit/test_security_hardening.py +119 -0
  171. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_selection_response.py +18 -2
  172. memframe-0.4.0/tests/unit/test_selection_sql_fingerprint.py +189 -0
  173. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_setup.py +6 -6
  174. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_stats_response.py +2 -2
  175. memframe-0.4.0/tests/unit/test_stats_sql_fingerprint.py +166 -0
  176. {memframe-0.2.2 → memframe-0.4.0}/tox.ini +1 -0
  177. {memframe-0.2.2 → memframe-0.4.0}/uv.lock +234 -200
  178. memframe-0.2.2/.github/workflows/tox.yml +0 -16
  179. memframe-0.2.2/CHANGELOG.md +0 -84
  180. memframe-0.2.2/docs/api/agent.md +0 -112
  181. memframe-0.2.2/src/memframe/core/analytix/inspection.py +0 -1948
  182. memframe-0.2.2/src/memframe/core/analytix/selection.py +0 -790
  183. memframe-0.2.2/src/memframe/core/analytix/stats.py +0 -1603
  184. memframe-0.2.2/src/memframe/core/ingestion/upload/postgres.py +0 -104
  185. memframe-0.2.2/src/memframe/db_manager/context.py +0 -152
  186. memframe-0.2.2/src/memframe/utils/async_sync.py +0 -43
  187. memframe-0.2.2/src/memframe_ai/config.py +0 -14
  188. memframe-0.2.2/tests/unit/ai/test_gateway.py +0 -45
  189. memframe-0.2.2/tests/unit/test_plot_renderer.py +0 -25
  190. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/SKILL.md +0 -0
  191. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/AGENTS-CORE.md +0 -0
  192. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/ARCHITECTURE.md +0 -0
  193. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/CAPABILITIES-AND-HOOKS.md +0 -0
  194. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/COMMON-TASKS.md +0 -0
  195. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/INPUT-AND-HISTORY.md +0 -0
  196. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/NATIVE-TOOLS.md +0 -0
  197. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/ON-DEMAND-CAPABILITIES.md +0 -0
  198. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/ORCHESTRATION-AND-INTEGRATIONS.md +0 -0
  199. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/TESTING-AND-DEBUGGING.md +0 -0
  200. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/TOOLS-ADVANCED.md +0 -0
  201. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/TOOLS-CORE.md +0 -0
  202. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/SKILL.md +0 -0
  203. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/collector/host-and-infra-metrics.md +0 -0
  204. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/ai-sdk.md +0 -0
  205. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/cloudflare-and-deno.md +0 -0
  206. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/frameworks.md +0 -0
  207. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/installation-and-env.md +0 -0
  208. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/nextjs.md +0 -0
  209. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/node-runtime.md +0 -0
  210. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/patterns.md +0 -0
  211. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/project-detection.md +0 -0
  212. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/react-browser.md +0 -0
  213. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/verification-troubleshooting.md +0 -0
  214. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/python/integrations.md +0 -0
  215. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/python/logging-patterns.md +0 -0
  216. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/rust/patterns.md +0 -0
  217. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-query/SKILL.md +0 -0
  218. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-query/references/client-usage.md +0 -0
  219. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-query/references/schema.md +0 -0
  220. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-ui/SKILL.md +0 -0
  221. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/pydantic/SKILL.md +0 -0
  222. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/pydantic-ai-harness/SKILL.md +0 -0
  223. {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/pydantic-ai-harness/references/CODE-MODE.md +0 -0
  224. {memframe-0.2.2 → memframe-0.4.0}/.githooks/pre-commit +0 -0
  225. {memframe-0.2.2 → memframe-0.4.0}/.githooks/precommit.sh +0 -0
  226. {memframe-0.2.2 → memframe-0.4.0}/.github/workflows/ci.yml +0 -0
  227. {memframe-0.2.2 → memframe-0.4.0}/.github/workflows/docs.yml +0 -0
  228. {memframe-0.2.2 → memframe-0.4.0}/.github/workflows/release-prod.yml +0 -0
  229. {memframe-0.2.2 → memframe-0.4.0}/.github/workflows/release-testpypi.yml +0 -0
  230. {memframe-0.2.2 → memframe-0.4.0}/.gitignore +0 -0
  231. {memframe-0.2.2 → memframe-0.4.0}/.opencode/opencode.json +0 -0
  232. {memframe-0.2.2 → memframe-0.4.0}/.opencode/plans/corr_cov_single_scan.md +0 -0
  233. {memframe-0.2.2 → memframe-0.4.0}/.python-version +0 -0
  234. {memframe-0.2.2 → memframe-0.4.0}/CODE_OF_CONDUCT.md +0 -0
  235. {memframe-0.2.2 → memframe-0.4.0}/LICENSE +0 -0
  236. {memframe-0.2.2 → memframe-0.4.0}/docs/CODE_OF_CONDUCT.md +0 -0
  237. {memframe-0.2.2 → memframe-0.4.0}/docs/api/arithmetic.md +0 -0
  238. {memframe-0.2.2 → memframe-0.4.0}/docs/api/bar.md +0 -0
  239. {memframe-0.2.2 → memframe-0.4.0}/docs/api/bar_polar.md +0 -0
  240. {memframe-0.2.2 → memframe-0.4.0}/docs/api/connector.md +0 -0
  241. {memframe-0.2.2 → memframe-0.4.0}/docs/api/line.md +0 -0
  242. {memframe-0.2.2 → memframe-0.4.0}/docs/api/pie.md +0 -0
  243. {memframe-0.2.2 → memframe-0.4.0}/docs/api/scatter.md +0 -0
  244. {memframe-0.2.2 → memframe-0.4.0}/docs/api/scatter3d.md +0 -0
  245. {memframe-0.2.2 → memframe-0.4.0}/docs/api/stats.md +0 -0
  246. {memframe-0.2.2 → memframe-0.4.0}/docs/assets/logo-nav.png +0 -0
  247. {memframe-0.2.2 → memframe-0.4.0}/docs/assets/memframe-logo-full.png +0 -0
  248. {memframe-0.2.2 → memframe-0.4.0}/docs/stylesheets/extra.css +0 -0
  249. {memframe-0.2.2 → memframe-0.4.0}/docs/testing.md +0 -0
  250. {memframe-0.2.2 → memframe-0.4.0}/skills-lock.json +0 -0
  251. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/cache/__init__.py +0 -0
  252. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/__init__.py +0 -0
  253. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/analytix/_response.py +0 -0
  254. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/ingestion/upload/strategies/__init__.py +0 -0
  255. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/ingestion/upload/strategies/df.py +0 -0
  256. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/ingestion/upload/strategies/parquet.py +0 -0
  257. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/__init__.py +0 -0
  258. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/adapters/base.py +0 -0
  259. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/adapters/factory.py +0 -0
  260. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/connection/__init__.py +0 -0
  261. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/setup/__init__.py +0 -0
  262. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/exceptions.py +0 -0
  263. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/main.pyi +0 -0
  264. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/py.typed +0 -0
  265. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/utils/__init__.py +0 -0
  266. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/__init__.py +0 -0
  267. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/__init__.py +0 -0
  268. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/arithmetic.py +0 -0
  269. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/arithmetic.pyi +0 -0
  270. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/cleaning.py +0 -0
  271. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/cleaning.pyi +0 -0
  272. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/selection.py +0 -0
  273. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/selection.pyi +0 -0
  274. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/stats.py +0 -0
  275. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/stats.pyi +0 -0
  276. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/base.py +0 -0
  277. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/__init__.py +0 -0
  278. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/bar.py +0 -0
  279. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/bar.pyi +0 -0
  280. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/bar_polar.py +0 -0
  281. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/bar_polar.pyi +0 -0
  282. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/line.py +0 -0
  283. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/line.pyi +0 -0
  284. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/pie.py +0 -0
  285. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/pie.pyi +0 -0
  286. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/scatter.py +0 -0
  287. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/scatter.pyi +0 -0
  288. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/scatter3d.py +0 -0
  289. {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/scatter3d.pyi +0 -0
  290. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/__init__.py +0 -0
  291. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/domain.py +0 -0
  292. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/entrypoints.py +0 -0
  293. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/__init__.py +0 -0
  294. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/arithmetic.py +0 -0
  295. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/clean.py +0 -0
  296. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/context.py +0 -0
  297. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/select.py +0 -0
  298. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/stats.py +0 -0
  299. {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/upload.py +0 -0
  300. {memframe-0.2.2 → memframe-0.4.0}/tests/conftest.py +0 -0
  301. {memframe-0.2.2 → memframe-0.4.0}/tests/datasets/sample.csv +0 -0
  302. {memframe-0.2.2 → memframe-0.4.0}/tests/datasets/sample.parquet +0 -0
  303. {memframe-0.2.2 → memframe-0.4.0}/tests/db_test_utils.py +0 -0
  304. {memframe-0.2.2 → memframe-0.4.0}/tests/integration/conftest.py +0 -0
  305. {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_selection.py +0 -0
  306. {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_stats.py +0 -0
  307. {memframe-0.2.2 → memframe-0.4.0}/tests/integration/test_concurrency.py +0 -0
  308. {memframe-0.2.2 → memframe-0.4.0}/tests/integration/test_parity.py +0 -0
  309. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_arithmetic_tools.py +0 -0
  310. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_clean_tools.py +0 -0
  311. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_fleet.py +0 -0
  312. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_inspect_tools.py +0 -0
  313. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_observe.py +0 -0
  314. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_planning.py +0 -0
  315. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_select_tools.py +0 -0
  316. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_stats_tools.py +0 -0
  317. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_tools.py +0 -0
  318. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_async_sync.py +0 -0
  319. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_cleaning_orchestrator_response.py +0 -0
  320. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_cleaning_response.py +0 -0
  321. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_connector.py +0 -0
  322. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_csv_invalid_values.py +0 -0
  323. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_datatype_detector.py +0 -0
  324. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_errors.py +0 -0
  325. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_exceptions.py +0 -0
  326. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_factory.py +0 -0
  327. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_inspection_orchestrator_response.py +0 -0
  328. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_inspection_response.py +0 -0
  329. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_pool.py +0 -0
  330. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_public_results.py +0 -0
  331. {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_response_unwrap.py +0 -0
@@ -15,3 +15,6 @@ CLICKHOUSE_UPLOAD_DB_BACKEND=clickhouse
15
15
  CLICKHOUSE_UPLOAD_DB_PARAMS='{"backend":"clickhouse", "host": "localhost", "port": xxxx, "user":"xxxxx", "password": "xxxxx"}'
16
16
  CLICKHOUSE_DB_PARAMS='{"backend":"clickhouse", "host": "localhost", "port": xxxx, "user":"xxxxx", "password": "xxxxx"}'
17
17
 
18
+ OPENAI_API_KEY = sk-proj-xxx
19
+ OLLAMA_API_KEY = xxx
20
+ OLLAMA_BASE_URL = xxx
@@ -0,0 +1,183 @@
1
+ # Changelog
2
+
3
+ All notable changes to memFrame are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/), and the project adheres
5
+ to [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.4.0] - 2026-09-08
10
+
11
+ ### Added
12
+ - **Datetime Wave 1 ops** (`ctx.dt.*`): day/month names, two-column `diff`, `to_datetime` (format, epoch units, raise/coerce), `between`/`before`/`after` filters, `select_year`/`select_month`.
13
+ - **Datetime Wave 2**: `resample` moved from inspection to `ctx.dt` with multi-aggregation, `group_by`, and label control; new `asfreq` reindexing with forward/backward fill.
14
+ - **Datetime Wave 3**: calendar-aware `add_offset` (years through days plus Mon–Fri business-day mode).
15
+ - **Plotly figures embedded as PNG in plot PDF reports** via a shared `_plot_pdf` helper (kaleido raster branch with graceful placeholder fallback); kaleido added to dev extras.
16
+
17
+ ### Fixed
18
+ - **Postgres resample/asfreq SQL**: `mean` maps to `AVG` on all backends, `median` to `percentile_cont` on Postgres; asfreq grid uses native `generate_series` on Postgres.
19
+ - **ClickHouse datetime**: day/month names via `DATE_FORMAT`, nullable result column for `to_datetime` coerce, proven `add<Unit>` date-math family plus `IGNORE NULLS` fill windows.
20
+ - **Plot PDF teardown**: report rendering no longer calls matplotlib-only `suptitle` on plotly Figures.
21
+ - **Python 3.10 compat**: `timezone.utc` replaces `datetime.UTC` / `datetime.utcnow`.
22
+
23
+ ### Changed
24
+ - **Datetime core split** into `base` plus per-backend modules (`duckdb`/`postgres`/`clickhouse` + factory), mirroring inspection; SQL fingerprints prove byte-identical output.
25
+
26
+ ## [0.3.1] - 2026-09-02
27
+
28
+ ### Changed
29
+ - **Sync API runs on one shared background event loop**: `async_to_sync` no longer spins a fresh `asyncio.run` per call — the asyncpg pool is no longer torn down/rebuilt on every sync call and the DuckDB connection is used from a single thread. Sync APIs called from a coroutine already running on the shared loop now raise a `RuntimeError` pointing at the async form.
30
+ - **Dataset contexts snapshot the active `data_id` at creation**: a later `set_active()` no longer retargets an existing context mid-flight (upload/`aset_active` contexts already behaved this way).
31
+
32
+ ### Fixed
33
+ - **SQL-injection hardening**: `fillna` constant fill values are escaped, the `iloc` raw-WHERE escape hatch rejects multi-statement strings, `map` placeholder substitution no longer corrupts function names, identifiers are quote-doubled everywhere, identifier validation rejects trailing newlines, agent credentials use `SecretStr`, and the dashboard guardrail page HTML-escapes model output.
34
+ - **Postgres numeric-text casts**: the arithmetic text-cast hook emitted DuckDB-only `TRY_CAST` (syntax error on Postgres); emulated with a numeric-pattern CASE guard, junk text still becomes NULL.
35
+ - **CSV typed-stream retries skip already-flushed rows** instead of re-inserting them (duplicated rows on mid-stream conversion failures).
36
+ - **Stale agent context**: `domain_context` caches are cleared by `invalidate()`/`advance_table()` — the previous table's schema is no longer served after a table switch.
37
+ - **Deep cache**: DataFrame/Series signatures include a content hash (same-shape frames can no longer collide into wrong cache hits).
38
+ - **Plot fetches capped at 10k rows**; AI-plot PNG rendering runs off-loop with a timeout so a hung Chromium cannot freeze the event loop.
39
+ - **Planner `UnexpectedModelBehavior`**: `SubQueryNode.query` coerces dict → string, planner `retries=3`, heuristic fallback for `value counts`/`correlation` (fixes dashboard one-sentence flake on `gpt-oss:120b-cloud`).
40
+
41
+ ### Refactor / CI
42
+ - Remove dead `DB_TO_PANDAS_DTYPE_MAP` 80-line map — zero runtime consumers (`helper.py:75-154`).
43
+ - Dedup CI: delete duplicated `tox.yml` workflow (keep `ci.yml:tox`), shrink `tox.ini:deps`.
44
+ - Remove `chardet`/`kaleido` from core deps — stdlib `utf-8` decode loop + best-effort PNG (`plot.py` already `except Exception: png=None`).
45
+
46
+ ### Internal
47
+ - The four analytix packages (cleaning, arithmetic, selection, stats) are consolidated onto hook bases mirroring `inspection/` — 10.3k → 6.3k lines, with SQL-fingerprint regression harnesses (182 scenarios × 3 backends) proving per-backend SQL unchanged.
48
+ - Ops integration assertions are order-insensitive (result samples come from unordered SELECTs; ClickHouse merges reorder rows under load).
49
+
50
+ ## [0.3.1rc1] - 2026-09-02
51
+
52
+ ### Changed
53
+ - **Sync API runs on one shared background event loop**: `async_to_sync` no longer spins a fresh `asyncio.run` per call — the asyncpg pool is no longer torn down/rebuilt on every sync call and the DuckDB connection is used from a single thread. Sync APIs called from a coroutine already running on the shared loop now raise a `RuntimeError` pointing at the async form.
54
+ - **Dataset contexts snapshot the active `data_id` at creation**: a later `set_active()` no longer retargets an existing context mid-flight (upload/`aset_active` contexts already behaved this way).
55
+
56
+ ### Fixed
57
+ - **SQL-injection hardening**: `fillna` constant fill values are escaped, the `iloc` raw-WHERE escape hatch rejects multi-statement strings, `map` placeholder substitution no longer corrupts function names, identifiers are quote-doubled everywhere, identifier validation rejects trailing newlines, agent credentials use `SecretStr`, and the dashboard guardrail page HTML-escapes model output.
58
+ - **Postgres numeric-text casts**: the arithmetic text-cast hook emitted DuckDB-only `TRY_CAST` (syntax error on Postgres); emulated with a numeric-pattern CASE guard, junk text still becomes NULL.
59
+ - **CSV typed-stream retries skip already-flushed rows** instead of re-inserting them (duplicated rows on mid-stream conversion failures).
60
+ - **Stale agent context**: `domain_context` caches are cleared by `invalidate()`/`advance_table()` — the previous table's schema is no longer served after a table switch.
61
+ - **Deep cache**: DataFrame/Series signatures include a content hash (same-shape frames can no longer collide into wrong cache hits).
62
+ - **Plot fetches capped at 10k rows**; AI-plot PNG rendering runs off-loop with a timeout so a hung Chromium cannot freeze the event loop.
63
+
64
+ ### Internal
65
+ - The four analytix packages (cleaning, arithmetic, selection, stats) are consolidated onto hook bases mirroring `inspection/` — 10.3k → 6.3k lines, with SQL-fingerprint regression harnesses (182 scenarios × 3 backends) proving per-backend SQL unchanged.
66
+ - Ops integration assertions are order-insensitive (result samples come from unordered SELECTs; ClickHouse merges reorder rows under load).
67
+
68
+ ## [0.3.0] - 2026-08-28
69
+
70
+ ### Added
71
+ - **Ollama Cloud support**: the AI gateway now forwards an explicit `base_url`/`api_key` (e.g. `https://ollama.com/v1`) for Ollama Cloud instead of assuming a local daemon; `OLLAMA_BASE_URL` remains a fallback and the `localhost:11434` default is preserved.
72
+
73
+ ### Fixed
74
+ - **Plots and dashboards render in Colab/Jupyter**: figures now embed plotly.js **inline**, so `df.bar`/`df.scatter`/`df.line`/`df.pie`/`df.scatter_3d`/`df.bar_polar` and the dashboard API render interactively without fetching plotly.js from the blocked `cdn.plot.ly` CDN. `smart_show()` no longer calls `fig.show()` inside a notebook; the kernel auto-displays the returned figure.
75
+ - **AI agent dynamic re-enable**: `AnalyticsAgent` rebuilds when memframe AI settings change, preserving chat history.
76
+
77
+ ## [0.3.0rc3] - 2026-08-26
78
+
79
+ ### Changed
80
+ - **Schema/table rename**: the three auto-created namespaces and their inner tables are now prefixed `memframe_` to avoid collisions in shared databases — `upload` → `memframe_upload`, `transient` → `memframe_transient`, `registry` → `memframe_csv_registry`; inner tables `csv_registry` → `memframe_csv_registry` and `transient_registry` → `memframe_transient_registry` (the transient-registry table lives in `memframe_csv_registry` — a schema on DuckDB/PostgreSQL, a database on ClickHouse). Existing databases are not auto-migrated; fresh databases pick up the new names.
81
+ - `aset_active`/`set_active` now return the dataset `ContextManager` (instead of the bare `data_id` string), so activation flows straight into operations: `ctx = mf.set_active(data_id); ctx.select_dtypes(...)`. `get_active_table()` still returns the active `data_id`.
82
+
83
+ ### Performance
84
+ - ClickHouse backend reuses a pooled `httpx` client with connection keep-alive per event loop, replacing per-query client creation that opened a new TCP connection for every statement (much faster integration runs).
85
+
86
+ ## [0.3.0rc2] - 2026-08-24
87
+
88
+ ### Fixed
89
+ - **Dashboard now renders in notebooks (Colab/Jupyter)**: the dashboard was composed as one Plotly figure but displayed via `display(HTML(...))`, whose `<script>` is stripped by notebook sanitization (blank dashboard). It now displays the native `go.Figure` via Plotly's mimebundle in a live kernel. Terminal/browser rendering unchanged.
90
+
91
+ ## [0.3.0rc1] - 2026-08-23
92
+
93
+ ### Added
94
+ - **AI Dashboard**: one-shot natural-language sentence produces an auto dashboard; renders as a single full-screen Plotly canvas with every DataFrame shown as a table (scalar/dict/list sub-query results now render correctly).
95
+ - **Query guardrail**: validates requests and returns a graceful "blocked" message instead of failing on unsupported queries.
96
+ - **Opt-in Logfire observability**: bring-your-own-key tracing across all agents (enable via `logfire_enabled`/`logfire_token`); host metrics via the optional `system-metrics` extra; traces flushed at the end of `achat`/`adashboard`.
97
+ - **SyncDB**: register pre-existing DuckDB/PostgreSQL/ClickHouse tables into the csv_registry as datasets.
98
+ - Unit-test parallelism via `pytest-xdist`.
99
+
100
+ ### Changed
101
+ - Renamed the `memframe_ai` logger name to `memframe.ai`.
102
+ - `memframe_ai` docs reorganized under `docs/memframe-ai/` (agent, dashboard, observability).
103
+ - The `[logfire]` extra now installs the `[ai]` runtime, so `pip install "memframe[logfire]"` pulls in `pydantic-ai` automatically.
104
+
105
+ ### Fixed
106
+ - Logfire configuration is resilient when the `system-metrics` extra is absent (host metrics are skipped instead of disabling all tracing).
107
+
108
+ ## [0.2.2] - 2026-08-19
109
+
110
+ ### Changed
111
+ - Data Quality Reports (missing-values, completeness, numeric summary, profile report) relocated from the cleaning module to the inspect module.
112
+ - Removed bivariate association methods (chi_square, cramers_v, theil_u, mutual_information) and their categorical wrappers.
113
+ - CONTRIBUTING.md: added a distinct `[refactor]` commit tag (pure restructuring, no behavior/public-API change) separate from `[upgrade]`.
114
+ - README and docs: documented that every call compiles to backend-native SQL; added Open-in-Colab badge.
115
+
116
+ ## [0.2.1] - 2026-08-17
117
+
118
+ ### Fixed
119
+ - Postgres `.corr()`/`.cov()` now compute via streaming in-memory numpy for wide
120
+ feature sets, removing the Postgres aggregate-explosion hang and greatly
121
+ speeding up wide correlation/covariance matrices.
122
+ - DuckDB `.corr()` recursion-depth failure fixed for large column-pair counts.
123
+ - Arithmetic `add`/`subtract`/`multiply`/`divide` now correctly handle
124
+ vector-scalar operands (column ± scalar, scalar ± column, negative and float
125
+ scalars); scalar-scalar operands are now rejected with a clear `OperationError`.
126
+ - Fixed `clip` date parsing bug.
127
+
128
+ ## [0.2.0] - 2026-08-16
129
+
130
+ ### Changed
131
+ - (BREAKING) `df.chat()` / `achat()` return shape changed: `answer` is now a
132
+ compact `sub_queryN`-style status string; `blocks` / `return_blocks` removed.
133
+ - Operation-result DataFrame is now returned in full (all rows, all columns)
134
+ via new `result` and `results` keys.
135
+ - Inline notebook display uses pandas/Colab's default truncation instead of
136
+ forcing every row inline (which hung notebooks on large tables).
137
+ - LLM tool-return payload stays capped (`max_output_rows`) to bound agent
138
+ context; full data is still returned to the caller.
139
+
140
+ ### Removed
141
+ - `src/memframe_ai/format.py` and the block/`return_blocks` machinery
142
+ (`analytics._package`, `ContextManager.achat`, `entrypoints`).
143
+
144
+ ### [0.1.3] - 2026-08-15
145
+
146
+ ### Changed
147
+ - Public operation results are now raw values (DataFrame, dict, scalar, or
148
+ streaming async iterator) instead of the internal response envelope.
149
+ Operations that fail raise `OperationError` instead of returning an
150
+ `is_error` dict.
151
+ - All `tests/integration` and `tests/integration/ops` tests updated to the
152
+ new raw public API.
153
+
154
+ ### Added
155
+ - Unit tests covering the public result boundary (`test_public_results.py`).
156
+
157
+ ### Docs
158
+ - `docs/api/{cleaning,arithmetic,stats,inspect,selection}.md` updated to the
159
+ raw return types.
160
+
161
+ ## [0.1.1] - 2026-08-13
162
+
163
+ ### Changed
164
+ - Removed two debug `print()` statements from `CleaningOrchestrator`
165
+ (`Inferred :` and `detected_dtype--------- :`) that were leaking into
166
+ agent chat output.
167
+
168
+ ### Notes
169
+ - Same `0.1.0` feature set; this is a packaging/cleanup patch.
170
+
171
+ ## [0.1.0] - 2026-08-13
172
+
173
+ ### Added
174
+ - Database-backed DataFrame API across DuckDB, PostgreSQL, and ClickHouse.
175
+ - Async-first surface with sync equivalents for every operation.
176
+ - Upload from CSV, Parquet, or pandas DataFrame.
177
+ - Inspection, selection, cleaning, statistics, arithmetic, Plotly charts.
178
+ - Two-level cache: lineage audit + replayable result tables.
179
+ - Optional AI agent layer (`memframe_ai`) for natural-language data work.
180
+ - Conventional commit tags (`[feat]`, `[fix]`, `[upgrade]`, `[ci]`, `[docs]`,
181
+ `[add]`, `[remove]`) documented in `CONTRIBUTING.md`.
182
+ - Slim README with Quick Start, AI Agent section, and links to per-domain
183
+ docs in `docs/api/`.
@@ -54,6 +54,7 @@ tidy. The full set:
54
54
  | `[docs]` | Documentation-only changes (README, `docs/`, docstrings). |
55
55
  | `[add]` | Adding a supporting file that does not introduce a feature (fixture, config, isolated helper). |
56
56
  | `[remove]` | Removing a tracked file from the repo (untracking / deletion of source, doc, or config). |
57
+ | `[chore]` | Routine maintenance that doesn't fit another tag — dependency bumps, build/packaging housekeeping, misc repo upkeep. Use `[upgrade]`/`[docs]`/`[ci]` for behavior/doc/CI changes. |
57
58
 
58
59
  ### Format
59
60
 
@@ -65,7 +66,7 @@ tidy. The full set:
65
66
 
66
67
  - Tag is lowercase, bracketed, single space, then the summary.
67
68
  - Summary is imperative mood, ≤72 chars, no trailing period.
68
- - The eight tags above are exhaustive. If a change genuinely fits none of them, prefer the closest tag and explain in the body. `[update]` is **not** a valid tag — use `[upgrade]` or `[docs]` instead.
69
+ - The tags above are exhaustive. If a change genuinely fits none of them, prefer the closest tag and explain in the body. `[update]` is **not** a valid tag — use `[upgrade]` or `[docs]` instead.
69
70
 
70
71
  ### Examples
71
72
 
@@ -78,6 +79,7 @@ git commit -m "[ci] Remove integration job from ci workflow"
78
79
  git commit -m "[docs] Slim README and add agent section"
79
80
  git commit -m "[add] tests/datasets/sample.parquet fixture"
80
81
  git commit -m "[remove] deprecated commands.md scratchpad"
82
+ git commit -m "[chore] Bump httpx and widen pyarrow range"
81
83
  ```
82
84
 
83
85
  ### Branch-required changes
@@ -101,7 +103,8 @@ branch + pull request — never commit directly to `main`):
101
103
  Direct commits to `main` are reserved for the maintainer's small,
102
104
  self-contained changes that don't need another pair of eyes: single-file
103
105
  `[fix]`, single-file `[docs]`, single-file `[add]`, single-file
104
- `[remove]`, small `[refactor]` (no public-API change), and small
106
+ `[remove]`, small `[refactor]` (no public-API change), small `[chore]`
107
+ maintenance (dependency bumps, build/packaging housekeeping), and small
105
108
  single-workflow `[ci]` tweaks.
106
109
 
107
110
  When in doubt, open a branch.
@@ -159,8 +162,8 @@ uv run ruff check src/
159
162
 
160
163
  1. `scripts/release.sh <version> "<message>" --dry-run` to preview.
161
164
  2. `scripts/release.sh <version> "<message>"` — runs the full gate, bumps, tags, and pushes.
162
- 3. Verify the TestPyPI install:
163
- `pip install --index-url https://test.pypi.org/simple memframe`
165
+ 3. Verify the TestPyPI install (dependencies come from real PyPI via `--extra-index-url`):
166
+ `pip install --index-url https://test.pypi.org/simple --extra-index-url https://pypi.org/simple "memframe[ai,logfire]"`
164
167
  4. Promote to PyPI via the `Release to PyPI` workflow (Actions → workflow_dispatch).
165
168
 
166
169
  ## Code of Conduct
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: memframe
3
- Version: 0.2.2
3
+ Version: 0.4.0
4
4
  Summary: memFrame is a Python package for working with database-backed DataFrame operations. It lets you upload CSV files, Parquet files, and pandas DataFrames into a local DuckDB database or a remote PostgreSQL/Clickhouse database, then run DataFrame-style inspection, selection, cleaning, and table-management operations through one consistent API.
5
5
  Project-URL: Homepage, https://github.com/Debojit95/memFrame
6
6
  Project-URL: Documentation, https://debojit95.github.io/memFrame/
@@ -19,11 +19,9 @@ Classifier: Programming Language :: Python :: 3.12
19
19
  Classifier: Programming Language :: Python :: 3.13
20
20
  Requires-Python: >=3.10
21
21
  Requires-Dist: asyncpg>=0.30
22
- Requires-Dist: chardet>=7.4.3
23
22
  Requires-Dist: clickhouse-connect>=1.4.2
24
23
  Requires-Dist: duckdb>=1.0.0
25
24
  Requires-Dist: httpx>=0.28.1
26
- Requires-Dist: kaleido>=0.2.1
27
25
  Requires-Dist: pandas<3.0,>=2.2
28
26
  Requires-Dist: plotly>=6.9.0
29
27
  Requires-Dist: pyarrow>=24.0.0
@@ -34,13 +32,20 @@ Requires-Dist: pydantic-ai>=2.22.0; extra == 'ai'
34
32
  Requires-Dist: pydantic-settings>=2.0; extra == 'ai'
35
33
  Provides-Extra: dev
36
34
  Requires-Dist: build>=1.0; extra == 'dev'
35
+ Requires-Dist: kaleido>=1.0.0; extra == 'dev'
37
36
  Requires-Dist: matplotlib>=3.10.9; extra == 'dev'
38
37
  Requires-Dist: mkdocs-material>=9.7.6; extra == 'dev'
39
38
  Requires-Dist: mkdocstrings[python]>=1.0.4; extra == 'dev'
40
39
  Requires-Dist: pytest-cov>=5.0; extra == 'dev'
40
+ Requires-Dist: pytest-xdist>=3.0; extra == 'dev'
41
41
  Requires-Dist: pytest>=8.0; extra == 'dev'
42
42
  Requires-Dist: tox>=4.0; extra == 'dev'
43
43
  Requires-Dist: twine>=6.0; extra == 'dev'
44
+ Provides-Extra: logfire
45
+ Requires-Dist: logfire[system-metrics]; extra == 'logfire'
46
+ Requires-Dist: pydantic-ai-harness[codemode]>=0.1; extra == 'logfire'
47
+ Requires-Dist: pydantic-ai>=2.22.0; extra == 'logfire'
48
+ Requires-Dist: pydantic-settings>=2.0; extra == 'logfire'
44
49
  Description-Content-Type: text/markdown
45
50
 
46
51
  <p align="center">
@@ -52,7 +57,7 @@ Description-Content-Type: text/markdown
52
57
  [![PyPI - Version](https://img.shields.io/pypi/v/memframe)](https://pypi.org/project/memframe/)
53
58
  [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://github.com/Debojit95/memFrame/blob/main/pyproject.toml)
54
59
  [![CI](https://img.shields.io/github/actions/workflow/status/Debojit95/memFrame/ci.yml?label=ci)](https://github.com/Debojit95/memFrame/actions/workflows/ci.yml)
55
- [![Tox](https://img.shields.io/github/actions/workflow/status/Debojit95/memFrame/tox.yml?label=tox)](https://github.com/Debojit95/memFrame/actions/workflows/tox.yml)
60
+ [![Tox](https://img.shields.io/github/actions/workflow/status/Debojit95/memFrame/ci.yml?label=tox)](https://github.com/Debojit95/memFrame/actions/workflows/ci.yml)
56
61
  [![License - AGPL-3.0](https://img.shields.io/github/license/Debojit95/memFrame)](https://github.com/Debojit95/memFrame/blob/main/LICENSE)
57
62
  [![PyPI - Downloads](https://img.shields.io/pypi/dm/memframe)](https://pypi.org/project/memframe/)
58
63
  [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1UtoPjzTmia4Cr6y2btDmV8mINgXaBPGP?usp=sharing)
@@ -65,17 +70,21 @@ Description-Content-Type: text/markdown
65
70
  - Compiles every pandas-style call to backend-native SQL (DuckDB / PostgreSQL / ClickHouse) and runs it in-engine — your data never leaves the database.
66
71
  - Async-first surface with sync equivalents for every operation.
67
72
  - Upload from CSV, Parquet, or pandas DataFrame.
73
+ - Sync pre-existing DuckDB, PostgreSQL, or ClickHouse tables as datasets — no re-upload.
68
74
  - Inspection, selection, cleaning, statistics, arithmetic, Plotly charts.
69
75
  - Two-level cache: lineage audit + replayable result tables.
70
76
  - Optional AI agent layer (`memframe_ai`) for chatting with your CSV.
77
+ - Optional **Logfire observability** for the AI agent layer — traces every agent run, LLM call, and tool call, plus host metrics. Opt-in via `logfire_enabled` (local console needs no token; bring-your-own-key for the cloud).
71
78
 
72
79
  ## Installation
73
80
 
74
81
  ```bash
75
- pip install memframe # core
76
- uv add memframe # alt: uv
77
- pip install "memframe[ai]" # + Pydantic AI agent layer
78
- uv add "memframe[ai]" # alt: uv
82
+ pip install memframe # core
83
+ uv add memframe # alt: uv
84
+ pip install "memframe[ai]" # + Pydantic AI agent layer
85
+ uv add "memframe[ai]" # alt: uv
86
+ pip install "memframe[logfire]" # + AI agent layer AND Logfire observability
87
+ pip install "memframe[ai,logfire]" # explicit equivalent of the above
79
88
  ```
80
89
 
81
90
  Local development from this repository:
@@ -127,6 +136,30 @@ Each upload returns a dataset context; chain inspection, selection, cleaning,
127
136
  arithmetic, statistics, and plotting on it. Sync methods drop the `a` prefix
128
137
  (`head`, `iloc`, `fillna`, …).
129
138
 
139
+ Already have tables in your database? Register them as datasets without
140
+ re-uploading:
141
+
142
+ ```python
143
+ registered = mf.register_tables()
144
+ # {'sales': [{'data_id': 'a1b2c3', 'table_name': 'orders', 'row_count': 100}, ...]}
145
+ ```
146
+
147
+ Registered tables act like uploads — activate with `set_active(data_id)` and
148
+ query via `memFrame()`. Deleting one only removes memFrame's registry entry;
149
+ your real table is left untouched.
150
+
151
+ ## Architecture
152
+
153
+ Every pandas-style call compiles to backend-native SQL and runs in-engine — your
154
+ data never leaves the database. The call path is a four-layer stack (public API →
155
+ orchestrator → core SQL engine → backend adapter), with connection, ingestion,
156
+ and a two-level cache as cross-cutting subsystems, plus an optional
157
+ [`memframe_ai`](docs/architecture.md#optional-ai-layer-memframe_ai) agent layer on top.
158
+
159
+
160
+ See the full [Architecture](docs/architecture.md) page for the component diagram
161
+ and a per-layer breakdown.
162
+
130
163
  ## AI Agent
131
164
 
132
165
  `memframe_ai` adds a Pydantic AI agent fleet on top of memFrame. After enabling
@@ -187,6 +220,7 @@ Full reference lives in [`docs/`](docs/):
187
220
  - [Getting Started](docs/getting-started.md) — connect, upload, first query.
188
221
  - [Connector & Connection](docs/api/connector.md) — DuckDB / Postgres / ClickHouse wiring.
189
222
  - [Upload Manager](docs/api/upload-manager.md) — CSV / Parquet / DataFrame ingestion.
223
+ - [Sync Existing Tables](docs/api/syncdb.md) — register pre-existing DB tables as datasets.
190
224
  - [Dataset Operations](docs/api/database.md) — table and active-dataset management.
191
225
  - [Inspection](docs/api/inspect.md) · [Selection](docs/api/selection.md) · [Cleaning](docs/api/cleaning.md)
192
226
  - [Statistics](docs/api/stats.md) · [Arithmetic](docs/api/arithmetic.md)
@@ -7,7 +7,7 @@
7
7
  [![PyPI - Version](https://img.shields.io/pypi/v/memframe)](https://pypi.org/project/memframe/)
8
8
  [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://github.com/Debojit95/memFrame/blob/main/pyproject.toml)
9
9
  [![CI](https://img.shields.io/github/actions/workflow/status/Debojit95/memFrame/ci.yml?label=ci)](https://github.com/Debojit95/memFrame/actions/workflows/ci.yml)
10
- [![Tox](https://img.shields.io/github/actions/workflow/status/Debojit95/memFrame/tox.yml?label=tox)](https://github.com/Debojit95/memFrame/actions/workflows/tox.yml)
10
+ [![Tox](https://img.shields.io/github/actions/workflow/status/Debojit95/memFrame/ci.yml?label=tox)](https://github.com/Debojit95/memFrame/actions/workflows/ci.yml)
11
11
  [![License - AGPL-3.0](https://img.shields.io/github/license/Debojit95/memFrame)](https://github.com/Debojit95/memFrame/blob/main/LICENSE)
12
12
  [![PyPI - Downloads](https://img.shields.io/pypi/dm/memframe)](https://pypi.org/project/memframe/)
13
13
  [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1UtoPjzTmia4Cr6y2btDmV8mINgXaBPGP?usp=sharing)
@@ -20,17 +20,21 @@
20
20
  - Compiles every pandas-style call to backend-native SQL (DuckDB / PostgreSQL / ClickHouse) and runs it in-engine — your data never leaves the database.
21
21
  - Async-first surface with sync equivalents for every operation.
22
22
  - Upload from CSV, Parquet, or pandas DataFrame.
23
+ - Sync pre-existing DuckDB, PostgreSQL, or ClickHouse tables as datasets — no re-upload.
23
24
  - Inspection, selection, cleaning, statistics, arithmetic, Plotly charts.
24
25
  - Two-level cache: lineage audit + replayable result tables.
25
26
  - Optional AI agent layer (`memframe_ai`) for chatting with your CSV.
27
+ - Optional **Logfire observability** for the AI agent layer — traces every agent run, LLM call, and tool call, plus host metrics. Opt-in via `logfire_enabled` (local console needs no token; bring-your-own-key for the cloud).
26
28
 
27
29
  ## Installation
28
30
 
29
31
  ```bash
30
- pip install memframe # core
31
- uv add memframe # alt: uv
32
- pip install "memframe[ai]" # + Pydantic AI agent layer
33
- uv add "memframe[ai]" # alt: uv
32
+ pip install memframe # core
33
+ uv add memframe # alt: uv
34
+ pip install "memframe[ai]" # + Pydantic AI agent layer
35
+ uv add "memframe[ai]" # alt: uv
36
+ pip install "memframe[logfire]" # + AI agent layer AND Logfire observability
37
+ pip install "memframe[ai,logfire]" # explicit equivalent of the above
34
38
  ```
35
39
 
36
40
  Local development from this repository:
@@ -82,6 +86,30 @@ Each upload returns a dataset context; chain inspection, selection, cleaning,
82
86
  arithmetic, statistics, and plotting on it. Sync methods drop the `a` prefix
83
87
  (`head`, `iloc`, `fillna`, …).
84
88
 
89
+ Already have tables in your database? Register them as datasets without
90
+ re-uploading:
91
+
92
+ ```python
93
+ registered = mf.register_tables()
94
+ # {'sales': [{'data_id': 'a1b2c3', 'table_name': 'orders', 'row_count': 100}, ...]}
95
+ ```
96
+
97
+ Registered tables act like uploads — activate with `set_active(data_id)` and
98
+ query via `memFrame()`. Deleting one only removes memFrame's registry entry;
99
+ your real table is left untouched.
100
+
101
+ ## Architecture
102
+
103
+ Every pandas-style call compiles to backend-native SQL and runs in-engine — your
104
+ data never leaves the database. The call path is a four-layer stack (public API →
105
+ orchestrator → core SQL engine → backend adapter), with connection, ingestion,
106
+ and a two-level cache as cross-cutting subsystems, plus an optional
107
+ [`memframe_ai`](docs/architecture.md#optional-ai-layer-memframe_ai) agent layer on top.
108
+
109
+
110
+ See the full [Architecture](docs/architecture.md) page for the component diagram
111
+ and a per-layer breakdown.
112
+
85
113
  ## AI Agent
86
114
 
87
115
  `memframe_ai` adds a Pydantic AI agent fleet on top of memFrame. After enabling
@@ -142,6 +170,7 @@ Full reference lives in [`docs/`](docs/):
142
170
  - [Getting Started](docs/getting-started.md) — connect, upload, first query.
143
171
  - [Connector & Connection](docs/api/connector.md) — DuckDB / Postgres / ClickHouse wiring.
144
172
  - [Upload Manager](docs/api/upload-manager.md) — CSV / Parquet / DataFrame ingestion.
173
+ - [Sync Existing Tables](docs/api/syncdb.md) — register pre-existing DB tables as datasets.
145
174
  - [Dataset Operations](docs/api/database.md) — table and active-dataset management.
146
175
  - [Inspection](docs/api/inspect.md) · [Selection](docs/api/selection.md) · [Cleaning](docs/api/cleaning.md)
147
176
  - [Statistics](docs/api/stats.md) · [Arithmetic](docs/api/arithmetic.md)
@@ -71,8 +71,8 @@ uv run ruff check src/
71
71
 
72
72
  1. `scripts/release.sh <version> "<message>" --dry-run` to preview.
73
73
  2. `scripts/release.sh <version> "<message>"` — runs the full gate, bumps, tags, and pushes.
74
- 3. Verify the TestPyPI install:
75
- `pip install --index-url https://test.pypi.org/simple memframe`
74
+ 3. Verify the TestPyPI install (dependencies come from real PyPI via `--extra-index-url`):
75
+ `pip install --index-url https://test.pypi.org/simple --extra-index-url https://pypi.org/simple "memframe[ai,logfire]"`
76
76
  4. Promote to PyPI via the `Release to PyPI` workflow (Actions → workflow_dispatch).
77
77
 
78
78
  ## Code of Conduct
@@ -11,7 +11,7 @@ so repeat work is either recorded (cheap signature logging) or fully reused
11
11
  `record_call` is a `CacheManager` instance (`from memframe.cache import
12
12
  record_call, CacheManager`). Every analytics orchestrator method (`selection`,
13
13
  `inspection`, `cleaning`, `stats`, `arithmetic`) is decorated with it. The
14
- decorator wraps the method, records the call into the `transient_registry`
14
+ decorator wraps the method, records the call into the `memframe_transient_registry`
15
15
  table, and — for deep cache — persists the returned DataFrame as a transient
16
16
  table.
17
17
 
@@ -37,7 +37,7 @@ requests and disables deep caching for the whole session.
37
37
 
38
38
  ### Level 1 — signature-only (default)
39
39
 
40
- Every call records its identity into `transient_registry`:
40
+ Every call records its identity into `memframe_transient_registry`:
41
41
 
42
42
  - `data_id` — the dataset the call ran on
43
43
  - `opidx` — monotonically increasing operation index per dataset
@@ -84,13 +84,14 @@ method**:
84
84
  ### Table relocation
85
85
 
86
86
  Methods that generate a table (e.g. a cleaned dataset) normally produce it in
87
- the upload schema. With deep caching, that table is moved into
88
- `transient_schema` so it can be reloaded on later calls and cleaned up with
87
+ the memframe_upload schema (DuckDB/PostgreSQL) or database (ClickHouse). With deep
88
+ caching, that table is moved into `transient_schema` (the transient schema on
89
+ DuckDB/PostgreSQL, database on ClickHouse) so it can be reloaded on later calls and cleaned up with
89
90
  `aclear_cache`. The relocation mechanism is backend-specific:
90
91
 
91
- - DuckDB — `CREATE TABLE transient AS SELECT * FROM upload...` then `DROP`.
92
- - PostgreSQL — `ALTER TABLE upload... SET SCHEMA transient`.
93
- - ClickHouse — `RENAME TABLE upload... TO transient...`.
92
+ - DuckDB — `CREATE TABLE memframe_transient AS SELECT * FROM memframe_upload...` then `DROP`.
93
+ - PostgreSQL — `ALTER TABLE memframe_upload... SET SCHEMA memframe_transient`.
94
+ - ClickHouse — `RENAME TABLE memframe_upload... TO memframe_transient...`.
94
95
 
95
96
  ### Cache invalidation
96
97
 
@@ -99,20 +100,20 @@ clears its registry rows. The original uploaded table is left untouched.
99
100
 
100
101
  ## Backend registry
101
102
 
102
- The transient registry lives in the backend registry schema:
103
+ The transient registry lives in the backend `memframe_csv_registry` schema (DuckDB/PostgreSQL) or database (ClickHouse):
103
104
 
104
- | Backend | Registry table | Transient schema |
105
+ | Backend | Registry table | Transient schema/database |
105
106
  | --- | --- | --- |
106
- | DuckDB | `registry.transient_registry` | `transient` |
107
- | PostgreSQL | `registry.transient_registry` | `transient` |
108
- | ClickHouse | `registry.transient_registry` | `transient` |
107
+ | DuckDB | `memframe_csv_registry.memframe_transient_registry` | `memframe_transient` |
108
+ | PostgreSQL | `memframe_csv_registry.memframe_transient_registry` | `memframe_transient` |
109
+ | ClickHouse | `memframe_csv_registry.memframe_transient_registry` | `memframe_transient` |
109
110
 
110
- Registry and transient schemas are fixed: `registry`, `transient`, and
111
- `upload`.
111
+ Registry and transient schemas/databases are fixed: `memframe_csv_registry`, `memframe_transient`, and
112
+ `memframe_upload`.
112
113
 
113
114
  ## Cache-key and registry index
114
115
 
115
- Lookups filter `transient_registry` by `data_id`, `class_name`, `method_name`,
116
+ Lookups filter `memframe_transient_registry` by `data_id`, `class_name`, `method_name`,
116
117
  `args`, `kwargs`. DuckDB and PostgreSQL backends install an index on
117
118
  `(data_id, class_name, method_name)` so repeated lookups do not scan the whole
118
119
  registry.
@@ -408,7 +408,7 @@ response envelope still carries `new_table`, column metadata, and fill metrics.
408
408
  ## Generated Tables
409
409
 
410
410
  Most cleaning operations are non-destructive to the source upload table. They
411
- create a generated table internally, usually in the same active schema.
411
+ create a generated table internally, usually in the same active schema (or database on ClickHouse).
412
412
 
413
413
  Column-cleaning operations usually:
414
414
 
@@ -14,7 +14,7 @@ the connection lifecycle lives on its `ConnectorManager`.
14
14
  | Synchronous | Asynchronous | Purpose |
15
15
  | --- | --- | --- |
16
16
  | `list_tables()` | `await alist_tables()` | List successful uploads |
17
- | `set_active(data_id)` | `await aset_active(data_id)` | Set the active dataset |
17
+ | `set_active(data_id)` | `await aset_active(data_id)` | Set the active dataset (returns a `ContextManager`) |
18
18
  | `get_active_table()` | `await aget_active_table()` | Read the active dataset ID |
19
19
  | `delete_table(data_id=None, filename=None)` | `await adelete_table(data_id=None, filename=None)` | Delete an uploaded dataset |
20
20
  | `list_operations(data_id=None)` | `await alist_operations(data_id=None)` | List operation history |
@@ -46,17 +46,21 @@ Only registry entries whose upload completed successfully are returned.
46
46
  ### Select the Active Dataset
47
47
 
48
48
  ```python
49
- mf.set_active("a1b2c3")
50
- active_id = mf.get_active_table()
49
+ # set_active returns a ContextManager bound to the dataset
50
+ ctx = mf.set_active("a1b2c3")
51
+ ctx.select_dtypes(include="numeric") # operate directly on the returned context
52
+ active_id = mf.get_active_table() # still returns the active data_id string
51
53
  ```
52
54
 
53
55
  ```python
54
- await mf.aset_active("a1b2c3")
55
- active_id = await mf.aget_active_table()
56
+ ctx = await mf.aset_active("a1b2c3")
56
57
  ```
57
58
 
58
- Setting an active dataset first verifies that its upload table exists. Methods
59
- that accept an optional `data_id` use the active dataset when no ID is given.
59
+ Setting an active dataset first verifies that its upload table exists.
60
+ `set_active`/`aset_active` return a `ContextManager` you can use for subsequent
61
+ operations; methods that accept an optional `data_id` use the active dataset
62
+ when no ID is given. `get_active_table()` continues to return the active
63
+ `data_id` string.
60
64
 
61
65
  ### Delete a Dataset
62
66
 
@@ -102,7 +106,7 @@ create generated tables.
102
106
  ## Errors
103
107
 
104
108
  - Operations that require a database raise `RuntimeError` when not connected.
105
- - Selecting an unknown `data_id` raises `ValueError`.
109
+ - Selecting an unknown `data_id` raises `DataNotFound`.
106
110
  - Deletion requires either `data_id` or `filename`.
107
111
  - Listing operations without a supplied or active dataset raises `ValueError`.
108
112