Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
with:
build-artifact-name: none
build-artifact-path: none
pyodide-versions: "0.27.2,0.26.4"
pyodide-versions: "0.28.0a3"

deploy:
runs-on: ubuntu-24.04
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ jobs:

- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
with:
python-version: 3.12
python-version: 3.13

- name: install pyodide-py
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/testall.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
with:
python-version: 3.12 # keep this in sync with Pyodide's Python version
python-version: 3.13 # keep this in sync with Pyodide's Python version
- name: Build test matrix
id: build-matrix
run: |
Expand Down
21 changes: 11 additions & 10 deletions COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ Other versions may work, however with no guarantee.

| pytest-pyodide | Tested Pyodide versions |
| -------------- | ----------------------- |
| main branch | 0.26.4, 0.27.2 |
| 0.58.* | 0.24.1, 0.25.1, 0.26.1 |
| 0.57.* | 0.23.4, 0.24.1, 0.25.1 |
| 0.56.* | 0.23.4, 0.24.1 |
| 0.55.* | 0.23.4, 0.24.1 |
| 0.54.* | 0.23.4, 0.24.1 |
| 0.53.* | 0.23.2, 0.22.0 |
| 0.52.* | 0.23.2, 0.22.0 |
| 0.51.* | 0.23.2, 0.22.0, 0.21.3 |
| 0.50.* | 0.22.0, 0.21.3 |
| main branch | 0.28.0a3 |
| 0.58.6 | 0.26.4, 0.27.2 |
| 0.58.1-5 | 0.24.1, 0.25.1, 0.26.1 |
| 0.57.* | 0.23.4, 0.24.1, 0.25.1 |
| 0.56.* | 0.23.4, 0.24.1 |
| 0.55.* | 0.23.4, 0.24.1 |
| 0.54.* | 0.23.4, 0.24.1 |
| 0.53.* | 0.23.2, 0.22.0 |
| 0.52.* | 0.23.2, 0.22.0 |
| 0.51.* | 0.23.2, 0.22.0, 0.21.3 |
| 0.50.* | 0.22.0, 0.21.3 |
| 0.23.* | 0.21.0 |
5 changes: 3 additions & 2 deletions pytest_pyodide/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
from collections.abc import Iterable, Sequence
from typing import Literal

PYODIDE_LOCKFILE_URL_PLACEHOLDER_STR = "PYODIDE_LOCKFILE_URL_PLACEHOLDER"

Check warning on line 8 in pytest_pyodide/config.py

View check run for this annotation

Codecov / codecov/patch

pytest_pyodide/config.py#L8

Added line #L8 was not covered by tests
RUNTIMES = Literal["chrome", "firefox", "node", "safari"]

_global_load_pyodide_script = """
let pyodide = await loadPyodide({ fullStdLib: false, jsglobals : self });
_global_load_pyodide_script = f"""

Check warning on line 11 in pytest_pyodide/config.py

View check run for this annotation

Codecov / codecov/patch

pytest_pyodide/config.py#L11

Added line #L11 was not covered by tests
let pyodide = await loadPyodide({{ fullStdLib: false, jsglobals : self, lockFileURL: "{PYODIDE_LOCKFILE_URL_PLACEHOLDER_STR}" }});
"""


Expand Down
2 changes: 1 addition & 1 deletion pytest_pyodide/decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@


def package_is_built(package_name: str):
return _package_is_built(package_name, pytest_wrapper.pyodide_dist_dir)
return _package_is_built(package_name, pytest_wrapper.pyodide_lockfile_dir)


class SeleniumType(Protocol):
Expand Down
48 changes: 34 additions & 14 deletions pytest_pyodide/fixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,12 @@
return None, as initializing Pyodide for selenium is expensive
"""

server_hostname, server_port, server_log = web_server_main
runtime_server, lockfile_server = web_server_main
runtime_server_url = f"http://{runtime_server[0]}:{runtime_server[1]}"
runtime_server_log = runtime_server[2]
lockfile_server_url = f"http://{lockfile_server[0]}:{lockfile_server[1]}"
lockfile_server_log = lockfile_server[2]

runner_type = request.config.option.runner.lower()

