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.
- {memframe-0.2.2 → memframe-0.4.0}/.env.test.example +3 -0
- memframe-0.4.0/CHANGELOG.md +183 -0
- {memframe-0.2.2 → memframe-0.4.0}/CONTRIBUTING.md +7 -4
- {memframe-0.2.2 → memframe-0.4.0}/PKG-INFO +42 -8
- {memframe-0.2.2 → memframe-0.4.0}/README.md +34 -5
- {memframe-0.2.2 → memframe-0.4.0}/docs/CONTRIBUTING.md +2 -2
- {memframe-0.2.2 → memframe-0.4.0}/docs/api/caching.md +16 -15
- {memframe-0.2.2 → memframe-0.4.0}/docs/api/cleaning.md +1 -1
- {memframe-0.2.2 → memframe-0.4.0}/docs/api/database.md +12 -8
- memframe-0.4.0/docs/api/datetime.md +840 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/api/inspect.md +9 -27
- {memframe-0.2.2 → memframe-0.4.0}/docs/api/selection.md +1 -1
- memframe-0.4.0/docs/api/syncdb.md +40 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/api/upload-manager.md +2 -2
- memframe-0.4.0/docs/architecture.md +62 -0
- memframe-0.4.0/docs/assets/memframe-arch.png +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/getting-started.md +23 -2
- {memframe-0.2.2 → memframe-0.4.0}/docs/index.md +6 -5
- memframe-0.4.0/docs/memframe-ai/agent.md +251 -0
- memframe-0.4.0/docs/memframe-ai/dashboard.md +114 -0
- memframe-0.4.0/docs/memframe-ai/observability.md +60 -0
- {memframe-0.2.2 → memframe-0.4.0}/mkdocs.yml +12 -2
- {memframe-0.2.2 → memframe-0.4.0}/pyproject.toml +14 -3
- {memframe-0.2.2 → memframe-0.4.0}/scripts/release.sh +2 -2
- {memframe-0.2.2 → memframe-0.4.0}/scripts/run-commit-checks.sh +15 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/__init__.py +2 -1
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/cache/cache_manager.py +19 -6
- memframe-0.4.0/src/memframe/core/analytix/arithmetic/__init__.py +15 -0
- memframe-0.2.2/src/memframe/core/analytix/arithmetic.py → memframe-0.4.0/src/memframe/core/analytix/arithmetic/base.py +296 -429
- memframe-0.4.0/src/memframe/core/analytix/arithmetic/clickhouse.py +36 -0
- memframe-0.4.0/src/memframe/core/analytix/arithmetic/duckdb.py +5 -0
- memframe-0.4.0/src/memframe/core/analytix/arithmetic/factory.py +23 -0
- memframe-0.4.0/src/memframe/core/analytix/arithmetic/postgres.py +24 -0
- memframe-0.4.0/src/memframe/core/analytix/cleaning/__init__.py +21 -0
- memframe-0.2.2/src/memframe/core/analytix/cleaning.py → memframe-0.4.0/src/memframe/core/analytix/cleaning/base.py +1146 -1934
- memframe-0.4.0/src/memframe/core/analytix/cleaning/clickhouse.py +1064 -0
- memframe-0.4.0/src/memframe/core/analytix/cleaning/duckdb.py +13 -0
- memframe-0.4.0/src/memframe/core/analytix/cleaning/factory.py +23 -0
- memframe-0.4.0/src/memframe/core/analytix/cleaning/postgres.py +409 -0
- memframe-0.4.0/src/memframe/core/analytix/datetime/__init__.py +14 -0
- memframe-0.4.0/src/memframe/core/analytix/datetime/base.py +1524 -0
- memframe-0.4.0/src/memframe/core/analytix/datetime/clickhouse.py +1230 -0
- memframe-0.4.0/src/memframe/core/analytix/datetime/duckdb.py +5 -0
- memframe-0.4.0/src/memframe/core/analytix/datetime/factory.py +25 -0
- memframe-0.4.0/src/memframe/core/analytix/datetime/postgres.py +54 -0
- memframe-0.4.0/src/memframe/core/analytix/inspection/__init__.py +13 -0
- memframe-0.4.0/src/memframe/core/analytix/inspection/base.py +1507 -0
- memframe-0.4.0/src/memframe/core/analytix/inspection/clickhouse.py +254 -0
- memframe-0.4.0/src/memframe/core/analytix/inspection/duckdb.py +5 -0
- memframe-0.4.0/src/memframe/core/analytix/inspection/factory.py +21 -0
- memframe-0.4.0/src/memframe/core/analytix/inspection/postgres.py +35 -0
- memframe-0.4.0/src/memframe/core/analytix/selection/__init__.py +22 -0
- memframe-0.4.0/src/memframe/core/analytix/selection/base.py +713 -0
- memframe-0.4.0/src/memframe/core/analytix/selection/clickhouse.py +44 -0
- memframe-0.4.0/src/memframe/core/analytix/selection/duckdb.py +5 -0
- memframe-0.4.0/src/memframe/core/analytix/selection/factory.py +23 -0
- memframe-0.4.0/src/memframe/core/analytix/selection/postgres.py +40 -0
- memframe-0.4.0/src/memframe/core/analytix/stats/__init__.py +15 -0
- memframe-0.4.0/src/memframe/core/analytix/stats/base.py +729 -0
- memframe-0.4.0/src/memframe/core/analytix/stats/clickhouse.py +214 -0
- memframe-0.4.0/src/memframe/core/analytix/stats/duckdb.py +13 -0
- memframe-0.4.0/src/memframe/core/analytix/stats/factory.py +23 -0
- memframe-0.4.0/src/memframe/core/analytix/stats/postgres.py +104 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/ingestion/datatype_detector.py +7 -20
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/ingestion/upload/__init__.py +7 -7
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/ingestion/upload/base.py +11 -282
- 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
- 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
- memframe-0.4.0/src/memframe/core/ingestion/upload/postgres_impl.py +142 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/ingestion/upload/strategies/base.py +3 -2
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/ingestion/upload/strategies/csv.py +12 -1
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/analytix/arithmetic.py +2 -2
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/analytix/cleaning.py +47 -2
- memframe-0.4.0/src/memframe/core/orchestrator/analytix/datetime.py +396 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/analytix/inspection.py +5 -21
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/analytix/selection.py +2 -2
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/analytix/stats.py +47 -2
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/plots/bar.py +5 -1
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/plots/bar_polar.py +5 -1
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/plots/line.py +5 -1
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/plots/pie.py +5 -1
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/plots/scatter.py +5 -1
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/orchestrator/plots/scatter_3d.py +5 -1
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/plots/bar.py +4 -2
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/plots/bar_polar.py +4 -2
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/plots/line.py +4 -2
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/plots/pie.py +4 -2
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/plots/scatter.py +4 -2
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/plots/scatter_3d.py +4 -2
- memframe-0.4.0/src/memframe/dashboard/__init__.py +27 -0
- memframe-0.4.0/src/memframe/dashboard/manager.py +141 -0
- memframe-0.4.0/src/memframe/dashboard/models.py +68 -0
- memframe-0.4.0/src/memframe/dashboard/render.py +416 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/adapters/clickhouse.py +181 -48
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/adapters/duckdb.py +5 -2
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/adapters/postgresql.py +8 -4
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/connection/connector.py +27 -9
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/connection/pool.py +75 -22
- memframe-0.4.0/src/memframe/db_manager/context.py +297 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/context.pyi +2 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/ops.py +87 -7
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/setup/base.py +49 -4
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/setup/clickhouse.py +32 -10
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/setup/duckdb.py +29 -11
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/setup/postgres.py +29 -11
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/main.py +3 -0
- memframe-0.4.0/src/memframe/utils/async_sync.py +55 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/utils/helper.py +9 -83
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/utils/plot_renderer.py +63 -11
- memframe-0.4.0/src/memframe/wrappers/analytix/datetime.py +587 -0
- memframe-0.4.0/src/memframe/wrappers/analytix/datetime.pyi +262 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/inspection.py +3 -45
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/inspection.pyi +2 -22
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/agents/__init__.py +2 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/agents/analytics.py +104 -31
- memframe-0.4.0/src/memframe_ai/agents/dashboard.py +80 -0
- memframe-0.4.0/src/memframe_ai/agents/guardrail.py +87 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/agents/planning.py +70 -4
- memframe-0.4.0/src/memframe_ai/config.py +31 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/gateway.py +19 -4
- memframe-0.4.0/src/memframe_ai/instrument.py +101 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/observe.py +7 -2
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/sessions.py +28 -17
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/_helpers.py +1 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/inspect.py +6 -4
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/plot.py +5 -9
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/wrappers.py +2 -0
- memframe-0.4.0/tests/integration/ops/_plot_pdf.py +74 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_arithmetic.py +9 -1
- {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_bar.py +3 -35
- {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_bar_polar.py +3 -35
- {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_cleaning.py +9 -1
- memframe-0.4.0/tests/integration/ops/test_datetime.py +1659 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_inspect.py +6 -34
- {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_line.py +3 -35
- {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_pie.py +3 -35
- {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_scatter.py +3 -35
- {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_scatter3d.py +3 -35
- {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_upload.py +1 -3
- memframe-0.4.0/tests/integration/test_dashboard_convenience.py +61 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/integration/test_lifecycle.py +5 -1
- memframe-0.4.0/tests/integration/test_syncdb.py +204 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/run_tests.py +1 -1
- memframe-0.4.0/tests/unit/ai/test_agents.py +44 -0
- memframe-0.4.0/tests/unit/ai/test_ai_settings.py +17 -0
- memframe-0.4.0/tests/unit/ai/test_datetime_binding.py +84 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_domain.py +24 -2
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_entrypoints.py +2 -2
- memframe-0.4.0/tests/unit/ai/test_gateway.py +89 -0
- memframe-0.4.0/tests/unit/ai/test_guardrail.py +141 -0
- memframe-0.4.0/tests/unit/ai/test_logfire.py +73 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_sessions.py +1 -1
- memframe-0.4.0/tests/unit/fixtures/arithmetic_sql_fingerprint.json +5942 -0
- memframe-0.4.0/tests/unit/fixtures/cleaning_sql_fingerprint.json +3316 -0
- memframe-0.4.0/tests/unit/fixtures/datetime_sql_fingerprint.json +2694 -0
- memframe-0.4.0/tests/unit/fixtures/selection_sql_fingerprint.json +972 -0
- memframe-0.4.0/tests/unit/fixtures/stats_sql_fingerprint.json +1712 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_arithmetic_response.py +2 -2
- memframe-0.4.0/tests/unit/test_arithmetic_sql_fingerprint.py +146 -0
- memframe-0.4.0/tests/unit/test_cleaning_sql_fingerprint.py +152 -0
- memframe-0.4.0/tests/unit/test_concurrency_lifecycle.py +141 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_context.py +28 -4
- memframe-0.4.0/tests/unit/test_dashboard.py +428 -0
- memframe-0.4.0/tests/unit/test_data_path_fixes.py +96 -0
- memframe-0.4.0/tests/unit/test_datetime_response.py +452 -0
- memframe-0.4.0/tests/unit/test_datetime_sql_fingerprint.py +204 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_helper.py +0 -15
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_ops_mixin.py +52 -2
- memframe-0.4.0/tests/unit/test_plot_renderer.py +76 -0
- memframe-0.4.0/tests/unit/test_security_hardening.py +119 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_selection_response.py +18 -2
- memframe-0.4.0/tests/unit/test_selection_sql_fingerprint.py +189 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_setup.py +6 -6
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_stats_response.py +2 -2
- memframe-0.4.0/tests/unit/test_stats_sql_fingerprint.py +166 -0
- {memframe-0.2.2 → memframe-0.4.0}/tox.ini +1 -0
- {memframe-0.2.2 → memframe-0.4.0}/uv.lock +234 -200
- memframe-0.2.2/.github/workflows/tox.yml +0 -16
- memframe-0.2.2/CHANGELOG.md +0 -84
- memframe-0.2.2/docs/api/agent.md +0 -112
- memframe-0.2.2/src/memframe/core/analytix/inspection.py +0 -1948
- memframe-0.2.2/src/memframe/core/analytix/selection.py +0 -790
- memframe-0.2.2/src/memframe/core/analytix/stats.py +0 -1603
- memframe-0.2.2/src/memframe/core/ingestion/upload/postgres.py +0 -104
- memframe-0.2.2/src/memframe/db_manager/context.py +0 -152
- memframe-0.2.2/src/memframe/utils/async_sync.py +0 -43
- memframe-0.2.2/src/memframe_ai/config.py +0 -14
- memframe-0.2.2/tests/unit/ai/test_gateway.py +0 -45
- memframe-0.2.2/tests/unit/test_plot_renderer.py +0 -25
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/SKILL.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/AGENTS-CORE.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/ARCHITECTURE.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/CAPABILITIES-AND-HOOKS.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/COMMON-TASKS.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/INPUT-AND-HISTORY.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/NATIVE-TOOLS.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/ON-DEMAND-CAPABILITIES.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/ORCHESTRATION-AND-INTEGRATIONS.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/TESTING-AND-DEBUGGING.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/TOOLS-ADVANCED.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/building-pydantic-ai-agents/references/TOOLS-CORE.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/SKILL.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/collector/host-and-infra-metrics.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/ai-sdk.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/cloudflare-and-deno.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/frameworks.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/installation-and-env.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/nextjs.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/node-runtime.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/patterns.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/project-detection.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/react-browser.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/javascript/verification-troubleshooting.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/python/integrations.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/python/logging-patterns.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-instrumentation/references/rust/patterns.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-query/SKILL.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-query/references/client-usage.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-query/references/schema.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/logfire-ui/SKILL.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/pydantic/SKILL.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/pydantic-ai-harness/SKILL.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.agents/skills/pydantic-ai-harness/references/CODE-MODE.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.githooks/pre-commit +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.githooks/precommit.sh +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.github/workflows/ci.yml +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.github/workflows/docs.yml +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.github/workflows/release-prod.yml +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.github/workflows/release-testpypi.yml +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.gitignore +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.opencode/opencode.json +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.opencode/plans/corr_cov_single_scan.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/.python-version +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/CODE_OF_CONDUCT.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/LICENSE +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/CODE_OF_CONDUCT.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/api/arithmetic.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/api/bar.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/api/bar_polar.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/api/connector.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/api/line.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/api/pie.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/api/scatter.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/api/scatter3d.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/api/stats.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/assets/logo-nav.png +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/assets/memframe-logo-full.png +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/stylesheets/extra.css +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/docs/testing.md +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/skills-lock.json +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/cache/__init__.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/__init__.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/analytix/_response.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/ingestion/upload/strategies/__init__.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/ingestion/upload/strategies/df.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/core/ingestion/upload/strategies/parquet.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/__init__.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/adapters/base.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/adapters/factory.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/connection/__init__.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/db_manager/setup/__init__.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/exceptions.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/main.pyi +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/py.typed +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/utils/__init__.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/__init__.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/__init__.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/arithmetic.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/arithmetic.pyi +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/cleaning.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/cleaning.pyi +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/selection.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/selection.pyi +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/stats.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/analytix/stats.pyi +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/base.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/__init__.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/bar.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/bar.pyi +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/bar_polar.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/bar_polar.pyi +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/line.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/line.pyi +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/pie.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/pie.pyi +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/scatter.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/scatter.pyi +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/scatter3d.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe/wrappers/plots/scatter3d.pyi +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/__init__.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/domain.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/entrypoints.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/__init__.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/arithmetic.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/clean.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/context.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/select.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/stats.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/src/memframe_ai/tools/upload.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/conftest.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/datasets/sample.csv +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/datasets/sample.parquet +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/db_test_utils.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/integration/conftest.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_selection.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/integration/ops/test_stats.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/integration/test_concurrency.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/integration/test_parity.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_arithmetic_tools.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_clean_tools.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_fleet.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_inspect_tools.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_observe.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_planning.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_select_tools.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_stats_tools.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/ai/test_tools.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_async_sync.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_cleaning_orchestrator_response.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_cleaning_response.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_connector.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_csv_invalid_values.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_datatype_detector.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_errors.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_exceptions.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_factory.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_inspection_orchestrator_response.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_inspection_response.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_pool.py +0 -0
- {memframe-0.2.2 → memframe-0.4.0}/tests/unit/test_public_results.py +0 -0
- {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
|
|
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),
|
|
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.
|
|
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
|
[](https://pypi.org/project/memframe/)
|
|
53
58
|
[](https://github.com/Debojit95/memFrame/blob/main/pyproject.toml)
|
|
54
59
|
[](https://github.com/Debojit95/memFrame/actions/workflows/ci.yml)
|
|
55
|
-
[](https://github.com/Debojit95/memFrame/actions/workflows/ci.yml)
|
|
56
61
|
[](https://github.com/Debojit95/memFrame/blob/main/LICENSE)
|
|
57
62
|
[](https://pypi.org/project/memframe/)
|
|
58
63
|
[](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
|
|
76
|
-
uv add memframe
|
|
77
|
-
pip install "memframe[ai]"
|
|
78
|
-
uv add "memframe[ai]"
|
|
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
|
[](https://pypi.org/project/memframe/)
|
|
8
8
|
[](https://github.com/Debojit95/memFrame/blob/main/pyproject.toml)
|
|
9
9
|
[](https://github.com/Debojit95/memFrame/actions/workflows/ci.yml)
|
|
10
|
-
[](https://github.com/Debojit95/memFrame/actions/workflows/ci.yml)
|
|
11
11
|
[](https://github.com/Debojit95/memFrame/blob/main/LICENSE)
|
|
12
12
|
[](https://pypi.org/project/memframe/)
|
|
13
13
|
[](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
|
|
31
|
-
uv add memframe
|
|
32
|
-
pip install "memframe[ai]"
|
|
33
|
-
uv add "memframe[ai]"
|
|
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 `
|
|
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 `
|
|
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
|
|
88
|
-
|
|
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
|
|
92
|
-
- PostgreSQL — `ALTER TABLE
|
|
93
|
-
- ClickHouse — `RENAME TABLE
|
|
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
|
|
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 | `
|
|
107
|
-
| PostgreSQL | `
|
|
108
|
-
| ClickHouse | `
|
|
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: `
|
|
111
|
-
`
|
|
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 `
|
|
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
|
-
|
|
50
|
-
|
|
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.
|
|
59
|
-
|
|
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 `
|
|
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
|
|