@datarecce/ui 0.1.29 → 0.1.31
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.
- package/dist/{RecceCheckContext-fAKHgsGz.js → RecceCheckContext-DPpu9nG5.js} +2 -2
- package/dist/{RecceCheckContext-fAKHgsGz.js.map → RecceCheckContext-DPpu9nG5.js.map} +1 -1
- package/dist/{RecceCheckContext-PT4-g1bW.mjs → RecceCheckContext-bXdfQLGG.mjs} +2 -2
- package/dist/{RecceCheckContext-PT4-g1bW.mjs.map → RecceCheckContext-bXdfQLGG.mjs.map} +1 -1
- package/dist/api.d.mts +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/api.js +4 -3
- package/dist/api.mjs +4 -3
- package/dist/{components-B9F5oJbK.js → components-B-YxuuPz.js} +66 -65
- package/dist/{components-B9F5oJbK.js.map → components-B-YxuuPz.js.map} +1 -1
- package/dist/{components-D2DRqJsz.css → components-BeAjVBV3.css} +1 -1
- package/dist/{components-D2DRqJsz.css.map → components-BeAjVBV3.css.map} +1 -1
- package/dist/{components-gDC1ucjo.mjs → components-DCOI1YlQ.mjs} +8 -7
- package/dist/{components-gDC1ucjo.mjs.map → components-DCOI1YlQ.mjs.map} +1 -1
- package/dist/{components-dVXbmdqd.css → components-iUxcqtUB.css} +1 -1
- package/dist/{components-dVXbmdqd.css.map → components-iUxcqtUB.css.map} +1 -1
- package/dist/components.d.mts +1 -1
- package/dist/components.d.ts +1 -1
- package/dist/components.js +6 -5
- package/dist/components.mjs +6 -5
- package/dist/{hooks-C2jUJ9EN.js → hooks-B9hsc1oD.js} +3 -3
- package/dist/{hooks-C2jUJ9EN.js.map → hooks-B9hsc1oD.js.map} +1 -1
- package/dist/{hooks-4hRUjy9Q.mjs → hooks-DjBNmTdh.mjs} +3 -3
- package/dist/{hooks-4hRUjy9Q.mjs.map → hooks-DjBNmTdh.mjs.map} +1 -1
- package/dist/hooks.d.mts +1 -1
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +5 -4
- package/dist/hooks.mjs +5 -4
- package/dist/{html2canvas-pro.esm-BR5xeFe-.mjs → html2canvas-pro.esm-BInzOtWO.mjs} +1 -1
- package/dist/{html2canvas-pro.esm-BR5xeFe-.mjs.map → html2canvas-pro.esm-BInzOtWO.mjs.map} +1 -1
- package/dist/{html2canvas-pro.esm-CVOsBdk0.js → html2canvas-pro.esm-WJxOmKlq.js} +1 -1
- package/dist/{html2canvas-pro.esm-CVOsBdk0.js.map → html2canvas-pro.esm-WJxOmKlq.js.map} +1 -1
- package/dist/{index-Bv5R8iLo.d.mts → index-B9lSPJTi.d.ts} +192 -12
- package/dist/index-B9lSPJTi.d.ts.map +1 -0
- package/dist/{index-CUtFlKOo.d.ts → index-IIXVIoOL.d.mts} +262 -78
- package/dist/index-IIXVIoOL.d.mts.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +15 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10 -8
- package/dist/index.mjs.map +1 -1
- package/dist/mui-theme-B2wm_cvZ.js +732 -0
- package/dist/mui-theme-B2wm_cvZ.js.map +1 -0
- package/dist/mui-theme-CUhybmBq.mjs +696 -0
- package/dist/mui-theme-CUhybmBq.mjs.map +1 -0
- package/dist/{state-CELzQ0tM.mjs → state-B9yzhuKs.mjs} +5 -694
- package/dist/state-B9yzhuKs.mjs.map +1 -0
- package/dist/{state-eEsMhIy4.css → state-DOUPNifc.css} +1 -1
- package/dist/{state-eEsMhIy4.css.map → state-DOUPNifc.css.map} +1 -1
- package/dist/{state-CemiRRon.js → state-lPCQsWy5.js} +24 -737
- package/dist/state-lPCQsWy5.js.map +1 -0
- package/dist/styles.css +4 -0
- package/dist/theme.d.mts +3 -0
- package/dist/theme.d.ts +3 -0
- package/dist/theme.js +9 -0
- package/dist/theme.mjs +4 -0
- package/dist/{tooltipMessage-CrXjOmVM.mjs → tooltipMessage-B--I3p1V.mjs} +1 -1
- package/dist/{tooltipMessage-CrXjOmVM.mjs.map → tooltipMessage-B--I3p1V.mjs.map} +1 -1
- package/dist/{tooltipMessage-Dbi1kkfi.js → tooltipMessage-DosF13kZ.js} +1 -1
- package/dist/{tooltipMessage-Dbi1kkfi.js.map → tooltipMessage-DosF13kZ.js.map} +1 -1
- package/dist/types.d.mts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +2 -2
- package/dist/types.mjs +2 -2
- package/dist/{urls-D7PrPolY.mjs → urls-B1Ymdoz-.mjs} +1 -1
- package/dist/{urls-D7PrPolY.mjs.map → urls-B1Ymdoz-.mjs.map} +1 -1
- package/dist/{urls-SazAekCZ.js → urls-C4eAc82S.js} +1 -1
- package/dist/{urls-SazAekCZ.js.map → urls-C4eAc82S.js.map} +1 -1
- package/dist/{version-bWg7XwOu.js → version-Dh8sZhvs.js} +2 -2
- package/dist/{version-bWg7XwOu.js.map → version-Dh8sZhvs.js.map} +1 -1
- package/dist/{version-paZ9esBk.mjs → version-OnOKzBeQ.mjs} +2 -2
- package/dist/{version-paZ9esBk.mjs.map → version-OnOKzBeQ.mjs.map} +1 -1
- package/package.json +9 -2
- package/recce-source/.editorconfig +26 -0
- package/recce-source/.flake8 +37 -0
- package/recce-source/.github/ISSUE_TEMPLATE/bug_report.yml +67 -0
- package/recce-source/.github/ISSUE_TEMPLATE/custom.md +10 -0
- package/recce-source/.github/ISSUE_TEMPLATE/feature_request.yml +42 -0
- package/recce-source/.github/PULL_REQUEST_TEMPLATE.md +21 -0
- package/recce-source/.github/copilot-instructions.md +331 -0
- package/recce-source/.github/instructions/backend-instructions.md +541 -0
- package/recce-source/.github/instructions/frontend-instructions.md +317 -0
- package/recce-source/.github/workflows/build-statics.yaml +72 -0
- package/recce-source/.github/workflows/bump.yaml +48 -0
- package/recce-source/.github/workflows/integration-tests-cloud.yaml +92 -0
- package/recce-source/.github/workflows/integration-tests-sqlmesh.yaml +33 -0
- package/recce-source/.github/workflows/integration-tests.yaml +52 -0
- package/recce-source/.github/workflows/nightly.yaml +246 -0
- package/recce-source/.github/workflows/release.yaml +196 -0
- package/recce-source/.github/workflows/tests-js.yaml +58 -0
- package/recce-source/.github/workflows/tests-python.yaml +128 -0
- package/recce-source/.pre-commit-config.yaml +26 -0
- package/recce-source/CLAUDE.md +483 -0
- package/recce-source/CODE_OF_CONDUCT.md +128 -0
- package/recce-source/CONTRIBUTING.md +107 -0
- package/recce-source/LICENSE +201 -0
- package/recce-source/Makefile +126 -0
- package/recce-source/README.md +182 -0
- package/recce-source/RECCE_CLOUD.md +81 -0
- package/recce-source/SECURITY.md +25 -0
- package/recce-source/docs/PACKAGING.md +340 -0
- package/recce-source/docs/README.md +1 -0
- package/recce-source/integration_tests/dbt/dbt_project.yml +26 -0
- package/recce-source/integration_tests/dbt/models/customers.sql +69 -0
- package/recce-source/integration_tests/dbt/models/docs.md +14 -0
- package/recce-source/integration_tests/dbt/models/orders.sql +56 -0
- package/recce-source/integration_tests/dbt/models/schema.yml +82 -0
- package/recce-source/integration_tests/dbt/models/staging/schema.yml +31 -0
- package/recce-source/integration_tests/dbt/models/staging/stg_customers.sql +22 -0
- package/recce-source/integration_tests/dbt/models/staging/stg_orders.sql +23 -0
- package/recce-source/integration_tests/dbt/models/staging/stg_payments.sql +25 -0
- package/recce-source/integration_tests/dbt/packages.yml +7 -0
- package/recce-source/integration_tests/dbt/profiles.yml +8 -0
- package/recce-source/integration_tests/dbt/seeds/raw_customers.csv +101 -0
- package/recce-source/integration_tests/dbt/seeds/raw_orders.csv +100 -0
- package/recce-source/integration_tests/dbt/seeds/raw_payments.csv +114 -0
- package/recce-source/integration_tests/dbt/seeds/raw_statuses.csv +5 -0
- package/recce-source/integration_tests/dbt/smoke_test.sh +72 -0
- package/recce-source/integration_tests/dbt/smoke_test_cloud.sh +71 -0
- package/recce-source/integration_tests/sqlmesh/__init__.py +0 -0
- package/recce-source/integration_tests/sqlmesh/audits/assert_item_price_above_zero.sql +9 -0
- package/recce-source/integration_tests/sqlmesh/audits/items.sql +7 -0
- package/recce-source/integration_tests/sqlmesh/audits/order_items.sql +7 -0
- package/recce-source/integration_tests/sqlmesh/config.py +171 -0
- package/recce-source/integration_tests/sqlmesh/helper.py +20 -0
- package/recce-source/integration_tests/sqlmesh/hooks/__init__.py +0 -0
- package/recce-source/integration_tests/sqlmesh/macros/__init__.py +0 -0
- package/recce-source/integration_tests/sqlmesh/macros/macros.py +8 -0
- package/recce-source/integration_tests/sqlmesh/macros/macros.sql +8 -0
- package/recce-source/integration_tests/sqlmesh/macros/utils.py +11 -0
- package/recce-source/integration_tests/sqlmesh/metrics/metrics.sql +25 -0
- package/recce-source/integration_tests/sqlmesh/models/customer_revenue_by_day.sql +41 -0
- package/recce-source/integration_tests/sqlmesh/models/customer_revenue_lifetime.sql +60 -0
- package/recce-source/integration_tests/sqlmesh/models/customers.sql +32 -0
- package/recce-source/integration_tests/sqlmesh/models/items.py +95 -0
- package/recce-source/integration_tests/sqlmesh/models/marketing.sql +15 -0
- package/recce-source/integration_tests/sqlmesh/models/order_items.py +95 -0
- package/recce-source/integration_tests/sqlmesh/models/orders.py +70 -0
- package/recce-source/integration_tests/sqlmesh/models/raw_marketing.py +62 -0
- package/recce-source/integration_tests/sqlmesh/models/top_waiters.sql +23 -0
- package/recce-source/integration_tests/sqlmesh/models/waiter_as_customer_by_day.sql +29 -0
- package/recce-source/integration_tests/sqlmesh/models/waiter_names.sql +10 -0
- package/recce-source/integration_tests/sqlmesh/models/waiter_revenue_by_day.sql +29 -0
- package/recce-source/integration_tests/sqlmesh/models/waiters.py +62 -0
- package/recce-source/integration_tests/sqlmesh/prep_env.sh +16 -0
- package/recce-source/integration_tests/sqlmesh/schema.yaml +5 -0
- package/recce-source/integration_tests/sqlmesh/seeds/waiter_names.csv +11 -0
- package/recce-source/integration_tests/sqlmesh/test_server.sh +29 -0
- package/recce-source/integration_tests/sqlmesh/tests/test_customer_revenue_by_day.yaml +63 -0
- package/recce-source/integration_tests/sqlmesh/tests/test_order_items.yaml +72 -0
- package/recce-source/js/.editorconfig +27 -0
- package/recce-source/js/.env.development +5 -0
- package/recce-source/js/.husky/pre-commit +29 -0
- package/recce-source/js/.nvmrc +1 -0
- package/recce-source/js/README.md +39 -0
- package/recce-source/js/app/(mainComponents)/DisplayModeToggle.tsx +65 -0
- package/recce-source/js/app/(mainComponents)/NavBar.tsx +228 -0
- package/recce-source/js/app/(mainComponents)/RecceVersionBadge.tsx +107 -0
- package/recce-source/js/app/(mainComponents)/TopBar.tsx +252 -0
- package/recce-source/js/app/@lineage/default.tsx +20 -0
- package/recce-source/js/app/@lineage/page.tsx +14 -0
- package/recce-source/js/app/MainLayout.tsx +170 -0
- package/recce-source/js/app/Providers.tsx +49 -0
- package/recce-source/js/app/checks/page.tsx +296 -0
- package/recce-source/js/app/error.tsx +93 -0
- package/recce-source/js/app/favicon.ico +0 -0
- package/recce-source/js/app/global-error.tsx +115 -0
- package/recce-source/js/app/global.css +82 -0
- package/recce-source/js/app/layout.tsx +48 -0
- package/recce-source/js/app/lineage/page.tsx +15 -0
- package/recce-source/js/app/page.tsx +12 -0
- package/recce-source/js/app/query/page.tsx +8 -0
- package/recce-source/js/biome.json +313 -0
- package/recce-source/js/jest.config.js +34 -0
- package/recce-source/js/jest.globals.d.ts +32 -0
- package/recce-source/js/jest.setup.js +91 -0
- package/recce-source/js/next.config.js +16 -0
- package/recce-source/js/package-lock.json +13843 -0
- package/recce-source/js/package.json +123 -0
- package/recce-source/js/pnpm-lock.yaml +9235 -0
- package/recce-source/js/pnpm-workspace.yaml +6 -0
- package/recce-source/js/postcss.config.js +5 -0
- package/recce-source/js/public/auth_callback.html +68 -0
- package/recce-source/js/public/imgs/feedback/thumbs-down.png +0 -0
- package/recce-source/js/public/imgs/feedback/thumbs-up.png +0 -0
- package/recce-source/js/public/imgs/reload-image.svg +4 -0
- package/recce-source/js/public/logo/recce-logo-white.png +0 -0
- package/recce-source/js/src/components/AuthModal/AuthModal.tsx +202 -0
- package/recce-source/js/src/components/app/AvatarDropdown.tsx +159 -0
- package/recce-source/js/src/components/app/EnvInfo.tsx +357 -0
- package/recce-source/js/src/components/app/Filename.tsx +388 -0
- package/recce-source/js/src/components/app/SetupConnectionPopover.tsx +91 -0
- package/recce-source/js/src/components/app/StateExporter.tsx +57 -0
- package/recce-source/js/src/components/app/StateImporter.tsx +198 -0
- package/recce-source/js/src/components/app/StateSharing.tsx +145 -0
- package/recce-source/js/src/components/app/StateSynchronizer.tsx +205 -0
- package/recce-source/js/src/components/charts/HistogramChart.tsx +291 -0
- package/recce-source/js/src/components/charts/SquareIcon.tsx +51 -0
- package/recce-source/js/src/components/charts/TopKSummaryList.tsx +457 -0
- package/recce-source/js/src/components/charts/chartTheme.ts +74 -0
- package/recce-source/js/src/components/check/CheckBreadcrumb.tsx +97 -0
- package/recce-source/js/src/components/check/CheckDescription.tsx +134 -0
- package/recce-source/js/src/components/check/CheckDetail.tsx +797 -0
- package/recce-source/js/src/components/check/CheckEmptyState.tsx +84 -0
- package/recce-source/js/src/components/check/CheckList.tsx +320 -0
- package/recce-source/js/src/components/check/LineageDiffView.tsx +32 -0
- package/recce-source/js/src/components/check/PresetCheckTemplateView.tsx +48 -0
- package/recce-source/js/src/components/check/SchemaDiffView.tsx +290 -0
- package/recce-source/js/src/components/check/check.ts +25 -0
- package/recce-source/js/src/components/check/timeline/CheckTimeline.tsx +163 -0
- package/recce-source/js/src/components/check/timeline/CommentInput.tsx +84 -0
- package/recce-source/js/src/components/check/timeline/TimelineEvent.tsx +468 -0
- package/recce-source/js/src/components/check/timeline/index.ts +12 -0
- package/recce-source/js/src/components/check/utils.ts +12 -0
- package/recce-source/js/src/components/data-grid/ScreenshotDataGrid.tsx +333 -0
- package/recce-source/js/src/components/data-grid/agGridStyles.css +55 -0
- package/recce-source/js/src/components/data-grid/agGridTheme.ts +43 -0
- package/recce-source/js/src/components/editor/CodeEditor.tsx +107 -0
- package/recce-source/js/src/components/editor/DiffEditor.tsx +162 -0
- package/recce-source/js/src/components/editor/index.ts +12 -0
- package/recce-source/js/src/components/errorboundary/ErrorBoundary.tsx +87 -0
- package/recce-source/js/src/components/histogram/HistogramDiffForm.tsx +147 -0
- package/recce-source/js/src/components/histogram/HistogramDiffResultView.tsx +63 -0
- package/recce-source/js/src/components/icons/index.tsx +142 -0
- package/recce-source/js/src/components/lineage/ActionControl.tsx +63 -0
- package/recce-source/js/src/components/lineage/ActionTag.tsx +141 -0
- package/recce-source/js/src/components/lineage/ChangeStatusLegend.tsx +46 -0
- package/recce-source/js/src/components/lineage/ColumnLevelLineageControl.tsx +327 -0
- package/recce-source/js/src/components/lineage/ColumnLevelLineageLegend.tsx +57 -0
- package/recce-source/js/src/components/lineage/GraphColumnNode.tsx +199 -0
- package/recce-source/js/src/components/lineage/GraphEdge.tsx +59 -0
- package/recce-source/js/src/components/lineage/GraphNode.tsx +555 -0
- package/recce-source/js/src/components/lineage/LineagePage.tsx +10 -0
- package/recce-source/js/src/components/lineage/LineageView.tsx +1384 -0
- package/recce-source/js/src/components/lineage/LineageViewContext.tsx +86 -0
- package/recce-source/js/src/components/lineage/LineageViewContextMenu.tsx +637 -0
- package/recce-source/js/src/components/lineage/LineageViewNotification.tsx +64 -0
- package/recce-source/js/src/components/lineage/LineageViewTopBar.tsx +596 -0
- package/recce-source/js/src/components/lineage/NodeSqlView.tsx +136 -0
- package/recce-source/js/src/components/lineage/NodeTag.tsx +278 -0
- package/recce-source/js/src/components/lineage/NodeView.tsx +642 -0
- package/recce-source/js/src/components/lineage/SandboxView.tsx +436 -0
- package/recce-source/js/src/components/lineage/ServerDisconnectedModalContent.tsx +105 -0
- package/recce-source/js/src/components/lineage/SetupConnectionBanner.tsx +52 -0
- package/recce-source/js/src/components/lineage/SingleEnvironmentQueryView.tsx +152 -0
- package/recce-source/js/src/components/lineage/graph.test.ts +31 -0
- package/recce-source/js/src/components/lineage/graph.ts +58 -0
- package/recce-source/js/src/components/lineage/lineage.test.ts +169 -0
- package/recce-source/js/src/components/lineage/lineage.ts +521 -0
- package/recce-source/js/src/components/lineage/styles.css +42 -0
- package/recce-source/js/src/components/lineage/styles.tsx +165 -0
- package/recce-source/js/src/components/lineage/useMultiNodesAction.ts +352 -0
- package/recce-source/js/src/components/lineage/useValueDiffAlertDialog.tsx +108 -0
- package/recce-source/js/src/components/onboarding-guide/Notification.tsx +62 -0
- package/recce-source/js/src/components/profile/ProfileDiffForm.tsx +134 -0
- package/recce-source/js/src/components/profile/ProfileDiffResultView.tsx +245 -0
- package/recce-source/js/src/components/query/ChangedOnlyCheckbox.tsx +29 -0
- package/recce-source/js/src/components/query/DiffText.tsx +120 -0
- package/recce-source/js/src/components/query/QueryDiffResultView.tsx +470 -0
- package/recce-source/js/src/components/query/QueryForm.tsx +80 -0
- package/recce-source/js/src/components/query/QueryPage.tsx +282 -0
- package/recce-source/js/src/components/query/QueryResultView.tsx +180 -0
- package/recce-source/js/src/components/query/SetupConnectionGuide.tsx +57 -0
- package/recce-source/js/src/components/query/SqlEditor.tsx +245 -0
- package/recce-source/js/src/components/query/ToggleSwitch.tsx +84 -0
- package/recce-source/js/src/components/query/styles.css +21 -0
- package/recce-source/js/src/components/routing/DirectUrlAccess.test.tsx +428 -0
- package/recce-source/js/src/components/routing/LineageStatePreservation.test.tsx +311 -0
- package/recce-source/js/src/components/routing/Navigation.test.tsx +256 -0
- package/recce-source/js/src/components/rowcount/RowCountDiffResultView.tsx +109 -0
- package/recce-source/js/src/components/rowcount/delta.ts +11 -0
- package/recce-source/js/src/components/run/RunList.tsx +303 -0
- package/recce-source/js/src/components/run/RunModal.tsx +191 -0
- package/recce-source/js/src/components/run/RunPage.tsx +26 -0
- package/recce-source/js/src/components/run/RunResultPane.tsx +454 -0
- package/recce-source/js/src/components/run/RunStatusAndDate.tsx +106 -0
- package/recce-source/js/src/components/run/RunToolbar.tsx +70 -0
- package/recce-source/js/src/components/run/RunView.tsx +196 -0
- package/recce-source/js/src/components/run/registry.ts +214 -0
- package/recce-source/js/src/components/run/types.ts +14 -0
- package/recce-source/js/src/components/schema/ColumnNameCell.test.tsx +169 -0
- package/recce-source/js/src/components/schema/ColumnNameCell.tsx +198 -0
- package/recce-source/js/src/components/schema/SchemaView.tsx +337 -0
- package/recce-source/js/src/components/schema/schemaDiff.ts +32 -0
- package/recce-source/js/src/components/schema/style.css +134 -0
- package/recce-source/js/src/components/screenshot/ScreenshotBox.tsx +39 -0
- package/recce-source/js/src/components/shared/HistoryToggle.tsx +35 -0
- package/recce-source/js/src/components/split/Split.tsx +40 -0
- package/recce-source/js/src/components/split/styles.css +24 -0
- package/recce-source/js/src/components/summary/ChangeSummary.tsx +264 -0
- package/recce-source/js/src/components/summary/SchemaSummary.tsx +123 -0
- package/recce-source/js/src/components/summary/SummaryView.tsx +29 -0
- package/recce-source/js/src/components/timeout/IdleTimeoutBadge.tsx +48 -0
- package/recce-source/js/src/components/top-k/TopKDiffForm.tsx +58 -0
- package/recce-source/js/src/components/top-k/TopKDiffResultView.tsx +73 -0
- package/recce-source/js/src/components/ui/dataGrid/DataFrameColumnGroupHeader.tsx +228 -0
- package/recce-source/js/src/components/ui/dataGrid/DataFrameColumnHeader.tsx +113 -0
- package/recce-source/js/src/components/ui/dataGrid/defaultRenderCell.tsx +72 -0
- package/recce-source/js/src/components/ui/dataGrid/index.ts +23 -0
- package/recce-source/js/src/components/ui/dataGrid/inlineRenderCell.test.tsx +607 -0
- package/recce-source/js/src/components/ui/dataGrid/inlineRenderCell.tsx +211 -0
- package/recce-source/js/src/components/ui/dataGrid/schemaCells.test.tsx +452 -0
- package/recce-source/js/src/components/ui/dataGrid/schemaCells.tsx +142 -0
- package/recce-source/js/src/components/ui/dataGrid/valueDiffCells.test.tsx +178 -0
- package/recce-source/js/src/components/ui/dataGrid/valueDiffCells.tsx +275 -0
- package/recce-source/js/src/components/ui/markdown/ExternalLinkConfirmDialog.tsx +134 -0
- package/recce-source/js/src/components/ui/markdown/MarkdownContent.tsx +364 -0
- package/recce-source/js/src/components/ui/mui/index.ts +13 -0
- package/recce-source/js/src/components/ui/mui-provider.tsx +67 -0
- package/recce-source/js/src/components/ui/mui-theme.ts +1039 -0
- package/recce-source/js/src/components/ui/mui-utils.ts +113 -0
- package/recce-source/js/src/components/ui/toaster.tsx +288 -0
- package/recce-source/js/src/components/valuediff/ValueDiffDetailResultView.tsx +217 -0
- package/recce-source/js/src/components/valuediff/ValueDiffForm.tsx +246 -0
- package/recce-source/js/src/components/valuediff/ValueDiffResultView.tsx +82 -0
- package/recce-source/js/src/components/valuediff/shared.ts +33 -0
- package/recce-source/js/src/constants/tooltipMessage.ts +3 -0
- package/recce-source/js/src/constants/urls.ts +1 -0
- package/recce-source/js/src/lib/UrlHash.ts +12 -0
- package/recce-source/js/src/lib/api/adhocQuery.ts +70 -0
- package/recce-source/js/src/lib/api/axiosClient.ts +9 -0
- package/recce-source/js/src/lib/api/cacheKeys.ts +13 -0
- package/recce-source/js/src/lib/api/checkEvents.ts +252 -0
- package/recce-source/js/src/lib/api/checks.ts +129 -0
- package/recce-source/js/src/lib/api/cll.ts +53 -0
- package/recce-source/js/src/lib/api/connectToCloud.ts +13 -0
- package/recce-source/js/src/lib/api/flag.ts +37 -0
- package/recce-source/js/src/lib/api/info.ts +198 -0
- package/recce-source/js/src/lib/api/instanceInfo.ts +25 -0
- package/recce-source/js/src/lib/api/keepAlive.ts +108 -0
- package/recce-source/js/src/lib/api/lineagecheck.ts +35 -0
- package/recce-source/js/src/lib/api/localStorageKeys.ts +7 -0
- package/recce-source/js/src/lib/api/models.ts +59 -0
- package/recce-source/js/src/lib/api/profile.ts +65 -0
- package/recce-source/js/src/lib/api/rowcount.ts +19 -0
- package/recce-source/js/src/lib/api/runs.ts +174 -0
- package/recce-source/js/src/lib/api/schemacheck.ts +31 -0
- package/recce-source/js/src/lib/api/select.ts +25 -0
- package/recce-source/js/src/lib/api/sessionStorageKeys.ts +8 -0
- package/recce-source/js/src/lib/api/state.ts +117 -0
- package/recce-source/js/src/lib/api/track.ts +281 -0
- package/recce-source/js/src/lib/api/types.ts +284 -0
- package/recce-source/js/src/lib/api/user.ts +42 -0
- package/recce-source/js/src/lib/api/valuediff.ts +46 -0
- package/recce-source/js/src/lib/api/version.ts +40 -0
- package/recce-source/js/src/lib/const.ts +9 -0
- package/recce-source/js/src/lib/dataGrid/crossFunctionConsistency.test.ts +626 -0
- package/recce-source/js/src/lib/dataGrid/dataGridFactory.test.ts +2140 -0
- package/recce-source/js/src/lib/dataGrid/dataGridFactory.ts +397 -0
- package/recce-source/js/src/lib/dataGrid/generators/rowCountUtils.test.ts +132 -0
- package/recce-source/js/src/lib/dataGrid/generators/rowCountUtils.ts +126 -0
- package/recce-source/js/src/lib/dataGrid/generators/toDataDiffGrid.test.ts +1627 -0
- package/recce-source/js/src/lib/dataGrid/generators/toDataDiffGrid.ts +140 -0
- package/recce-source/js/src/lib/dataGrid/generators/toDataGrid.ts +67 -0
- package/recce-source/js/src/lib/dataGrid/generators/toRowCountDataGrid.test.ts +142 -0
- package/recce-source/js/src/lib/dataGrid/generators/toRowCountDataGrid.ts +71 -0
- package/recce-source/js/src/lib/dataGrid/generators/toRowCountDiffDataGrid.test.ts +258 -0
- package/recce-source/js/src/lib/dataGrid/generators/toRowCountDiffDataGrid.ts +153 -0
- package/recce-source/js/src/lib/dataGrid/generators/toSchemaDataGrid.test.ts +951 -0
- package/recce-source/js/src/lib/dataGrid/generators/toSchemaDataGrid.ts +221 -0
- package/recce-source/js/src/lib/dataGrid/generators/toValueDataGrid.test.ts +395 -0
- package/recce-source/js/src/lib/dataGrid/generators/toValueDataGrid.ts +184 -0
- package/recce-source/js/src/lib/dataGrid/generators/toValueDiffGrid.test.ts +884 -0
- package/recce-source/js/src/lib/dataGrid/generators/toValueDiffGrid.ts +113 -0
- package/recce-source/js/src/lib/dataGrid/index.ts +51 -0
- package/recce-source/js/src/lib/dataGrid/propertyBased.test.ts +858 -0
- package/recce-source/js/src/lib/dataGrid/shared/columnBuilders.test.ts +482 -0
- package/recce-source/js/src/lib/dataGrid/shared/columnBuilders.ts +345 -0
- package/recce-source/js/src/lib/dataGrid/shared/dataTypeEdgeCases.test.ts +698 -0
- package/recce-source/js/src/lib/dataGrid/shared/diffColumnBuilder.test.tsx +820 -0
- package/recce-source/js/src/lib/dataGrid/shared/diffColumnBuilder.tsx +277 -0
- package/recce-source/js/src/lib/dataGrid/shared/gridUtils.test.ts +785 -0
- package/recce-source/js/src/lib/dataGrid/shared/gridUtils.ts +370 -0
- package/recce-source/js/src/lib/dataGrid/shared/index.ts +81 -0
- package/recce-source/js/src/lib/dataGrid/shared/rowBuilders.test.ts +909 -0
- package/recce-source/js/src/lib/dataGrid/shared/rowBuilders.ts +325 -0
- package/recce-source/js/src/lib/dataGrid/shared/simpleColumnBuilder.tsx +240 -0
- package/recce-source/js/src/lib/dataGrid/shared/toDiffColumn.test.tsx +719 -0
- package/recce-source/js/src/lib/dataGrid/shared/toDiffColumn.tsx +231 -0
- package/recce-source/js/src/lib/dataGrid/shared/validation.test.ts +559 -0
- package/recce-source/js/src/lib/dataGrid/shared/validation.ts +367 -0
- package/recce-source/js/src/lib/dataGrid/warehouseNamingConventions.test.ts +1117 -0
- package/recce-source/js/src/lib/formatSelect.ts +50 -0
- package/recce-source/js/src/lib/hooks/ApiConfigContext.tsx +181 -0
- package/recce-source/js/src/lib/hooks/IdleTimeoutContext.tsx +177 -0
- package/recce-source/js/src/lib/hooks/LineageGraphContext.tsx +512 -0
- package/recce-source/js/src/lib/hooks/RecceActionContext.tsx +269 -0
- package/recce-source/js/src/lib/hooks/RecceCheckContext.tsx +33 -0
- package/recce-source/js/src/lib/hooks/RecceContextProvider.tsx +54 -0
- package/recce-source/js/src/lib/hooks/RecceInstanceContext.tsx +129 -0
- package/recce-source/js/src/lib/hooks/RecceQueryContext.tsx +98 -0
- package/recce-source/js/src/lib/hooks/RecceShareStateContext.tsx +59 -0
- package/recce-source/js/src/lib/hooks/ScreenShot.tsx +399 -0
- package/recce-source/js/src/lib/hooks/useAppRouter.test.ts +211 -0
- package/recce-source/js/src/lib/hooks/useAppRouter.ts +200 -0
- package/recce-source/js/src/lib/hooks/useCheckEvents.ts +99 -0
- package/recce-source/js/src/lib/hooks/useCheckToast.tsx +14 -0
- package/recce-source/js/src/lib/hooks/useClipBoardToast.tsx +27 -0
- package/recce-source/js/src/lib/hooks/useCountdownToast.tsx +102 -0
- package/recce-source/js/src/lib/hooks/useFeedbackCollectionToast.tsx +130 -0
- package/recce-source/js/src/lib/hooks/useGuideToast.tsx +45 -0
- package/recce-source/js/src/lib/hooks/useIdleDetection.tsx +185 -0
- package/recce-source/js/src/lib/hooks/useModelColumns.tsx +113 -0
- package/recce-source/js/src/lib/hooks/useRecceInstanceInfo.tsx +13 -0
- package/recce-source/js/src/lib/hooks/useRecceServerFlag.tsx +13 -0
- package/recce-source/js/src/lib/hooks/useRun.tsx +89 -0
- package/recce-source/js/src/lib/hooks/useThemeColors.ts +115 -0
- package/recce-source/js/src/lib/mergeKeys.test.ts +89 -0
- package/recce-source/js/src/lib/mergeKeys.ts +86 -0
- package/recce-source/js/src/lib/result/ResultErrorFallback.tsx +9 -0
- package/recce-source/js/src/lib/utils/formatTime.ts +84 -0
- package/recce-source/js/src/lib/utils/urls.ts +16 -0
- package/recce-source/js/src/utils/DropdownValuesInput.tsx +297 -0
- package/recce-source/js/src/utils/formatters.tsx +237 -0
- package/recce-source/js/src/utils/transforms.ts +81 -0
- package/recce-source/js/tsconfig.json +47 -0
- package/recce-source/macros/README.md +8 -0
- package/recce-source/macros/recce_athena.sql +73 -0
- package/recce-source/pyproject.toml +109 -0
- package/recce-source/recce/VERSION +1 -0
- package/recce-source/recce/__init__.py +84 -0
- package/recce-source/recce/adapter/__init__.py +0 -0
- package/recce-source/recce/adapter/base.py +109 -0
- package/recce-source/recce/adapter/dbt_adapter/__init__.py +1699 -0
- package/recce-source/recce/adapter/dbt_adapter/dbt_version.py +42 -0
- package/recce-source/recce/adapter/sqlmesh_adapter.py +141 -0
- package/recce-source/recce/apis/__init__.py +0 -0
- package/recce-source/recce/apis/check_api.py +203 -0
- package/recce-source/recce/apis/check_events_api.py +353 -0
- package/recce-source/recce/apis/check_func.py +130 -0
- package/recce-source/recce/apis/run_api.py +130 -0
- package/recce-source/recce/apis/run_func.py +258 -0
- package/recce-source/recce/artifact.py +266 -0
- package/recce-source/recce/cli.py +1846 -0
- package/recce-source/recce/config.py +127 -0
- package/recce-source/recce/connect_to_cloud.py +138 -0
- package/recce-source/recce/core.py +334 -0
- package/recce-source/recce/diff.py +26 -0
- package/recce-source/recce/event/CONFIG +1 -0
- package/recce-source/recce/event/SENTRY_DNS +1 -0
- package/recce-source/recce/event/__init__.py +304 -0
- package/recce-source/recce/event/collector.py +184 -0
- package/recce-source/recce/event/track.py +158 -0
- package/recce-source/recce/exceptions.py +21 -0
- package/recce-source/recce/git.py +77 -0
- package/recce-source/recce/github.py +222 -0
- package/recce-source/recce/mcp_server.py +861 -0
- package/recce-source/recce/models/__init__.py +6 -0
- package/recce-source/recce/models/check.py +473 -0
- package/recce-source/recce/models/run.py +46 -0
- package/recce-source/recce/models/types.py +218 -0
- package/recce-source/recce/pull_request.py +124 -0
- package/recce-source/recce/run.py +390 -0
- package/recce-source/recce/server.py +877 -0
- package/recce-source/recce/state/__init__.py +31 -0
- package/recce-source/recce/state/cloud.py +644 -0
- package/recce-source/recce/state/const.py +26 -0
- package/recce-source/recce/state/local.py +56 -0
- package/recce-source/recce/state/state.py +119 -0
- package/recce-source/recce/state/state_loader.py +174 -0
- package/recce-source/recce/summary.py +575 -0
- package/recce-source/recce/tasks/__init__.py +23 -0
- package/recce-source/recce/tasks/core.py +134 -0
- package/recce-source/recce/tasks/dataframe.py +170 -0
- package/recce-source/recce/tasks/histogram.py +433 -0
- package/recce-source/recce/tasks/lineage.py +19 -0
- package/recce-source/recce/tasks/profile.py +298 -0
- package/recce-source/recce/tasks/query.py +450 -0
- package/recce-source/recce/tasks/rowcount.py +277 -0
- package/recce-source/recce/tasks/schema.py +65 -0
- package/recce-source/recce/tasks/top_k.py +172 -0
- package/recce-source/recce/tasks/utils.py +147 -0
- package/recce-source/recce/tasks/valuediff.py +497 -0
- package/recce-source/recce/util/__init__.py +4 -0
- package/recce-source/recce/util/api_token.py +80 -0
- package/recce-source/recce/util/breaking.py +330 -0
- package/recce-source/recce/util/cache.py +25 -0
- package/recce-source/recce/util/cll.py +355 -0
- package/recce-source/recce/util/cloud/__init__.py +15 -0
- package/recce-source/recce/util/cloud/base.py +115 -0
- package/recce-source/recce/util/cloud/check_events.py +190 -0
- package/recce-source/recce/util/cloud/checks.py +242 -0
- package/recce-source/recce/util/io.py +120 -0
- package/recce-source/recce/util/lineage.py +83 -0
- package/recce-source/recce/util/logger.py +25 -0
- package/recce-source/recce/util/onboarding_state.py +45 -0
- package/recce-source/recce/util/perf_tracking.py +85 -0
- package/recce-source/recce/util/pydantic_model.py +22 -0
- package/recce-source/recce/util/recce_cloud.py +454 -0
- package/recce-source/recce/util/singleton.py +18 -0
- package/recce-source/recce/util/startup_perf.py +121 -0
- package/recce-source/recce/yaml/__init__.py +58 -0
- package/recce-source/recce_cloud/README.md +780 -0
- package/recce-source/recce_cloud/VERSION +1 -0
- package/recce-source/recce_cloud/__init__.py +24 -0
- package/recce-source/recce_cloud/api/__init__.py +17 -0
- package/recce-source/recce_cloud/api/base.py +132 -0
- package/recce-source/recce_cloud/api/client.py +186 -0
- package/recce-source/recce_cloud/api/exceptions.py +26 -0
- package/recce-source/recce_cloud/api/factory.py +63 -0
- package/recce-source/recce_cloud/api/github.py +106 -0
- package/recce-source/recce_cloud/api/gitlab.py +111 -0
- package/recce-source/recce_cloud/artifact.py +57 -0
- package/recce-source/recce_cloud/ci_providers/__init__.py +9 -0
- package/recce-source/recce_cloud/ci_providers/base.py +82 -0
- package/recce-source/recce_cloud/ci_providers/detector.py +147 -0
- package/recce-source/recce_cloud/ci_providers/github_actions.py +136 -0
- package/recce-source/recce_cloud/ci_providers/gitlab_ci.py +130 -0
- package/recce-source/recce_cloud/cli.py +434 -0
- package/recce-source/recce_cloud/download.py +230 -0
- package/recce-source/recce_cloud/hatch_build.py +20 -0
- package/recce-source/recce_cloud/pyproject.toml +49 -0
- package/recce-source/recce_cloud/upload.py +214 -0
- package/recce-source/test.py +0 -0
- package/recce-source/tests/__init__.py +0 -0
- package/recce-source/tests/adapter/__init__.py +0 -0
- package/recce-source/tests/adapter/dbt_adapter/__init__.py +0 -0
- package/recce-source/tests/adapter/dbt_adapter/conftest.py +17 -0
- package/recce-source/tests/adapter/dbt_adapter/dbt_test_helper.py +298 -0
- package/recce-source/tests/adapter/dbt_adapter/test_dbt_adapter.py +25 -0
- package/recce-source/tests/adapter/dbt_adapter/test_dbt_cll.py +717 -0
- package/recce-source/tests/adapter/dbt_adapter/test_proj/dbt_project.yml +4 -0
- package/recce-source/tests/adapter/dbt_adapter/test_proj/manifest.json +1 -0
- package/recce-source/tests/adapter/dbt_adapter/test_proj/package-lock.yml +8 -0
- package/recce-source/tests/adapter/dbt_adapter/test_proj/packages.yml +7 -0
- package/recce-source/tests/adapter/dbt_adapter/test_proj/profiles.yml +6 -0
- package/recce-source/tests/adapter/dbt_adapter/test_selector.py +205 -0
- package/recce-source/tests/apis/__init__.py +0 -0
- package/recce-source/tests/apis/row_count_diff.json +59 -0
- package/recce-source/tests/apis/test_check_events_api.py +615 -0
- package/recce-source/tests/apis/test_run_func.py +433 -0
- package/recce-source/tests/catalog.json +527 -0
- package/recce-source/tests/data/manifest/base/catalog.json +1 -0
- package/recce-source/tests/data/manifest/base/manifest.json +1 -0
- package/recce-source/tests/data/manifest/pr2/catalog.json +1 -0
- package/recce-source/tests/data/manifest/pr2/manifest.json +1 -0
- package/recce-source/tests/manifest.json +10655 -0
- package/recce-source/tests/models/__init__.py +0 -0
- package/recce-source/tests/models/test_check.py +731 -0
- package/recce-source/tests/models/test_run_models.py +295 -0
- package/recce-source/tests/recce_cloud/__init__.py +0 -0
- package/recce-source/tests/recce_cloud/test_ci_providers.py +351 -0
- package/recce-source/tests/recce_cloud/test_cli.py +735 -0
- package/recce-source/tests/recce_cloud/test_client.py +379 -0
- package/recce-source/tests/recce_cloud/test_platform_clients.py +483 -0
- package/recce-source/tests/recce_state.json +1 -0
- package/recce-source/tests/state/test_cloud.py +719 -0
- package/recce-source/tests/state/test_local.py +164 -0
- package/recce-source/tests/state/test_state_loader.py +211 -0
- package/recce-source/tests/tasks/__init__.py +0 -0
- package/recce-source/tests/tasks/conftest.py +4 -0
- package/recce-source/tests/tasks/test_histogram.py +129 -0
- package/recce-source/tests/tasks/test_lineage.py +55 -0
- package/recce-source/tests/tasks/test_preset_checks.py +64 -0
- package/recce-source/tests/tasks/test_profile.py +397 -0
- package/recce-source/tests/tasks/test_query.py +528 -0
- package/recce-source/tests/tasks/test_row_count.py +133 -0
- package/recce-source/tests/tasks/test_schema.py +122 -0
- package/recce-source/tests/tasks/test_top_k.py +77 -0
- package/recce-source/tests/tasks/test_utils.py +439 -0
- package/recce-source/tests/tasks/test_valuediff.py +361 -0
- package/recce-source/tests/test_cli.py +236 -0
- package/recce-source/tests/test_cli_mcp_optional.py +45 -0
- package/recce-source/tests/test_cloud_listing_cli.py +324 -0
- package/recce-source/tests/test_config.py +43 -0
- package/recce-source/tests/test_connect_to_cloud.py +82 -0
- package/recce-source/tests/test_core.py +174 -0
- package/recce-source/tests/test_dbt.py +36 -0
- package/recce-source/tests/test_mcp_server.py +505 -0
- package/recce-source/tests/test_pull_request.py +130 -0
- package/recce-source/tests/test_server.py +202 -0
- package/recce-source/tests/test_server_lifespan.py +138 -0
- package/recce-source/tests/test_summary.py +73 -0
- package/recce-source/tests/util/__init__.py +0 -0
- package/recce-source/tests/util/cloud/__init__.py +0 -0
- package/recce-source/tests/util/cloud/test_check_events.py +255 -0
- package/recce-source/tests/util/cloud/test_checks.py +204 -0
- package/recce-source/tests/util/test_api_token.py +119 -0
- package/recce-source/tests/util/test_breaking.py +1427 -0
- package/recce-source/tests/util/test_cll.py +706 -0
- package/recce-source/tests/util/test_lineage.py +122 -0
- package/recce-source/tests/util/test_onboarding_state.py +84 -0
- package/recce-source/tests/util/test_recce_cloud.py +231 -0
- package/recce-source/tox.ini +40 -0
- package/recce-source/uv.lock +3928 -0
- package/src/api/index.ts +32 -0
- package/src/components/index.ts +154 -0
- package/src/global.d.ts +14 -0
- package/src/hooks/index.ts +56 -0
- package/src/index.ts +17 -0
- package/src/lib/hooks/RouteConfigContext.ts +139 -0
- package/src/lib/hooks/useAppRouter.ts +240 -0
- package/src/mui-augmentation.d.ts +139 -0
- package/src/theme/index.ts +13 -0
- package/src/theme.ts +23 -0
- package/src/types/index.ts +23 -0
- package/dist/index-Bv5R8iLo.d.mts.map +0 -1
- package/dist/index-CUtFlKOo.d.ts.map +0 -1
- package/dist/state-CELzQ0tM.mjs.map +0 -1
- package/dist/state-CemiRRon.js.map +0 -1
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
"""Tests for recce/apis/run_func.py
|
|
2
|
+
|
|
3
|
+
This module tests the run function API, specifically:
|
|
4
|
+
1. materialize_run_results() - aggregates run results by node
|
|
5
|
+
2. Params propagation - ensures updated task.params flow back to run.params
|
|
6
|
+
3. Params serialization - handles Pydantic v1/v2 models and plain dicts
|
|
7
|
+
|
|
8
|
+
The params propagation is critical for warehouse-resilient naming:
|
|
9
|
+
after task execution, normalized primary_keys must be reflected in run.params.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import asyncio
|
|
13
|
+
import os
|
|
14
|
+
from unittest.mock import MagicMock, patch
|
|
15
|
+
from uuid import UUID
|
|
16
|
+
|
|
17
|
+
import pytest
|
|
18
|
+
from pydantic import BaseModel
|
|
19
|
+
|
|
20
|
+
from recce.apis.run_func import materialize_run_results
|
|
21
|
+
from recce.state import RecceState
|
|
22
|
+
|
|
23
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# =============================================================================
|
|
27
|
+
# Existing Test: materialize_run_results
|
|
28
|
+
# =============================================================================
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_materialize_run_results():
|
|
32
|
+
"""Test materialize_run_results aggregates run results correctly."""
|
|
33
|
+
path = os.path.join(os.path.join(current_dir, "row_count_diff.json"))
|
|
34
|
+
state = RecceState.from_file(path)
|
|
35
|
+
result = materialize_run_results(state.runs)
|
|
36
|
+
|
|
37
|
+
node_result = result["customers"]["row_count_diff"]
|
|
38
|
+
assert node_result["run_id"] == UUID("92f31d63-0758-46af-a674-0e969208ec96")
|
|
39
|
+
assert node_result["result"]["base"] == 1856
|
|
40
|
+
assert node_result["result"]["curr"] == 1856
|
|
41
|
+
|
|
42
|
+
result = materialize_run_results(state.runs, nodes=["xyz"])
|
|
43
|
+
assert result == {}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# =============================================================================
|
|
47
|
+
# Tests: Params Merge Logic (update_run_result behavior)
|
|
48
|
+
# =============================================================================
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class TestUpdateRunResultBehavior:
|
|
52
|
+
"""Tests for the params merge behavior in update_run_result.
|
|
53
|
+
|
|
54
|
+
Since update_run_result is a nested function, we test the behavior
|
|
55
|
+
by verifying the merge logic that would occur.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
def test_params_merge_updates_existing_params(self):
|
|
59
|
+
"""Updated params should be merged into run.params."""
|
|
60
|
+
# Simulate run.params before task execution
|
|
61
|
+
original_params = {"model": "customers", "primary_key": ["customer_id"]}
|
|
62
|
+
|
|
63
|
+
# Simulate updated params after task execution (PK normalized to UPPERCASE)
|
|
64
|
+
updated_params = {"model": "customers", "primary_key": ["CUSTOMER_ID"]}
|
|
65
|
+
|
|
66
|
+
# Simulate the merge behavior from update_run_result
|
|
67
|
+
original_params.update(updated_params)
|
|
68
|
+
|
|
69
|
+
assert original_params["primary_key"] == ["CUSTOMER_ID"]
|
|
70
|
+
assert original_params["model"] == "customers"
|
|
71
|
+
|
|
72
|
+
def test_params_merge_preserves_fields_not_in_updated(self):
|
|
73
|
+
"""Fields not in updated_params should be preserved."""
|
|
74
|
+
original_params = {
|
|
75
|
+
"model": "customers",
|
|
76
|
+
"primary_key": ["customer_id"],
|
|
77
|
+
"columns": ["name", "age"], # Not in updated_params
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# Task only updates primary_key
|
|
81
|
+
updated_params = {"model": "customers", "primary_key": ["CUSTOMER_ID"]}
|
|
82
|
+
|
|
83
|
+
original_params.update(updated_params)
|
|
84
|
+
|
|
85
|
+
assert original_params["columns"] == ["name", "age"]
|
|
86
|
+
assert original_params["primary_key"] == ["CUSTOMER_ID"]
|
|
87
|
+
|
|
88
|
+
def test_params_merge_handles_none_updated_params(self):
|
|
89
|
+
"""When updated_params is None, original params should be unchanged."""
|
|
90
|
+
original_params = {"model": "customers", "primary_key": ["customer_id"]}
|
|
91
|
+
original_copy = original_params.copy()
|
|
92
|
+
|
|
93
|
+
updated_params = None
|
|
94
|
+
|
|
95
|
+
# Simulate the conditional merge from update_run_result
|
|
96
|
+
if updated_params is not None:
|
|
97
|
+
original_params.update(updated_params)
|
|
98
|
+
|
|
99
|
+
assert original_params == original_copy
|
|
100
|
+
|
|
101
|
+
def test_params_merge_adds_new_fields(self):
|
|
102
|
+
"""New fields in updated_params should be added to run.params."""
|
|
103
|
+
original_params = {"model": "customers"}
|
|
104
|
+
|
|
105
|
+
updated_params = {
|
|
106
|
+
"model": "customers",
|
|
107
|
+
"primary_key": ["CUSTOMER_ID"], # Added by task
|
|
108
|
+
"in_a": "in_a", # Normalized by task
|
|
109
|
+
"in_b": "in_b",
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
original_params.update(updated_params)
|
|
113
|
+
|
|
114
|
+
assert original_params["primary_key"] == ["CUSTOMER_ID"]
|
|
115
|
+
assert original_params["in_a"] == "in_a"
|
|
116
|
+
assert original_params["in_b"] == "in_b"
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# =============================================================================
|
|
120
|
+
# Tests: Params Serialization Logic (fn() behavior)
|
|
121
|
+
# =============================================================================
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class TestParamsSerializationBehavior:
|
|
125
|
+
"""Tests for params serialization in the fn() closure.
|
|
126
|
+
|
|
127
|
+
The fn() closure extracts task.params after execution using:
|
|
128
|
+
1. model_dump() for Pydantic v2
|
|
129
|
+
2. dict() for Pydantic v1
|
|
130
|
+
3. Direct pass-through for plain dicts
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
def test_extracts_pydantic_v2_params(self):
|
|
134
|
+
"""Pydantic v2 models should use model_dump()."""
|
|
135
|
+
|
|
136
|
+
class PydanticV2Params(BaseModel):
|
|
137
|
+
model: str
|
|
138
|
+
primary_key: list
|
|
139
|
+
|
|
140
|
+
params = PydanticV2Params(model="customers", primary_key=["CUSTOMER_ID"])
|
|
141
|
+
|
|
142
|
+
# Simulate the extraction logic from fn()
|
|
143
|
+
if hasattr(params, "model_dump"):
|
|
144
|
+
extracted = params.model_dump()
|
|
145
|
+
elif hasattr(params, "dict"):
|
|
146
|
+
extracted = params.dict()
|
|
147
|
+
else:
|
|
148
|
+
extracted = params
|
|
149
|
+
|
|
150
|
+
assert extracted == {"model": "customers", "primary_key": ["CUSTOMER_ID"]}
|
|
151
|
+
assert isinstance(extracted, dict)
|
|
152
|
+
|
|
153
|
+
def test_extracts_pydantic_v1_params(self):
|
|
154
|
+
"""Pydantic v1 models should use dict() method."""
|
|
155
|
+
|
|
156
|
+
# Simulate a Pydantic v1-style object (has dict() but not model_dump())
|
|
157
|
+
class PydanticV1Params:
|
|
158
|
+
def __init__(self):
|
|
159
|
+
self.model = "customers"
|
|
160
|
+
self.primary_key = ["CUSTOMER_ID"]
|
|
161
|
+
|
|
162
|
+
def dict(self):
|
|
163
|
+
return {"model": self.model, "primary_key": self.primary_key}
|
|
164
|
+
|
|
165
|
+
params = PydanticV1Params()
|
|
166
|
+
|
|
167
|
+
# Simulate the extraction logic from fn()
|
|
168
|
+
if hasattr(params, "model_dump"):
|
|
169
|
+
extracted = params.model_dump()
|
|
170
|
+
elif hasattr(params, "dict"):
|
|
171
|
+
extracted = params.dict()
|
|
172
|
+
else:
|
|
173
|
+
extracted = params
|
|
174
|
+
|
|
175
|
+
assert extracted == {"model": "customers", "primary_key": ["CUSTOMER_ID"]}
|
|
176
|
+
|
|
177
|
+
def test_extracts_plain_dict_params(self):
|
|
178
|
+
"""Plain dict params should pass through directly."""
|
|
179
|
+
params = {"model": "customers", "primary_key": ["CUSTOMER_ID"]}
|
|
180
|
+
|
|
181
|
+
# Simulate the extraction logic from fn()
|
|
182
|
+
if hasattr(params, "model_dump"):
|
|
183
|
+
extracted = params.model_dump()
|
|
184
|
+
elif hasattr(params, "dict"):
|
|
185
|
+
extracted = params.dict()
|
|
186
|
+
elif isinstance(params, dict):
|
|
187
|
+
extracted = params
|
|
188
|
+
else:
|
|
189
|
+
extracted = None
|
|
190
|
+
|
|
191
|
+
assert extracted == {"model": "customers", "primary_key": ["CUSTOMER_ID"]}
|
|
192
|
+
|
|
193
|
+
def test_handles_serialization_exception(self):
|
|
194
|
+
"""Serialization exceptions should be caught and logged."""
|
|
195
|
+
|
|
196
|
+
class BrokenParams:
|
|
197
|
+
def model_dump(self):
|
|
198
|
+
raise RuntimeError("Serialization failed")
|
|
199
|
+
|
|
200
|
+
params = BrokenParams()
|
|
201
|
+
updated_params = None
|
|
202
|
+
|
|
203
|
+
# Simulate the try/catch from fn()
|
|
204
|
+
try:
|
|
205
|
+
if hasattr(params, "model_dump"):
|
|
206
|
+
updated_params = params.model_dump()
|
|
207
|
+
elif hasattr(params, "dict"):
|
|
208
|
+
updated_params = params.dict()
|
|
209
|
+
elif isinstance(params, dict):
|
|
210
|
+
updated_params = params
|
|
211
|
+
except Exception:
|
|
212
|
+
updated_params = None
|
|
213
|
+
|
|
214
|
+
assert updated_params is None
|
|
215
|
+
|
|
216
|
+
def test_handles_none_params(self):
|
|
217
|
+
"""None task.params should result in None updated_params."""
|
|
218
|
+
params = None
|
|
219
|
+
updated_params = None
|
|
220
|
+
|
|
221
|
+
# Simulate the conditional check from fn()
|
|
222
|
+
if params is not None:
|
|
223
|
+
if hasattr(params, "model_dump"):
|
|
224
|
+
updated_params = params.model_dump()
|
|
225
|
+
elif hasattr(params, "dict"):
|
|
226
|
+
updated_params = params.dict()
|
|
227
|
+
elif isinstance(params, dict):
|
|
228
|
+
updated_params = params
|
|
229
|
+
|
|
230
|
+
assert updated_params is None
|
|
231
|
+
|
|
232
|
+
def test_logs_warning_for_unknown_type(self):
|
|
233
|
+
"""Unknown params types should trigger a warning log."""
|
|
234
|
+
|
|
235
|
+
class UnknownParams:
|
|
236
|
+
"""A params object without model_dump(), dict(), or being a dict."""
|
|
237
|
+
|
|
238
|
+
pass
|
|
239
|
+
|
|
240
|
+
params = UnknownParams()
|
|
241
|
+
updated_params = "SENTINEL" # Use sentinel to detect if branch was taken
|
|
242
|
+
warning_logged = False
|
|
243
|
+
|
|
244
|
+
# Simulate the extraction logic from fn()
|
|
245
|
+
if hasattr(params, "model_dump"):
|
|
246
|
+
updated_params = params.model_dump()
|
|
247
|
+
elif hasattr(params, "dict"):
|
|
248
|
+
updated_params = params.dict()
|
|
249
|
+
elif isinstance(params, dict):
|
|
250
|
+
updated_params = params
|
|
251
|
+
else:
|
|
252
|
+
# This is the warning branch
|
|
253
|
+
warning_logged = True
|
|
254
|
+
updated_params = None
|
|
255
|
+
|
|
256
|
+
assert warning_logged is True
|
|
257
|
+
assert updated_params is None
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
# =============================================================================
|
|
261
|
+
# Integration Tests: submit_run with Mocked Task
|
|
262
|
+
# =============================================================================
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
class TestSubmitRunParamsPropagation:
|
|
266
|
+
"""Integration tests for params propagation through submit_run.
|
|
267
|
+
|
|
268
|
+
These tests verify that when a task normalizes its params during execution,
|
|
269
|
+
those changes are propagated back to the run object.
|
|
270
|
+
"""
|
|
271
|
+
|
|
272
|
+
@pytest.fixture
|
|
273
|
+
def mock_context(self):
|
|
274
|
+
"""Create a mock RecceContext for testing."""
|
|
275
|
+
with (
|
|
276
|
+
patch("recce.apis.run_func.default_context") as mock_run_func_ctx,
|
|
277
|
+
patch("recce.core.default_context") as mock_core_ctx,
|
|
278
|
+
):
|
|
279
|
+
context = MagicMock()
|
|
280
|
+
context.adapter_type = "dbt"
|
|
281
|
+
context.review_mode = False
|
|
282
|
+
context.runs = []
|
|
283
|
+
# Both patches should return the same mock context
|
|
284
|
+
mock_run_func_ctx.return_value = context
|
|
285
|
+
mock_core_ctx.return_value = context
|
|
286
|
+
yield context
|
|
287
|
+
|
|
288
|
+
@pytest.fixture
|
|
289
|
+
def mock_task_class(self):
|
|
290
|
+
"""Create a mock task class that normalizes params."""
|
|
291
|
+
|
|
292
|
+
class MockTask:
|
|
293
|
+
def __init__(self, params):
|
|
294
|
+
# Simulate Pydantic model
|
|
295
|
+
self.params = MagicMock()
|
|
296
|
+
self.params.model_dump = MagicMock(
|
|
297
|
+
return_value={
|
|
298
|
+
**params,
|
|
299
|
+
# Simulate normalization: lowercase -> UPPERCASE
|
|
300
|
+
"primary_key": [pk.upper() for pk in params.get("primary_key", [])],
|
|
301
|
+
}
|
|
302
|
+
)
|
|
303
|
+
self.is_cancelled = False
|
|
304
|
+
self._progress_listener = None
|
|
305
|
+
|
|
306
|
+
@property
|
|
307
|
+
def progress_listener(self):
|
|
308
|
+
return self._progress_listener
|
|
309
|
+
|
|
310
|
+
@progress_listener.setter
|
|
311
|
+
def progress_listener(self, value):
|
|
312
|
+
self._progress_listener = value
|
|
313
|
+
|
|
314
|
+
def execute(self):
|
|
315
|
+
return {"diff": {"columns": [], "data": []}}
|
|
316
|
+
|
|
317
|
+
def cancel(self):
|
|
318
|
+
self.is_cancelled = True
|
|
319
|
+
|
|
320
|
+
return MockTask
|
|
321
|
+
|
|
322
|
+
@pytest.mark.asyncio
|
|
323
|
+
async def test_normalized_params_propagate_to_run(self, mock_context, mock_task_class):
|
|
324
|
+
"""Test that normalized params from task execution flow to run.params."""
|
|
325
|
+
from recce.apis.run_func import submit_run
|
|
326
|
+
|
|
327
|
+
# Register the mock task
|
|
328
|
+
with patch("recce.apis.run_func.create_task") as mock_create_task:
|
|
329
|
+
mock_task = mock_task_class({"model": "customers", "primary_key": ["customer_id"]})
|
|
330
|
+
mock_create_task.return_value = mock_task
|
|
331
|
+
|
|
332
|
+
# Get the event loop
|
|
333
|
+
asyncio.get_event_loop()
|
|
334
|
+
|
|
335
|
+
# Submit the run
|
|
336
|
+
run, future = submit_run(
|
|
337
|
+
type="value_diff",
|
|
338
|
+
params={"model": "customers", "primary_key": ["customer_id"]},
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
# Wait for the task to complete
|
|
342
|
+
await asyncio.wrap_future(future)
|
|
343
|
+
|
|
344
|
+
# Verify params were normalized
|
|
345
|
+
assert run.params["primary_key"] == ["CUSTOMER_ID"]
|
|
346
|
+
|
|
347
|
+
@pytest.mark.asyncio
|
|
348
|
+
async def test_run_params_unchanged_when_task_has_no_params(self, mock_context):
|
|
349
|
+
"""Test that run.params is unchanged when task.params is None."""
|
|
350
|
+
from recce.apis.run_func import submit_run
|
|
351
|
+
|
|
352
|
+
class TaskWithNoParams:
|
|
353
|
+
def __init__(self, params):
|
|
354
|
+
self.params = None
|
|
355
|
+
self.is_cancelled = False
|
|
356
|
+
self._progress_listener = None
|
|
357
|
+
|
|
358
|
+
@property
|
|
359
|
+
def progress_listener(self):
|
|
360
|
+
return self._progress_listener
|
|
361
|
+
|
|
362
|
+
@progress_listener.setter
|
|
363
|
+
def progress_listener(self, value):
|
|
364
|
+
self._progress_listener = value
|
|
365
|
+
|
|
366
|
+
def execute(self):
|
|
367
|
+
return {"result": "success"}
|
|
368
|
+
|
|
369
|
+
def cancel(self):
|
|
370
|
+
self.is_cancelled = True
|
|
371
|
+
|
|
372
|
+
with patch("recce.apis.run_func.create_task") as mock_create_task:
|
|
373
|
+
mock_create_task.return_value = TaskWithNoParams({})
|
|
374
|
+
|
|
375
|
+
original_params = {"model": "customers", "primary_key": ["customer_id"]}
|
|
376
|
+
run, future = submit_run(type="value_diff", params=original_params.copy())
|
|
377
|
+
|
|
378
|
+
await asyncio.wrap_future(future)
|
|
379
|
+
|
|
380
|
+
# Params should be unchanged since task.params was None
|
|
381
|
+
assert run.params == original_params
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
# =============================================================================
|
|
385
|
+
# Edge Case Tests
|
|
386
|
+
# =============================================================================
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
class TestEdgeCases:
|
|
390
|
+
"""Edge case tests for run_func behavior."""
|
|
391
|
+
|
|
392
|
+
def test_empty_params_dict_is_valid(self):
|
|
393
|
+
"""Empty dict params should be handled gracefully."""
|
|
394
|
+
params = {}
|
|
395
|
+
|
|
396
|
+
if hasattr(params, "model_dump"):
|
|
397
|
+
extracted = params.model_dump()
|
|
398
|
+
elif hasattr(params, "dict"):
|
|
399
|
+
extracted = params.dict()
|
|
400
|
+
elif isinstance(params, dict):
|
|
401
|
+
extracted = params
|
|
402
|
+
else:
|
|
403
|
+
extracted = None
|
|
404
|
+
|
|
405
|
+
assert extracted == {}
|
|
406
|
+
|
|
407
|
+
def test_params_with_none_values_preserved(self):
|
|
408
|
+
"""Params containing None values should be preserved."""
|
|
409
|
+
params = {"model": "customers", "primary_key": None, "columns": None}
|
|
410
|
+
|
|
411
|
+
original = {"model": "customers"}
|
|
412
|
+
original.update(params)
|
|
413
|
+
|
|
414
|
+
assert original["primary_key"] is None
|
|
415
|
+
assert original["columns"] is None
|
|
416
|
+
|
|
417
|
+
def test_nested_params_are_merged(self):
|
|
418
|
+
"""Nested dict structures should be merged (shallow merge)."""
|
|
419
|
+
original = {
|
|
420
|
+
"model": "customers",
|
|
421
|
+
"options": {"limit": 100, "offset": 0},
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
updated = {
|
|
425
|
+
"model": "customers",
|
|
426
|
+
"options": {"limit": 50}, # Replaces entire options dict
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
original.update(updated)
|
|
430
|
+
|
|
431
|
+
# Note: dict.update() does shallow merge, so options is replaced entirely
|
|
432
|
+
assert original["options"] == {"limit": 50}
|
|
433
|
+
assert "offset" not in original["options"]
|