runner_set: dict[tuple[str, str], type[_BrowserBaseRunner]] = {
Expand All @@ -105,15 +110,18 @@
if runner_cls is None:
raise AssertionError(f"Unknown runner or browser: {runner_type} / {runtime}")

dist_dir = Path(os.getcwd(), request.config.getoption("--dist-dir"))
dist_dir = Path(os.getcwd(), pytest_wrapper.pyodide_dist_dir)
lockfile_dir = Path(os.getcwd(), pytest_wrapper.pyodide_lockfile_dir)
runner = runner_cls(
server_port=server_port,
server_hostname=server_hostname,
server_log=server_log,
runtime_server_url=runtime_server_url,
runtime_server_log=runtime_server_log,
lockfile_server_url=lockfile_server_url,
lockfile_server_log=lockfile_server_log,
load_pyodide=load_pyodide,
browsers=browsers,
script_type=script_type,
dist_dir=dist_dir,
lockfile_dir=lockfile_dir,
jspi=jspi,
)
try:
Expand Down Expand Up @@ -328,9 +336,7 @@
load_pyodide=False,
browsers=playwright_browsers,
) as selenium:
selenium.goto(
f"http://{selenium.server_hostname}:{selenium.server_port}/console.html"
)
selenium.goto(f"{selenium.dist_url}/console.html")

Check warning on line 339 in pytest_pyodide/fixture.py

View check run for this annotation

Codecov / codecov/patch

pytest_pyodide/fixture.py#L339

Added line #L339 was not covered by tests
selenium.javascript_setup()
try:
yield selenium
Expand All @@ -339,17 +345,31 @@


@pytest.fixture(scope="session")
def web_server_main(request):
def web_server_main():

Check warning on line 348 in pytest_pyodide/fixture.py

View check run for this annotation

Codecov / codecov/patch

pytest_pyodide/fixture.py#L348

Added line #L348 was not covered by tests
"""Web server that serves files in the dist directory"""
with spawn_web_server(request.config.option.dist_dir) as output:
yield output
with spawn_web_server(
pytest_wrapper.pyodide_dist_dir
) as dist_dir_server, spawn_web_server(
pytest_wrapper.pyodide_lockfile_dir
) as lockfile_dir_server:
yield (
dist_dir_server,
lockfile_dir_server,
)


@pytest.fixture(scope="session")
def web_server_secondary(request):
def web_server_secondary():

Check warning on line 362 in pytest_pyodide/fixture.py

View check run for this annotation

Codecov / codecov/patch

pytest_pyodide/fixture.py#L362

Added line #L362 was not covered by tests
"""Secondary web server that serves files dist directory"""
with spawn_web_server(request.config.option.dist_dir) as output:
yield output
with spawn_web_server(
pytest_wrapper.pyodide_dist_dir
) as dist_dir_server, spawn_web_server(
pytest_wrapper.pyodide_lockfile_dir
) as lockfile_dir_server:
yield (
dist_dir_server,
lockfile_dir_server,
)


@pytest.fixture(params=["classic", "module"], scope="module")
Expand Down
17 changes: 16 additions & 1 deletion pytest_pyodide/hook.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
pyodide_run_host_test: bool
pyodide_runtimes: set[str]
pyodide_dist_dir: Path
pyodide_options_stack: list[tuple[bool, set[str], Path]]
pyodide_lockfile_dir: Path
pyodide_options_stack: list[tuple[bool, set[str], Path, Path]]

Check warning on line 43 in pytest_pyodide/hook.py

View check run for this annotation

Codecov / codecov/patch

pytest_pyodide/hook.py#L42-L43

Added lines #L42 - L43 were not covered by tests

def __setattr__(self, name, value):
setattr(pytest, name, value)
Expand Down Expand Up @@ -113,6 +114,9 @@
)

config.option.dist_dir = Path(config.option.dist_dir).resolve()
config.option.lockfile_dir = Path(
config.option.lockfile_dir or config.option.dist_dir
).resolve()
run_host, runtimes = _filter_runtimes(config.option.runtime)

if not hasattr(pytest, "pyodide_options_stack"):
Expand All @@ -123,11 +127,13 @@
pytest_wrapper.pyodide_run_host_test,
pytest_wrapper.pyodide_runtimes,
pytest_wrapper.pyodide_dist_dir,
pytest_wrapper.pyodide_lockfile_dir,
)
)
pytest_wrapper.pyodide_run_host_test = run_host
pytest_wrapper.pyodide_runtimes = runtimes
pytest_wrapper.pyodide_dist_dir = config.option.dist_dir
pytest_wrapper.pyodide_lockfile_dir = config.option.lockfile_dir


