@marimo-team/islands 0.16.1 → 0.16.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/dist/{ConnectedDataExplorerComponent-DyqLQGPc.js → ConnectedDataExplorerComponent-CareOso9.js} +2 -2
  2. package/dist/{ImageComparisonComponent-CQDGJfUA.js → ImageComparisonComponent-I_Z738Uj.js} +1 -1
  3. package/dist/{_baseUniq-B2Nna6Kt.js → _baseUniq-D-Kb4EU4.js} +1 -1
  4. package/dist/{any-language-editor-D-wq0tOG.js → any-language-editor-BRWmYor8.js} +1 -1
  5. package/dist/{architectureDiagram-W76B3OCA-C6tdnMBf.js → architectureDiagram-W76B3OCA-bZJcJYGH.js} +4 -4
  6. package/dist/assets/{worker-B0C57BK8.js → worker-DMlIUTIq.js} +18 -17
  7. package/dist/{blockDiagram-QIGZ2CNN-IagL8LCN.js → blockDiagram-QIGZ2CNN-DyXjO8fR.js} +5 -5
  8. package/dist/{c4Diagram-FPNF74CW-D3_lIWUP.js → c4Diagram-FPNF74CW-Bfs9ui2r.js} +2 -2
  9. package/dist/{channel-DCJI_DKk.js → channel-CMup9X3Z.js} +1 -1
  10. package/dist/{chunk-4BX2VUAB-B2DrODwN.js → chunk-4BX2VUAB-CW-ni6M_.js} +1 -1
  11. package/dist/{chunk-55IACEB6-BUWDsQ-t.js → chunk-55IACEB6-Bj-Indya.js} +1 -1
  12. package/dist/{chunk-FMBD7UC4-BExPNFv1.js → chunk-FMBD7UC4-9IC8qSSk.js} +1 -1
  13. package/dist/{chunk-K7UQS3LO-Cixi-Yko.js → chunk-K7UQS3LO-aapkEuWN.js} +4 -4
  14. package/dist/{chunk-QN33PNHL-B83MtvER.js → chunk-QN33PNHL-Bo5dJ5T5.js} +1 -1
  15. package/dist/{chunk-QZHKN3VN-CXvbu85X.js → chunk-QZHKN3VN-BkMzjJYY.js} +1 -1
  16. package/dist/{chunk-TVAH2DTR-CpiumCHg.js → chunk-TVAH2DTR-Wqy_C_Rn.js} +3 -3
  17. package/dist/{chunk-TZMSLE5B-DIzaZjcI.js → chunk-TZMSLE5B-DjBmEAUz.js} +1 -1
  18. package/dist/{classDiagram-v2-RKCZMP56-DyN5HPdk.js → classDiagram-KNZD7YFC-DUsaN1O4.js} +2 -2
  19. package/dist/{classDiagram-KNZD7YFC-DyN5HPdk.js → classDiagram-v2-RKCZMP56-DUsaN1O4.js} +2 -2
  20. package/dist/{clone-DrJYap2i.js → clone-Dkt_7KOK.js} +1 -1
  21. package/dist/{cose-bilkent-S5V4N54A-D39b4WrQ.js → cose-bilkent-S5V4N54A-ClBuGZWI.js} +2 -2
  22. package/dist/{dagre-5GWH7T2D-BLjRxDpS.js → dagre-5GWH7T2D-BzmDIGaM.js} +6 -6
  23. package/dist/{data-grid-overlay-editor-DTALqerV.js → data-grid-overlay-editor-NiU9Ea77.js} +2 -2
  24. package/dist/{diagram-N5W7TBWH-MM8AIKGR.js → diagram-N5W7TBWH-BlO1yw_g.js} +5 -5
  25. package/dist/{diagram-QEK2KX5R-BZGarWuJ.js → diagram-QEK2KX5R-BvK83LUx.js} +3 -3
  26. package/dist/{diagram-S2PKOQOG-CnPinN9Q.js → diagram-S2PKOQOG-DvBzRYd7.js} +3 -3
  27. package/dist/{dockerfile-U8DnCJ4X.js → dockerfile-CPQG2tLO.js} +1 -1
  28. package/dist/{erDiagram-AWTI2OKA-CvDVbxOO.js → erDiagram-AWTI2OKA-Doy9FRTX.js} +4 -4
  29. package/dist/{flowDiagram-PVAE7QVJ-C2uuBTZS.js → flowDiagram-PVAE7QVJ-D_tX_HU1.js} +5 -5
  30. package/dist/{ganttDiagram-OWAHRB6G-BEff10RF.js → ganttDiagram-OWAHRB6G-CV03BHVY.js} +4 -4
  31. package/dist/{gitGraphDiagram-NY62KEGX-wggu0kb2.js → gitGraphDiagram-NY62KEGX-w3szEguZ.js} +4 -4
  32. package/dist/{glide-data-editor-Bqh5_dzJ.js → glide-data-editor-akznFrmp.js} +3 -3
  33. package/dist/{graph-DKpp_wzf.js → graph-CjrrDHdT.js} +3 -3
  34. package/dist/index-CIJJs0Tu.js +40382 -0
  35. package/dist/{index-DzJ_YPCG.js → index-DMo6cbcV.js} +3 -3
  36. package/dist/{index-4XruEJkp.js → index-DlV2CtJb.js} +1 -1
  37. package/dist/{index-DdfF_cLK.js → index-Y-Vbae6Z.js} +1 -1
  38. package/dist/{infoDiagram-STP46IZ2-DF7KW-Op.js → infoDiagram-STP46IZ2-BcBV2j75.js} +2 -2
  39. package/dist/{journeyDiagram-BIP6EPQ6-B_jmhmqd.js → journeyDiagram-BIP6EPQ6-BTGMSgvB.js} +3 -3
  40. package/dist/{kanban-definition-6OIFK2YF-B-M9FTyw.js → kanban-definition-6OIFK2YF-aopNqZ1Y.js} +2 -2
  41. package/dist/{layout-C4oVYZZD.js → layout-Dvo9pb_w.js} +4 -4
  42. package/dist/{linear-C-HCGr0T.js → linear-CHnELER9.js} +1 -1
  43. package/dist/{main-B9x2-9f2.js → main-kLZGkzVQ.js} +41787 -40423
  44. package/dist/main.js +1 -1
  45. package/dist/{mermaid-BE4cM3Qs.js → mermaid-DgM4_4bD.js} +30 -30
  46. package/dist/{min-DTpHJ698.js → min-cX4DuL_n.js} +2 -2
  47. package/dist/{mindmap-definition-Q6HEUPPD-Cpd-hO1E.js → mindmap-definition-Q6HEUPPD-DZjbYryy.js} +3 -3
  48. package/dist/{number-overlay-editor-CvURA2Ud.js → number-overlay-editor-8MpIObf7.js} +2 -2
  49. package/dist/{pieDiagram-ADFJNKIX-D9f_f6fn.js → pieDiagram-ADFJNKIX-D6L1IYAc.js} +3 -3
  50. package/dist/{quadrantDiagram-LMRXKWRM-DgllE7xw.js → quadrantDiagram-LMRXKWRM-nOyuc3Bf.js} +2 -2
  51. package/dist/{react-plotly-BU-JRJSi.js → react-plotly-ChkfYiVe.js} +1 -1
  52. package/dist/{requirementDiagram-4UW4RH46-Dk_G8eUb.js → requirementDiagram-4UW4RH46-OVV8wsju.js} +3 -3
  53. package/dist/{sankeyDiagram-GR3RE2ED-BhLIhDc1.js → sankeyDiagram-GR3RE2ED-qZHMdnE_.js} +1 -1
  54. package/dist/{sequenceDiagram-C3RYC4MD-DHoZdMFJ.js → sequenceDiagram-C3RYC4MD-D0bOqf-t.js} +3 -3
  55. package/dist/{slides-component-DXAgdf7K.js → slides-component-CNzLDdA3.js} +1 -1
  56. package/dist/{stateDiagram-KXAO66HF-C1Ie-7Xf.js → stateDiagram-KXAO66HF-CFNCnNJS.js} +4 -4
  57. package/dist/{stateDiagram-v2-UMBNRL4Z--CRuIHtM.js → stateDiagram-v2-UMBNRL4Z-CnIh27m8.js} +2 -2
  58. package/dist/style.css +1 -1
  59. package/dist/{time-yQjlGPwa.js → time-Z7CJSfOW.js} +2 -2
  60. package/dist/{timeline-definition-XQNQX7LJ-D_PjxB1B.js → timeline-definition-XQNQX7LJ-BYLMfrvK.js} +1 -1
  61. package/dist/{treemap-75Q7IDZK--NYqQjUZ.js → treemap-75Q7IDZK-BEh1HacP.js} +5 -5
  62. package/dist/{vega-component-CCUOMM5K.js → vega-component-iMjXd3tD.js} +2 -2
  63. package/dist/{xychartDiagram-6GGTOJPD-WLKsEnzs.js → xychartDiagram-6GGTOJPD-Bmi13ZSG.js} +2 -2
  64. package/package.json +8 -8
  65. package/src/__mocks__/common.ts +5 -3
  66. package/src/__mocks__/notebook.ts +2 -2
  67. package/src/__mocks__/requests.ts +1 -0
  68. package/src/__tests__/main.test.tsx +2 -2
  69. package/src/components/ai/ai-provider-icon.tsx +2 -0
  70. package/src/components/app-config/ai-config.tsx +32 -1
  71. package/src/components/app-config/common.tsx +2 -2
  72. package/src/components/app-config/user-config-form.tsx +26 -0
  73. package/src/components/audio/audio-recorder.tsx +0 -1
  74. package/src/components/chat/acp/blocks.tsx +2 -2
  75. package/src/components/chat/acp/thread.tsx +3 -5
  76. package/src/components/chat/acp/utils.ts +5 -5
  77. package/src/components/chat/chat-panel.tsx +1 -1
  78. package/src/components/data-table/__tests__/columns.test.tsx +38 -0
  79. package/src/components/data-table/__tests__/data-table.test.tsx +2 -2
  80. package/src/components/data-table/cell-hover-template/feature.ts +1 -1
  81. package/src/components/data-table/cell-hover-template/types.ts +1 -1
  82. package/src/components/data-table/charts/__tests__/altair-generator.test.ts +1 -1
  83. package/src/components/data-table/charts/chart-spec/tooltips.ts +3 -3
  84. package/src/components/data-table/charts/components/chart-items.tsx +1 -1
  85. package/src/components/data-table/charts/components/form-fields.tsx +2 -2
  86. package/src/components/data-table/charts/constants.ts +1 -1
  87. package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
  88. package/src/components/data-table/column-summary/chart-spec-model.tsx +2 -2
  89. package/src/components/data-table/columns.tsx +22 -3
  90. package/src/components/data-table/data-table.tsx +35 -3
  91. package/src/components/data-table/date-popover.tsx +1 -1
  92. package/src/components/data-table/download-actions.tsx +1 -1
  93. package/src/components/data-table/range-focus/__tests__/utils.test.ts +5 -5
  94. package/src/components/data-table/renderers.tsx +22 -13
  95. package/src/components/data-table/row-viewer-panel/row-viewer.tsx +1 -1
  96. package/src/components/data-table/schemas.ts +16 -0
  97. package/src/components/data-table/types.ts +4 -3
  98. package/src/components/datasources/column-preview.tsx +9 -6
  99. package/src/components/debugger/debugger-code.tsx +1 -1
  100. package/src/components/dependency-graph/custom-node.tsx +15 -6
  101. package/src/components/dependency-graph/dependency-graph-minimap.tsx +2 -2
  102. package/src/components/dependency-graph/dependency-graph-tree.tsx +2 -2
  103. package/src/components/dependency-graph/dependency-graph.tsx +1 -1
  104. package/src/components/dependency-graph/elements.ts +7 -7
  105. package/src/components/dependency-graph/utils/changes.ts +4 -4
  106. package/src/components/editor/Cell.tsx +7 -1
  107. package/src/components/editor/ai/transport/chat-transport.tsx +1 -1
  108. package/src/components/editor/chrome/panels/outline/useActiveOutline.tsx +1 -1
  109. package/src/components/editor/chrome/panels/packages-panel.tsx +1 -1
  110. package/src/components/editor/columns/storage.ts +1 -1
  111. package/src/components/editor/database/__tests__/__snapshots__/as-code.test.ts.snap +36 -0
  112. package/src/components/editor/database/__tests__/as-code.test.ts +30 -7
  113. package/src/components/editor/database/add-database-form.tsx +11 -0
  114. package/src/components/editor/database/as-code.ts +104 -5
  115. package/src/components/editor/database/schemas.ts +36 -18
  116. package/src/components/editor/errors/auto-fix.tsx +12 -2
  117. package/src/components/editor/errors/sql-validation-errors.tsx +40 -0
  118. package/src/components/editor/navigation/clipboard.ts +2 -2
  119. package/src/components/editor/output/ConsoleOutput.tsx +14 -2
  120. package/src/components/editor/output/JsonOutput.tsx +1 -1
  121. package/src/components/editor/output/MarimoErrorOutput.tsx +60 -1
  122. package/src/components/editor/output/MarimoTracebackOutput.tsx +17 -2
  123. package/src/components/editor/renderers/grid-layout/types.ts +2 -2
  124. package/src/components/editor/renderers/plugins.ts +1 -1
  125. package/src/components/editor/renderers/types.ts +1 -1
  126. package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +7 -7
  127. package/src/components/forms/form.tsx +5 -5
  128. package/src/components/ui/links.tsx +1 -0
  129. package/src/core/ai/__tests__/model-registry.test.ts +0 -10
  130. package/src/core/ai/context/providers/cell-output.ts +1 -18
  131. package/src/core/ai/context/providers/error.ts +2 -2
  132. package/src/core/ai/ids/ids.ts +1 -0
  133. package/src/core/ai/model-registry.ts +2 -1
  134. package/src/core/cells/cells.ts +5 -5
  135. package/src/core/cells/logs.ts +1 -1
  136. package/src/core/cells/types.ts +1 -1
  137. package/src/core/codemirror/__tests__/format.test.ts +6 -0
  138. package/src/core/codemirror/cells/traceback-decorations.ts +1 -1
  139. package/src/core/codemirror/editing/commands.ts +2 -2
  140. package/src/core/codemirror/find-replace/navigate.ts +1 -1
  141. package/src/core/codemirror/language/__tests__/extension.test.ts +24 -0
  142. package/src/core/codemirror/language/__tests__/sql-validation.test.ts +133 -0
  143. package/src/core/codemirror/language/__tests__/sql.test.ts +764 -79
  144. package/src/core/codemirror/language/languages/markdown.ts +4 -1
  145. package/src/core/codemirror/language/languages/sql/banner-validation-errors.ts +85 -0
  146. package/src/core/codemirror/language/languages/sql/completion-builder.ts +160 -0
  147. package/src/core/codemirror/language/languages/sql/completion-sources.tsx +9 -3
  148. package/src/core/codemirror/language/languages/sql/completion-store.ts +46 -50
  149. package/src/core/codemirror/language/languages/sql/renderers.tsx +485 -0
  150. package/src/core/codemirror/language/languages/sql/sql-mode.ts +20 -0
  151. package/src/core/codemirror/language/languages/sql/sql.ts +218 -4
  152. package/src/core/codemirror/language/languages/sql/utils.ts +4 -1
  153. package/src/core/codemirror/language/panel/panel.tsx +8 -2
  154. package/src/core/codemirror/language/panel/sql.tsx +86 -4
  155. package/src/core/codemirror/language/utils/ast.ts +3 -3
  156. package/src/core/codemirror/lsp/federated-lsp.ts +4 -4
  157. package/src/core/codemirror/lsp/lens.ts +4 -4
  158. package/src/core/codemirror/lsp/notebook-lsp.ts +1 -1
  159. package/src/core/codemirror/lsp/types.ts +1 -1
  160. package/src/core/codemirror/markdown/completions.ts +1 -1
  161. package/src/core/codemirror/reactive-references/analyzer.ts +2 -2
  162. package/src/core/codemirror/rtc/loro/awareness.ts +1 -1
  163. package/src/core/config/config-schema.ts +1 -0
  164. package/src/core/config/feature-flag.tsx +6 -2
  165. package/src/core/datasets/request-registry.ts +24 -1
  166. package/src/core/dom/events.ts +1 -1
  167. package/src/core/dom/outline.ts +2 -2
  168. package/src/core/dom/uiregistry.ts +2 -8
  169. package/src/core/errors/__tests__/errors.test.ts +22 -4
  170. package/src/core/errors/errors.ts +29 -1
  171. package/src/core/errors/state.ts +1 -1
  172. package/src/core/islands/bridge.ts +1 -0
  173. package/src/core/islands/main.ts +3 -2
  174. package/src/core/islands/parse.ts +1 -3
  175. package/src/core/kernel/messages.ts +2 -1
  176. package/src/core/network/CachingRequestRegistry.ts +74 -0
  177. package/src/core/network/DeferredRequestRegistry.ts +3 -1
  178. package/src/core/network/__tests__/CachingRequestRegistry.test.ts +73 -0
  179. package/src/core/network/requests-network.ts +7 -0
  180. package/src/core/network/requests-static.ts +1 -0
  181. package/src/core/network/requests-toasting.ts +1 -0
  182. package/src/core/network/types.ts +3 -1
  183. package/src/core/variables/state.ts +2 -2
  184. package/src/core/wasm/__tests__/state.test.ts +1 -1
  185. package/src/core/wasm/bridge.ts +5 -0
  186. package/src/core/websocket/useMarimoWebSocket.tsx +9 -2
  187. package/src/custom.d.ts +1 -1
  188. package/src/hooks/useCellRenderCount.ts +1 -0
  189. package/src/hooks/useResizeHandle.ts +4 -1
  190. package/src/plugins/core/RenderHTML.tsx +1 -2
  191. package/src/plugins/core/registerReactComponent.tsx +23 -19
  192. package/src/plugins/impl/DataTablePlugin.tsx +18 -6
  193. package/src/plugins/impl/FileUploadPlugin.tsx +1 -1
  194. package/src/plugins/impl/RefreshPlugin.tsx +1 -1
  195. package/src/plugins/impl/SliderPlugin.tsx +4 -0
  196. package/src/plugins/impl/anywidget/AnyWidgetPlugin.tsx +27 -9
  197. package/src/plugins/impl/anywidget/__tests__/AnyWidgetPlugin.test.tsx +58 -2
  198. package/src/plugins/impl/anywidget/__tests__/model.test.ts +3 -4
  199. package/src/plugins/impl/anywidget/model.ts +2 -3
  200. package/src/plugins/impl/data-editor/types.ts +1 -1
  201. package/src/plugins/impl/data-explorer/components/query-form.tsx +1 -1
  202. package/src/plugins/impl/data-frames/DataFramePlugin.tsx +17 -5
  203. package/src/plugins/impl/data-frames/types.ts +1 -1
  204. package/src/plugins/impl/panel/PanelPlugin.tsx +2 -2
  205. package/src/plugins/impl/plotly/PlotlyPlugin.tsx +3 -3
  206. package/src/plugins/impl/vega/__tests__/loader.test.ts +2 -2
  207. package/src/plugins/impl/vega/loader.ts +1 -1
  208. package/src/plugins/impl/vega/vega-component.tsx +1 -1
  209. package/src/plugins/impl/vega/vega-loader.ts +2 -2
  210. package/src/plugins/layout/NavigationMenuPlugin.tsx +1 -1
  211. package/src/plugins/layout/RoutesPlugin.tsx +1 -2
  212. package/src/plugins/plugins.ts +2 -2
  213. package/src/stories/dataframe.stories.tsx +2 -0
  214. package/src/utils/Logger.ts +1 -1
  215. package/src/utils/__tests__/data-views.test.ts +30 -68
  216. package/src/utils/__tests__/dom.test.ts +167 -0
  217. package/src/utils/__tests__/id-tree.test.ts +49 -1
  218. package/src/utils/__tests__/storage.test.ts +1 -1
  219. package/src/utils/__tests__/traceback.test.ts +13 -2
  220. package/src/utils/arrays.ts +1 -1
  221. package/src/utils/createReducer.ts +1 -5
  222. package/src/utils/data-views.ts +6 -19
  223. package/src/utils/dom.ts +55 -0
  224. package/src/utils/edit-distance.ts +1 -1
  225. package/src/utils/fileToBase64.ts +1 -1
  226. package/src/utils/id-tree.tsx +20 -18
  227. package/src/utils/json/base64.ts +13 -0
  228. package/src/utils/json/json-parser.ts +2 -2
  229. package/src/utils/lru.ts +4 -0
  230. package/src/utils/mergeRefs.ts +1 -1
  231. package/src/utils/objects.ts +3 -3
  232. package/src/utils/pluralize.ts +1 -1
  233. package/src/utils/routes.ts +2 -2
  234. package/src/utils/sets.ts +1 -1
  235. package/src/utils/traceback.ts +45 -15
  236. package/src/utils/tracer.ts +11 -9
  237. package/dist/index-DW0BCGJE.js +0 -40315
  238. package/src/__tests__/lru.test.ts +0 -74
