From ce8bac08ec842c51e427a3ab8a04e6e28a419a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20Sj=C3=B6green?= Date: Mon, 10 Feb 2025 10:49:04 +0100 Subject: [PATCH 1/3] fix: Use JSR dependencies for `ext/pip` (#82) --- ext/pip.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ext/pip.ts b/ext/pip.ts index 3f4e8bd..d06a2fc 100644 --- a/ext/pip.ts +++ b/ext/pip.ts @@ -1,12 +1,12 @@ import { kw, python, PythonError } from "../mod.ts"; -import { join } from "https://deno.land/std@0.203.0/path/mod.ts"; -import { ensureDir } from "https://deno.land/std@0.203.0/fs/mod.ts"; -import { green, yellow } from "https://deno.land/std@0.203.0/fmt/colors.ts"; +import { join } from "jsr:@std/path@^1/join"; +import { ensureDir } from "jsr:@std/fs@^1/ensure-dir"; +import { green, yellow } from "jsr:@std/fmt@^1/colors"; -import type { CacheLocation } from "https://deno.land/x/plug@1.0.3/types.ts"; -import { ensureCacheLocation } from "https://deno.land/x/plug@1.0.3/download.ts"; -import { hash } from "https://deno.land/x/plug@1.0.3/util.ts"; +import type { CacheLocation } from "jsr:@denosaurs/plug@^1/types"; +import { ensureCacheLocation } from "jsr:@denosaurs/plug@^1/download"; +import { hash } from "jsr:@denosaurs/plug@^1/util"; const sys = python.import("sys"); const runpy = python.import("runpy"); From 8b06a60d30494433534affb44adfd156473fba20 Mon Sep 17 00:00:00 2001 From: Bedis Nbiba Date: Tue, 24 Jun 2025 08:48:30 +0100 Subject: [PATCH 2/3] feat: set python exception if an error happens in a js callback (#83) * feat: set python exception if an error happens in a js callback * remove extra log * change pyobject -> null, gives slightly better error message --- src/python.ts | 39 ++++++++++++++++++++++++++++++++------- src/symbols.ts | 5 +++++ test/test.ts | 24 ++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/src/python.ts b/src/python.ts index 0b39e4a..8054590 100644 --- a/src/python.ts +++ b/src/python.ts @@ -154,13 +154,38 @@ export class Callback { args: Deno.PointerValue, kwargs: Deno.PointerValue, ) => { - return PyObject.from(callback( - kwargs === null ? {} : Object.fromEntries( - new PyObject(kwargs).asDict() - .entries(), - ), - ...(args === null ? [] : new PyObject(args).valueOf()), - )).handle; + let result: PythonConvertible; + // Prepare arguments for the JS callback + try { + // Prepare arguments for the JS callback + const jsKwargs = kwargs === null + ? {} + : Object.fromEntries(new PyObject(kwargs).asDict().entries()); + const jsArgs = args === null ? [] : new PyObject(args).valueOf(); + + // Call the actual JS function + result = callback(jsKwargs, ...jsArgs); + + // Convert the JS return value back to a Python object + return PyObject.from(result).handle; + } catch (e) { + // An error occurred in the JS callback. + // We need to set a Python exception and return NULL. + + // Prepare the error message for Python + const errorMessage = e instanceof Error + ? `${e.name}: ${e.message}` // Include JS error type and message + : String(e); // Fallback for non-Error throws + const cErrorMessage = cstr(`JS Callback Error: ${errorMessage}`); + + const errorTypeHandle = + python.builtins.RuntimeError[ProxiedPyObject].handle; + + // Set the Python exception (type and message) + py.PyErr_SetString(errorTypeHandle, cErrorMessage); + + return null; + } }, ); } diff --git a/src/symbols.ts b/src/symbols.ts index 1bd0def..c7a0abc 100644 --- a/src/symbols.ts +++ b/src/symbols.ts @@ -39,6 +39,11 @@ export const SYMBOLS = { result: "void", }, + PyErr_SetString: { + parameters: ["pointer", "buffer"], // type, message + result: "void", + }, + PyDict_New: { parameters: [], result: "pointer", diff --git a/test/test.ts b/test/test.ts index 796a159..8293618 100644 --- a/test/test.ts +++ b/test/test.ts @@ -360,3 +360,27 @@ Deno.test("callbacks have signature", async (t) => { fn.destroy(); }); }); + +Deno.test("js exception inside python callback returns python exception", () => { + const pyCallback = python.callback(() => { + throw new Error("This is an intentional error from JS!"); + }); + + const pyModule = python.runModule( + ` +def call_the_callback(cb): + result = cb() + return result + `, + "test_module", + ); + + try { + pyModule.call_the_callback(pyCallback); + } catch (e) { + // deno-lint-ignore no-explicit-any + assertEquals((e as any).name, "PythonError"); + } finally { + pyCallback.destroy(); + } +}); From bafbae353798d2125e41197e5e9be32e5ce99452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20Sj=C3=B6green?= Date: Thu, 26 Jun 2025 16:12:54 +0200 Subject: [PATCH 3/3] chore: Release 0.4.5 --- deno.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deno.json b/deno.json index 571d1e7..d8901e3 100644 --- a/deno.json +++ b/deno.json @@ -1,6 +1,6 @@ { "name": "@denosaurs/python", - "version": "0.4.4", + "version": "0.4.5", "exports": { ".": "./mod.ts", "./ext/pip": "./ext/pip.ts" diff --git a/package.json b/package.json index 27063ee..a87ea3c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bunpy", - "version": "0.4.4", + "version": "0.4.5", "description": "JavaScript -> Python Bridge for Deno and Bun", "main": "mod.bun.ts", "directories": {