def pytest_unconfigure(config):
Expand All @@ -137,6 +143,7 @@
pytest_wrapper.pyodide_run_host_test,
pytest_wrapper.pyodide_runtimes,
pytest_wrapper.pyodide_dist_dir,
pytest_wrapper.pyodide_lockfile_dir,
) = pytest_wrapper.pyodide_options_stack.pop()
except IndexError:
pass
Expand All @@ -153,6 +160,14 @@
help="Path to the pyodide dist directory",
type=Path,
)
group.addoption(
"--lockfile-dir",
dest="lockfile_dir",
action="store",
default=None,
help="Path to the directory where the pyodide lockfile is stored. Defaults to the dist directory.",
type=Path,
)
group.addoption(
"--runner",
default="selenium",
Expand Down
34 changes: 24 additions & 10 deletions pytest_pyodide/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import pexpect
import pytest

from .config import RUNTIMES, get_global_config
from .config import PYODIDE_LOCKFILE_URL_PLACEHOLDER_STR, RUNTIMES, get_global_config

Check warning on line 9 in pytest_pyodide/runner.py

View check run for this annotation

Codecov / codecov/patch

pytest_pyodide/runner.py#L9

Added line #L9 was not covered by tests
from .hook import pytest_wrapper

TEST_SETUP_CODE = """
Expand Down Expand Up @@ -115,24 +115,26 @@

def __init__(
self,
server_port,
server_hostname="127.0.0.1",
server_log=None,
runtime_server_url,
lockfile_server_url,
runtime_server_log=None,
lockfile_server_log=None,
load_pyodide=True,
script_type="classic",
dist_dir=None,
lockfile_dir=None,
jspi=False,
*args,
**kwargs,
):
self._config = get_global_config()

self.server_port = server_port
self.server_hostname = server_hostname
self.base_url = f"http://{self.server_hostname}:{self.server_port}"
self.server_log = server_log
self.base_url = runtime_server_url
self.lockfile_server_url = lockfile_server_url
self.server_log = runtime_server_log
self.script_type = script_type
self.dist_dir = dist_dir
self.lockfile_dir = lockfile_dir
self.driver = self.get_driver(jspi)

self.set_script_timeout(self.script_timeout)
Expand Down Expand Up @@ -178,7 +180,10 @@

def load_pyodide(self):
self.run_js(
self._config.get_load_pyodide_script(self.browser)
self._config.get_load_pyodide_script(self.browser).replace(
PYODIDE_LOCKFILE_URL_PLACEHOLDER_STR,
f"{self.lockfile_server_url}/pyodide-lock.json",
)
+ self.POST_LOAD_PYODIDE_SCRIPT
)

Expand Down Expand Up @@ -321,7 +326,7 @@
}});
return await res
""".format(
f"http://{self.server_hostname}:{self.server_port}/{worker_file}",
f"{self.base_url}/{worker_file}",
self.script_type,
code,
),
Expand Down Expand Up @@ -566,6 +571,15 @@
except (pexpect.exceptions.EOF, pexpect.exceptions.TIMEOUT):
raise JavascriptException("", self.p.before.decode()) from None

def load_pyodide(self):

Check warning on line 574 in pytest_pyodide/runner.py

View check run for this annotation

Codecov / codecov/patch

pytest_pyodide/runner.py#L574

Added line #L574 was not covered by tests
self.run_js(
self._config.get_load_pyodide_script(self.browser).replace(
PYODIDE_LOCKFILE_URL_PLACEHOLDER_STR,
f"{self.lockfile_dir}/pyodide-lock.json",
)
+ self.POST_LOAD_PYODIDE_SCRIPT
)

def get_driver(self, jspi=False):
self._logs = []
self.init_node(jspi)
Expand Down
10 changes: 5 additions & 5 deletions pytest_pyodide/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,16 @@


@functools.cache
def built_packages(dist_dir: Path) -> list[str]:
def built_packages(lockfile_dir: Path) -> list[str]:

Check warning on line 43 in pytest_pyodide/utils.py

View check run for this annotation

Codecov / codecov/patch

pytest_pyodide/utils.py#L43

Added line #L43 was not covered by tests
"""Returns the list of built package names from repodata.json"""
repodata_path = dist_dir / "pyodide-lock.json"
repodata_path = lockfile_dir / "pyodide-lock.json"
if not repodata_path.exists():
# Try again for backwards compatibility
repodata_path = dist_dir / "repodata.json"
repodata_path = lockfile_dir / "repodata.json"
if not repodata_path.exists():
return []
return list(json.loads(repodata_path.read_text())["packages"].keys())


def package_is_built(package_name: str, dist_dir: Path) -> bool:
return package_name.lower() in built_packages(dist_dir)
def package_is_built(package_name: str, lockfile_dir: Path) -> bool:

Check warning on line 54 in pytest_pyodide/utils.py

View check run for this annotation

Codecov / codecov/patch

pytest_pyodide/utils.py#L54

Added line #L54 was not covered by tests
return package_name.lower() in built_packages(lockfile_dir)
4 changes: 2 additions & 2 deletions tests/test_doctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ def pytest_fixture_setup(self, fixturedef, request):
captured = capsys.readouterr()
expected = dedent(
"""
003 >>> from js import Object # doctest: +RUN_IN_PYODIDE
004 >>> 1 == 2
003 >>> from js import Object # doctest: +RUN_IN_PYODIDE
004 >>> 1 == 2
Expected:
True
Got:
Expand Down
Loading
Loading