@@ -17,6 +17,7 @@ import { JsonOutput } from "../editor/output/JsonOutput";
17
17
  import { Button } from "../ui/button";
18
18
  import { Checkbox } from "../ui/checkbox";
19
19
  import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
20
+ import { Tooltip } from "../ui/tooltip";
20
21
  import { DataTableColumnHeader } from "./column-header";
21
22
  import type { ColumnChartSpecModel } from "./column-summary/chart-spec-model";
22
23
  import { TableColumnSummary } from "./column-summary/column-summary";
@@ -103,6 +104,7 @@ export function generateColumns<T>({
103
104
  chartSpecModel,
104
105
  textJustifyColumns,
105
106
  wrappedColumns,
107
+ headerTooltip,
106
108
  showDataTypes,
107
109
  calculateTopKRows,
108
110
  }: {
@@ -112,9 +114,10 @@ export function generateColumns<T>({
112
114
  chartSpecModel?: ColumnChartSpecModel<unknown>;
113
115
  textJustifyColumns?: Record<string, "left" | "center" | "right">;
114
116
  wrappedColumns?: string[];
117
+ headerTooltip?: Record<string, string>;
115
118
  showDataTypes?: boolean;
116
119
  calculateTopKRows?: CalculateTopKRows;
117
- }): Array<ColumnDef<T>> {
120
+ }): ColumnDef<T>[] {
118
121
  // Row-headers are typically index columns
119
122
  const rowHeadersSet = new Set(rowHeaders.map(([columnName]) => columnName));
120
123
 
@@ -165,6 +168,7 @@ export function generateColumns<T>({
165
168
  header: ({ column }) => {
166
169
  const stats = chartSpecModel?.getColumnStats(key);
167
170
  const dtype = column.columnDef.meta?.dtype;
171
+ const headerTitle = headerTooltip?.[key];
168
172
  const dtypeHeader =
169
173
  showDataTypes && dtype ? (
170
174
  <div className="flex flex-row gap-1">
@@ -179,14 +183,29 @@ export function generateColumns<T>({
179
183
 
180
184
  const headerWithType = (
181
185
  <div className="flex flex-col">
182
- <span className="font-bold">{key === "" ? " " : key}</span>
186
+ <span
187
+ className={cn(
188
+ "font-bold",
189
+ headerTitle && "underline decoration-dotted",
190
+ )}
191
+ >
192
+ {key === "" ? " " : key}
193
+ </span>
183
194
  {dtypeHeader}
184
195
  </div>
185
196
  );
186
197
 
198
+ const headerWithTooltip = headerTitle ? (
199
+ <Tooltip content={headerTitle} delayDuration={300}>
200
+ {headerWithType}
201
+ </Tooltip>
202
+ ) : (
203
+ headerWithType
204
+ );
205
+
187
206
  const dataTableColumnHeader = (
188
207
  <DataTableColumnHeader
189
- header={headerWithType}
208
+ header={headerWithTooltip}
190
209
  column={column}
191
210
  calculateTopKRows={calculateTopKRows}
192
211
  />
@@ -47,7 +47,8 @@ import { getStableRowId } from "./utils";
47
47
  interface DataTableProps<TData> extends Partial<DownloadActionProps> {
48
48
  wrapperClassName?: string;
49
49
  className?: string;
50
- columns: Array<ColumnDef<TData>>;
50
+ maxHeight?: number;
51
+ columns: ColumnDef<TData>[];
51
52
  data: TData[];
52
53
  // Sorting
53
54
  manualSorting?: boolean; // server-side sorting
@@ -95,6 +96,7 @@ interface DataTableProps<TData> extends Partial<DownloadActionProps> {
95
96
  const DataTableInternal = <TData,>({
96
97
  wrapperClassName,
97
98
  className,
99
+ maxHeight,
98
100
  columns,
99
101
  data,
100
102
  selection,
@@ -250,6 +252,36 @@ const DataTableInternal = <TData,>({
250
252
 
251
253
  const rowViewerPanelOpen = isPanelOpen?.("row-viewer") ?? false;
252
254
 
255
+ const tableRef = React.useRef<HTMLTableElement | null>(null);
256
+
257
+ // Why use a ref to set max-height on the wrapper?
258
+ // - position: sticky only works when the sticky element's nearest scrollable
259
+ // ancestor is its immediate container. If max-height/overflow are applied
260
+ // on a grandparent, sticky table headers (th) will not stick.
261
+ // - We keep the scroll wrapper colocated with the base Table component, but
262
+ // derive the scroll boundary from maxHeight here to avoid coupling UI base
263
+ // components to data-table specifics or expanding their API surface.
264
+ // - Setting styles on the table's direct wrapper ensures the header sticks
265
+ // reliably across browsers without changing upstream components.
266
+ React.useEffect(() => {
267
+ if (!tableRef.current) {
268
+ return;
269
+ }
270
+ const wrapper = tableRef.current.parentElement as HTMLDivElement | null;
271
+ if (!wrapper) {
272
+ return;
273
+ }
274
+ if (maxHeight) {
275
+ wrapper.style.maxHeight = `${maxHeight}px`;
276
+ // Ensure wrapper scrolls
277
+ if (!wrapper.style.overflow) {
278
+ wrapper.style.overflow = "auto";
279
+ }
280
+ } else {
281
+ wrapper.style.removeProperty("max-height");
282
+ }
283
+ }, [maxHeight]);
284
+
253
285
  return (
254
286
  <div className={cn(wrapperClassName, "flex flex-col space-y-1")}>
255
287
  <FilterPills filters={filters} table={table} />
@@ -263,11 +295,11 @@ const DataTableInternal = <TData,>({
263
295
  reloading={reloading}
264
296
  />
265
297
  )}
266
- <Table className="relative">
298
+ <Table className="relative" ref={tableRef}>
267
299
  {showLoadingBar && (
268
300
  <div className="absolute top-0 left-0 h-[3px] w-1/2 bg-primary animate-slide" />
269
301
  )}
270
- {renderTableHeader(table)}
302
+ {renderTableHeader(table, Boolean(maxHeight))}
271
303
  <CellSelectionProvider>
272
304
  <DataTableBody
273
305
  table={table}
@@ -124,7 +124,7 @@ const RelativeTime = ({ date }: { date: Date }) => {
124
124
  const differenceInSeconds = (currentTime.getTime() - date.getTime()) / 1000;
125
125
 
126
126
  // Define time units with their thresholds and conversion factors
127
- const timeUnits: Array<[number, number, string]> = [
127
+ const timeUnits: [number, number, string][] = [
128
128
  [60, 1, "second"], // Less than 60 seconds
129
129
  [60, 60, "minute"], // Less than 60 minutes
130
130
  [24, 3600, "hour"], // Less than 24 hours
@@ -167,7 +167,7 @@ export const DownloadAs: React.FC<DownloadActionProps> = (props) => {
167
167
  );
168
168
  };
169
169
 
170
- function fetchJson(url: string): Promise<Array<Record<string, unknown>>> {
170
+ function fetchJson(url: string): Promise<Record<string, unknown>[]> {
171
171
  return fetch(url).then((res) => {
172
172
  if (!res.ok) {
173
173
  throw new Error(res.statusText);
@@ -20,17 +20,17 @@ function createMockCell(id: string, value: unknown): Cell<unknown, unknown> {
20
20
  function createMockColumn(id: string): Column<unknown> {
21
21
  return {
22
22
  id: id,
23
- getIndex: () => Number.parseInt(id),
23
+ getIndex: () => Number.parseInt(id, 10),
24
24
  } as unknown as Column<unknown>;
25
25
  }
26
26
 
27
27
  function createMockRow(
28
28
  id: string,
29
- cells: Array<Cell<unknown, unknown>>,
29
+ cells: Cell<unknown, unknown>[],
30
30
  ): Row<unknown> {
31
31
  return {
32
32
  id,
33
- index: Number.parseInt(id),
33
+ index: Number.parseInt(id, 10),
34
34
  getAllCells: () => cells,
35
35
  original: {},
36
36
  depth: 0,
@@ -43,8 +43,8 @@ function createMockRow(
43
43
  }
44
44
 
45
45
  function createMockTable(
46
- rows: Array<Row<unknown>>,
47
- columns: Array<Column<unknown>>,
46
+ rows: Row<unknown>[],
47
+ columns: Column<unknown>[],
48
48
  ): Table<unknown> {
49
49
  return {
50
50
  getRow: (id: string) => rows.find((row) => row.id === id),
@@ -26,12 +26,13 @@ import { useScrollIntoViewOnFocus } from "./range-focus/use-scroll-into-view";
26
26
 
27
27
  export function renderTableHeader<TData>(
28
28
  table: Table<TData>,
29
+ isSticky?: boolean,
29
30
  ): JSX.Element | null {
30
31
  if (!table.getRowModel().rows?.length) {
31
32
  return null;
32
33
  }
33
34
 
34
- const renderHeaderGroup = (headerGroups: Array<HeaderGroup<TData>>) => {
35
+ const renderHeaderGroup = (headerGroups: HeaderGroup<TData>[]) => {
35
36
  return headerGroups.map((headerGroup) =>
36
37
  headerGroup.headers.map((header) => {
37
38
  const { className, style } = getPinningStyles(header.column);
@@ -57,7 +58,7 @@ export function renderTableHeader<TData>(
57
58
  };
58
59
 
59
60
  return (
60
- <TableHeader>
61
+ <TableHeader className={cn(isSticky && "sticky top-0 z-10")}>
61
62
  <TableRow>
62
63
  {renderHeaderGroup(table.getLeftHeaderGroups())}
63
64
  {renderHeaderGroup(table.getCenterHeaderGroups())}
@@ -69,7 +70,7 @@ export function renderTableHeader<TData>(
69
70
 
70
71
  interface DataTableBodyProps<TData> {
71
72
  table: Table<TData>;
72
- columns: Array<ColumnDef<TData>>;
73
+ columns: ColumnDef<TData>[];
73
74
  rowViewerPanelOpen: boolean;
74
75
  getRowIndex?: (row: TData, idx: number) => number;
75
76
  viewedRowIdx?: number;
@@ -95,7 +96,7 @@ export const DataTableBody = <TData,>({
95
96
 
96
97
  function applyHoverTemplate(
97
98
  template: string,
98
- cells: Array<Cell<TData, unknown>>,
99
+ cells: Cell<TData, unknown>[],
99
100
  ): string {
100
101
  const variableRegex = /{{(\w+)}}/g;
101
102
  // Map column id -> stringified value
@@ -106,13 +107,13 @@ export const DataTableBody = <TData,>({
106
107
  const s = renderUnknownValue({ value: v, nullAsEmptyString: true });
107
108
  idToValue.set(c.column.id, s);
108
109
  }
109
- return template.replace(variableRegex, (_substr, varName: string) => {
110
+ return template.replaceAll(variableRegex, (_substr, varName: string) => {
110
111
  const val = idToValue.get(varName);
111
- return val !== undefined ? val : `{{${varName}}}`;
112
+ return val === undefined ? `{{${varName}}}` : val;
112
113
  });
113
114
  }
114
115
 
115
- const renderCells = (cells: Array<Cell<TData, unknown>>) => {
116
+ const renderCells = (cells: Cell<TData, unknown>[]) => {
116
117
  return cells.map((cell) => {
117
118
  const { className, style: pinningstyle } = getPinningStyles(cell.column);
118
119
  const style = Object.assign(
@@ -154,6 +155,8 @@ export const DataTableBody = <TData,>({
154
155
  }
155
156
  };
156
157
 
158
+ const hoverTemplate = table.getState().cellHoverTemplate || null;
159
+
157
160
  return (
158
161
  <TableBody onKeyDown={handleCellsKeyDown} ref={tableRef}>
159
162
  {table.getRowModel().rows?.length ? (
@@ -165,12 +168,18 @@ export const DataTableBody = <TData,>({
165
168
  const isRowViewedInPanel =
166
169
  rowViewerPanelOpen && viewedRowIdx === rowIndex;
167
170
 
168
- // Compute hover title once per row using this row's cells (visible or hidden)
169
- const hoverTemplate = table.getState().cellHoverTemplate || null;
170
- const rowCells = row.getAllCells();
171
- const rowTitle = hoverTemplate
172
- ? applyHoverTemplate(hoverTemplate, rowCells)
173
- : undefined;
171
+ // Compute hover title once per row using all visible cells
172
+ let rowTitle: string | undefined;
173
+ if (hoverTemplate) {
174
+ const visibleCells = row.getVisibleCells?.() ?? [
175
+ ...row.getLeftVisibleCells(),
176
+ ...row.getCenterVisibleCells(),
177
+ ...row.getRightVisibleCells(),
178
+ ];
179
+ rowTitle = hoverTemplate
180
+ ? applyHoverTemplate(hoverTemplate, visibleCells)
181
+ : undefined;
182
+ }
174
183
 
175
184
  return (
176
185
  <TableRow
@@ -188,7 +188,7 @@ export const RowViewerPanel: React.FC<RowViewerPanelProps> = ({
188
188
  </TableRow>
189
189
  </TableHeader>
190
190
  <TableBody>
191
- {fieldTypes?.map(([columnName, [dataType, externalType]]) => {
191
+ {fieldTypes?.map(([columnName, [dataType, _externalType]]) => {
192
192
  const columnValue = rowValues[columnName];
193
193
 
194
194
  if (!inSearchQuery({ columnName, columnValue, searchQuery })) {
@@ -0,0 +1,16 @@
1
+ /* Copyright 2024 Marimo. All rights reserved. */
2
+
3
+ import z from "zod";
4
+ import { rpc } from "@/plugins/core/rpc";
5
+
6
+ export type DownloadAsArgs = (req: {
7
+ format: "csv" | "json" | "parquet";
8
+ }) => Promise<string>;
9
+
10
+ export const DownloadAsSchema = rpc
11
+ .input(
12
+ z.object({
13
+ format: z.enum(["csv", "json", "parquet"]),
14
+ }),
15
+ )
16
+ .output(z.string());
@@ -27,9 +27,10 @@ export type ColumnHeaderStats = Record<
27
27
  number | string | null
28
28
  >;
29
29
 
30
- export type FieldTypesWithExternalType = Array<
31
- [columnName: string, [dataType: DataType, externalType: string]]
32
- >;
30
+ export type FieldTypesWithExternalType = [
31
+ columnName: string,
32
+ [dataType: DataType, externalType: string],
33
+ ][];
33
34
  export type FieldTypes = Record<string, DataType>;
34
35
 
35
36
  export function toFieldTypes(
@@ -110,7 +110,8 @@ export const DatasetColumnPreview: React.FC<{
110
110
  });
111
111
 
112
112
  const stats =
113
- preview.stats && renderStats(preview.stats, column.type, locale);
113
+ preview.stats &&
114
+ renderStats({ stats: preview.stats, dataType: column.type, locale });
114
115
 
115
116
  const chart = preview.chart_spec && renderChart(preview.chart_spec, theme);
116
117
 
@@ -175,11 +176,13 @@ export function renderPreviewError({
175
176
  );
176
177
  }
177
178
 
178
- export function renderStats(
179
- stats: Partial<Record<ColumnHeaderStatsKey, unknown>>,
180
- dataType: DataType,
181
- locale: string,
182
- ) {
179
+ interface RenderStatsProps {
180
+ stats: Partial<Record<ColumnHeaderStatsKey, unknown>>;
181
+ dataType: DataType;
182
+ locale: string;
183
+ }
184
+
185
+ export function renderStats({ stats, dataType, locale }: RenderStatsProps) {
183
186
  return (
184
187
  <div className="gap-x-16 gap-y-1 grid grid-cols-2-fit border rounded p-2 empty:hidden">
185
188
  {Object.entries(stats).map(([key, value]) => {
@@ -106,7 +106,7 @@ const DebuggerInput: React.FC<{
106
106
  key: "Enter",
107
107
  preventDefault: true,
108
108
  stopPropagation: true,
109
- run: (view: EditorView) => {
109
+ run: () => {
110
110
  const v = value.trim().replaceAll("\n", "\\n");
111
111
  if (!v) {
112
112
  return true;
@@ -1,7 +1,7 @@
1
1
  /* Copyright 2024 Marimo. All rights reserved. */
2
2
 
3
3
  import { useAtomValue } from "jotai";
4
- import React, { memo, use } from "react";
4
+ import React, { memo, use, useId } from "react";
5
5
  import { Handle, Position, useStore } from "reactflow";
6
6
  import { TinyCode } from "@/components/editor/cell/TinyCode";
7
7
  import { useCellIds } from "@/core/cells/cells";
@@ -23,7 +23,7 @@ const EQUALITY_CHECK = (
23
23
  prevProps: CustomNodeProps,
24
24
  nextProps: CustomNodeProps,
25
25
  ) => {
26
- const keys: Array<keyof CustomNodeProps> = ["data", "selected", "id"];
26
+ const keys: (keyof CustomNodeProps)[] = ["data", "selected", "id"];
27
27
  return keys.every((key) => prevProps[key] === nextProps[key]);
28
28
  };
29
29
 
@@ -37,18 +37,25 @@ export const CustomNode = memo((props: CustomNodeProps) => {
37
37
  const reactFlowWidth = useStore(({ width }) => width);
38
38
  const edgeMarkers = use(EdgeMarkerContext);
39
39
 
40
+ const inputOneId = useId();
41
+ const inputTwoId = useId();
42
+ const outputOneId = useId();
43
+ const outputTwoId = useId();
44
+
40
45
  const linesOfCode = cell.code.split("\n").length;
41
46
  return (
42
47
  <div>
43
48
  <Handle
44
49
  type="target"
45
- id="inputs"
50
+ id={inputOneId}
51
+ data-testid="input-one"
46
52
  position={edgeMarkers === "LR" ? Position.Left : Position.Top}
47
53
  style={{ background: color }}
48
54
  />
49
55
  <Handle
50
56
  type="source"
51
- id="inputs"
57
+ id={inputTwoId}
58
+ data-testid="input-two"
52
59
  position={edgeMarkers === "LR" ? Position.Left : Position.Top}
53
60
  style={{ background: color }}
54
61
  />
@@ -69,13 +76,15 @@ export const CustomNode = memo((props: CustomNodeProps) => {
69
76
  </div>
70
77
  <Handle
71
78
  type="source"
72
- id="outputs"
79
+ id={outputOneId}
80
+ data-testid="output-one"
73
81
  position={edgeMarkers === "LR" ? Position.Right : Position.Bottom}
74
82
  style={{ background: color }}
75
83
  />
76
84
  <Handle
77
85
  type="target"
78
- id="outputs"
86
+ id={outputTwoId}
87
+ data-testid="output-two"
79
88
  position={edgeMarkers === "LR" ? Position.Right : Position.Bottom}
80
89
  style={{ background: color }}
81
90
  />
@@ -31,7 +31,7 @@ import { useFitToViewOnDimensionChange } from "./utils/useFitToViewOnDimensionCh
31
31
  interface Props {
32
32
  cellIds: CellId[];
33
33
  variables: Variables;
34
- cellAtoms: Array<Atom<CellData>>;
34
+ cellAtoms: Atom<CellData>[];
35
35
  }
36
36
 
37
37
  const elementsBuilder = new VerticalElementsBuilder();
@@ -57,7 +57,7 @@ export const DependencyGraphMinimap: React.FC<PropsWithChildren<Props>> = ({
57
57
 
58
58
  // If the cellIds change, update the nodes.
59
59
  const syncChanges = useEvent(
60
- (elements: { nodes: Array<Node<NodeData>>; edges: Edge[] }) => {
60
+ (elements: { nodes: Node<NodeData>[]; edges: Edge[] }) => {
61
61
  setNodes(elements.nodes);
62
62
  setEdges([]);
63
63
  },
@@ -36,7 +36,7 @@ import { useFitToViewOnDimensionChange } from "./utils/useFitToViewOnDimensionCh
36
36
  interface Props {
37
37
  cellIds: CellId[];
38
38
  variables: Variables;
39
- cellAtoms: Array<Atom<CellData>>;
39
+ cellAtoms: Atom<CellData>[];
40
40
  layoutDirection: LayoutDirection;
41
41
  settings: GraphSettings;
42
42
  }
@@ -74,7 +74,7 @@ export const DependencyGraphTree: React.FC<PropsWithChildren<Props>> = ({
74
74
  const api = useReactFlow();
75
75
 
76
76
  const syncChanges = useEvent(
77
- (elements: { nodes: Array<Node<NodeData>>; edges: Edge[] }) => {
77
+ (elements: { nodes: Node<NodeData>[]; edges: Edge[] }) => {
78
78
  // Layout the elements
79
79
  const result = layoutElements({
80
80
  nodes: elements.nodes,
@@ -18,7 +18,7 @@ import "./dependency-graph.css";
18
18
  interface Props {
19
19
  cellIds: CellId[];
20
20
  variables: Variables;
21
- cellAtoms: Array<Atom<CellData>>;
21
+ cellAtoms: Atom<CellData>[];
22
22
  children?: React.ReactNode;
23
23
  }
24
24
 
@@ -22,10 +22,10 @@ export function getNodeHeight(linesOfCode: number) {
22
22
  interface ElementsBuilder {
23
23
  createElements: (
24
24
  cellIds: CellId[],
25
- cellAtoms: Array<Atom<CellData>>,
25
+ cellAtoms: Atom<CellData>[],
26
26
  variables: Variables,
27
27
  hidePureMarkdown: boolean,
28
- ) => { nodes: Array<Node<NodeData>>; edges: Edge[] };
28
+ ) => { nodes: Node<NodeData>[]; edges: Edge[] };
29
29
  }
30
30
 
31
31
  export class VerticalElementsBuilder implements ElementsBuilder {
@@ -69,12 +69,12 @@ export class VerticalElementsBuilder implements ElementsBuilder {
69
69
 
70
70
  createElements(
71
71
  cellIds: CellId[],
72
- cellAtoms: Array<Atom<CellData>>,
72
+ cellAtoms: Atom<CellData>[],
73
73
  variables: Variables,
74
- hidePureMarkdown: boolean,
74
+ _hidePureMarkdown: boolean,
75
75
  ) {
76
76
  let prevY = 0;
77
- const nodes: Array<Node<NodeData>> = [];
77
+ const nodes: Node<NodeData>[] = [];
78
78
  const edges: Edge[] = [];
79
79
  for (const [cellId, cellAtom] of Arrays.zip(cellIds, cellAtoms)) {
80
80
  const node = this.createNode(cellId, cellAtom, prevY);
@@ -135,11 +135,11 @@ export class TreeElementsBuilder implements ElementsBuilder {
135
135
 
136
136
  createElements(
137
137
  cellIds: CellId[],
138
- cellAtoms: Array<Atom<CellData>>,
138
+ cellAtoms: Atom<CellData>[],
139
139
  variables: Variables,
140
140
  hidePureMarkdown: boolean,
141
141
  ) {
142
- const nodes: Array<Node<NodeData>> = [];
142
+ const nodes: Node<NodeData>[] = [];
143
143
  const edges: Edge[] = [];
144
144
 
145
145
  const nodesWithEdges = new Set<CellId>();
@@ -11,8 +11,8 @@ import type {
11
11
  export function getNodeChanges(
12
12
  prevNodes: Node[],
13
13
  nextNodes: Node[],
14
- ): Array<NodeAddChange | NodeRemoveChange> {
15
- const changes: Array<NodeAddChange | NodeRemoveChange> = [];
14
+ ): (NodeAddChange | NodeRemoveChange)[] {
15
+ const changes: (NodeAddChange | NodeRemoveChange)[] = [];
16
16
  const prevNodeIds = new Set(prevNodes.map((node) => node.id));
17
17
  const nextNodeIds = new Set(nextNodes.map((node) => node.id));
18
18
 
@@ -33,8 +33,8 @@ export function getNodeChanges(
33
33
  export function getEdgeChanges(
34
34
  prevEdges: Edge[],
35
35
  nextEdges: Edge[],
36
- ): Array<EdgeAddChange | EdgeRemoveChange> {
37
- const changes: Array<EdgeAddChange | EdgeRemoveChange> = [];
36
+ ): (EdgeAddChange | EdgeRemoveChange)[] {
37
+ const changes: (EdgeAddChange | EdgeRemoveChange)[] = [];
38
38
  const prevEdgeIds = new Set(prevEdges.map((edge) => edge.id));
39
39
  const nextEdgeIds = new Set(nextEdges.map((edge) => edge.id));
40
40
 
@@ -80,6 +80,7 @@ import { useDeleteCellCallback } from "./cell/useDeleteCell";
80
80
  import { useRunCell } from "./cell/useRunCells";
81
81
  import { HideCodeButton } from "./code/readonly-python-code";
82
82
  import { cellDomProps } from "./common";
83
+ import { SqlValidationErrorBanner } from "./errors/sql-validation-errors";
83
84
  import { useCellNavigationProps } from "./navigation/navigation";
84
85
  import {
85
86
  useTemporarilyShownCode,
@@ -450,6 +451,7 @@ const EditableCellComponent = ({
450
451
  });
451
452
  const canCollapse = canCollapseOutline(cellRuntime.outline);
452
453
  const hasOutput = !isOutputEmpty(cellRuntime.output);
454
+ const isStaleCell = outputIsStale(cellRuntime, cellData.edited);
453
455
  const hasConsoleOutput = cellRuntime.consoleOutputs.length > 0;
454
456
  const cellOutput = userConfig.display.cell_output;
455
457
 
@@ -510,7 +512,7 @@ const EditableCellComponent = ({
510
512
  className="output-area"
511
513
  cellId={cellId}
512
514
  output={cellRuntime.output}
513
- stale={outputIsStale(cellRuntime, cellData.edited)}
515
+ stale={isStaleCell}
514
516
  loading={outputIsLoading(cellRuntime.status)}
515
517
  />
516
518
  {isMarkdownCodeHidden &&
@@ -653,6 +655,10 @@ const EditableCellComponent = ({
653
655
  )}
654
656
  </div>
655
657
  </div>
658
+ <SqlValidationErrorBanner
659
+ cellId={cellId}
660
+ hide={cellRuntime.errored && !isStaleCell}
661
+ />
656
662
  {cellOutput === "below" && outputArea}
657
663
  {cellRuntime.serialization && (
658
664
  <div className="py-1 px-2 flex items-center justify-end gap-2 last:rounded-b">
@@ -16,7 +16,7 @@ export class StreamingChunkTransport<
16
16
  private onChunkReceived: (chunk: UIMessageChunk) => void;
17
17
 
18
18
  constructor(
19
- options: HttpChatTransportInitOptions<UI_MESSAGE> = {},
19
+ options: HttpChatTransportInitOptions<UI_MESSAGE>,
20
20
  onChunkReceived: (chunk: UIMessageChunk) => void,
21
21
  ) {
22
22
  super(options);
@@ -18,7 +18,7 @@ function getRootScrollableElement() {
18
18
  * React hook to find the active header in the outline
19
19
  */
20
20
  export function useActiveOutline(
21
- headerElements: Array<readonly [HTMLElement, string]>,
21
+ headerElements: (readonly [HTMLElement, string])[],
22
22
  ) {
23
23
  const [activeHeaderId, setActiveHeaderId] = useState<string | undefined>(
24
24
  undefined,
@@ -300,7 +300,7 @@ const InstallPackageForm: React.FC<{
300
300
 
301
301
  const PackagesList: React.FC<{
302
302
  onSuccess: () => void;
303
- packages: Array<{ name: string; version: string }>;
303
+ packages: { name: string; version: string }[];
304
304
  }> = ({ onSuccess, packages }) => {
305
305
  if (packages.length === 0) {
306
306
  return (
@@ -7,7 +7,7 @@ import { NotebookScopedLocalStorage } from "@/utils/localStorage";
7
7
  const BASE_KEY = "marimo:notebook-col-sizes";
8
8
 
9
9
  interface ColumnSizes {
10
- widths: Array<number | "contentWidth">;
10
+ widths: (number | "contentWidth")[];
11
11
  }
12
12
 
13
13
  function initialState(): ColumnSizes {
@@ -28,6 +28,42 @@ engine = clickhouse_connect.get_client(
28
28
  )"
29
29
  `;
30
30
 
31
+ exports[`generateDatabaseCode > basic connections > databricks 1`] = `
32
+ "import os
33
+ import sqlalchemy
34
+
35
+ _access_token = os.environ.get("DATABRICKS_ACCESS_TOKEN", "my_access_token")
36
+ _server_hostname = os.environ.get("DATABRICKS_SERVER_HOSTNAME", "localhost")
37
+ _http_path = os.environ.get("DATABRICKS_HTTP_PATH", "http://localhost:8080")
38
+ DATABASE_URL = f"databricks://token:{_access_token}@{_server_hostname}?http_path={_http_path}"
39
+ engine = sqlalchemy.create_engine(DATABASE_URL)"
40
+ `;
41
+
42
+ exports[`generateDatabaseCode > basic connections > databricks with catalog and schema 1`] = `
43
+ "import os
44
+ import sqlalchemy
45
+
46
+ _access_token = os.environ.get("DATABRICKS_ACCESS_TOKEN", "my_access_token")
47
+ _server_hostname = os.environ.get("DATABRICKS_SERVER_HOSTNAME", "localhost")
48
+ _http_path = os.environ.get("DATABRICKS_HTTP_PATH", "http://localhost:8080")
49
+ DATABASE_URL = f"databricks://token:{_access_token}@{_server_hostname}?http_path={_http_path}&catalog=my_catalog&schema=my_schema"
50
+ engine = sqlalchemy.create_engine(DATABASE_URL)"
51
+ `;
52
+
53
+ exports[`generateDatabaseCode > basic connections > databricks with ibis 1`] = `
54
+ "import ibis
55
+ import os
56
+
57
+ _access_token = os.environ.get("DATABRICKS_ACCESS_TOKEN", "my_access_token")
58
+ _server_hostname = os.environ.get("DATABRICKS_SERVER_HOSTNAME", "localhost")
59
+ _http_path = os.environ.get("DATABRICKS_HTTP_PATH", "http://localhost:8080")
60
+ engine = ibis.databricks.connect(
61
+ server_hostname=_server_hostname,
62
+ http_path=_http_path,
63
+ access_token=_access_token
64
+ )"
65
+ `;
66
+
31
67
  exports[`generateDatabaseCode > basic connections > datafusion 1`] = `
32
68
  "from datafusion import SessionContext
33
69
  import ibis