From 720b01e706388fbb55e1e1438598cd34e2906b6c Mon Sep 17 00:00:00 2001 From: Jakub Novak Date: Wed, 30 Oct 2024 15:56:42 -0700 Subject: [PATCH 1/6] Change javascript kernel to Deno --- js/tests/languages/js.test.ts | 62 +++++++++++++++++++++ python/tests/languages/test_js.py | 68 +++++++++++++++++++++++ python/tests/sync/test_default_kernels.py | 10 ++++ template/Dockerfile | 7 ++- template/deno.json | 14 +++++ template/server/api/models/result.py | 5 +- template/server/contexts.py | 7 ++- template/server/main.py | 5 +- template/server/messaging.py | 60 ++++++++++++++++---- template/test.Dockerfile | 7 ++- 10 files changed, 224 insertions(+), 21 deletions(-) create mode 100644 js/tests/languages/js.test.ts create mode 100644 python/tests/languages/test_js.py create mode 100644 template/deno.json diff --git a/js/tests/languages/js.test.ts b/js/tests/languages/js.test.ts new file mode 100644 index 00000000..914c175e --- /dev/null +++ b/js/tests/languages/js.test.ts @@ -0,0 +1,62 @@ +import { expect } from 'vitest' + +import { sandboxTest } from '../setup' + +sandboxTest('js simple', async ({ sandbox }) => { + const result = await sandbox.runCode('console.log("Hello, World!")', {language: "js"}) + + expect(result.logs.stdout.join().trim()).toEqual('Hello, World!') +}) + +sandboxTest('js import', async ({ sandbox }) => { + const result = await sandbox.runCode('import isOdd from "npm:is-odd"\nisOdd(3)', {language: "js"}) + + expect(result.results[0].text).toEqual('true') +}) + +sandboxTest('js top level await', async ({ sandbox }) => { + const result = await sandbox.runCode(` + async function main() { + return 'Hello, World!' + } + + await main() + `, {language: "js"}) + expect(result.results[0].text).toEqual('Hello, World!') +}) + +sandboxTest('js es6', async ({ sandbox }) => { + const result = await sandbox.runCode(` +const add = (x, y) => x + y; +add(1, 2) +`, {language: "js"}) + expect(result.results[0].text).toEqual('3') +}) + + +sandboxTest('js context', async ({ sandbox }) => { + await sandbox.runCode('const z = 1', {language: "js"}) + const result = await sandbox.runCode('z', {language: "js"}) + expect(result.results[0].text).toEqual('1') +}) + +sandboxTest('js cwd', async ({ sandbox }) => { + const result = await sandbox.runCode('process.cwd()', {language: "js"}) + expect(result.results[0].text).toEqual('/home/user') + + const ctx = await sandbox.createCodeContext( {cwd: '/home', language: "js"}) + const result2 = await sandbox.runCode('process.cwd()', {context: ctx}) + expect(result2.results[0].text).toEqual('/home') +}) + +sandboxTest('ts simple', async ({ sandbox }) => { + const result = await sandbox.runCode(` +function subtract(x: number, y: number): number { + return x - y; +} + +subtract(1, 2) +`, {language: "ts"}) + + expect(result.results[0].text).toEqual('-1') +}) diff --git a/python/tests/languages/test_js.py b/python/tests/languages/test_js.py new file mode 100644 index 00000000..31f2657f --- /dev/null +++ b/python/tests/languages/test_js.py @@ -0,0 +1,68 @@ +from e2b_code_interpreter import AsyncSandbox + + +async def test_javascript(async_sandbox: AsyncSandbox): + code = """ + console.log('Hello, World!') + """ + execution = await async_sandbox.run_code(code, language="js") + assert execution.logs.stdout == ["Hello, World!\n"] + + +async def test_import(async_sandbox: AsyncSandbox): + code = """ + import isOdd from 'npm:is-odd' + isOdd(3) + """ + execution = await async_sandbox.run_code(code, language="js") + assert execution.results[0].text == "true" + + +async def test_toplevel_await(async_sandbox: AsyncSandbox): + code = """ + async function main() { + return 'Hello, World!' + } + + await main() + """ + execution = await async_sandbox.run_code(code, language="js") + assert execution.results[0].text == "Hello, World!" + + +async def test_es6(async_sandbox: AsyncSandbox): + code = """ +const add = (x, y) => x + y; +add(1, 2); + """ + execution = await async_sandbox.run_code(code, language="js") + assert execution.results[0].text == "3" + + +async def test_context(async_sandbox: AsyncSandbox): + await async_sandbox.run_code("const x = 1", language="js") + execution = await async_sandbox.run_code("x", language="js") + assert execution.results[0].text == "1" + + +async def test_cwd(async_sandbox: AsyncSandbox): + execution = await async_sandbox.run_code("process.cwd()", language="js") + assert execution.results[0].text == "/home/user" + + ctx = await async_sandbox.create_code_context("/home", language="js") + execution = await async_sandbox.run_code("process.cwd()", context=ctx) + assert execution.results[0].text == "/home" + + +async def test_typescript(async_sandbox: AsyncSandbox): + execution = await async_sandbox.run_code( + """ +function subtract(x: number, y: number): number { + return x - y; +} + +subtract(1, 2); +""", + language="ts", + ) + assert execution.results[0].text == "-1" diff --git a/python/tests/sync/test_default_kernels.py b/python/tests/sync/test_default_kernels.py index cb21cdc5..a743dc08 100644 --- a/python/tests/sync/test_default_kernels.py +++ b/python/tests/sync/test_default_kernels.py @@ -4,3 +4,13 @@ def test_js_kernel(sandbox: Sandbox): execution = sandbox.run_code("console.log('Hello, World!')", language="js") assert execution.logs.stdout == ["Hello, World!\n"] + + +def test_r_kernel(sandbox: Sandbox): + execution = sandbox.run_code('print("Hello, World!")', language="r") + assert execution.logs.stdout == ['[1] "Hello, World!"\n'] + + +def test_java_kernel(sandbox: Sandbox): + execution = sandbox.run_code('System.out.println("Hello, World!")', language="java") + assert execution.logs.stdout[0] == "Hello, World!" diff --git a/template/Dockerfile b/template/Dockerfile index 57171089..21083b01 100644 --- a/template/Dockerfile +++ b/template/Dockerfile @@ -23,9 +23,10 @@ RUN R -e "install.packages('IRkernel')" RUN R -e "IRkernel::installspec(user = FALSE, name = 'r', displayname = 'R')" # Javascript Kernel -RUN npm install -g node-gyp -RUN npm install -g --unsafe-perm ijavascript -RUN ijsinstall --install=global +COPY --from=denoland/deno:bin-2.0.4 /deno /usr/bin/deno +RUN chmod +x /usr/bin/deno +RUN deno jupyter --unstable --install +COPY ./deno.json /root/.local/share/jupyter/kernels/deno/kernel.json # Bash Kernel RUN pip install bash_kernel diff --git a/template/deno.json b/template/deno.json new file mode 100644 index 00000000..3c491e44 --- /dev/null +++ b/template/deno.json @@ -0,0 +1,14 @@ +{ + "argv": [ + "/usr/bin/deno", + "jupyter", + "--kernel", + "--conn", + "{connection_file}" + ], + "display_name": "Deno", + "env": { + "NO_COLOR": "1" + }, + "language": "typescript" +} diff --git a/template/server/api/models/result.py b/template/server/api/models/result.py index e63cdd0e..90e24a9a 100644 --- a/template/server/api/models/result.py +++ b/template/server/api/models/result.py @@ -45,7 +45,10 @@ def __init__(self, is_main_result: bool, data: [str, str]): self.is_main_result = is_main_result self.text = data.pop("text/plain", None) - if self.text and self.text.startswith("'") and self.text.endswith("'"): + if self.text and ( + (self.text.startswith("'") and self.text.endswith("'")) + or (self.text.startswith('"') and self.text.endswith('"')) + ): self.text = self.text[1:-1] self.html = data.pop("text/html", None) diff --git a/template/server/contexts.py b/template/server/contexts.py index 87b8cad5..6f47ebd0 100644 --- a/template/server/contexts.py +++ b/template/server/contexts.py @@ -20,11 +20,16 @@ def normalize_language(language: Optional[str]) -> str: if language == "js": return "javascript" + if language == "ts": + return "typescript" return language async def create_context(client, websockets: dict, language: str, cwd: str) -> Context: + if language == "javascript" or language == "typescript": + language = "deno" + data = { "path": str(uuid.uuid4()), "kernel": {"name": language}, @@ -53,7 +58,7 @@ async def create_context(client, websockets: dict, language: str, cwd: str) -> C logger.info(f"Setting working directory to {cwd}") try: - await ws.change_current_directory(cwd) + await ws.change_current_directory(cwd, language) except ExecutionError as e: return PlainTextResponse( "Failed to set working directory", diff --git a/template/server/main.py b/template/server/main.py index ba35abfa..7ed36477 100644 --- a/template/server/main.py +++ b/template/server/main.py @@ -110,7 +110,10 @@ async def post_execute(request: ExecutionRequest): ) return StreamingListJsonResponse( - ws.execute(request.code, env_vars=request.env_vars) + ws.execute( + request.code, + env_vars=request.env_vars, + ) ) diff --git a/template/server/messaging.py b/template/server/messaging.py index 6d4635c8..91934459 100644 --- a/template/server/messaging.py +++ b/template/server/messaging.py @@ -1,3 +1,4 @@ +import datetime import json import logging import uuid @@ -95,14 +96,21 @@ def _get_execute_request( "session": self.session_id, "msg_type": "execute_request", "version": "5.3", + "date": datetime.datetime.now(datetime.timezone.utc).isoformat(), }, "parent_header": {}, - "metadata": {}, + "metadata": { + "trusted": True, + "deletedCells": [], + "recordTiming": False, + "cellId": str(uuid.uuid4()), + }, "content": { "code": code, "silent": background, "store_history": True, "user_expressions": {}, + "stop_on_error": True, "allow_stdin": False, }, } @@ -127,10 +135,25 @@ async def _wait_for_result(self, message_id: str): yield output.model_dump(exclude_none=True) - async def change_current_directory(self, path: Union[str, StrictStr]): + async def change_current_directory( + self, path: Union[str, StrictStr], language: str + ): message_id = str(uuid.uuid4()) self._executions[message_id] = Execution(in_background=True) - request = self._get_execute_request(message_id, f"%cd {path}", True) + if language == "python": + request = self._get_execute_request(message_id, f"%cd {path}", True) + elif language == "deno": + request = self._get_execute_request( + message_id, f"Deno.chdir('{path}')", True + ) + elif language == "r": + request = self._get_execute_request(message_id, f"setwd('{path}')", True) + elif language == "java": + request = self._get_execute_request( + message_id, f"System.setProperty('user.dir', '{path}')", True + ) + else: + return await self._ws.send(request) @@ -165,11 +188,12 @@ async def execute( indent = len(line) - len(line.lstrip()) break - code = ( - indent * " " - + f"os.environ.set_envs_for_execution({vars_to_set})\n" - + code - ) + if self.language == "python": + code = ( + indent * " " + + f"os.environ.set_envs_for_execution({vars_to_set})\n" + + code + ) logger.info(code) request = self._get_execute_request(message_id, code, False) @@ -192,7 +216,9 @@ async def _receive_message(self): async for message in self._ws: await self._process_message(json.loads(message)) except Exception as e: - logger.error(f"WebSocket received error while receiving messages: {e}") + logger.error( + f"WebSocket received error while receiving messages: {type(e)}: {str(e)}" + ) async def _process_message(self, data: dict): """ @@ -308,11 +334,21 @@ async def _process_message(self, data: dict): execution.errored = True await queue.put( Error( - name=data["content"]["ename"], - value=data["content"]["evalue"], - traceback="".join(data["content"]["traceback"]), + name=data["content"].get("ename", ""), + value=data["content"].get("evalue", ""), + traceback="".join(data["content"].get("traceback", [])), ) ) + elif data["content"]["status"] == "abort": + logger.debug(f"Execution {parent_msg_ig} was aborted") + await queue.put( + Error( + name="ExecutionAborted", + value="Execution was aborted", + traceback="", + ) + ) + await queue.put(EndOfExecution()) elif data["content"]["status"] == "ok": pass diff --git a/template/test.Dockerfile b/template/test.Dockerfile index 195f3ab9..40d5f135 100644 --- a/template/test.Dockerfile +++ b/template/test.Dockerfile @@ -19,9 +19,10 @@ COPY ./template/requirements.txt requirements.txt RUN pip install --no-cache-dir -r requirements.txt && ipython kernel install --name "python3" --user # Javascript Kernel -RUN npm install -g node-gyp -RUN npm install -g --unsafe-perm ijavascript -RUN ijsinstall --install=global +COPY --from=denoland/deno:bin-2.0.4 /deno /usr/bin/deno +RUN chmod +x /usr/bin/deno +RUN deno jupyter --unstable --install +COPY ./template/deno.json /root/.local/share/jupyter/kernels/deno/kernel.json # Create separate virtual environment for server RUN python -m venv $SERVER_PATH/.venv From 07cadb1bfbc53b823318176bcd19da4643bf1c3b Mon Sep 17 00:00:00 2001 From: Jakub Novak Date: Wed, 30 Oct 2024 17:34:45 -0700 Subject: [PATCH 2/6] Return js kernel --- .../languages/{js.test.ts => deno.test.ts} | 21 +++++++++---------- .../languages/{test_js.py => test_deno.py} | 18 ++++++++-------- template/Dockerfile | 5 +++++ template/server/contexts.py | 5 ----- template/test.Dockerfile | 5 +++++ 5 files changed, 29 insertions(+), 25 deletions(-) rename js/tests/languages/{js.test.ts => deno.test.ts} (81%) rename python/tests/languages/{test_js.py => test_deno.py} (76%) diff --git a/js/tests/languages/js.test.ts b/js/tests/languages/deno.test.ts similarity index 81% rename from js/tests/languages/js.test.ts rename to js/tests/languages/deno.test.ts index 914c175e..48cfecd7 100644 --- a/js/tests/languages/js.test.ts +++ b/js/tests/languages/deno.test.ts @@ -3,13 +3,13 @@ import { expect } from 'vitest' import { sandboxTest } from '../setup' sandboxTest('js simple', async ({ sandbox }) => { - const result = await sandbox.runCode('console.log("Hello, World!")', {language: "js"}) + const result = await sandbox.runCode('console.log("Hello, World!")', {language: "deno"}) expect(result.logs.stdout.join().trim()).toEqual('Hello, World!') }) sandboxTest('js import', async ({ sandbox }) => { - const result = await sandbox.runCode('import isOdd from "npm:is-odd"\nisOdd(3)', {language: "js"}) + const result = await sandbox.runCode('import isOdd from "npm:is-odd"\nisOdd(3)', {language: "deno"}) expect(result.results[0].text).toEqual('true') }) @@ -21,30 +21,29 @@ sandboxTest('js top level await', async ({ sandbox }) => { } await main() - `, {language: "js"}) + `, {language: "deno"}) expect(result.results[0].text).toEqual('Hello, World!') }) sandboxTest('js es6', async ({ sandbox }) => { const result = await sandbox.runCode(` -const add = (x, y) => x + y; -add(1, 2) -`, {language: "js"}) + const add = (x, y) => x + y; + add(1, 2)`, {language: "deno"}) expect(result.results[0].text).toEqual('3') }) sandboxTest('js context', async ({ sandbox }) => { - await sandbox.runCode('const z = 1', {language: "js"}) - const result = await sandbox.runCode('z', {language: "js"}) + await sandbox.runCode('const z = 1', {language: "deno"}) + const result = await sandbox.runCode('z', {language: "deno"}) expect(result.results[0].text).toEqual('1') }) sandboxTest('js cwd', async ({ sandbox }) => { - const result = await sandbox.runCode('process.cwd()', {language: "js"}) + const result = await sandbox.runCode('process.cwd()', {language: "deno}) expect(result.results[0].text).toEqual('/home/user') - const ctx = await sandbox.createCodeContext( {cwd: '/home', language: "js"}) + const ctx = await sandbox.createCodeContext( {cwd: '/home', language: "deno"}) const result2 = await sandbox.runCode('process.cwd()', {context: ctx}) expect(result2.results[0].text).toEqual('/home') }) @@ -56,7 +55,7 @@ function subtract(x: number, y: number): number { } subtract(1, 2) -`, {language: "ts"}) +`, {language: "deno"}) expect(result.results[0].text).toEqual('-1') }) diff --git a/python/tests/languages/test_js.py b/python/tests/languages/test_deno.py similarity index 76% rename from python/tests/languages/test_js.py rename to python/tests/languages/test_deno.py index 31f2657f..6f8e80e8 100644 --- a/python/tests/languages/test_js.py +++ b/python/tests/languages/test_deno.py @@ -5,7 +5,7 @@ async def test_javascript(async_sandbox: AsyncSandbox): code = """ console.log('Hello, World!') """ - execution = await async_sandbox.run_code(code, language="js") + execution = await async_sandbox.run_code(code, language="deno") assert execution.logs.stdout == ["Hello, World!\n"] @@ -14,7 +14,7 @@ async def test_import(async_sandbox: AsyncSandbox): import isOdd from 'npm:is-odd' isOdd(3) """ - execution = await async_sandbox.run_code(code, language="js") + execution = await async_sandbox.run_code(code, language="deno") assert execution.results[0].text == "true" @@ -26,7 +26,7 @@ async def test_toplevel_await(async_sandbox: AsyncSandbox): await main() """ - execution = await async_sandbox.run_code(code, language="js") + execution = await async_sandbox.run_code(code, language="deno") assert execution.results[0].text == "Hello, World!" @@ -35,21 +35,21 @@ async def test_es6(async_sandbox: AsyncSandbox): const add = (x, y) => x + y; add(1, 2); """ - execution = await async_sandbox.run_code(code, language="js") + execution = await async_sandbox.run_code(code, language="deno") assert execution.results[0].text == "3" async def test_context(async_sandbox: AsyncSandbox): - await async_sandbox.run_code("const x = 1", language="js") - execution = await async_sandbox.run_code("x", language="js") + await async_sandbox.run_code("const x = 1", language="deno") + execution = await async_sandbox.run_code("x", language="deno") assert execution.results[0].text == "1" async def test_cwd(async_sandbox: AsyncSandbox): - execution = await async_sandbox.run_code("process.cwd()", language="js") + execution = await async_sandbox.run_code("process.cwd()", language="deno") assert execution.results[0].text == "/home/user" - ctx = await async_sandbox.create_code_context("/home", language="js") + ctx = await async_sandbox.create_code_context("/home", language="deno") execution = await async_sandbox.run_code("process.cwd()", context=ctx) assert execution.results[0].text == "/home" @@ -63,6 +63,6 @@ async def test_typescript(async_sandbox: AsyncSandbox): subtract(1, 2); """, - language="ts", + language="deno", ) assert execution.results[0].text == "-1" diff --git a/template/Dockerfile b/template/Dockerfile index 21083b01..5a2e1af3 100644 --- a/template/Dockerfile +++ b/template/Dockerfile @@ -23,6 +23,11 @@ RUN R -e "install.packages('IRkernel')" RUN R -e "IRkernel::installspec(user = FALSE, name = 'r', displayname = 'R')" # Javascript Kernel +RUN npm install -g node-gyp +RUN npm install -g --unsafe-perm ijavascript +RUN ijsinstall --install=global + +# Deno Kernel COPY --from=denoland/deno:bin-2.0.4 /deno /usr/bin/deno RUN chmod +x /usr/bin/deno RUN deno jupyter --unstable --install diff --git a/template/server/contexts.py b/template/server/contexts.py index 6f47ebd0..9f3b3834 100644 --- a/template/server/contexts.py +++ b/template/server/contexts.py @@ -20,16 +20,11 @@ def normalize_language(language: Optional[str]) -> str: if language == "js": return "javascript" - if language == "ts": - return "typescript" return language async def create_context(client, websockets: dict, language: str, cwd: str) -> Context: - if language == "javascript" or language == "typescript": - language = "deno" - data = { "path": str(uuid.uuid4()), "kernel": {"name": language}, diff --git a/template/test.Dockerfile b/template/test.Dockerfile index 40d5f135..6dea866f 100644 --- a/template/test.Dockerfile +++ b/template/test.Dockerfile @@ -19,6 +19,11 @@ COPY ./template/requirements.txt requirements.txt RUN pip install --no-cache-dir -r requirements.txt && ipython kernel install --name "python3" --user # Javascript Kernel +RUN npm install -g node-gyp +RUN npm install -g --unsafe-perm ijavascript +RUN ijsinstall --install=global + +# Deno Kernel COPY --from=denoland/deno:bin-2.0.4 /deno /usr/bin/deno RUN chmod +x /usr/bin/deno RUN deno jupyter --unstable --install From 646ea1ed89da4a0f70feb1d9bb25e265ebad7dbe Mon Sep 17 00:00:00 2001 From: Jakub Novak Date: Wed, 30 Oct 2024 17:38:37 -0700 Subject: [PATCH 3/6] Add changeset --- .changeset/lazy-impalas-accept.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/lazy-impalas-accept.md diff --git a/.changeset/lazy-impalas-accept.md b/.changeset/lazy-impalas-accept.md new file mode 100644 index 00000000..cf0eb9f0 --- /dev/null +++ b/.changeset/lazy-impalas-accept.md @@ -0,0 +1,5 @@ +--- +'@e2b/code-interpreter-template': patch +--- + +Add [Deno kernel](https://docs.deno.com/runtime/reference/cli/jupyter/) From 7c42c4378ca755bdb09fa8f9042e10d529161885 Mon Sep 17 00:00:00 2001 From: Jakub Novak Date: Wed, 30 Oct 2024 17:59:10 -0700 Subject: [PATCH 4/6] Add display test --- js/tests/languages/deno.test.ts | 21 ++++++++++++++++++++- python/tests/languages/test_deno.py | 19 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/js/tests/languages/deno.test.ts b/js/tests/languages/deno.test.ts index 48cfecd7..91e4b3a2 100644 --- a/js/tests/languages/deno.test.ts +++ b/js/tests/languages/deno.test.ts @@ -40,7 +40,7 @@ sandboxTest('js context', async ({ sandbox }) => { }) sandboxTest('js cwd', async ({ sandbox }) => { - const result = await sandbox.runCode('process.cwd()', {language: "deno}) + const result = await sandbox.runCode('process.cwd()', {language: "deno"}) expect(result.results[0].text).toEqual('/home/user') const ctx = await sandbox.createCodeContext( {cwd: '/home', language: "deno"}) @@ -59,3 +59,22 @@ subtract(1, 2) expect(result.results[0].text).toEqual('-1') }) + +sandboxTest('test display', async ({ sandbox }) => { + const result = await sandbox.runCode(` + { + [Symbol.for("Jupyter.display")]() { + return { + // Plain text content + "text/plain": "Hello world!", + + // HTML output + "text/html": "

