pyodide 0.19.0 → 0.20.0

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.
@@ -1,4 +1,4 @@
1
- // This file is generated by applying the C preprocessor to core/pyproxy.js
1
+ // This file is generated by applying the C preprocessor to core/pyproxy.ts
2
2
  // It uses the macros defined in core/pyproxy.c
3
3
  // Do not edit it directly!
4
4
 
@@ -84,28 +84,6 @@
84
84
 
85
85
 
86
86
 
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
-
108
-
109
87
 
110
88
 
111
89
 
@@ -140,33 +118,34 @@
140
118
  * any macros available in pyproxy.c are available here. We only need the flags
141
119
  * macros HAS_LENGTH, etc.
142
120
  *
143
- * See Makefile recipe for src/js/pyproxy.js
121
+ * See Makefile recipe for src/js/pyproxy.gen.ts
144
122
  */
145
-
146
- import { Module } from "./module.js";
147
-
123
+ import { Module, API, Hiwire } from "./module.js";
148
124
  /**
149
125
  * Is the argument a :any:`PyProxy`?
150
- * @param jsobj {any} Object to test.
151
- * @returns {jsobj is PyProxy} Is ``jsobj`` a :any:`PyProxy`?
126
+ * @param jsobj Object to test.
127
+ * @returns Is ``jsobj`` a :any:`PyProxy`?
152
128
  */
