Skip to content

Commit 23b99b1

Browse files
authored
Merge branch 'main' into data_explorer-embed-preview-fix
2 parents d16139e + 3a86451 commit 23b99b1

File tree

13 files changed

+110
-120
lines changed

13 files changed

+110
-120
lines changed

.github/workflows/test_cli.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ jobs:
8686
fi
8787
done
8888
89+
- name: Run LSP binary
90+
run: ./scripts/test-lsp.sh
8991
- name: Upload wheel
9092
uses: actions/upload-artifact@v4
9193
with:

examples/sql/misc/database_explorer.py

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,22 @@
33
# dependencies = [
44
# "duckdb==1.1.1",
55
# "marimo",
6+
# "numpy==2.2.6",
7+
# "pandas==2.2.3",
68
# "polars==1.18.0",
79
# "pyarrow==18.1.0",
10+
# "sqlglot==26.19.0",
811
# ]
912
# ///
1013

1114
import marimo
1215

13-
__generated_with = "0.9.1"
16+
__generated_with = "0.13.11"
1417
app = marimo.App(width="full")
1518

1619

1720
@app.cell
18-
def __():
21+
def _():
1922
import os
2023

2124
import duckdb
@@ -24,19 +27,19 @@ def __():
2427

2528

2629
@app.cell(hide_code=True)
27-
def __(mo):
30+
def _(mo):
2831
mo.md(
2932
r"""
30-
# Database explorer
33+
# Database explorer
3134
32-
This notebook lets you explore the contents of a database. Start by providing a database URL.
33-
"""
35+
This notebook lets you explore the contents of a database. Start by providing a database URL.
36+
"""
3437
)
3538
return
3639

3740

3841
@app.cell
39-
def __(mo, os):
42+
def _(mo, os):
4043
database_url = mo.ui.text(
4144
label="Database URL",
4245
full_width=True,
@@ -47,9 +50,7 @@ def __(mo, os):
4750

4851

4952
@app.cell
50-
def __(database_url):
51-
import duckdb
52-
53+
def _(database_url, duckdb):
5354
if database_url.value:
5455
duckdb.sql(
5556
f"""
@@ -60,23 +61,23 @@ def __(database_url):
6061
ATTACH DATABASE '{database_url.value}' AS my_db (TYPE postgres, READ_ONLY);
6162
"""
6263
)
63-
return duckdb, my_db
64+
return (my_db,)
6465

6566

6667
@app.cell
67-
def __(duckdb):
68+
def _(duckdb):
6869
duckdb.sql("SHOW DATABASES").show()
6970
return
7071

7172

7273
@app.cell(hide_code=True)
73-
def __(mo):
74+
def _(mo):
7475
mo.md(r"""## Tables""")
7576
return
7677

7778

7879
@app.cell
79-
def __(mo):
80+
def _(mo):
8081
_df = mo.sql(
8182
f"""
8283
SHOW ALL TABLES;
@@ -86,13 +87,13 @@ def __(mo):
8687

8788

8889
@app.cell(hide_code=True)
89-
def __(mo):
90+
def _(mo):
9091
mo.md(r"""## Other meta table functions""")
9192
return
9293

9394

9495
@app.cell
95-
def __():
96+
def _():
9697
FUNCTIONS = [
9798
"duckdb_columns()", # columns
9899
"duckdb_constraints()", # constraints
@@ -115,7 +116,7 @@ def __():
115116

116117

117118
@app.cell
118-
def __(FUNCTIONS, mo):
119+
def _(FUNCTIONS, mo):
119120
function = mo.ui.dropdown(
120121
label="Dropdown",
121122
options=FUNCTIONS,
@@ -126,7 +127,7 @@ def __(FUNCTIONS, mo):
126127

127128

128129
@app.cell
129-
def __(_, function, mo):
130+
def _(function, mo):
130131
_df = mo.sql(
131132
f"""
132133
SELECT * FROM {function.value} WHERE database_name == 'my_db'
@@ -136,25 +137,25 @@ def __(_, function, mo):
136137

137138

138139
@app.cell(hide_code=True)
139-
def __(mo):
140+
def _(mo):
140141
mo.md(r"""## Interact with your tables""")
141142
return
142143

143144

144145
@app.cell
145-
def __(duckdb, duckdb_tables, mo):
146+
def _(duckdb, mo):
146147
tables = duckdb.execute(
147148
"""
148149
SELECT table_name FROM duckdb_tables() WHERE internal = False;
149150
"""
150151
).df()
151152
table_names = list(tables["table_name"])
152153
mo.accordion({f"Found {len(table_names)} tables": table_names})
153-
return table_names, tables
154+
return (table_names,)
154155

155156

156157
@app.cell
157-
def __(mo, table_names):
158+
def _(mo, table_names):
158159
mo.stop(not table_names)
159160
table_select = mo.ui.dropdown(
160161
label="Table",
@@ -173,14 +174,14 @@ def __(mo, table_names):
173174

174175

175176
@app.cell
176-
def __(mo, table_select):
177+
def _(mo, table_select):
177178
mo.stop(not table_select.value)
178179
table_select_value = table_select.value
179180
return (table_select_value,)
180181

181182

182183
@app.cell
183-
def __(limit, mo, table_select_value):
184+
def _(limit, mo, my_db, null, table_select_value):
184185
selected_table = mo.sql(
185186
f"""
186187
select * from my_db.{table_select_value} LIMIT {limit.value};
@@ -190,7 +191,7 @@ def __(limit, mo, table_select_value):
190191

191192

192193
@app.cell
193-
def __(mo, selected_table):
194+
def _(mo, selected_table):
194195
mo.ui.data_explorer(selected_table)
195196
return
196197

frontend/src/core/codemirror/copilot/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ function getSuggestion(
200200
state: EditorState,
201201
): string {
202202
if (!response) {
203-
logger.error("No response from copilot");
203+
logger.debug("No response from copilot");
204204
return "";
205205
}
206206

frontend/src/plugins/impl/data-explorer/spec.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ export function toSpecQuery(spec: ChartSpec): SpecQuery {
1616
};
1717
}
1818

19-
function adaptEncodings(encoding: SpecificEncoding): EncodingQuery[] {
19+
function adaptEncodings(
20+
encoding: SpecificEncoding | undefined,
21+
): EncodingQuery[] {
22+
if (!encoding) {
23+
return [];
24+
}
2025
return Object.entries(encoding).map(([channel, def]) => {
2126
return toFieldQuery(def, channel as EncodingChannel);
2227
});

lsp/index.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type * as rpc from "@sourcegraph/vscode-ws-jsonrpc";
66
import * as rpcServer from "@sourcegraph/vscode-ws-jsonrpc/lib/server";
77
import path from "node:path";
88
import fs from "node:fs/promises";
9+
import fsSync from "node:fs";
910

1011
const LOG_FILE = path.join(
1112
process.env.XDG_CACHE_HOME || path.join(process.env.HOME || "", ".cache"),
@@ -43,18 +44,28 @@ const Logger = {
4344
};
4445

4546
// Adapted from https://github.com/wylieconlon/jsonrpc-ws-proxy
47+
const COPILOT_LSP_PATH = path.join(
48+
__dirname,
49+
"copilot",
50+
"dist",
51+
"language-server.js",
52+
);
53+
if (!fsSync.existsSync(COPILOT_LSP_PATH)) {
54+
Logger.error("Compilation artifact does not exist. Exiting.");
55+
process.exit(1);
56+
}
4657

4758
const argv = parseArgs(process.argv.slice(2));
4859

4960
if (argv.help) {
50-
console.log("Usage: index.js --port 3000");
51-
process.exit(1);
61+
Logger.log("Usage: index.js --port 3000");
62+
process.exit(0);
5263
}
5364

5465
const serverPort: number = Number.parseInt(argv.port) || 3000;
5566

5667
const languageServers: Record<string, string[]> = {
57-
copilot: ["node", path.join(__dirname, "language-server.js"), "--stdio"],
68+
copilot: ["node", COPILOT_LSP_PATH, "--stdio"],
5869
};
5970

6071
function toSocket(webSocket: ws): rpc.IWebSocket {
@@ -102,6 +113,15 @@ function toSocket(webSocket: ws): rpc.IWebSocket {
102113
};
103114
}
104115

116+
async function verifyCopilotLSP() {
117+
if (!fsSync.existsSync(COPILOT_LSP_PATH)) {
118+
Logger.error(
119+
`Copilot LSP not found at ${COPILOT_LSP_PATH}. Likely a build error or missing dependencies.`,
120+
);
121+
process.exit(1);
122+
}
123+
}
124+
105125
// Add error handling for WebSocket server creation
106126
try {
107127
const wss = new WebSocketServer(
@@ -121,6 +141,8 @@ try {
121141
wss.on("connection", (client: ws, request: http.IncomingMessage) => {
122142
Logger.log(`New connection from ${request.socket.remoteAddress}`);
123143

144+
void verifyCopilotLSP();
145+
124146
let langServer: string[] | undefined;
125147

126148
Object.keys(languageServers).forEach((key) => {

marimo/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
"vstack",
8585
"watch",
8686
]
87-
__version__ = "0.13.11"
87+
__version__ = "0.13.12"
8888

8989
import marimo._ai as ai
9090
import marimo._islands as islands

marimo/_loggers.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,22 @@
99
from marimo._utils.log_formatter import LogFormatter
1010

1111
# This file manages and creates loggers used throughout marimo.
12+
#
1213
# It contains a global log level, which can be updated and all handlers
1314
# will be updated to use the new level.
15+
#
1416
# Our loggers contain two handlers:
1517
# - A StreamHandler to stdout
1618
# - A FileHandler to a rotating log file
19+
#
1720
# The stream handler is set to the global log level, but the file handler
1821
# is set to either INFO or DEBUG, depending on the global log level.
22+
#
23+
# NB: As is best practice for Python libraries, we do not configure the
24+
# root logger, and in particular we don't call basicConfig() (which would
25+
# preclude client of our library from configuring the root logger to their
26+
# own end).
27+
# See https://docs.python.org/3/howto/logging.html#configuring-logging-for-a-library
1928

2029
# Global log level for loggers
2130
_LOG_LEVEL: int = logging.WARNING
@@ -26,15 +35,6 @@
2635
# Cache of initialized loggers
2736
_LOGGERS: dict[str, logging.Logger] = {}
2837

29-
# Set basic config to INFO
30-
# This is so notebooks pick this up automatically
31-
# when they write:
32-
# ```
33-
# import logging
34-
# logging.info("Hello, world!")
35-
# ```
36-
logging.basicConfig(level=logging.INFO)
37-
3838

3939
def log_level_string_to_int(level: str) -> int:
4040
level = level.upper()
@@ -72,6 +72,11 @@ def set_level(level: str | int = logging.WARNING) -> None:
7272
_LOG_LEVEL = level
7373

7474
for logger in _LOGGERS.values():
75+
# We have to set update the logger's level in order
76+
# for its handlers level's to be respected.
77+
# but it needs to be set to the minimum LOG_LEVEL and INFO
78+
# so the file handler can still pick it up
79+
logger.setLevel(min(_LOG_LEVEL, logging.INFO))
7580
for handler in logger.handlers:
7681
if isinstance(handler, logging.FileHandler):
7782
# Don't increase the log level of a file handler
@@ -101,8 +106,10 @@ def get_logger(name: str, level: Optional[int] = None) -> logging.Logger:
101106
stream_handler.setFormatter(_LOG_FORMATTER)
102107
if level is None:
103108
stream_handler.setLevel(_LOG_LEVEL)
109+
logger.setLevel(_LOG_LEVEL)
104110
else:
105111
stream_handler.setLevel(level)
112+
logger.setLevel(level)
106113

107114
logger.addHandler(stream_handler)
108115

0 commit comments

Comments
 (0)