Hello world!

", + } + } +} +`, {language: "deno"}) + + expect(result.results[0].html).toBe('

Hello world!

') + expect(result.results[0].text).toBe('Hello world!') +}) diff --git a/python/tests/languages/test_deno.py b/python/tests/languages/test_deno.py index 6f8e80e8..0a0e58e7 100644 --- a/python/tests/languages/test_deno.py +++ b/python/tests/languages/test_deno.py @@ -66,3 +66,22 @@ async def test_typescript(async_sandbox: AsyncSandbox): language="deno", ) assert execution.results[0].text == "-1" + + +async def test_display(async_sandbox: AsyncSandbox): + code = """ +{ + [Symbol.for("Jupyter.display")]() { + return { + // Plain text content + "text/plain": "Hello world!", + + // HTML output + "text/html": "

Hello world!

", + } + } +} + """ + execution = await async_sandbox.run_code(code, language="deno") + assert execution.results[0].text == "Hello world!" + assert execution.results[0].html == "

Hello world!

" From 382153db9d4ea13e4c3ba399c7bcef68027b1e84 Mon Sep 17 00:00:00 2001 From: Jakub Novak Date: Wed, 30 Oct 2024 20:03:29 -0700 Subject: [PATCH 5/6] Clean up --- template/server/messaging.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/template/server/messaging.py b/template/server/messaging.py index 91934459..4f537aa8 100644 --- a/template/server/messaging.py +++ b/template/server/messaging.py @@ -146,6 +146,10 @@ async def change_current_directory( request = self._get_execute_request( message_id, f"Deno.chdir('{path}')", True ) + elif language == "js": + request = self._get_execute_request( + message_id, f"process.chdir('{path}')", True + ) elif language == "r": request = self._get_execute_request(message_id, f"setwd('{path}')", True) elif language == "java": @@ -216,9 +220,7 @@ async def _receive_message(self): async for message in self._ws: await self._process_message(json.loads(message)) except Exception as e: - logger.error( - f"WebSocket received error while receiving messages: {type(e)}: {str(e)}" - ) + logger.error(f"WebSocket received error while receiving messages: {str(e)}") async def _process_message(self, data: dict): """ From 039f34db97f423721d98fd1e90380359ed32bca2 Mon Sep 17 00:00:00 2001 From: Jakub Novak Date: Wed, 30 Oct 2024 20:19:42 -0700 Subject: [PATCH 6/6] Handle wrong language --- python/tests/sync/test_default_kernels.py | 4 ++++ template/server/contexts.py | 3 +-- template/server/main.py | 15 +++++++++++---- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/python/tests/sync/test_default_kernels.py b/python/tests/sync/test_default_kernels.py index a743dc08..d0daf820 100644 --- a/python/tests/sync/test_default_kernels.py +++ b/python/tests/sync/test_default_kernels.py @@ -1,3 +1,5 @@ +import pytest + from e2b_code_interpreter.code_interpreter_sync import Sandbox @@ -6,11 +8,13 @@ def test_js_kernel(sandbox: Sandbox): assert execution.logs.stdout == ["Hello, World!\n"] +@pytest.mark.skip_debug() def test_r_kernel(sandbox: Sandbox): execution = sandbox.run_code('print("Hello, World!")', language="r") assert execution.logs.stdout == ['[1] "Hello, World!"\n'] +@pytest.mark.skip_debug() def test_java_kernel(sandbox: Sandbox): execution = sandbox.run_code('System.out.println("Hello, World!")', language="java") assert execution.logs.stdout[0] == "Hello, World!" diff --git a/template/server/contexts.py b/template/server/contexts.py index 9f3b3834..3af317d3 100644 --- a/template/server/contexts.py +++ b/template/server/contexts.py @@ -36,9 +36,8 @@ async def create_context(client, websockets: dict, language: str, cwd: str) -> C response = await client.post(f"{JUPYTER_BASE_URL}/api/sessions", json=data) if not response.is_success: - return PlainTextResponse( + raise Exception( f"Failed to create context: {response.text}", - status_code=500, ) session_data = response.json() diff --git a/template/server/main.py b/template/server/main.py index 7ed36477..fa7760a9 100644 --- a/template/server/main.py +++ b/template/server/main.py @@ -89,9 +89,13 @@ async def post_execute(request: ExecutionRequest): context_id = default_websockets.get(language) if not context_id: - context = await create_context( - client, websockets, language, "/home/user" - ) + try: + context = await create_context( + client, websockets, language, "/home/user" + ) + except Exception as e: + return PlainTextResponse(str(e), status_code=500) + context_id = context.id default_websockets[language] = context_id @@ -124,7 +128,10 @@ async def post_contexts(request: CreateContext) -> Context: language = normalize_language(request.language) cwd = request.cwd or "/home/user" - return await create_context(client, websockets, language, cwd) + try: + return await create_context(client, websockets, language, cwd) + except Exception as e: + return PlainTextResponse(str(e), status_code=500) @app.get("/contexts")