pyodide 0.19.1 → 0.20.1-alpha.1

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/api.js DELETED
@@ -1,421 +0,0 @@
1
- import { Module } from "./module.js";
2
- import { loadPackage, loadedPackages } from "./load-pyodide.js";
3
- import { isPyProxy, PyBuffer } from "./pyproxy.gen.js";
4
- export { loadPackage, loadedPackages, isPyProxy };
5
-
6
- /**
7
- * @typedef {import('./pyproxy.gen').Py2JsResult} Py2JsResult
8
- * @typedef {import('./pyproxy.gen').PyProxy} PyProxy
9
- * @typedef {import('./pyproxy.gen').TypedArray} TypedArray
10
- * @typedef {import('emscripten')} Emscripten
11
- * @typedef {import('emscripten').Module.FS} FS
12
- */
13
-
14
- /**
15
- * An alias to the Python :py:mod:`pyodide` package.
16
- *
17
- * You can use this to call functions defined in the Pyodide Python package
18
- * from JavaScript.
19
- *
20
- * @type {PyProxy}
21
- */
22
- let pyodide_py = {}; // actually defined in loadPyodide (see pyodide.js)
23
-
24
- /**
25
- *
26
- * An alias to the global Python namespace.
27
- *
28
- * For example, to access a variable called ``foo`` in the Python global
29
- * scope, use ``pyodide.globals.get("foo")``
30
- *
31
- * @type {PyProxy}
32
- */
33
- let globals = {}; // actually defined in loadPyodide (see pyodide.js)
34
-
35
- /**
36
- * A JavaScript error caused by a Python exception.
37
- *
38
- * In order to reduce the risk of large memory leaks, the ``PythonError``
39
- * contains no reference to the Python exception that caused it. You can find
40
- * the actual Python exception that caused this error as `sys.last_value
41
- * <https://docs.python.org/3/library/sys.html#sys.last_value>`_.
42
- *
43
- * See :ref:`type-translations-errors` for more information.
44
- *
45
- * .. admonition:: Avoid Stack Frames
46
- * :class: warning
47
- *
48
- * If you make a :any:`PyProxy` of ``sys.last_value``, you should be
49
- * especially careful to :any:`destroy() <PyProxy.destroy>` it when you are
50
- * done. You may leak a large amount of memory including the local
51
- * variables of all the stack frames in the traceback if you don't. The
52
- * easiest way is to only handle the exception in Python.
53
- *
54
- * @class
55
- */
56
- export class PythonError {
57
- // actually defined in error_handling.c. TODO: would be good to move this
58
- // documentation and the definition of PythonError to error_handling.js
59
- constructor() {
60
- /**
61
- * The Python traceback.
62
- * @type {string}
63
- */
64
- this.message;
65
- }
66
- }
67
-
68
- /**
69
- *
70
- * The Pyodide version.
71
- *
72
- * It can be either the exact release version (e.g. ``0.1.0``), or
73
- * the latest release version followed by the number of commits since, and
74
- * the git hash of the current commit (e.g. ``0.1.0-1-bd84646``).
75
- *
76
- * @type {string}
77
- */
78
- export let version = ""; // actually defined in loadPyodide (see pyodide.js)
79
-
80
- /**
81
- * Runs a string of Python code from JavaScript.
82
- *
83
- * The last part of the string may be an expression, in which case, its value
84
- * is returned.
85
- *
86
- * @param {string} code Python code to evaluate
87
- * @param {PyProxy=} globals An optional Python dictionary to use as the globals.
88
- * Defaults to :any:`pyodide.globals`. Uses the Python API
89
- * :any:`pyodide.eval_code` to evaluate the code.
90
- * @returns {Py2JsResult} The result of the Python code translated to JavaScript. See the
91
- * documentation for :any:`pyodide.eval_code` for more info.
92
- */
93
- export function runPython(code, globals = Module.globals) {
94
- return Module.pyodide_py.eval_code(code, globals);
95
- }
96
- Module.runPython = runPython;
97
-
98
- /**
99
- * @callback LogFn
100
- * @param {string} msg
101
- * @returns {void}
102
- * @private
103
- */
104
-
105
- /**
106
- * Inspect a Python code chunk and use :js:func:`pyodide.loadPackage` to install
107
- * any known packages that the code chunk imports. Uses the Python API
108
- * :func:`pyodide.find\_imports` to inspect the code.
109
- *
110
- * For example, given the following code as input
111
- *
112
- * .. code-block:: python
113
- *
114
- * import numpy as np x = np.array([1, 2, 3])
115
- *
116
- * :js:func:`loadPackagesFromImports` will call
117
- * ``pyodide.loadPackage(['numpy'])``.
118
- *
119
- * @param {string} code The code to inspect.
120
- * @param {LogFn=} messageCallback The ``messageCallback`` argument of
121
- * :any:`pyodide.loadPackage` (optional).
122
- * @param {LogFn=} errorCallback The ``errorCallback`` argument of
123
- * :any:`pyodide.loadPackage` (optional).
124
- * @async
125
- */
126
- export async function loadPackagesFromImports(
127
- code,
128
- messageCallback,
129
- errorCallback
130
- ) {
131
- let pyimports = Module.pyodide_py.find_imports(code);
132
- let imports;
133
- try {
134
- imports = pyimports.toJs();
135
- } finally {
136
- pyimports.destroy();
137
- }
138
- if (imports.length === 0) {
139
- return;
140
- }
141
-
142
- let packageNames = Module._import_name_to_package_name;
143
- let packages = new Set();
144
- for (let name of imports) {
145
- if (packageNames.has(name)) {
146
- packages.add(packageNames.get(name));
147
- }
148
- }
149
- if (packages.size) {
150
- await loadPackage(Array.from(packages), messageCallback, errorCallback);
151
- }
152
- }
153
-
154
- /**
155
- * Runs Python code using `PyCF_ALLOW_TOP_LEVEL_AWAIT
156
- * <https://docs.python.org/3/library/ast.html?highlight=pycf_allow_top_level_await#ast.PyCF_ALLOW_TOP_LEVEL_AWAIT>`_.
157
- *
158
- * .. admonition:: Python imports
159
- * :class: warning
160
- *
161
- * Since pyodide 0.18.0, you must call :js:func:`loadPackagesFromImports` to
162
- * import any python packages referenced via `import` statements in your code.
163
- * This function will no longer do it for you.
164
- *
165
- * For example:
166
- *
167
- * .. code-block:: pyodide
168
- *
169
- * let result = await pyodide.runPythonAsync(`
170
- * from js import fetch
171
- * response = await fetch("./packages.json")
172
- * packages = await response.json()
173
- * # If final statement is an expression, its value is returned to JavaScript
174
- * len(packages.packages.object_keys())
175
- * `);
176
- * console.log(result); // 79
177
- *
178
- * @param {string} code Python code to evaluate
179
- * @param {PyProxy=} globals An optional Python dictionary to use as the globals.
180
- * Defaults to :any:`pyodide.globals`. Uses the Python API
181
- * :any:`pyodide.eval_code_async` to evaluate the code.
182
- * @returns {Py2JsResult} The result of the Python code translated to JavaScript.
183
- * @async
184
- */
185
- export async function runPythonAsync(code, globals = Module.globals) {
186
- return await Module.pyodide_py.eval_code_async(code, globals);
187
- }
188
- Module.runPythonAsync = runPythonAsync;
189
-
190
- /**
191
- * Registers the JavaScript object ``module`` as a JavaScript module named
192
- * ``name``. This module can then be imported from Python using the standard
193
- * Python import system. If another module by the same name has already been
194
- * imported, this won't have much effect unless you also delete the imported
195
- * module from ``sys.modules``. This calls the ``pyodide_py`` API
196
- * :func:`pyodide.register_js_module`.
197
- *
198
- * @param {string} name Name of the JavaScript module to add
199
- * @param {object} module JavaScript object backing the module
200
- */
201
- export function registerJsModule(name, module) {
202
- Module.pyodide_py.register_js_module(name, module);
203
- }
204
-
205
- /**
206
- * Tell Pyodide about Comlink.
207
- * Necessary to enable importing Comlink proxies into Python.
208
- */
209
- export function registerComlink(Comlink) {
210
- Module._Comlink = Comlink;
211
- }
212
-
213
- /**
214
- * Unregisters a JavaScript module with given name that has been previously
215
- * registered with :js:func:`pyodide.registerJsModule` or
216
- * :func:`pyodide.register_js_module`. If a JavaScript module with that name
217
- * does not already exist, will throw an error. Note that if the module has
218
- * already been imported, this won't have much effect unless you also delete
219
- * the imported module from ``sys.modules``. This calls the ``pyodide_py`` API
220
- * :func:`pyodide.unregister_js_module`.
221
- *
222
- * @param {string} name Name of the JavaScript module to remove
223
- */
224
- export function unregisterJsModule(name) {
225
- Module.pyodide_py.unregister_js_module(name);
226
- }
227
-
228
- /**
229
- * Convert the JavaScript object to a Python object as best as possible.
230
- *
231
- * This is similar to :any:`JsProxy.to_py` but for use from JavaScript. If the
232
- * object is immutable or a :any:`PyProxy`, it will be returned unchanged. If
233
- * the object cannot be converted into Python, it will be returned unchanged.
234
- *
235
- * See :ref:`type-translations-jsproxy-to-py` for more information.
236
- *
237
- * @param {*} obj
238
- * @param {object} options
239
- * @param {number=} options.depth Optional argument to limit the depth of the
240
- * conversion.
241
- * @returns {PyProxy} The object converted to Python.
242
- */
243
- export function toPy(obj, { depth = -1 } = {}) {
244
- // No point in converting these, it'd be dumb to proxy them so they'd just
245
- // get converted back by `js2python` at the end
246
- switch (typeof obj) {
247
- case "string":
248
- case "number":
249
- case "boolean":
250
- case "bigint":
251
- case "undefined":
252
- return obj;
253
- }
254
- if (!obj || Module.isPyProxy(obj)) {
255
- return obj;
256
- }
257
- let obj_id = 0;
258
- let py_result = 0;
259
- let result = 0;
260
- try {
261
- obj_id = Module.hiwire.new_value(obj);
262
- try {
263
- py_result = Module.js2python_convert(obj_id, new Map(), depth);
264
- } catch (e) {
265
- if (e instanceof Module._PropagatePythonError) {
266
- Module._pythonexc2js();
267
- }
268
- throw e;
269
- }
270
- if (Module._JsProxy_Check(py_result)) {
271
- // Oops, just created a JsProxy. Return the original object.
272
- return obj;
273
- // return Module.pyproxy_new(py_result);
274
- }
275
- result = Module._python2js(py_result);
276
- if (result === 0) {
277
- Module._pythonexc2js();
278
- }
279
- } finally {
280
- Module.hiwire.decref(obj_id);
281
- Module._Py_DecRef(py_result);
282
- }
283
- return Module.hiwire.pop_value(result);
284
- }
285
-
286
- /**
287
- * Imports a module and returns it.
288
- *
289
- * .. admonition:: Warning
290
- * :class: warning
291
- *
292
- * This function has a completely different behavior than the old removed pyimport function!
293
- *
294
- * ``pyimport`` is roughly equivalent to:
295
- *
296
- * .. code-block:: js
297
- *
298
- * pyodide.runPython(`import ${pkgname}; ${pkgname}`);
299
- *
300
- * except that the global namespace will not change.
301
- *
302
- * Example:
303
- *
304
- * .. code-block:: js
305
- *
306
- * let sysmodule = pyodide.pyimport("sys");
307
- * let recursionLimit = sys.getrecursionlimit();
308
- *
309
- * @param {string} mod_name The name of the module to import
310
- * @returns A PyProxy for the imported module
311
- */
312
- export function pyimport(mod_name) {
313
- return Module.importlib.import_module(mod_name);
314
- }
315
-
316
- /**
317
- * Unpack an archive into a target directory.
318
- *
319
- * @param {ArrayBuffer} buffer The archive as an ArrayBuffer (it's also fine to pass a TypedArray).
320
- * @param {string} format The format of the archive. Should be one of the formats recognized by `shutil.unpack_archive`.
321
- * By default the options are 'bztar', 'gztar', 'tar', 'zip', and 'wheel'. Several synonyms are accepted for each format, e.g.,
322
- * for 'gztar' any of '.gztar', '.tar.gz', '.tgz', 'tar.gz' or 'tgz' are considered to be synonyms.
323
- *
324
- * @param {string=} extract_dir The directory to unpack the archive into. Defaults to the working directory.
325
- */
326
- export function unpackArchive(buffer, format, extract_dir) {
327
- if (!Module._util_module) {
328
- Module._util_module = pyimport("pyodide._util");
329
- }
330
- Module._util_module.unpack_buffer_archive.callKwargs(buffer, {
331
- format,
332
- extract_dir,
333
- });
334
- }
335
-
336
- /**
337
- * @private
338
- */
339
- Module.saveState = () => Module.pyodide_py._state.save_state();
340
-
341
- /**
342
- * @private
343
- */
344
- Module.restoreState = (state) => Module.pyodide_py._state.restore_state(state);
345
-
346
- /**
347
- * Sets the interrupt buffer to be `interrupt_buffer`. This is only useful when
348
- * Pyodide is used in a webworker. The buffer should be a `SharedArrayBuffer`
349
- * shared with the main browser thread (or another worker). To request an
350
- * interrupt, a `2` should be written into `interrupt_buffer` (2 is the posix
351
- * constant for SIGINT).
352
- *
353
- * @param {TypedArray} interrupt_buffer
354
- */
355
- export function setInterruptBuffer(interrupt_buffer) {
356
- Module.interrupt_buffer = interrupt_buffer;
357
- Module._set_pyodide_callback(!!interrupt_buffer);
358
- }
359
-
360
- /**
361
- * Throws a KeyboardInterrupt error if a KeyboardInterrupt has been requested
362
- * via the interrupt buffer.
363
- *
364
- * This can be used to enable keyboard interrupts during execution of JavaScript
365
- * code, just as `PyErr_CheckSignals` is used to enable keyboard interrupts
366
- * during execution of C code.
367
- */
368
- export function checkInterrupt() {
369
- if (Module.interrupt_buffer[0] === 2) {
370
- Module.interrupt_buffer[0] = 0;
371
- Module._PyErr_SetInterrupt();
372
- Module.runPython("");
373
- }
374
- }
375
-
376
- export function makePublicAPI() {
377
- /**
378
- * An alias to the `Emscripten File System API
379
- * <https://emscripten.org/docs/api_reference/Filesystem-API.html>`_.
380
- *
381
- * This provides a wide range of POSIX-`like` file/device operations, including
382
- * `mount
383
- * <https://emscripten.org/docs/api_reference/Filesystem-API.html#FS.mount>`_
384
- * which can be used to extend the in-memory filesystem with features like `persistence
385
- * <https://emscripten.org/docs/api_reference/Filesystem-API.html#persistent-data>`_.
386
- *
387
- * While all the file systems implementations are enabled, only the default
388
- * ``MEMFS`` is guaranteed to work in all runtime settings. The implementations
389
- * are available as members of ``FS.filesystems``:
390
- * ``IDBFS``, ``NODEFS``, ``PROXYFS``, ``WORKERFS``.
391
- *
392
- * @type {FS}
393
- */
394
- const FS = Module.FS;
395
- let namespace = {
396
- globals,
397
- FS,
398
- pyodide_py,
399
- version,
400
- loadPackage,
401
- loadPackagesFromImports,
402
- loadedPackages,
403
- isPyProxy,
404
- runPython,
405
- runPythonAsync,
406
- registerJsModule,
407
- unregisterJsModule,
408
- setInterruptBuffer,
409
- checkInterrupt,
410
- toPy,
411
- pyimport,
412
- unpackArchive,
413
- registerComlink,
414
- PythonError,
415
- PyBuffer,
416
- };
417
-
418
- namespace._module = Module; // @private
419
- Module.public_api = namespace;
420
- return namespace;
421
- }
@@ -1,294 +0,0 @@
1
- import ErrorStackParser from "error-stack-parser";
2
- import { Module, API, Hiwire, Tests } from "./module.js";
3
-
4
- /**
5
- * Dump the Python traceback to the browser console.
6
- *
7
- * @private
8
- */
9
- API.dump_traceback = function () {
10
- const fd_stdout = 1;
11
- Module.__Py_DumpTraceback(fd_stdout, Module._PyGILState_GetThisThreadState());
12
- };
13
-
14
- let fatal_error_occurred = false;
15
- /**
16
- * Signal a fatal error.
17
- *
18
- * Dumps the Python traceback, shows a JavaScript traceback, and prints a clear
19
- * message indicating a fatal error. It then dummies out the public API so that
20
- * further attempts to use Pyodide will clearly indicate that Pyodide has failed
21
- * and can no longer be used. pyodide._module is left accessible, and it is
22
- * possible to continue using Pyodide for debugging purposes if desired.
23
- *
24
- * @argument e {Error} The cause of the fatal error.
25
- * @private
26
- */
27
- API.fatal_error = function (e: any) {
28
- if (e.pyodide_fatal_error) {
29
- return;
30
- }
31
- if (fatal_error_occurred) {
32
- console.error("Recursive call to fatal_error. Inner error was:");
33
- console.error(e);
34
- return;
35
- }
36
- if (typeof e === "number") {
37
- // A C++ exception. Have to do some conversion work.
38
- e = convertCppException(e);
39
- } else if (typeof e === "string") {
40
- e = new Error(e);
41
- } else if (typeof e !== "object") {
42
- e = new Error(
43
- `An object of type ${typeof e} was thrown as an error. toString returns ${e.toString()}`
44
- );
45
- }
46
- // Mark e so we know not to handle it later in EM_JS wrappers
47
- e.pyodide_fatal_error = true;
48
- fatal_error_occurred = true;
49
- console.error(
50
- "Pyodide has suffered a fatal error. Please report this to the Pyodide maintainers."
51
- );
52
- console.error("The cause of the fatal error was:");
53
- if (API.inTestHoist) {
54
- // Test hoist won't print the error object in a useful way so convert it to
55
- // string.
56
- console.error(e.toString());
57
- console.error(e.stack);
58
- } else {
59
- console.error(e);
60
- }
61
- try {
62
- API.dump_traceback();
63
- for (let key of Object.keys(API.public_api)) {
64
- if (key.startsWith("_") || key === "version") {
65
- continue;
66
- }
67
- Object.defineProperty(API.public_api, key, {
68
- enumerable: true,
69
- configurable: true,
70
- get: () => {
71
- throw new Error(
72
- "Pyodide already fatally failed and can no longer be used."
73
- );
74
- },
75
- });
76
- }
77
- if (API.on_fatal) {
78
- API.on_fatal(e);
79
- }
80
- } catch (err2) {
81
- console.error("Another error occurred while handling the fatal error:");
82
- console.error(err2);
83
- }
84
- throw e;
85
- };
86
-
87
- class CppException extends Error {
88
- ty: string;
89
- constructor(ty: string, msg: string) {
90
- super(msg);
91
- this.ty = ty;
92
- }
93
- }
94
- Object.defineProperty(CppException.prototype, "name", {
95
- get() {
96
- return `${this.constructor.name} ${this.ty}`;
97
- },
98
- });
99
-
100
- /**
101
- *
102
- * Return the type name, whether the pointer inherits from exception, and the
103
- * vtable pointer for the type.
104
- *
105
- * This code is based on imitating:
106
- * 1. the implementation of __cxa_find_matching_catch
107
- * 2. the disassembly from:
108
- * ```C++
109
- * try {
110
- * ...
111
- * } catch(exception e){
112
- * ...
113
- * }
114
- *
115
- * @param ptr
116
- * @returns
117
- * exc_type_name : the type name of the exception, as would be reported by
118
- * `typeid(type).name()` but also demangled.
119
- *
120
- * is_exception_subclass : true if the object is a subclass of exception. In
121
- * this case we will use `exc.what()` to get an error message.
122
- *
123
- * adjusted_ptr : The adjusted vtable pointer for the exception to use to invoke
124
- * exc.what().
125
- *
126
- * @private
127
- */
128
- function cppExceptionInfo(ptr: number): [string, boolean, number] {
129
- const base_exception_type = Module._exc_type();
130
- const ei = new Module.ExceptionInfo(ptr);
131
- const caught_exception_type = ei.get_type();
132
- const stackTop = Module.stackSave();
133
- const exceptionThrowBuf = Module.stackAlloc(4);
134
- Module.HEAP32[exceptionThrowBuf / 4] = ptr;
135
- const exc_type_name = Module.demangle(
136
- Module.UTF8ToString(Module._exc_typename(caught_exception_type))
137
- );
138
- const is_exception_subclass = !!Module.___cxa_can_catch(
139
- base_exception_type,
140
- caught_exception_type,
141
- exceptionThrowBuf
142
- );
143
- const adjusted_ptr = Module.HEAP32[exceptionThrowBuf / 4];
144
- Module.stackRestore(stackTop);
145
- return [exc_type_name, is_exception_subclass, adjusted_ptr];
146
- }
147
-
148
- function convertCppException(ptr: number): CppException {
149
- const [exc_type_name, is_exception_subclass, adjusted_ptr] =
150
- cppExceptionInfo(ptr);
151
- let msg;
152
- if (is_exception_subclass) {
153
- // If the ptr inherits from exception, we can use exception.what() to
154
- // generate a message
155
- const msgPtr = Module._exc_what(adjusted_ptr);
156
- msg = Module.UTF8ToString(msgPtr);
157
- } else {
158
- msg = `The exception is an object of type ${exc_type_name} at address ${ptr} which does not inherit from std::exception`;
159
- }
160
- return new CppException(exc_type_name, msg);
161
- }
162
- // Expose for testing
163
- Tests.convertCppException = convertCppException;
164
-
165
- function isPyodideFrame(frame: ErrorStackParser.StackFrame): boolean {
166
- const fileName = frame.fileName || "";
167
- if (fileName.includes("pyodide.asm")) {
168
- return true;
169
- }
170
- if (fileName.includes("wasm-function")) {
171
- return true;
172
- }
173
- if (!fileName.includes("pyodide.js")) {
174
- return false;
175
- }
176
- let funcName = frame.functionName || "";
177
- if (funcName.startsWith("Object.")) {
178
- funcName = funcName.slice("Object.".length);
179
- }
180
- if (funcName in API.public_api && funcName !== "PythonError") {
181
- frame.functionName = funcName;
182
- return false;
183
- }
184
- return true;
185
- }
186
-
187
- function isErrorStart(frame: ErrorStackParser.StackFrame): boolean {
188
- if (!isPyodideFrame(frame)) {
189
- return false;
190
- }
191
- const funcName = frame.functionName;
192
- return funcName === "PythonError" || funcName === "new_error";
193
- }
194
-
195
- Module.handle_js_error = function (e: any) {
196
- if (e.pyodide_fatal_error) {
197
- throw e;
198
- }
199
- if (e instanceof Module._PropagatePythonError) {
200
- // Python error indicator is already set in this case. If this branch is
201
- // not taken, Python error indicator should be unset, and we have to set
202
- // it. In this case we don't want to tamper with the traceback.
203
- return;
204
- }
205
- let restored_error = false;
206
- if (e instanceof API.PythonError) {
207
- // Try to restore the original Python exception.
208
- restored_error = Module._restore_sys_last_exception(e.__error_address);
209
- }
210
- if (!restored_error) {
211
- // Wrap the JavaScript error
212
- let eidx = Hiwire.new_value(e);
213
- let err = Module._JsProxy_create(eidx);
214
- Module._set_error(err);
215
- Module._Py_DecRef(err);
216
- Hiwire.decref(eidx);
217
- }
218
- let stack = ErrorStackParser.parse(e);
219
- if (isErrorStart(stack[0])) {
220
- while (isPyodideFrame(stack[0])) {
221
- stack.shift();
222
- }
223
- }
224
- // Add the Javascript stack frames to the Python traceback
225
- for (const frame of stack) {
226
- if (isPyodideFrame(frame)) {
227
- break;
228
- }
229
- const funcnameAddr = Module.stringToNewUTF8(frame.functionName || "???");
230
- const fileNameAddr = Module.stringToNewUTF8(frame.fileName || "???.js");
231
- Module.__PyTraceback_Add(funcnameAddr, fileNameAddr, frame.lineNumber);
232
- Module._free(funcnameAddr);
233
- Module._free(fileNameAddr);
234
- }
235
- };
236
-
237
- /**
238
- * A JavaScript error caused by a Python exception.
239
- *
240
- * In order to reduce the risk of large memory leaks, the ``PythonError``
241
- * contains no reference to the Python exception that caused it. You can find
242
- * the actual Python exception that caused this error as `sys.last_value
243
- * <https://docs.python.org/3/library/sys.html#sys.last_value>`_.
244
- *
245
- * See :ref:`type-translations-errors` for more information.
246
- *
247
- * .. admonition:: Avoid Stack Frames
248
- * :class: warning
249
- *
250
- * If you make a :any:`PyProxy` of ``sys.last_value``, you should be
251
- * especially careful to :any:`destroy() <PyProxy.destroy>` it when you are
252
- * done. You may leak a large amount of memory including the local
253
- * variables of all the stack frames in the traceback if you don't. The
254
- * easiest way is to only handle the exception in Python.
255
- */
256
- export class PythonError extends Error {
257
- /** The address of the error we are wrapping. We may later compare this
258
- * against sys.last_value.
259
- * WARNING: we don't own a reference to this pointer, dereferencing it
260
- * may be a use-after-free error!
261
- * @private
262
- */
263
- __error_address: number;
264
-
265
- constructor(message: string, error_address: number) {
266
- const oldLimit = Error.stackTraceLimit;
267
- Error.stackTraceLimit = Infinity;
268
- super(message);
269
- Error.stackTraceLimit = oldLimit;
270
- this.__error_address = error_address;
271
- }
272
- }
273
- Object.defineProperty(PythonError.prototype, "name", {
274
- value: PythonError.name,
275
- });
276
- API.PythonError = PythonError;
277
- // A special marker. If we call a CPython API from an EM_JS function and the
278
- // CPython API sets an error, we might want to return an error status back to
279
- // C keeping the current Python error flag. This signals to the EM_JS wrappers
280
- // that the Python error flag is set and to leave it alone and return the
281
- // appropriate error value (either NULL or -1).
282
- class _PropagatePythonError extends Error {
283
- constructor() {
284
- API.fail_test = true;
285
- super(
286
- "If you are seeing this message, an internal Pyodide error has " +
287
- "occurred. Please report it to the Pyodide maintainers."
288
- );
289
- }
290
- }
291
- Object.defineProperty(_PropagatePythonError.prototype, "name", {
292
- value: _PropagatePythonError.name,
293
- });
294
- Module._PropagatePythonError = _PropagatePythonError;
package/index.d.ts DELETED
@@ -1 +0,0 @@
1
- // This file is just needed to make "npx tsd" work (otherwise it will quit with an error).