@ryanking13 added these very nice error messages to the `ModuleNotFound`
errors. However they introduce a few problems:
1. `find_spec` is supposed to return `None` or a spec and not to raise an error.
If it raises errors, it can cause trouble in code that tries to check if a module is
installed or not.
2. Other code that tries to add new import hooks has to know to insert them
before these error-raising import hooks.
See the discussion in #3262.
This instead patches `importlib._bootstrap` to create a function called
`_get_module_not_found_error`. We then can monkey patch this to modify
the error messages that `importlib` raises.
See Python issue: https://github.com/python/cpython/issues/100208
If a JavaScript has a `next` method and exactly one of `Symbol.iterator` or `Symbol.asyncIterator`
we use that to tell us whether we think `next` is sync or async. If both or neither of these
Symbols are present then we define both `__next__` and `__anext__`.
Continuing with my work on support for generators, this adds `athrow` and
`aclose` for async generators.
Currently if you use `athrow` and the generator doesn't catch the error, it will
throw a double wrapped error. This is probably also a problem with async calls
Python --> Js --> Python because the way that we control the Python exception
lifetime only works correctly in synchronous contexts. Fixing this is a TODO.
Also, there is still a question of what to do with return values of async Javascript
generators. Currently I think they are available from Python as
`async_stop_iteration_exception.args[0]`.
This adds tests of all the `MutableMapping` methods for objects returned by
`as_object_map`. They all worked but I was accidentally adding only the non
mutating methods. I also added `JsMap` and `JsMutableMap` to `pyodide.ffi`
and fixed it so that `isinstance` works correctly and mypy agrees with the usage.
Adds a new key in meta.yaml spec: requirements/executable which specifies the list of executables required to build a package. Unlike conda, we don't build or install these executables. This key exists just to halt build earlier
Co-authored-by: Hood Chatham <roberthoodchatham@gmail.com>
This defines `__aiter__` for JavaScript objects with a `Symbol.iterator`.
It also defines `anext` and `asend` for JavaScript objects with a `next` function.
These will fail with a suggestion to use `next`/`send` instead if the `next` function
does not return a promise.
This adds two new types to `pyodide.ffi`: `JsIterator` (which requires an object
to have a `next` method) and `JsGenerator` (which requires an object to be a true
JavaScript generator). The `JsIterator` type has `__next__` and `send` implementations,
and `JsGenerator` has also `throw` and `close` methods.
Unlike for Python generators, it's allowed to `send` a non-None value into a not-started
generator. We have no way to detect that the generator isn't started (JavaScript just
ignores the value).
This also improves the error messages when `next` called on an object returns something
unexpected.
My local build fails with:
```
RollupError: Node tried to load your configuration file as CommonJS
even though it is likely an ES module. To resolve this, change the
extension of your configuration to ".mjs", set "type": "module" in
your package.json file or pass the "--bundleConfigAsCjs" flag.
Original error: Cannot use import statement outside a module
```
This fixes it.
This ensures that `PySequence_Check` of a `JsProxy` of a `Array` returns
`True`, that `isinstance(jsproxy_of_array, Sequence)` returns `True`, and
that `isinstance(jsproxy_of_mapping, Mapping)` returns `True`.
This makes it possible to use `JsArray` and `JsMap` with the `match` keyword.
See https://github.com/pyodide/pyodide/discussions/2903.
This adds methods `keys`, `items`, `values`, `get`, `pop`, `setdefault`, `popitem`,
`update`, and `clear` to a `JsProxy` of a map-like object. Since both Sequence-like
objects and Map-like objects have a `pop` method but they have different
signatures, I had to split the `JsProxy` documentation class into several different
classes. This is probably a good idea anyways. As a followup I could set it up so
that `isinstance` and `issubclass` work correctly on these documentation classes.
This improves compute_typeflags by moving the implementation
into JavaScript. This makes it more readable (because the conditions
are all in one place right next to each other rather than spread through
hiwire.c) and faster (because we don't have to call 15 different JavaScript
functions).
Before we had a single `JsProxy` documentation class. Apparently mypy treated
it as `Any`. It had a bunch of methods on it that may or may not appear in
any specific ` sProxy`.
This does two things:
1. Split up `JsProxy` class into several synthetic subclasses like `JsArray`,
`JsBuffer` etc. These work much better with mypy, they should also improve
documentation layout and it helps when different subclassess have different
methods with the same name (e.g., `JsArray` and `JsMap` both will have `pop`
methods).
2. Make `isinstance` and `issubclass` work correctly both with synthetic `JsProxy`
classes like `JsArray`, `JsBuffer` etc and with `type(an_actual_jsproxy)`.
This cleans up the bootstrapping mess in `_importhook` because the `JsProxy`
from `_core_docs` works fine for instance checks now.
I had to make changes to various other Python files
because mypy now understands the types better and noticed that there were type errors.
For instance, this fixed several minor mistakes in the types in `http.py`.