153
- export function isPyProxy(jsobj) {
129
+ export function isPyProxy(jsobj: any): jsobj is PyProxy {
154
130
  return !!jsobj && jsobj.$$ !== undefined && jsobj.$$.type === "PyProxy";
155
131
  }
156
- Module.isPyProxy = isPyProxy;
157
-
132
+ API.isPyProxy = isPyProxy;
133
+ declare var FinalizationRegistry: any;
134
+ declare var globalThis: any;
158
135
  if (globalThis.FinalizationRegistry) {
159
- Module.finalizationRegistry = new FinalizationRegistry(([ptr, cache]) => {
160
- cache.leaked = (!!1);
161
- pyproxy_decref_cache(cache);
162
- try {
163
- Module._Py_DecRef(ptr);
164
- } catch (e) {
165
- // I'm not really sure what happens if an error occurs inside of a
166
- // finalizer...
167
- Module.fatal_error(e);
136
+ Module.finalizationRegistry = new FinalizationRegistry(
137
+ ([ptr, cache]: [ptr: number, cache: PyProxyCache]) => {
138
+ cache.leaked = (!!1);
139
+ pyproxy_decref_cache(cache);
140
+ try {
141
+ Module._Py_DecRef(ptr);
142
+ } catch (e) {
143
+ // I'm not really sure what happens if an error occurs inside of a
144
+ // finalizer...
145
+ API.fatal_error(e);
146
+ }
168
147
  }
169
- });
148
+ );
170
149
  // For some unclear reason this code screws up selenium FirefoxDriver. Works
171
150
  // fine in chrome and when I test it in browser. It seems to be sensitive to
172
151
  // changes that don't make a difference to the semantics.
@@ -176,35 +155,33 @@ if (globalThis.FinalizationRegistry) {
176
155
  // Module._PyBuffer_Release(ptr);
177
156
  // Module._PyMem_Free(ptr);
178
157
  // } catch (e) {
179
- // Module.fatal_error(e);
158
+ // API.fatal_error(e);
180
159
  // }
181
160
  // });
182
161
  } else {
183
162
  Module.finalizationRegistry = { register() {}, unregister() {} };
184
163
  // Module.bufferFinalizationRegistry = finalizationRegistry;
185
164
  }
186
-
187
165
  let pyproxy_alloc_map = new Map();
188
166
  Module.pyproxy_alloc_map = pyproxy_alloc_map;
189
- let trace_pyproxy_alloc;
190
- let trace_pyproxy_dealloc;
191
-
167
+ let trace_pyproxy_alloc: (proxy: any) => void;
168
+ let trace_pyproxy_dealloc: (proxy: any) => void;
192
169
  Module.enable_pyproxy_allocation_tracing = function () {
193
- trace_pyproxy_alloc = function (proxy) {
170
+ trace_pyproxy_alloc = function (proxy: any) {
194
171
  pyproxy_alloc_map.set(proxy, Error().stack);
195
172
  };
196
- trace_pyproxy_dealloc = function (proxy) {
173
+ trace_pyproxy_dealloc = function (proxy: any) {
197
174
  pyproxy_alloc_map.delete(proxy);
198
175
  };
199
176
  };
200
177
  Module.disable_pyproxy_allocation_tracing = function () {
201
- trace_pyproxy_alloc = function (proxy) {};
202
- trace_pyproxy_dealloc = function (proxy) {};
178
+ trace_pyproxy_alloc = function (proxy: any) {};
179
+ trace_pyproxy_dealloc = function (proxy: any) {};
203
180
  };
204
181
  Module.disable_pyproxy_allocation_tracing();
205
-
182
+ type PyProxyCache = { cacheId: number; refcnt: number; leaked?: boolean };
206
183
  /**
207
- * Create a new PyProxy wraping ptrobj which is a PyObject*.
184
+ * Create a new PyProxy wrapping ptrobj which is a PyObject*.
208
185
  *
209
186
  * The argument cache is only needed to implement the PyProxy.copy API, it
210
187
  * allows the copy of the PyProxy to share its attribute cache with the original
@@ -216,7 +193,7 @@ Module.disable_pyproxy_allocation_tracing();
216
193
  * many as possible.
217
194
  * @private
218
195
  */
219
- Module.pyproxy_new = function (ptrobj, cache) {
196
+ Module.pyproxy_new = function (ptrobj: number, cache?: PyProxyCache) {
220
197
  let flags = Module._pyproxy_getflags(ptrobj);
221
198
  let cls = Module.getPyProxyClass(flags);
222
199
  // Reflect.construct calls the constructor of Module.PyProxyClass but sets
@@ -241,7 +218,7 @@ Module.pyproxy_new = function (ptrobj, cache) {
241
218
  if (!cache) {
242
219
  // The cache needs to be accessed primarily from the C function
243
220
  // _pyproxy_getattr so we make a hiwire id.
244
- let cacheId = Module.hiwire.new_value(new Map());
221
+ let cacheId = Hiwire.new_value(new Map());
245
222
  cache = { cacheId, refcnt: 0 };
246
223
  }
247
224
  cache.refcnt++;
@@ -254,33 +231,24 @@ Module.pyproxy_new = function (ptrobj, cache) {
254
231
  Module.finalizationRegistry.register(proxy, [ptrobj, cache], proxy);
255
232
  return proxy;
256
233
  };
257
-
258
- function _getPtr(jsobj) {
259
- let ptr = jsobj.$$.ptr;
260
- if (ptr === null) {
261
- throw new Error(
262
- jsobj.$$.destroyed_msg || "Object has already been destroyed"
263
- );
234
+ function _getPtr(jsobj: any) {
235
+ let ptr: number = jsobj.$$.ptr;
236
+ if (ptr === 0) {
237
+ throw new Error(jsobj.$$.destroyed_msg);
264
238
  }
265
239
  return ptr;
266
240
  }
267
-
268
241
  let pyproxyClassMap = new Map();
269
242
  /**
270
- * Retreive the appropriate mixins based on the features requested in flags.
243
+ * Retrieve the appropriate mixins based on the features requested in flags.
271
244
  * Used by pyproxy_new. The "flags" variable is produced by the C function
272
245
  * pyproxy_getflags. Multiple PyProxies with the same set of feature flags
273
246
  * will share the same prototype, so the memory footprint of each individual
274
247
  * PyProxy is minimal.
275
248
  * @private
276
249
  */
277
- Module.getPyProxyClass = function (flags) {
278
- let result = pyproxyClassMap.get(flags);
279
- if (result) {
280
- return result;
281
- }
282
- let descriptors = {};
283
- for (let [feature_flag, methods] of [
250
+ Module.getPyProxyClass = function (flags: number) {
251
+ const FLAG_TYPE_PAIRS: [number, any][] = [
284
252
  [(1 << 0), PyProxyLengthMethods],
285
253
  [(1 << 1), PyProxyGetItemMethods],
286
254
  [(1 << 2), PyProxySetItemMethods],
@@ -290,7 +258,13 @@ Module.getPyProxyClass = function (flags) {
290
258
  [(1 << 6), PyProxyAwaitableMethods],
291
259
  [(1 << 7), PyProxyBufferMethods],
292
260
  [(1 << 8), PyProxyCallableMethods],
293
- ]) {
261
+ ];
262
+ let result = pyproxyClassMap.get(flags);
263
+ if (result) {
264
+ return result;
265
+ }
266
+ let descriptors: any = {};
267
+ for (let [feature_flag, methods] of FLAG_TYPE_PAIRS) {
294
268
  if (flags & feature_flag) {
295
269
  Object.assign(
296
270
  descriptors,
@@ -313,54 +287,64 @@ Module.getPyProxyClass = function (flags) {
313
287
  pyproxyClassMap.set(flags, NewPyProxyClass);
314
288
  return NewPyProxyClass;
315
289
  };
316
-
317
290
  // Static methods
318
291
  Module.PyProxy_getPtr = _getPtr;
319
-
320
292
  const pyproxy_cache_destroyed_msg =
321
293
  "This borrowed attribute proxy was automatically destroyed in the " +
322
294
  "process of destroying the proxy it was borrowed from. Try using the 'copy' method.";
323
-
324
- function pyproxy_decref_cache(cache) {
295
+ function pyproxy_decref_cache(cache: PyProxyCache) {
325
296
  if (!cache) {
326
297
  return;
327
298
  }
328
299
  cache.refcnt--;
329
300
  if (cache.refcnt === 0) {
330
- let cache_map = Module.hiwire.pop_value(cache.cacheId);
301
+ let cache_map = Hiwire.pop_value(cache.cacheId);
331
302
  for (let proxy_id of cache_map.values()) {
332
- const cache_entry = Module.hiwire.pop_value(proxy_id);
303
+ const cache_entry = Hiwire.pop_value(proxy_id);
333
304
  if (!cache.leaked) {
334
305
  Module.pyproxy_destroy(cache_entry, pyproxy_cache_destroyed_msg);
335
306
  }
336
307
  }
337
308
  }
338
309
  }
339
-
340
- Module.pyproxy_destroy = function (proxy, destroyed_msg) {
341
- if (proxy.$$.ptr === null) {
310
+ Module.pyproxy_destroy = function (proxy: PyProxy, destroyed_msg: string) {
311
+ if (proxy.$$.ptr === 0) {
342
312
  return;
343
313
  }
344
314
  let ptrobj = _getPtr(proxy);
345
315
  Module.finalizationRegistry.unregister(proxy);
316
+ destroyed_msg = destroyed_msg || "Object has already been destroyed";
317
+ let proxy_type = proxy.type;
318
+ let proxy_repr;
319
+ try {
320
+ proxy_repr = proxy.toString();
321
+ } catch (e) {
322
+ if (e.pyodide_fatal_error) {
323
+ throw e;
324
+ }
325
+ }
346
326
  // Maybe the destructor will call JavaScript code that will somehow try
347
327
  // to use this proxy. Mark it deleted before decrementing reference count
348
328
  // just in case!
349
- proxy.$$.ptr = null;
329
+ proxy.$$.ptr = 0;
330
+ destroyed_msg += "\n" + `The object was of type "${proxy_type}" and `;
331
+ if (proxy_repr) {
332
+ destroyed_msg += `had repr "${proxy_repr}"`;
333
+ } else {
334
+ destroyed_msg += "an error was raised when trying to generate its repr";
335
+ }
350
336
  proxy.$$.destroyed_msg = destroyed_msg;
351
337
  pyproxy_decref_cache(proxy.$$.cache);
352
338
  try {
353
339
  Module._Py_DecRef(ptrobj);
354
340
  trace_pyproxy_dealloc(proxy);
355
341
  } catch (e) {
356
- Module.fatal_error(e);
342
+ API.fatal_error(e);
357
343
  }
358
344
  };
359
-
360
345
  // Now a lot of boilerplate to wrap the abstract Object protocol wrappers
361
346
  // defined in pyproxy.c in JavaScript functions.
362
-
363
- Module.callPyObjectKwargs = function (ptrobj, ...jsargs) {
347
+ Module.callPyObjectKwargs = function (ptrobj: number, ...jsargs: any) {
364
348
  // We don't do any checking for kwargs, checks are in PyProxy.callKwargs
365
349
  // which only is used when the keyword arguments come from the user.
366
350
  let kwargs = jsargs.pop();
@@ -369,9 +353,8 @@ Module.callPyObjectKwargs = function (ptrobj, ...jsargs) {
369
353
  let kwargs_values = Object.values(kwargs);
370
354
  let num_kwargs = kwargs_names.length;
371
355
  jsargs.push(...kwargs_values);
372
-
373
- let idargs = Module.hiwire.new_value(jsargs);
374
- let idkwnames = Module.hiwire.new_value(kwargs_names);
356
+ let idargs = Hiwire.new_value(jsargs);
357
+ let idkwnames = Hiwire.new_value(kwargs_names);
375
358
  let idresult;
376
359
  try {
377
360
  idresult = Module.__pyproxy_apply(
@@ -382,30 +365,32 @@ Module.callPyObjectKwargs = function (ptrobj, ...jsargs) {
382
365
  num_kwargs
383
366
  );
384
367
  } catch (e) {
385
- Module.fatal_error(e);
368
+ API.fatal_error(e);
386
369
  } finally {
387
- Module.hiwire.decref(idargs);
388
- Module.hiwire.decref(idkwnames);
370
+ Hiwire.decref(idargs);
371
+ Hiwire.decref(idkwnames);
389
372
  }
390
373
  if (idresult === 0) {
391
374
  Module._pythonexc2js();
392
375
  }
393
- return Module.hiwire.pop_value(idresult);
376
+ let result = Hiwire.pop_value(idresult);
377
+ // Automatically schedule coroutines
378
+ if (result && result.type === "coroutine" && result._ensure_future) {
379
+ result._ensure_future();
380
+ }
381
+ return result;
394
382
  };
395
-
396
- Module.callPyObject = function (ptrobj, ...jsargs) {
383
+ Module.callPyObject = function (ptrobj: number, ...jsargs: any) {
397
384
  return Module.callPyObjectKwargs(ptrobj, ...jsargs, {});
398
385
  };
399
-
400
- /**
401
- * @typedef {(PyProxyClass & {[x : string] : Py2JsResult})} PyProxy
402
- * @typedef { PyProxy | number | bigint | string | boolean | undefined } Py2JsResult
403
- */
404
- class PyProxyClass {
386
+ export type PyProxy = PyProxyClass & { [x: string]: any };
387
+ export class PyProxyClass {
388
+ $$: { ptr: number; cache: PyProxyCache; destroyed_msg?: string };
389
+ $$flags: number;
390
+ /** @private */
405
391
  constructor() {
406
392
  throw new TypeError("PyProxy is not a constructor");
407
393
  }
408
-
409
394
  get [Symbol.toStringTag]() {
410
395
  return "PyProxy";
411
396
  }
@@ -423,51 +408,45 @@ class PyProxyClass {
423
408
  * else:
424
409
  * ty.__module__ + "." + ty.__name__
425
410
  *
426
- * @type {string}
427
411
  */
428
- get type() {
412
+ get type(): string {
429
413
  let ptrobj = _getPtr(this);
430
- return Module.hiwire.pop_value(Module.__pyproxy_type(ptrobj));
414
+ return Hiwire.pop_value(Module.__pyproxy_type(ptrobj));
431
415
  }
432
- /**
433
- * @returns {string}
434
- */
435
- toString() {
416
+ toString(): string {
436
417
  let ptrobj = _getPtr(this);
437
418
  let jsref_repr;
438
419
  try {
439
420
  jsref_repr = Module.__pyproxy_repr(ptrobj);
440
421
  } catch (e) {
441
- Module.fatal_error(e);
422
+ API.fatal_error(e);
442
423
  }
443
424
  if (jsref_repr === 0) {
444
425
  Module._pythonexc2js();
445
426
  }
446
- return Module.hiwire.pop_value(jsref_repr);
427
+ return Hiwire.pop_value(jsref_repr);
447
428
  }
448
429
  /**
449
- * Destroy the ``PyProxy``. This will release the memory. Any further
450
- * attempt to use the object will raise an error.
430
+ * Destroy the ``PyProxy``. This will release the memory. Any further attempt
431
+ * to use the object will raise an error.
451
432
  *
452
433
  * In a browser supporting `FinalizationRegistry
453
434
  * <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry>`_
454
435
  * Pyodide will automatically destroy the ``PyProxy`` when it is garbage
455
- * collected, however there is no guarantee that the finalizer will be run
456
- * in a timely manner so it is better to ``destroy`` the proxy explicitly.
436
+ * collected, however there is no guarantee that the finalizer will be run in
437
+ * a timely manner so it is better to ``destroy`` the proxy explicitly.
457
438
  *
458
- * @param {string} [destroyed_msg] The error message to print if use is
459
- * attempted after destroying. Defaults to "Object has already been
460
- * destroyed".
439
+ * @param destroyed_msg The error message to print if use is attempted after
440
+ * destroying. Defaults to "Object has already been destroyed".
461
441
  */
462
- destroy(destroyed_msg) {
442
+ destroy(destroyed_msg?: string) {
463
443
  Module.pyproxy_destroy(this, destroyed_msg);
464
444
  }
465
445
  /**
466
446
  * Make a new PyProxy pointing to the same Python object.
467
447
  * Useful if the PyProxy is destroyed somewhere else.
468
- * @returns {PyProxy}
469
448
  */
470
- copy() {
449
+ copy(): PyProxy {
471
450
  let ptrobj = _getPtr(this);
472
451
  return Module.pyproxy_new(ptrobj, this.$$.cache);
473
452
  }
@@ -476,125 +455,141 @@ class PyProxyClass {
476
455
  * default does a deep conversion, if a shallow conversion is desired, you can
477
456
  * use ``proxy.toJs({depth : 1})``. See :ref:`Explicit Conversion of PyProxy
478
457
  * <type-translations-pyproxy-to-js>` for more info.
479
- *
480
- * @param {object} options
481
- * @param {number} [options.depth] How many layers deep to perform the
482
- * conversion. Defaults to infinite.
483
- * @param {array} [options.pyproxies] If provided, ``toJs`` will store all
484
- * PyProxies created in this list. This allows you to easily destroy all the
485
- * PyProxies by iterating the list without having to recurse over the
486
- * generated structure. The most common use case is to create a new empty
487
- * list, pass the list as `pyproxies`, and then later iterate over `pyproxies`
488
- * to destroy all of created proxies.
489
- * @param {boolean} [options.create_pyproxies] If false, ``toJs`` will throw a
490
- * ``ConversionError`` rather than producing a ``PyProxy``.
491
- * @param {boolean} [options.dict_converter] A function to be called on an
492
- * iterable of pairs ``[key, value]``. Convert this iterable of pairs to the
493
- * desired output. For instance, ``Object.fromEntries`` would convert the dict
494
- * to an object, ``Array.from`` converts it to an array of entries, and ``(it) =>
495
- * new Map(it)`` converts it to a ``Map`` (which is the default behavior).
496
- * @return {any} The JavaScript object resulting from the conversion.
458
+ * @param options
459
+ * @return The JavaScript object resulting from the conversion.
497
460
  */
498
461
  toJs({
499
462
  depth = -1,
500
- pyproxies,
463
+ pyproxies = undefined,
501
464
  create_pyproxies = (!!1),
502
- dict_converter,
503
- } = {}) {
465
+ dict_converter = undefined,
466
+ default_converter = undefined,
467
+ }: {
468
+ /** How many layers deep to perform the conversion. Defaults to infinite */
469
+ depth?: number;
470
+ /**
471
+ * If provided, ``toJs`` will store all PyProxies created in this list. This
472
+ * allows you to easily destroy all the PyProxies by iterating the list
473
+ * without having to recurse over the generated structure. The most common
474
+ * use case is to create a new empty list, pass the list as `pyproxies`, and
475
+ * then later iterate over `pyproxies` to destroy all of created proxies.
476
+ */
477
+ pyproxies?: PyProxy[];
478
+ /**
479
+ * If false, ``toJs`` will throw a ``ConversionError`` rather than
480
+ * producing a ``PyProxy``.
481
+ */
482
+ create_pyproxies?: boolean;
483
+ /**
484
+ * A function to be called on an iterable of pairs ``[key, value]``. Convert
485
+ * this iterable of pairs to the desired output. For instance,
486
+ * ``Object.fromEntries`` would convert the dict to an object, ``Array.from``
487
+ * converts it to an array of entries, and ``(it) => new Map(it)`` converts
488
+ * it to a ``Map`` (which is the default behavior).
489
+ */
490
+ dict_converter?: (array: Iterable<[key: string, value: any]>) => any;
491
+ /**
492
+ * Optional argument to convert objects with no default conversion. See the
493
+ * documentation of :any:`pyodide.to_js`.
494
+ */
495
+ default_converter?: (
496
+ obj: PyProxy,
497
+ convert: (obj: PyProxy) => any,
498
+ cacheConversion: (obj: PyProxy, result: any) => void
499
+ ) => any;
500
+ } = {}): any {
504
501
  let ptrobj = _getPtr(this);
505
502
  let idresult;
506
503
  let proxies_id;
507
504
  let dict_converter_id = 0;
505
+ let default_converter_id = 0;
508
506
  if (!create_pyproxies) {
509
507
  proxies_id = 0;
510
508
  } else if (pyproxies) {
511
- proxies_id = Module.hiwire.new_value(pyproxies);
509
+ proxies_id = Hiwire.new_value(pyproxies);
512
510
  } else {
513
- proxies_id = Module.hiwire.new_value([]);
511
+ proxies_id = Hiwire.new_value([]);
514
512
  }
515
513
  if (dict_converter) {
516
- dict_converter_id = Module.hiwire.new_value(dict_converter);
514
+ dict_converter_id = Hiwire.new_value(dict_converter);
515
+ }
516
+ if (default_converter) {
517
+ default_converter_id = Hiwire.new_value(default_converter);
517
518
  }
518
519
  try {
519
- idresult = Module._python2js_custom_dict_converter(
520
+ idresult = Module._python2js_custom(
520
521
  ptrobj,
521
522
  depth,
522
523
  proxies_id,
523
- dict_converter_id
524
+ dict_converter_id,
525
+ default_converter_id
524
526
  );
525
527
  } catch (e) {
526
- Module.fatal_error(e);
528
+ API.fatal_error(e);
527
529
  } finally {
528
- Module.hiwire.decref(proxies_id);
529
- Module.hiwire.decref(dict_converter_id);
530
+ Hiwire.decref(proxies_id);
531
+ Hiwire.decref(dict_converter_id);
532
+ Hiwire.decref(default_converter_id);
530
533
  }
531
534
  if (idresult === 0) {
532
535
  Module._pythonexc2js();
533
536
  }
534
- return Module.hiwire.pop_value(idresult);
537
+ return Hiwire.pop_value(idresult);
535
538
  }
536
539
  /**
537
540
  * Check whether the :any:`PyProxy.length` getter is available on this PyProxy. A
538
541
  * Typescript type guard.
539
- * @returns {this is PyProxyWithLength}
540
542
  */
541
- supportsLength() {
543
+ supportsLength(): this is PyProxyWithLength {
542
544
  return !!(this.$$flags & (1 << 0));
543
545
  }
544
546
  /**
545
547
  * Check whether the :any:`PyProxy.get` method is available on this PyProxy. A
546
548
  * Typescript type guard.
547
- * @returns {this is PyProxyWithGet}
548
549
  */
549
- supportsGet() {
550
+ supportsGet(): this is PyProxyWithGet {
550
551
  return !!(this.$$flags & (1 << 1));
551
552
  }
552
553
  /**
553
554
  * Check whether the :any:`PyProxy.set` method is available on this PyProxy. A
554
555
  * Typescript type guard.
555
- * @returns {this is PyProxyWithSet}
556
556
  */
557
- supportsSet() {
557
+ supportsSet(): this is PyProxyWithSet {
558
558
  return !!(this.$$flags & (1 << 2));
559
559
  }
560
560
  /**
561
561
  * Check whether the :any:`PyProxy.has` method is available on this PyProxy. A
562
562
  * Typescript type guard.
563
- * @returns {this is PyProxyWithHas}
564
563
  */
565
- supportsHas() {
564
+ supportsHas(): this is PyProxyWithHas {
566
565
  return !!(this.$$flags & (1 << 3));
567
566
  }
568
567
  /**
569
568
  * Check whether the PyProxy is iterable. A Typescript type guard for
570
- * :any:`PyProxy.[Symbol.iterator]`.
571
- * @returns {this is PyProxyIterable}
569
+ * :any:`PyProxy.[iterator]`.
572
570
  */
573
- isIterable() {
571
+ isIterable(): this is PyProxyIterable {
574
572
  return !!(this.$$flags & ((1 << 4) | (1 << 5)));
575
573
  }
576
574
  /**
577
575
  * Check whether the PyProxy is iterable. A Typescript type guard for
578
576
  * :any:`PyProxy.next`.
579
- * @returns {this is PyProxyIterator}
580
577
  */
581
- isIterator() {
578
+ isIterator(): this is PyProxyIterator {
582
579
  return !!(this.$$flags & (1 << 5));
583
580
  }
584
581
  /**
585
582
  * Check whether the PyProxy is awaitable. A Typescript type guard, if this
586
583
  * function returns true Typescript considers the PyProxy to be a ``Promise``.
587
- * @returns {this is PyProxyAwaitable}
588
584
  */
589
- isAwaitable() {
585
+ isAwaitable(): this is PyProxyAwaitable {
590
586
  return !!(this.$$flags & (1 << 6));
591
587
  }
592
588
  /**
593
589
  * Check whether the PyProxy is a buffer. A Typescript type guard for
594
590
  * :any:`PyProxy.getBuffer`.
595
- * @returns {this is PyProxyBuffer}
596
591
  */
597
- isBuffer() {
592
+ isBuffer(): this is PyProxyBuffer {
598
593
  return !!(this.$$flags & (1 << 7));
599
594
  }
600
595
  /**
@@ -602,32 +597,27 @@ class PyProxyClass {
602
597
  * returns true then Typescript considers the Proxy to be callable of
603
598
  * signature ``(args... : any[]) => PyProxy | number | bigint | string |
604
599
  * boolean | undefined``.
605
- * @returns {this is PyProxyCallable}
606
600
  */
607
- isCallable() {
601
+ isCallable(): this is PyProxyCallable {
608
602
  return !!(this.$$flags & (1 << 8));
609
603
  }
610
604
  }
611
-
612
- /**
613
- * @typedef { PyProxy & PyProxyLengthMethods } PyProxyWithLength
614
- */
605
+ export type PyProxyWithLength = PyProxy & PyProxyLengthMethods;
615
606
  // Controlled by HAS_LENGTH, appears for any object with __len__ or sq_length
616
607
  // or mp_length methods
617
- class PyProxyLengthMethods {
608
+ export class PyProxyLengthMethods {
618
609
  /**
619
610
  * The length of the object.
620
611
  *
621
612
  * Present only if the proxied Python object has a ``__len__`` method.
622
- * @returns {number}
623
613
  */
624
- get length() {
614
+ get length(): number {
625
615
  let ptrobj = _getPtr(this);
626
616
  let length;
627
617
  try {
628
618
  length = Module._PyObject_Size(ptrobj);
629
619
  } catch (e) {
630
- Module.fatal_error(e);
620
+ API.fatal_error(e);
631
621
  }
632
622
  if (length === -1) {
633
623
  Module._pythonexc2js();
@@ -635,35 +625,28 @@ class PyProxyLengthMethods {
635
625
  return length;
636
626
  }
637
627
  }
638
-
639
- /**
640
- * @typedef {PyProxy & PyProxyGetItemMethods} PyProxyWithGet
641
- */
642
-
628
+ export type PyProxyWithGet = PyProxy & PyProxyGetItemMethods;
643
629
  // Controlled by HAS_GET, appears for any class with __getitem__,
644
630
  // mp_subscript, or sq_item methods
645
- /**
646
- * @interface
647
- */
648
- class PyProxyGetItemMethods {
631
+ export class PyProxyGetItemMethods {
649
632
  /**
650
633
  * This translates to the Python code ``obj[key]``.
651
634
  *
652
635
  * Present only if the proxied Python object has a ``__getitem__`` method.
653
636
  *
654
- * @param {any} key The key to look up.
655
- * @returns {Py2JsResult} The corresponding value.
637
+ * @param key The key to look up.
638
+ * @returns The corresponding value.
656
639
  */
657
- get(key) {
640
+ get(key: any): any {
658
641
  let ptrobj = _getPtr(this);
659
- let idkey = Module.hiwire.new_value(key);
642
+ let idkey = Hiwire.new_value(key);
660
643
  let idresult;
661
644
  try {
662
645
  idresult = Module.__pyproxy_getitem(ptrobj, idkey);
663
646
  } catch (e) {
664
- Module.fatal_error(e);
647
+ API.fatal_error(e);
665
648
  } finally {
666
- Module.hiwire.decref(idkey);
649
+ Hiwire.decref(idkey);
667
650
  }
668
651
  if (idresult === 0) {
669
652
  if (Module._PyErr_Occurred()) {
@@ -672,36 +655,33 @@ class PyProxyGetItemMethods {
672
655
  return undefined;
673
656
  }
674
657
  }
675
- return Module.hiwire.pop_value(idresult);
658
+ return Hiwire.pop_value(idresult);
676
659
  }
677
660
  }
678
-
679
- /**
680
- * @typedef {PyProxy & PyProxySetItemMethods} PyProxyWithSet
681
- */
661
+ export type PyProxyWithSet = PyProxy & PyProxySetItemMethods;
682
662
  // Controlled by HAS_SET, appears for any class with __setitem__, __delitem__,
683
663
  // mp_ass_subscript, or sq_ass_item.
684
- class PyProxySetItemMethods {
664
+ export class PyProxySetItemMethods {
685
665
  /**
686
666
  * This translates to the Python code ``obj[key] = value``.
687
667
  *
688
668
  * Present only if the proxied Python object has a ``__setitem__`` method.
689
669
  *
690
- * @param {any} key The key to set.
691
- * @param {any} value The value to set it to.
670
+ * @param key The key to set.
671
+ * @param value The value to set it to.
692
672
  */
693
- set(key, value) {
673
+ set(key: any, value: any) {
694
674
  let ptrobj = _getPtr(this);
695
- let idkey = Module.hiwire.new_value(key);
696
- let idval = Module.hiwire.new_value(value);
675
+ let idkey = Hiwire.new_value(key);
676
+ let idval = Hiwire.new_value(value);
697
677
  let errcode;
698
678
  try {
699
679
  errcode = Module.__pyproxy_setitem(ptrobj, idkey, idval);
700
680
  } catch (e) {
701
- Module.fatal_error(e);
681
+ API.fatal_error(e);
702
682
  } finally {
703
- Module.hiwire.decref(idkey);
704
- Module.hiwire.decref(idval);
683
+ Hiwire.decref(idkey);
684
+ Hiwire.decref(idval);
705
685
  }
706
686
  if (errcode === -1) {
707
687
  Module._pythonexc2js();
@@ -712,50 +692,46 @@ class PyProxySetItemMethods {
712
692
  *
713
693
  * Present only if the proxied Python object has a ``__delitem__`` method.
714
694
  *
715
- * @param {any} key The key to delete.
695
+ * @param key The key to delete.
716
696
  */
717
- delete(key) {
697
+ delete(key: any) {
718
698
  let ptrobj = _getPtr(this);
719
- let idkey = Module.hiwire.new_value(key);
699
+ let idkey = Hiwire.new_value(key);
720
700
  let errcode;
721
701
  try {
722
702
  errcode = Module.__pyproxy_delitem(ptrobj, idkey);
723
703
  } catch (e) {
724
- Module.fatal_error(e);
704
+ API.fatal_error(e);
725
705
  } finally {
726
- Module.hiwire.decref(idkey);
706
+ Hiwire.decref(idkey);
727
707
  }
728
708
  if (errcode === -1) {
729
709
  Module._pythonexc2js();
730
710
  }
731
711
  }
732
712
  }
733
-
734
- /**
735
- * @typedef {PyProxy & PyProxyContainsMethods} PyProxyWithHas
736
- */
737
-
713
+ export type PyProxyWithHas = PyProxy & PyProxyContainsMethods;
738
714
  // Controlled by HAS_CONTAINS flag, appears for any class with __contains__ or
739
715
  // sq_contains
740
- class PyProxyContainsMethods {
716
+ export class PyProxyContainsMethods {
741
717
  /**
742
718
  * This translates to the Python code ``key in obj``.
743
719
  *
744
720
  * Present only if the proxied Python object has a ``__contains__`` method.
745
721
  *
746
- * @param {*} key The key to check for.
747
- * @returns {boolean} Is ``key`` present?
722
+ * @param key The key to check for.
723
+ * @returns Is ``key`` present?
748
724
  */
749
- has(key) {
725
+ has(key: any): boolean {
750
726
  let ptrobj = _getPtr(this);
751
- let idkey = Module.hiwire.new_value(key);
727
+ let idkey = Hiwire.new_value(key);
752
728
  let result;
753
729
  try {
754
730
  result = Module.__pyproxy_contains(ptrobj, idkey);
755
731
  } catch (e) {
756
- Module.fatal_error(e);
732
+ API.fatal_error(e);
757
733
  } finally {
758
- Module.hiwire.decref(idkey);
734
+ Hiwire.decref(idkey);
759
735
  }
760
736
  if (result === -1) {
761
737
  Module._pythonexc2js();
@@ -763,7 +739,6 @@ class PyProxyContainsMethods {
763
739
  return result === 1;
764
740
  }
765
741
  }
766
-
767
742
  /**
768
743
  * A helper for [Symbol.iterator].
769
744
  *
@@ -780,14 +755,14 @@ class PyProxyContainsMethods {
780
755
  *
781
756
  * @private
782
757
  */
783
- function* iter_helper(iterptr, token) {
758
+ function* iter_helper(iterptr: number, token: {}): Generator<any> {
784
759
  try {
785
760
  let item;
786
761
  while ((item = Module.__pyproxy_iter_next(iterptr))) {
787
- yield Module.hiwire.pop_value(item);
762
+ yield Hiwire.pop_value(item);
788
763
  }
789
764
  } catch (e) {
790
- Module.fatal_error(e);
765
+ API.fatal_error(e);
791
766
  } finally {
792
767
  Module.finalizationRegistry.unregister(token);
793
768
  Module._Py_DecRef(iterptr);
@@ -796,16 +771,12 @@ function* iter_helper(iterptr, token) {
796
771
  Module._pythonexc2js();
797
772
  }
798
773
  }
799
-
800
- /**
801
- * @typedef {PyProxy & PyProxyIterableMethods} PyProxyIterable
802
- */
803
-
774
+ export type PyProxyIterable = PyProxy & PyProxyIterableMethods;
804
775
  // Controlled by IS_ITERABLE, appears for any object with __iter__ or tp_iter,
805
776
  // unless they are iterators. See: https://docs.python.org/3/c-api/iter.html
806
777
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols
807
778
  // This avoids allocating a PyProxy wrapper for the temporary iterator.
808
- class PyProxyIterableMethods {
779
+ export class PyProxyIterableMethods {
809
780
  /**
810
781
  * This translates to the Python code ``iter(obj)``. Return an iterator
811
782
  * associated to the proxy. See the documentation for `Symbol.iterator
@@ -815,117 +786,110 @@ class PyProxyIterableMethods {
815
786
  * ``__iter__`` method).
816
787
  *
817
788
  * This will be used implicitly by ``for(let x of proxy){}``.
818
- *
819
- * @returns {Iterator<Py2JsResult, Py2JsResult, any>} An iterator for the proxied Python object.
820
789
  */
821
- [Symbol.iterator]() {
790
+ [Symbol.iterator](): Iterator<any, any, any> {
822
791
  let ptrobj = _getPtr(this);
823
792
  let token = {};
824
793
  let iterptr;
825
794
  try {
826
795
  iterptr = Module._PyObject_GetIter(ptrobj);
827
796
  } catch (e) {
828
- Module.fatal_error(e);
797
+ API.fatal_error(e);
829
798
  }
830
799
  if (iterptr === 0) {
831
800
  Module._pythonexc2js();
832
801
  }
833
-
834
802
  let result = iter_helper(iterptr, token);
835
803
  Module.finalizationRegistry.register(result, [iterptr, undefined], token);
836
804
  return result;
837
805
  }
838
806
  }
839
-
840
- /**
841
- * @typedef {PyProxy & PyProxyIteratorMethods} PyProxyIterator
842
- */
843
-
807
+ export type PyProxyIterator = PyProxy & PyProxyIteratorMethods;
844
808
  // Controlled by IS_ITERATOR, appears for any object with a __next__ or
845
809
  // tp_iternext method.
846
- class PyProxyIteratorMethods {
810
+ export class PyProxyIteratorMethods {
811
+ /** @private */
847
812
  [Symbol.iterator]() {
848
813
  return this;
849
814
  }
850
815
  /**
851
- * This translates to the Python code ``next(obj)``. Returns the next value
852
- * of the generator. See the documentation for `Generator.prototype.next
816
+ * This translates to the Python code ``next(obj)``. Returns the next value of
817
+ * the generator. See the documentation for `Generator.prototype.next
853
818
  * <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/next>`_.
854
819
  * The argument will be sent to the Python generator.
855
820
  *
856
821
  * This will be used implicitly by ``for(let x of proxy){}``.
857
822
  *
858
- * Present only if the proxied Python object is a generator or iterator
859
- * (i.e., has a ``send`` or ``__next__`` method).
823
+ * Present only if the proxied Python object is a generator or iterator (i.e.,
824
+ * has a ``send`` or ``__next__`` method).
860
825
  *
861
- * @param {any=} [value] The value to send to the generator. The value will be
862
- * assigned as a result of a yield expression.
863
- * @returns {IteratorResult<Py2JsResult, Py2JsResult>} An Object with two properties: ``done`` and ``value``.
864
- * When the generator yields ``some_value``, ``next`` returns ``{done :
865
- * false, value : some_value}``. When the generator raises a
866
- * ``StopIteration(result_value)`` exception, ``next`` returns ``{done :
867
- * true, value : result_value}``.
826
+ * @param any The value to send to the generator. The value will be assigned
827
+ * as a result of a yield expression.
828
+ * @returns An Object with two properties: ``done`` and ``value``. When the
829
+ * generator yields ``some_value``, ``next`` returns ``{done : false, value :
830
+ * some_value}``. When the generator raises a ``StopIteration(result_value)``
831
+ * exception, ``next`` returns ``{done : true, value : result_value}``.
868
832
  */
869
- next(arg = undefined) {
870
- let idresult;
833
+ next(arg: any = undefined): IteratorResult<any, any> {
871
834
  // Note: arg is optional, if arg is not supplied, it will be undefined
872
835
  // which gets converted to "Py_None". This is as intended.
873
- let idarg = Module.hiwire.new_value(arg);
836
+ let idarg = Hiwire.new_value(arg);
837
+ let status;
874
838
  let done;
839
+ let stackTop = Module.stackSave();
840
+ let res_ptr = Module.stackAlloc(4);
875
841
  try {
876
- idresult = Module.__pyproxyGen_Send(_getPtr(this), idarg);
877
- done = idresult === 0;
878
- if (done) {
879
- idresult = Module.__pyproxyGen_FetchStopIterationValue();
880
- }
842
+ status = Module.__pyproxyGen_Send(_getPtr(this), idarg, res_ptr);
881
843
  } catch (e) {
882
- Module.fatal_error(e);
844
+ API.fatal_error(e);
883
845
  } finally {
884
- Module.hiwire.decref(idarg);
846
+ Hiwire.decref(idarg);
885
847
  }
886
- if (done && idresult === 0) {
848
+ let HEAPU32 = Module.HEAPU32;
849
+ let idresult = HEAPU32[(res_ptr >> 2) + 0];
850
+ Module.stackRestore(stackTop);
851
+ if (status === -1) {
887
852
  Module._pythonexc2js();
888
853
  }
889
- let value = Module.hiwire.pop_value(idresult);
854
+ let value = Hiwire.pop_value(idresult);
855
+ done = status === 0;
890
856
  return { done, value };
891
857
  }
892
858
  }
893
-
894
859
  // Another layer of boilerplate. The PyProxyHandlers have some annoying logic
895
860
  // to deal with straining out the spurious "Function" properties "prototype",
896
861
  // "arguments", and "length", to deal with correctly satisfying the Proxy
897
862
  // invariants, and to deal with the mro
898
- function python_hasattr(jsobj, jskey) {
863
+ function python_hasattr(jsobj: PyProxyClass, jskey: any) {
899
864
  let ptrobj = _getPtr(jsobj);
900
- let idkey = Module.hiwire.new_value(jskey);
865
+ let idkey = Hiwire.new_value(jskey);
901
866
  let result;
902
867
  try {
903
868
  result = Module.__pyproxy_hasattr(ptrobj, idkey);
904
869
  } catch (e) {
905
- Module.fatal_error(e);
870
+ API.fatal_error(e);
906
871
  } finally {
907
- Module.hiwire.decref(idkey);
872
+ Hiwire.decref(idkey);
908
873
  }
909
874
  if (result === -1) {
910
875
  Module._pythonexc2js();
911
876
  }
912
877
  return result !== 0;
913
878
  }
914
-
915
879
  // Returns a JsRef in order to allow us to differentiate between "not found"
916
880
  // (in which case we return 0) and "found 'None'" (in which case we return
917
881
  // Js_undefined).
918
- function python_getattr(jsobj, jskey) {
882
+ function python_getattr(jsobj: PyProxyClass, jskey: any) {
919
883
  let ptrobj = _getPtr(jsobj);
920
- let idkey = Module.hiwire.new_value(jskey);
884
+ let idkey = Hiwire.new_value(jskey);
921
885
  let idresult;
922
886
  let cacheId = jsobj.$$.cache.cacheId;
923
887
  try {
924
888
  idresult = Module.__pyproxy_getattr(ptrobj, idkey, cacheId);
925
889
  } catch (e) {
926
- Module.fatal_error(e);
890
+ API.fatal_error(e);
927
891
  } finally {
928
- Module.hiwire.decref(idkey);
892
+ Hiwire.decref(idkey);
929
893
  }
930
894
  if (idresult === 0) {
931
895
  if (Module._PyErr_Occurred()) {
@@ -934,41 +898,38 @@ function python_getattr(jsobj, jskey) {
934
898
  }
935
899
  return idresult;
936
900
  }
937
-
938
- function python_setattr(jsobj, jskey, jsval) {
901
+ function python_setattr(jsobj: PyProxyClass, jskey: any, jsval: any) {
939
902
  let ptrobj = _getPtr(jsobj);
940
- let idkey = Module.hiwire.new_value(jskey);
941
- let idval = Module.hiwire.new_value(jsval);
903
+ let idkey = Hiwire.new_value(jskey);
904
+ let idval = Hiwire.new_value(jsval);
942
905
  let errcode;
943
906
  try {
944
907
  errcode = Module.__pyproxy_setattr(ptrobj, idkey, idval);
945
908
  } catch (e) {
946
- Module.fatal_error(e);
909
+ API.fatal_error(e);
947
910
  } finally {
948
- Module.hiwire.decref(idkey);
949
- Module.hiwire.decref(idval);
911
+ Hiwire.decref(idkey);
912
+ Hiwire.decref(idval);
950
913
  }
951
914
  if (errcode === -1) {
952
915
  Module._pythonexc2js();
953
916
  }
954
917
  }
955
-
956
- function python_delattr(jsobj, jskey) {
918
+ function python_delattr(jsobj: PyProxyClass, jskey: any) {
957
919
  let ptrobj = _getPtr(jsobj);
958
- let idkey = Module.hiwire.new_value(jskey);
920
+ let idkey = Hiwire.new_value(jskey);
959
921
  let errcode;
960
922
  try {
961
923
  errcode = Module.__pyproxy_delattr(ptrobj, idkey);
962
924
  } catch (e) {
963
- Module.fatal_error(e);
925
+ API.fatal_error(e);
964
926
  } finally {
965
- Module.hiwire.decref(idkey);
927
+ Hiwire.decref(idkey);
966
928
  }
967
929
  if (errcode === -1) {
968
930
  Module._pythonexc2js();
969
931
  }
970
932
  }
971
-
972
933
  // See explanation of which methods should be defined here and what they do
973
934
  // here:
974
935
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
@@ -976,7 +937,7 @@ let PyProxyHandlers = {
976
937
  isExtensible() {
977
938
  return (!!1);
978
939
  },
979
- has(jsobj, jskey) {
940
+ has(jsobj: PyProxyClass, jskey: any) {
980
941
  // Note: must report "prototype" in proxy when we are callable.
981
942
  // (We can return the wrong value from "get" handler though.)
982
943
  let objHasKey = Reflect.has(jsobj, jskey);
@@ -992,11 +953,10 @@ let PyProxyHandlers = {
992
953
  }
993
954
  return python_hasattr(jsobj, jskey);
994
955
  },
995
- get(jsobj, jskey) {
956
+ get(jsobj: PyProxyClass, jskey: any) {
996
957
  // Preference order:
997
958
  // 1. stuff from JavaScript
998
959
  // 2. the result of Python getattr
999
-
1000
960
  // python_getattr will crash if given a Symbol.
1001
961
  if (jskey in jsobj || typeof jskey === "symbol") {
1002
962
  return Reflect.get(jsobj, jskey);
@@ -1009,10 +969,10 @@ let PyProxyHandlers = {
1009
969
  // 2. The result of getattr
1010
970
  let idresult = python_getattr(jsobj, jskey);
1011
971
  if (idresult !== 0) {
1012
- return Module.hiwire.pop_value(idresult);
972
+ return Hiwire.pop_value(idresult);
1013
973
  }
1014
974
  },
1015
- set(jsobj, jskey, jsval) {
975
+ set(jsobj: PyProxyClass, jskey: any, jsval: any) {
1016
976
  let descr = Object.getOwnPropertyDescriptor(jsobj, jskey);
1017
977
  if (descr && !descr.writable) {
1018
978
  throw new TypeError(`Cannot set read only field '${jskey}'`);
@@ -1027,7 +987,7 @@ let PyProxyHandlers = {
1027
987
  python_setattr(jsobj, jskey, jsval);
1028
988
  return (!!1);
1029
989
  },
1030
- deleteProperty(jsobj, jskey) {
990
+ deleteProperty(jsobj: PyProxyClass, jskey: any): boolean {
1031
991
  let descr = Object.getOwnPropertyDescriptor(jsobj, jskey);
1032
992
  if (descr && !descr.writable) {
1033
993
  throw new TypeError(`Cannot delete read only field '${jskey}'`);
@@ -1041,44 +1001,41 @@ let PyProxyHandlers = {
1041
1001
  python_delattr(jsobj, jskey);
1042
1002
  // Must return "false" if "jskey" is a nonconfigurable own property.
1043
1003
  // Otherwise JavaScript will throw a TypeError.
1044
- return !descr || descr.configurable;
1004
+ return !descr || !!descr.configurable;
1045
1005
  },
1046
- ownKeys(jsobj) {
1006
+ ownKeys(jsobj: PyProxyClass) {
1047
1007
  let ptrobj = _getPtr(jsobj);
1048
1008
  let idresult;
1049
1009
  try {
1050
1010
  idresult = Module.__pyproxy_ownKeys(ptrobj);
1051
1011
  } catch (e) {
1052
- Module.fatal_error(e);
1012
+ API.fatal_error(e);
1053
1013
  }
1054
1014
  if (idresult === 0) {
1055
1015
  Module._pythonexc2js();
1056
1016
  }
1057
- let result = Module.hiwire.pop_value(idresult);
1017
+ let result = Hiwire.pop_value(idresult);
1058
1018
  result.push(...Reflect.ownKeys(jsobj));
1059
1019
  return result;
1060
1020
  },
1061
- apply(jsobj, jsthis, jsargs) {
1021
+ apply(jsobj: PyProxyClass & Function, jsthis: any, jsargs: any) {
1062
1022
  return jsobj.apply(jsthis, jsargs);
1063
1023
  },
1064
1024
  };
1065
-
1066
- /**
1067
- * @typedef {PyProxy & Promise<Py2JsResult>} PyProxyAwaitable
1068
- */
1069
-
1025
+ export type PyProxyAwaitable = PyProxy & Promise<any>;
1070
1026
  /**
1071
1027
  * The Promise / JavaScript awaitable API.
1072
1028
  * @private
1073
1029
  */
1074
- class PyProxyAwaitableMethods {
1030
+ export class PyProxyAwaitableMethods {
1031
+ $$: any;
1075
1032
  /**
1076
1033
  * This wraps __pyproxy_ensure_future and makes a function that converts a
1077
1034
  * Python awaitable to a promise, scheduling the awaitable on the Python
1078
1035
  * event loop if necessary.
1079
1036
  * @private
1080
1037
  */
1081
- _ensure_future() {
1038
+ _ensure_future(): Promise<any> {
1082
1039
  if (this.$$.promise) {
1083
1040
  return this.$$.promise;
1084
1041
  }
@@ -1089,8 +1046,8 @@ class PyProxyAwaitableMethods {
1089
1046
  resolveHandle = resolve;
1090
1047
  rejectHandle = reject;
1091
1048
  });
1092
- let resolve_handle_id = Module.hiwire.new_value(resolveHandle);
1093
- let reject_handle_id = Module.hiwire.new_value(rejectHandle);
1049
+ let resolve_handle_id = Hiwire.new_value(resolveHandle);
1050
+ let reject_handle_id = Hiwire.new_value(rejectHandle);
1094
1051
  let errcode;
1095
1052
  try {
1096
1053
  errcode = Module.__pyproxy_ensure_future(
@@ -1099,15 +1056,16 @@ class PyProxyAwaitableMethods {
1099
1056
  reject_handle_id
1100
1057
  );
1101
1058
  } catch (e) {
1102
- Module.fatal_error(e);
1059
+ API.fatal_error(e);
1103
1060
  } finally {
1104
- Module.hiwire.decref(reject_handle_id);
1105
- Module.hiwire.decref(resolve_handle_id);
1061
+ Hiwire.decref(reject_handle_id);
1062
+ Hiwire.decref(resolve_handle_id);
1106
1063
  }
1107
1064
  if (errcode === -1) {
1108
1065
  Module._pythonexc2js();
1109
1066
  }
1110
1067
  this.$$.promise = promise;
1068
+ // @ts-ignore
1111
1069
  this.destroy();
1112
1070
  return promise;
1113
1071
  }
@@ -1115,7 +1073,7 @@ class PyProxyAwaitableMethods {
1115
1073
  * Runs ``asyncio.ensure_future(awaitable)``, executes
1116
1074
  * ``onFulfilled(result)`` when the ``Future`` resolves successfully,
1117
1075
  * executes ``onRejected(error)`` when the ``Future`` fails. Will be used
1118
- * implictly by ``await obj``.
1076
+ * implicitly by ``await obj``.
1119
1077
  *
1120
1078
  * See the documentation for
1121
1079
  * `Promise.then
@@ -1124,13 +1082,16 @@ class PyProxyAwaitableMethods {
1124
1082
  * Present only if the proxied Python object is `awaitable
1125
1083
  * <https://docs.python.org/3/library/asyncio-task.html?highlight=awaitable#awaitables>`_.
1126
1084
  *
1127
- * @param {Function} onFulfilled A handler called with the result as an
1085
+ * @param onFulfilled A handler called with the result as an
1128
1086
  * argument if the awaitable succeeds.
1129
- * @param {Function} onRejected A handler called with the error as an
1087
+ * @param onRejected A handler called with the error as an
1130
1088
  * argument if the awaitable fails.
1131
- * @returns {Promise} The resulting Promise.
1089
+ * @returns The resulting Promise.
1132
1090
  */
1133
- then(onFulfilled, onRejected) {
1091
+ then(
1092
+ onFulfilled: (value: any) => any,
1093
+ onRejected: (reason: any) => any
1094
+ ): Promise<any> {
1134
1095
  let promise = this._ensure_future();
1135
1096
  return promise.then(onFulfilled, onRejected);
1136
1097
  }
@@ -1145,11 +1106,11 @@ class PyProxyAwaitableMethods {
1145
1106
  * Present only if the proxied Python object is `awaitable
1146
1107
  * <https://docs.python.org/3/library/asyncio-task.html?highlight=awaitable#awaitables>`_.
1147
1108
  *
1148
- * @param {Function} onRejected A handler called with the error as an
1109
+ * @param onRejected A handler called with the error as an
1149
1110
  * argument if the awaitable fails.
1150
- * @returns {Promise} The resulting Promise.
1111
+ * @returns The resulting Promise.
1151
1112
  */
1152
- catch(onRejected) {
1113
+ catch(onRejected: (reason: any) => any) {
1153
1114
  let promise = this._ensure_future();
1154
1115
  return promise.catch(onRejected);
1155
1116
  }
@@ -1165,33 +1126,32 @@ class PyProxyAwaitableMethods {
1165
1126
  * <https://docs.python.org/3/library/asyncio-task.html?highlight=awaitable#awaitables>`_.
1166
1127
  *
1167
1128
  *
1168
- * @param {Function} onFinally A handler that is called with zero arguments
1129
+ * @param onFinally A handler that is called with zero arguments
1169
1130
  * when the awaitable resolves.
1170
- * @returns {Promise} A Promise that resolves or rejects with the same
1131
+ * @returns A Promise that resolves or rejects with the same
1171
1132
  * result as the original Promise, but only after executing the
1172
1133
  * ``onFinally`` handler.
1173
1134
  */
1174
- finally(onFinally) {
1135
+ finally(onFinally: () => void) {
1175
1136
  let promise = this._ensure_future();
1176
1137
  return promise.finally(onFinally);
1177
1138
  }
1178
1139
  }
1179
-
1180
- /**
1181
- * @typedef { PyProxy & PyProxyCallableMethods & ((...args : any[]) => Py2JsResult) } PyProxyCallable
1182
- */
1183
- class PyProxyCallableMethods {
1184
- apply(jsthis, jsargs) {
1140
+ export type PyProxyCallable = PyProxy &
1141
+ PyProxyCallableMethods &
1142
+ ((...args: any[]) => any);
1143
+ export class PyProxyCallableMethods {
1144
+ apply(jsthis: PyProxyClass, jsargs: any) {
1185
1145
  return Module.callPyObject(_getPtr(this), ...jsargs);
1186
1146
  }
1187
- call(jsthis, ...jsargs) {
1147
+ call(jsthis: PyProxyClass, ...jsargs: any) {
1188
1148
  return Module.callPyObject(_getPtr(this), ...jsargs);
1189
1149
  }
1190
1150
  /**
1191
1151
  * Call the function with key word arguments.
1192
1152
  * The last argument must be an object with the keyword arguments.
1193
1153
  */
1194
- callKwargs(...jsargs) {
1154
+ callKwargs(...jsargs: any) {
1195
1155
  if (jsargs.length === 0) {
1196
1156
  throw new TypeError(
1197
1157
  "callKwargs requires at least one argument (the key word argument object)"
@@ -1207,9 +1167,10 @@ class PyProxyCallableMethods {
1207
1167
  return Module.callPyObjectKwargs(_getPtr(this), ...jsargs);
1208
1168
  }
1209
1169
  }
1170
+ // @ts-ignore
1210
1171
  PyProxyCallableMethods.prototype.prototype = Function.prototype;
1211
-
1212
- let type_to_array_map = new Map([
1172
+ // @ts-ignore
1173
+ let type_to_array_map: Map<string, any> = new Map([
1213
1174
  ["i8", Int8Array],
1214
1175
  ["u8", Uint8Array],
1215
1176
  ["u8clamped", Uint8ClampedArray],
@@ -1227,11 +1188,8 @@ let type_to_array_map = new Map([
1227
1188
  ["f64", Float64Array],
1228
1189
  ["dataview", DataView],
1229
1190
  ]);
1230
-
1231
- /**
1232
- * @typedef {PyProxy & PyProxyBufferMethods} PyProxyBuffer
1233
- */
1234
- class PyProxyBufferMethods {
1191
+ export type PyProxyBuffer = PyProxy & PyProxyBufferMethods;
1192
+ export class PyProxyBufferMethods {
1235
1193
  /**
1236
1194
  * Get a view of the buffer data which is usable from JavaScript. No copy is
1237
1195
  * ever performed.
@@ -1253,16 +1211,16 @@ class PyProxyBufferMethods {
1253
1211
  * have support for big endian data, so you might want to pass
1254
1212
  * ``'dataview'`` as the type argument in that case.
1255
1213
  *
1256
- * @param {string=} [type] The type of the :any:`PyBuffer.data <pyodide.PyBuffer.data>` field in the
1214
+ * @param type The type of the :any:`PyBuffer.data <pyodide.PyBuffer.data>` field in the
1257
1215
  * output. Should be one of: ``"i8"``, ``"u8"``, ``"u8clamped"``, ``"i16"``,
1258
1216
  * ``"u16"``, ``"i32"``, ``"u32"``, ``"i32"``, ``"u32"``, ``"i64"``,
1259
1217
  * ``"u64"``, ``"f32"``, ``"f64``, or ``"dataview"``. This argument is
1260
1218
  * optional, if absent ``getBuffer`` will try to determine the appropriate
1261
1219
  * output type based on the buffer `format string
1262
1220
  * <https://docs.python.org/3/library/struct.html#format-strings>`_.
1263
- * @returns {PyBuffer} :any:`PyBuffer <pyodide.PyBuffer>`
1221
+ * @returns :any:`PyBuffer <pyodide.PyBuffer>`
1264
1222
  */
1265
- getBuffer(type) {
1223
+ getBuffer(type?: string): PyBuffer {
1266
1224
  let ArrayType = undefined;
1267
1225
  if (type) {
1268
1226
  ArrayType = type_to_array_map.get(type);
@@ -1280,30 +1238,25 @@ class PyProxyBufferMethods {
1280
1238
  try {
1281
1239
  errcode = Module.__pyproxy_get_buffer(buffer_struct_ptr, this_ptr);
1282
1240
  } catch (e) {
1283
- Module.fatal_error(e);
1241
+ API.fatal_error(e);
1284
1242
  }
1285
1243
  if (errcode === -1) {
1286
1244
  Module._pythonexc2js();
1287
1245
  }
1288
-
1289
1246
  // This has to match the fields in buffer_struct
1290
1247
  let startByteOffset = HEAPU32[(buffer_struct_ptr >> 2) + 0];
1291
1248
  let minByteOffset = HEAPU32[(buffer_struct_ptr >> 2) + 1];
1292
1249
  let maxByteOffset = HEAPU32[(buffer_struct_ptr >> 2) + 2];
1293
-
1294
1250
  let readonly = !!HEAPU32[(buffer_struct_ptr >> 2) + 3];
1295
1251
  let format_ptr = HEAPU32[(buffer_struct_ptr >> 2) + 4];
1296
1252
  let itemsize = HEAPU32[(buffer_struct_ptr >> 2) + 5];
1297
- let shape = Module.hiwire.pop_value(HEAPU32[(buffer_struct_ptr >> 2) + 6]);
1298
- let strides = Module.hiwire.pop_value(HEAPU32[(buffer_struct_ptr >> 2) + 7]);
1299
-
1253
+ let shape = Hiwire.pop_value(HEAPU32[(buffer_struct_ptr >> 2) + 6]);
1254
+ let strides = Hiwire.pop_value(HEAPU32[(buffer_struct_ptr >> 2) + 7]);
1300
1255
  let view_ptr = HEAPU32[(buffer_struct_ptr >> 2) + 8];
1301
1256
  let c_contiguous = !!HEAPU32[(buffer_struct_ptr >> 2) + 9];
1302
1257
  let f_contiguous = !!HEAPU32[(buffer_struct_ptr >> 2) + 10];
1303
-
1304
1258
  let format = Module.UTF8ToString(format_ptr);
1305
1259
  Module.stackRestore(orig_stack_ptr);
1306
-
1307
1260
  let success = (!!0);
1308
1261
  try {
1309
1262
  let bigEndian = (!!0);
@@ -1346,7 +1299,6 @@ class PyProxyBufferMethods {
1346
1299
  for (let i of strides.keys()) {
1347
1300
  strides[i] /= alignment;
1348
1301
  }
1349
-
1350
1302
  success = (!!1);
1351
1303
  let result = Object.create(
1352
1304
  PyBuffer.prototype,
@@ -1374,17 +1326,23 @@ class PyProxyBufferMethods {
1374
1326
  Module._PyBuffer_Release(view_ptr);
1375
1327
  Module._PyMem_Free(view_ptr);
1376
1328
  } catch (e) {
1377
- Module.fatal_error(e);
1329
+ API.fatal_error(e);
1378
1330
  }
1379
1331
  }
1380
1332
  }
1381
1333
  }
1382
1334
  }
1383
-
1384
- /**
1385
- * @typedef {Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array} TypedArray;
1386
- */
1387
-
1335
+ export type TypedArray =
1336
+ | Int8Array
1337
+ | Uint8Array
1338
+ | Int16Array
1339
+ | Uint16Array
1340
+ | Int32Array
1341
+ | Uint32Array
1342
+ | Uint8ClampedArray
1343
+ | Float32Array
1344
+ | Float64Array;
1345
+ export type PyProxyDict = PyProxyWithGet & PyProxyWithSet & PyProxyWithHas;
1388
1346
  /**
1389
1347
  * A class to allow access to a Python data buffers from JavaScript. These are
1390
1348
  * produced by :any:`PyProxy.getBuffer` and cannot be constructed directly.
@@ -1452,93 +1410,82 @@ class PyProxyBufferMethods {
1452
1410
  * );
1453
1411
  */
1454
1412
  export class PyBuffer {
1413
+ /**
1414
+ * The offset of the first entry of the array. For instance if our array
1415
+ * is 3d, then you will find ``array[0,0,0]`` at
1416
+ * ``pybuf.data[pybuf.offset]``
1417
+ */
1418
+ offset: number;
1419
+ /**
1420
+ * If the data is readonly, you should not modify it. There is no way
1421
+ * for us to enforce this, but it may cause very weird behavior.
1422
+ */
1423
+ readonly: boolean;
1424
+ /**
1425
+ * The format string for the buffer. See `the Python documentation on
1426
+ * format strings
1427
+ * <https://docs.python.org/3/library/struct.html#format-strings>`_.
1428
+ */
1429
+ format: string;
1430
+ /**
1431
+ * How large is each entry (in bytes)?
1432
+ */
1433
+ itemsize: number;
1434
+ /**
1435
+ * The number of dimensions of the buffer. If ``ndim`` is 0, the buffer
1436
+ * represents a single scalar or struct. Otherwise, it represents an
1437
+ * array.
1438
+ */
1439
+ ndim: number;
1440
+ /**
1441
+ * The total number of bytes the buffer takes up. This is equal to
1442
+ * ``buff.data.byteLength``.
1443
+ */
1444
+ nbytes: number;
1445
+ /**
1446
+ * The shape of the buffer, that is how long it is in each dimension.
1447
+ * The length will be equal to ``ndim``. For instance, a 2x3x4 array
1448
+ * would have shape ``[2, 3, 4]``.
1449
+ */
1450
+ shape: number[];
1451
+ /**
1452
+ * An array of of length ``ndim`` giving the number of elements to skip
1453
+ * to get to a new element in each dimension. See the example definition
1454
+ * of a ``multiIndexToIndex`` function above.
1455
+ */
1456
+ strides: number[];
1457
+ /**
1458
+ * The actual data. A typed array of an appropriate size backed by a
1459
+ * segment of the WASM memory.
1460
+ *
1461
+ * The ``type`` argument of :any:`PyProxy.getBuffer`
1462
+ * determines which sort of ``TypedArray`` this is. By default
1463
+ * :any:`PyProxy.getBuffer` will look at the format string to determine the most
1464
+ * appropriate option.
1465
+ */
1466
+ data: TypedArray;
1467
+ /**
1468
+ * Is it C contiguous?
1469
+ */
1470
+ c_contiguous: boolean;
1471
+ /**
1472
+ * Is it Fortran contiguous?
1473
+ */
1474
+ f_contiguous: boolean;
1475
+ /**
1476
+ * @private
1477
+ */
1478
+ _released: boolean;
1479
+ /**
1480
+ * @private
1481
+ */
1482
+ _view_ptr: number;
1483
+ /**
1484
+ * @private
1485
+ */
1455
1486
  constructor() {
1456
- /**
1457
- * The offset of the first entry of the array. For instance if our array
1458
- * is 3d, then you will find ``array[0,0,0]`` at
1459
- * ``pybuf.data[pybuf.offset]``
1460
- * @type {number}
1461
- */
1462
- this.offset;
1463
-
1464
- /**
1465
- * If the data is readonly, you should not modify it. There is no way
1466
- * for us to enforce this, but it may cause very weird behavior.
1467
- * @type {boolean}
1468
- */
1469
- this.readonly;
1470
-
1471
- /**
1472
- * The format string for the buffer. See `the Python documentation on
1473
- * format strings
1474
- * <https://docs.python.org/3/library/struct.html#format-strings>`_.
1475
- * @type {string}
1476
- */
1477
- this.format;
1478
-
1479
- /**
1480
- * How large is each entry (in bytes)?
1481
- * @type {number}
1482
- */
1483
- this.itemsize;
1484
-
1485
- /**
1486
- * The number of dimensions of the buffer. If ``ndim`` is 0, the buffer
1487
- * represents a single scalar or struct. Otherwise, it represents an
1488
- * array.
1489
- * @type {number}
1490
- */
1491
- this.ndim;
1492
-
1493
- /**
1494
- * The total number of bytes the buffer takes up. This is equal to
1495
- * ``buff.data.byteLength``.
1496
- * @type {number}
1497
- */
1498
- this.nbytes;
1499
-
1500
- /**
1501
- * The shape of the buffer, that is how long it is in each dimension.
1502
- * The length will be equal to ``ndim``. For instance, a 2x3x4 array
1503
- * would have shape ``[2, 3, 4]``.
1504
- * @type {number[]}
1505
- */
1506
- this.shape;
1507
-
1508
- /**
1509
- * An array of of length ``ndim`` giving the number of elements to skip
1510
- * to get to a new element in each dimension. See the example definition
1511
- * of a ``multiIndexToIndex`` function above.
1512
- * @type {number[]}
1513
- */
1514
- this.strides;
1515
-
1516
- /**
1517
- * The actual data. A typed array of an appropriate size backed by a
1518
- * segment of the WASM memory.
1519
- *
1520
- * The ``type`` argument of :any:`PyProxy.getBuffer`
1521
- * determines which sort of ``TypedArray`` this is. By default
1522
- * :any:`PyProxy.getBuffer` will look at the format string to determine the most
1523
- * appropriate option.
1524
- * @type {TypedArray}
1525
- */
1526
- this.data;
1527
-
1528
- /**
1529
- * Is it C contiguous?
1530
- * @type {boolean}
1531
- */
1532
- this.c_contiguous;
1533
-
1534
- /**
1535
- * Is it Fortran contiguous?
1536
- * @type {boolean}
1537
- */
1538
- this.f_contiguous;
1539
1487
  throw new TypeError("PyBuffer is not a constructor");
1540
1488
  }
1541
-
1542
1489
  /**
1543
1490
  * Release the buffer. This allows the memory to be reclaimed.
1544
1491
  */
@@ -1551,9 +1498,10 @@ export class PyBuffer {
1551
1498
  Module._PyBuffer_Release(this._view_ptr);
1552
1499
  Module._PyMem_Free(this._view_ptr);
1553
1500
  } catch (e) {
1554
- Module.fatal_error(e);
1501
+ API.fatal_error(e);
1555
1502
  }
1556
1503
  this._released = (!!1);
1504
+ // @ts-ignore
1557
1505
  this.data = null;
1558
1506
  }
1559
1507
  }