From 957337fd8cb34d4ad69347f5f441bdc209c8860b Mon Sep 17 00:00:00 2001 From: David A Roberts Date: Thu, 24 Oct 2024 18:17:15 +1000 Subject: [PATCH 1/5] Create pyodide.yml --- .github/workflows/pyodide.yml | 62 +++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 .github/workflows/pyodide.yml diff --git a/.github/workflows/pyodide.yml b/.github/workflows/pyodide.yml new file mode 100644 index 000000000..0522f0eb2 --- /dev/null +++ b/.github/workflows/pyodide.yml @@ -0,0 +1,62 @@ +# Copied from SymPy https://github.com/sympy/sympy/pull/27183 + +name: Mathics3 (Pyodide) + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + pyodide-test: + runs-on: ubuntu-latest + env: + PYODIDE_VERSION: 0.27.0a2 + # PYTHON_VERSION and EMSCRIPTEN_VERSION are determined by PYODIDE_VERSION. + # The appropriate versions can be found in the Pyodide repodata.json + # "info" field, or in Makefile.envs: + # https://github.com/pyodide/pyodide/blob/main/Makefile.envs#L2 + PYTHON_VERSION: 3.12.1 + EMSCRIPTEN_VERSION: 3.1.58 + NODE_VERSION: 20 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python ${{ env.PYTHON_VERSION }} + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: Set up Emscripten toolchain + uses: mymindstorm/setup-emsdk@v14 + with: + version: ${{ env.EMSCRIPTEN_VERSION }} + actions-cache-folder: emsdk-cache + + - name: Install pyodide-build + run: pip install pyodide-build + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Set up Pyodide virtual environment and run tests + run: | + # Set up Pyodide virtual environment + pyodide xbuildenv install ${{ env.PYODIDE_VERSION }} + pyodide venv .venv-pyodide + + # Activate the virtual environment + source .venv-pyodide/bin/activate + + git clone https://github.com/Mathics3/mathics-scanner.git + cd mathics-scanner/ + pip install --no-build-isolation -e . + cd .. + + make mathics/data/op-tables.json mathics/data/operator-tables.json + pip install --no-build-isolation -e . + make -j3 check From 7d60138e6bf2d1e4577cfb870903c3800dfea57a Mon Sep 17 00:00:00 2001 From: David A Roberts Date: Thu, 24 Oct 2024 18:27:29 +1000 Subject: [PATCH 2/5] Install build dependencies --- .github/workflows/pyodide.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pyodide.yml b/.github/workflows/pyodide.yml index 0522f0eb2..7816441a9 100644 --- a/.github/workflows/pyodide.yml +++ b/.github/workflows/pyodide.yml @@ -51,7 +51,9 @@ jobs: # Activate the virtual environment source .venv-pyodide/bin/activate - + + pip install "setuptools>=70.0.0" PyYAML click packaging + git clone https://github.com/Mathics3/mathics-scanner.git cd mathics-scanner/ pip install --no-build-isolation -e . From d053833e29f68299941b2805087a11d548fda04c Mon Sep 17 00:00:00 2001 From: David A Roberts Date: Thu, 24 Oct 2024 18:33:43 +1000 Subject: [PATCH 3/5] Install pytest --- .github/workflows/pyodide.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pyodide.yml b/.github/workflows/pyodide.yml index 7816441a9..c5d5f655e 100644 --- a/.github/workflows/pyodide.yml +++ b/.github/workflows/pyodide.yml @@ -52,7 +52,7 @@ jobs: # Activate the virtual environment source .venv-pyodide/bin/activate - pip install "setuptools>=70.0.0" PyYAML click packaging + pip install "setuptools>=70.0.0" PyYAML click packaging pytest git clone https://github.com/Mathics3/mathics-scanner.git cd mathics-scanner/ From 14bad2f8c43045ea20c709eb29a92def545572b7 Mon Sep 17 00:00:00 2001 From: David A Roberts Date: Thu, 24 Oct 2024 18:56:40 +1000 Subject: [PATCH 4/5] Skip failing tests on pyodide --- .gitignore | 1 + test/builtin/files_io/test_files.py | 4 ++++ test/builtin/test_datentime.py | 2 +- test/test_main.py | 7 +++++++ test/test_returncode.py | 7 +++++++ 5 files changed, 20 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index cdf405b6c..68aa74947 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ /.cache /.gdbinit /.python-version +/.pyodide-xbuildenv-* /Mathics.egg-info /Mathics3.egg-info ChangeLog diff --git a/test/builtin/files_io/test_files.py b/test/builtin/files_io/test_files.py index 7042a728b..c4cd469dd 100644 --- a/test/builtin/files_io/test_files.py +++ b/test/builtin/files_io/test_files.py @@ -99,6 +99,10 @@ def test_close(): ), f"temporary filename {temp_filename} should not appear" +@pytest.mark.skipif( + sys.platform in ("emscripten",), + reason="Pyodide has restricted filesystem access", +) @pytest.mark.parametrize( ("str_expr", "msgs", "str_expected", "fail_msg"), [ diff --git a/test/builtin/test_datentime.py b/test/builtin/test_datentime.py index 0fc894483..01583ecfd 100644 --- a/test/builtin/test_datentime.py +++ b/test/builtin/test_datentime.py @@ -11,7 +11,7 @@ @pytest.mark.skipif( - sys.platform in ("win32",) or hasattr(sys, "pyston_version_info"), + sys.platform in ("win32", "emscripten") or hasattr(sys, "pyston_version_info"), reason="TimeConstrained needs to be rewritten", ) def test_timeremaining(): diff --git a/test/test_main.py b/test/test_main.py index 982e593e1..dd5671e2b 100644 --- a/test/test_main.py +++ b/test/test_main.py @@ -2,6 +2,9 @@ import os.path as osp import re import subprocess +import sys + +import pytest def get_testdir(): @@ -9,6 +12,10 @@ def get_testdir(): return osp.realpath(filename) +@pytest.mark.skipif( + sys.platform in ("emscripten",), + reason="Pyodide does not support processes", +) def test_cli(): script_file = osp.join(get_testdir(), "data", "script.m") diff --git a/test/test_returncode.py b/test/test_returncode.py index a1eb67dc8..1e1d11abb 100644 --- a/test/test_returncode.py +++ b/test/test_returncode.py @@ -1,6 +1,9 @@ # -*- coding: utf-8 -*- import os.path as osp import subprocess +import sys + +import pytest def get_testdir(): @@ -8,6 +11,10 @@ def get_testdir(): return osp.realpath(filename) +@pytest.mark.skipif( + sys.platform in ("emscripten",), + reason="Pyodide does not support processes", +) def test_returncode(): assert subprocess.run(["mathics", "-e", "Quit[5]"]).returncode == 5 assert subprocess.run(["mathics", "-e", "1 + 2'"]).returncode == 0 From 44a475a57919a369156e3167db5b7233584df4d6 Mon Sep 17 00:00:00 2001 From: David A Roberts Date: Thu, 24 Oct 2024 19:42:14 +1000 Subject: [PATCH 5/5] Move doctests to pytests so they can be skipped --- .../builtin/file_operations/file_properties.py | 3 --- mathics/builtin/files_io/files.py | 2 -- test/builtin/files_io/test_files.py | 16 ++++++++++++++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/mathics/builtin/file_operations/file_properties.py b/mathics/builtin/file_operations/file_properties.py index d16fa5d2e..0a6dd26ff 100644 --- a/mathics/builtin/file_operations/file_properties.py +++ b/mathics/builtin/file_operations/file_properties.py @@ -241,9 +241,6 @@ class SetFileDate(Builtin): >> SetFileDate[tmpfilename, {2002, 1, 1, 0, 0, 0.}, "Access"]; - >> FileDate[tmpfilename, "Access"] - = {2002, 1, 1, 0, 0, 0.} - #> DeleteFile[tmpfilename] """ diff --git a/mathics/builtin/files_io/files.py b/mathics/builtin/files_io/files.py index dd7df7146..3746d3915 100644 --- a/mathics/builtin/files_io/files.py +++ b/mathics/builtin/files_io/files.py @@ -461,8 +461,6 @@ class OpenRead(_OpenAction): The stream must be closed after using it to release the resource: >> Close[%]; - - S> Close[OpenRead["https://raw.githubusercontent.com/Mathics3/mathics-core/master/README.rst"]]; """ summary_text = "open a file for reading" diff --git a/test/builtin/files_io/test_files.py b/test/builtin/files_io/test_files.py index c4cd469dd..a66d1d821 100644 --- a/test/builtin/files_io/test_files.py +++ b/test/builtin/files_io/test_files.py @@ -151,6 +151,12 @@ def test_close(): "OpenRead[]", "", ), + ( + 'Close[OpenRead["https://raw.githubusercontent.com/Mathics3/mathics-core/master/README.rst"]];', + None, + "Null", + "", + ), ( 'fd=OpenRead["ExampleData/EinsteinSzilLetter.txt", BinaryFormat -> True, CharacterEncoding->"UTF8"]//Head', None, @@ -318,6 +324,16 @@ def test_close(): ), ("FilePrint[pathname]", None, "Null", ""), ("DeleteFile[pathname];Clear[pathname];", None, "Null", ""), + ('tmpfilename = $TemporaryDirectory <> "/tmp0";', None, "Null", ""), + ("Close[OpenWrite[tmpfilename]];", None, "Null", ""), + ( + 'SetFileDate[tmpfilename, {2002, 1, 1, 0, 0, 0.}, "Access"];', + None, + "Null", + "", + ), + ('FileDate[tmpfilename, "Access"]', None, "{2002, 1, 1, 0, 0, 0.}", ""), + ("DeleteFile[tmpfilename]", None, "Null", ""), ], ) def test_private_doctests_files(str_expr, msgs, str_expected, fail_msg):