├── pyodide ├── test │ ├── __init__.py │ ├── data.txt │ ├── data.cgi │ ├── test_bz2.py │ ├── src │ │ └── test_pyodide.py │ ├── test_testing.py │ ├── test_sqlite3.py │ ├── make_test_list.py │ ├── largish.json.cgi │ ├── pyodide_build │ │ └── test_pywasmcross.py │ ├── test_webworker.py │ ├── test_core_python.py │ └── test_common.py ├── pyodide_build │ ├── __init__.py │ ├── _fixes.py │ ├── common.py │ ├── __main__.py │ ├── serve.py │ ├── mkpkg.py │ └── buildall.py ├── src │ ├── _headers │ ├── _testcapi.py │ ├── pyimport.h │ ├── jsimport.h │ ├── sitecustomize.py │ ├── runpython.h │ ├── pyproxy.h │ ├── webbrowser.py │ ├── python2js_buffer.h │ ├── js2python.h │ ├── python2js.h │ ├── test.html │ ├── pyimport.c │ ├── webworker.js │ ├── jsproxy.h │ ├── main.c │ ├── jsimport.c │ ├── console.html │ ├── pyodide.py │ └── js2python.c ├── docs │ ├── requirements-doc.txt │ ├── rootdir.rst │ ├── Makefile │ ├── README.md │ ├── make.bat │ ├── pypi.md │ ├── index.rst │ ├── using_pyodide_from_iodide.md │ └── using_pyodide_from_javascript.md ├── CLAPACK │ ├── checksums │ ├── Makefile.envs │ ├── Makefile │ └── patches │ │ └── 0002-Add-fPIC-flag-and-skip-cblaswrap.patch ├── pytest.ini ├── lz4 │ ├── checksums │ └── Makefile ├── tools │ └── .gitignore ├── .netlify │ └── state.json ├── six │ ├── checksums │ ├── README.md │ └── Makefile ├── cpython │ ├── checksums │ ├── README.md │ ├── config.site │ ├── patches │ │ ├── zlib │ │ │ └── include_unistd.patch │ │ ├── no_af_vsock.patch │ │ ├── dont-test-undecodable-filenames.patch │ │ ├── disable-set_inheritable.patch │ │ ├── add-emscripten-host.patch │ │ ├── testing.patch │ │ └── sqlite-MODULE_NAME.patch │ ├── pyconfig.undefs.h │ └── Setup.local ├── benchmark │ ├── benchmarks │ │ ├── README.md │ │ ├── fft.py │ │ ├── large_decimal_list.py │ │ ├── rosen.py │ │ ├── reverse_cumsum.py │ │ ├── l2norm.py │ │ ├── create_grid.py │ │ ├── vibr_energy.py │ │ ├── repeating.py │ │ ├── cronbach.py │ │ ├── log_likelihood.py │ │ ├── multiple_sum.py │ │ ├── allpairs_distances_loops.py │ │ ├── grouping.py │ │ ├── smoothing.py │ │ ├── specialconvolve.py │ │ ├── allpairs_distances.py │ │ ├── pairwise_loop.py │ │ ├── check_mask.py │ │ ├── hasting.py │ │ ├── diffusion.py │ │ ├── lstsqr.py │ │ ├── arc_distance.py │ │ ├── evolve.py │ │ ├── harris.py │ │ ├── hyantes.py │ │ ├── julia.py │ │ ├── slowparts.py │ │ ├── local_maxima.py │ │ ├── mandel.py │ │ ├── grayscott.py │ │ ├── fdtd.py │ │ ├── periodic_dist.py │ │ ├── wave.py │ │ └── growcut.py │ └── plot_benchmark.py ├── packages │ ├── matplotlib │ │ ├── src │ │ │ └── setup.cfg │ │ ├── patches │ │ │ ├── hardcoded_font_cache.patch │ │ │ ├── force_malloc_free.patch │ │ │ └── font_name_encoding.patch │ │ ├── test_matplotlib.py │ │ └── meta.yaml │ ├── micropip │ │ ├── meta.yaml │ │ ├── micropip │ │ │ └── setup.py │ │ └── test_micropip.py │ ├── minidump │ │ └── meta.yaml │ ├── aiowinreg │ │ └── meta.yaml │ ├── asn1crypto │ │ └── meta.yaml │ ├── py │ │ └── meta.yaml │ ├── pluggy │ │ └── meta.yaml │ ├── joblib │ │ ├── patches │ │ │ ├── use-setuptools.patch │ │ │ └── ctypes-import.patch │ │ ├── meta.yaml │ │ └── test_joblib.py │ ├── cycler │ │ └── meta.yaml │ ├── atomicwrites │ │ └── meta.yaml │ ├── nltk │ │ ├── meta.yaml │ │ └── test_nltk.py │ ├── Jinja2 │ │ ├── test_jinja2.py │ │ └── meta.yaml │ ├── kiwisolver │ │ └── meta.yaml │ ├── minikerberos │ │ └── meta.yaml │ ├── more-itertools │ │ └── meta.yaml │ ├── nose │ │ └── meta.yaml │ ├── distlib │ │ └── meta.yaml │ ├── Pygments │ │ └── meta.yaml │ ├── docutils │ │ └── meta.yaml │ ├── soupsieve │ │ └── meta.yaml │ ├── MarkupSafe │ │ └── meta.yaml │ ├── attrs │ │ ├── meta.yaml │ │ └── patches │ │ │ └── use-dummy-threading.patch │ ├── mpmath │ │ └── meta.yaml │ ├── decorator │ │ └── meta.yaml │ ├── pypykatz │ │ └── meta.yaml │ ├── biopython │ │ └── meta.yaml │ ├── webencodings │ │ └── meta.yaml │ ├── Makefile │ ├── pyparsing │ │ ├── meta.yaml │ │ └── patches │ │ │ └── dummy_threading.patch │ ├── sympy │ │ └── meta.yaml │ ├── beautifulsoup4 │ │ └── meta.yaml │ ├── bleach │ │ └── meta.yaml │ ├── python-dateutil │ │ ├── meta.yaml │ │ └── patches │ │ │ └── dummy-thread-lock.patch │ ├── pytz │ │ ├── meta.yaml │ │ └── patches │ │ │ └── dummy-threading.patch │ ├── mne │ │ └── meta.yaml │ ├── html5lib │ │ └── meta.yaml │ ├── setuptools │ │ ├── meta.yaml │ │ └── patches │ │ │ └── remove-ctypes.patch │ ├── networkx │ │ ├── test_networkx.py │ │ └── meta.yaml │ ├── pandas │ │ ├── meta.yaml │ │ └── test_pandas.py │ ├── numpy │ │ ├── patches │ │ │ ├── dont-include-execinfo.patch │ │ │ ├── disable-maybe-uninitialized.patch │ │ │ ├── fix-install-with-skip-build.patch │ │ │ ├── use-local-blas-lapack.patch │ │ │ ├── force_malloc.patch │ │ │ ├── fix-longdouble.patch │ │ │ ├── fix-static-init-of-nditer-pywrap.patch │ │ │ ├── add-emscripten-cpu.patch │ │ │ └── init-alloc-cache.patch │ │ ├── meta.yaml │ │ ├── config │ │ │ └── _numpyconfig.h │ │ └── test_numpy.py │ ├── pytest │ │ ├── meta.yaml │ │ └── patches │ │ │ └── named-tmp-and-rm-dup2.patch │ ├── scikit-learn │ │ ├── patches │ │ │ └── use-site-joblib.patch │ │ ├── test_scikit-learn.py │ │ └── meta.yaml │ └── scipy │ │ ├── test_scipy.py │ │ ├── patches │ │ ├── disable_scipy_stats_mvn.patch │ │ ├── fix-build-gcc5-a80460.patch │ │ ├── skip_ellip_harm_2_pyx_ctypes.patch │ │ ├── force_malloc.patch │ │ └── dummy_threading.patch │ │ └── meta.yaml ├── setup.cfg ├── jedi │ ├── checksums │ └── Makefile ├── parso │ ├── checksums │ └── Makefile ├── remove_modules.txt ├── .bumpversion.cfg ├── bin │ └── pyodide ├── .editorconfig ├── .gitignore ├── run_docker ├── .readthedocs.yml ├── emsdk │ ├── clean_for_dist.sh │ ├── patches │ │ ├── num_params.patch │ │ └── dynCall_so.patch │ └── Makefile ├── Makefile.envs ├── CHANGELOG.md ├── Dockerfile └── .clang-format ├── http_server.py ├── .gitignore └── README.md /pyodide/test/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pyodide/test/data.txt: -------------------------------------------------------------------------------- 1 | HELLO 2 | -------------------------------------------------------------------------------- /pyodide/pyodide_build/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = '0.1.0' 2 | -------------------------------------------------------------------------------- /pyodide/src/_headers: -------------------------------------------------------------------------------- 1 | /* 2 | Access-Control-Allow-Origin: * -------------------------------------------------------------------------------- /pyodide/docs/requirements-doc.txt: -------------------------------------------------------------------------------- 1 | sphinx 2 | sphinx_rtd_theme 3 | m2r 4 | -------------------------------------------------------------------------------- /pyodide/CLAPACK/checksums: -------------------------------------------------------------------------------- 1 | 040da31f3a7d4fbc9ac376c748d18d1f clapack.tgz 2 | -------------------------------------------------------------------------------- /pyodide/pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | norecursedirs = build src cpython emsdk/ 3 | -------------------------------------------------------------------------------- /pyodide/lz4/checksums: -------------------------------------------------------------------------------- 1 | d5ce78f7b1b76002bbfffa6f78a5fc4e downloads/lz4-1.8.3.tgz 2 | -------------------------------------------------------------------------------- /pyodide/tools/.gitignore: -------------------------------------------------------------------------------- 1 | ar 2 | c++ 3 | cc 4 | cxx 5 | gcc 6 | ld 7 | gfortran 8 | -------------------------------------------------------------------------------- /pyodide/.netlify/state.json: -------------------------------------------------------------------------------- 1 | { 2 | "siteId": "1fd8fb2d-3267-4664-afca-dae42e7e5b64" 3 | } -------------------------------------------------------------------------------- /pyodide/six/checksums: -------------------------------------------------------------------------------- 1 | d12789f9baf7e9fb2524c0c64f1773f8 downloads/six-1.11.0.tgz 2 | -------------------------------------------------------------------------------- /pyodide/cpython/checksums: -------------------------------------------------------------------------------- 1 | 41b6595deb4147a1ed517a7d9a580271 downloads/Python-3.7.0.tgz 2 | -------------------------------------------------------------------------------- /pyodide/CLAPACK/Makefile.envs: -------------------------------------------------------------------------------- 1 | CFLAGS_OPT=-Os -s INLINING_LIMIT=5 2 | LDFLAGS_OPT=-Os -s INLINING_LIMIT=5 3 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/README.md: -------------------------------------------------------------------------------- 1 | From https: // github.com / serge - sans - paille / numpy - benchmarks 2 | -------------------------------------------------------------------------------- /pyodide/packages/matplotlib/src/setup.cfg: -------------------------------------------------------------------------------- 1 | [rc_options] 2 | backend=module://matplotlib.backends.wasm_backend 3 | -------------------------------------------------------------------------------- /pyodide/setup.cfg: -------------------------------------------------------------------------------- 1 | [tool:pytest] 2 | addopts = 3 | -r sxX 4 | --instafail 5 | --doctest-modules 6 | -------------------------------------------------------------------------------- /pyodide/test/data.cgi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | print("Content-Type: text/text") 3 | print() 4 | print("HELLO") 5 | -------------------------------------------------------------------------------- /pyodide/jedi/checksums: -------------------------------------------------------------------------------- 1 | ba859c74fa3c966a22f2aeebe1b74ee27e2a462f56d3f5f7ca4a59af61bfe42e downloads/jedi-0.15.1.tar.gz 2 | -------------------------------------------------------------------------------- /pyodide/parso/checksums: -------------------------------------------------------------------------------- 1 | 666b0ee4a7a1220f65d367617f2cd3ffddff3e205f3f16a0284df30e774c2a9c downloads/parso-0.5.1.tar.gz 2 | -------------------------------------------------------------------------------- /pyodide/six/README.md: -------------------------------------------------------------------------------- 1 | Six is a special case package, since it's so commonly used, we want to include 2 | it in the main Python package. 3 | -------------------------------------------------------------------------------- /pyodide/cpython/README.md: -------------------------------------------------------------------------------- 1 | # Credits 2 | 3 | Based on the hard work of [@dgym](https://github.com/dgym) on 4 | [cpython-emscripten](https://github.com/dgym/cpython-emscripten). 5 | -------------------------------------------------------------------------------- /pyodide/remove_modules.txt: -------------------------------------------------------------------------------- 1 | _osx_support.py 2 | ctypes 3 | curses 4 | dbm 5 | ensurepip 6 | idlelib 7 | lib2to3 8 | multiprocessing 9 | tkinter 10 | turtle.py 11 | turtledemo 12 | venv 13 | -------------------------------------------------------------------------------- /pyodide/src/_testcapi.py: -------------------------------------------------------------------------------- 1 | """ 2 | A shim to skip tests involving the _testcapi extension, since we don't build 3 | it. 4 | """ 5 | 6 | import unittest 7 | 8 | raise unittest.SkipTest("No _testcapi") 9 | -------------------------------------------------------------------------------- /pyodide/cpython/config.site: -------------------------------------------------------------------------------- 1 | ac_cv_file__dev_ptmx=no 2 | ac_cv_file__dev_ptc=no 3 | ac_cv_func_dlopen=yes 4 | ac_cv_lib_socket_socket=no 5 | ac_cv_header_linux_vm_sockets_h=yes 6 | ac_cv_little_endian_double=yes 7 | -------------------------------------------------------------------------------- /pyodide/packages/micropip/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: micropip 3 | version: "0.1" 4 | requirements: 5 | run: 6 | - distlib 7 | source: 8 | path: micropip 9 | test: 10 | imports: 11 | - micropip 12 | -------------------------------------------------------------------------------- /pyodide/src/pyimport.h: -------------------------------------------------------------------------------- 1 | #ifndef PYIMPORT_H 2 | #define PYIMPORT_H 3 | 4 | /** Makes `var foo = pyodide.pyimport('foo')` work in Javascript. 5 | */ 6 | 7 | int 8 | pyimport_init(); 9 | 10 | #endif /* PYIMPORT_H */ 11 | -------------------------------------------------------------------------------- /pyodide/.bumpversion.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 0.14.0 3 | commit = True 4 | tag = True 5 | tag_name = {new_version} 6 | 7 | [bumpversion:file:src/pyodide.py] 8 | search = __version__ = '{current_version}' 9 | replace = __version__ = '{new_version}' 10 | 11 | -------------------------------------------------------------------------------- /pyodide/packages/minidump/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: minidump 3 | version: '0.0.10' 4 | source: 5 | url: https://files.pythonhosted.org/packages/c8/cb/241960cf88ac6dce03ec4e60e4b17a55c5083ed45ddcc2953bfb32e3f0b9/minidump-0.0.10.tar.gz 6 | test: 7 | imports: 8 | - minidump -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/fft.py: -------------------------------------------------------------------------------- 1 | # setup: N = 2**11 ; import numpy ; a = numpy.array(numpy.random.rand(N), dtype=complex) # noqa 2 | # run: fft(a) 3 | 4 | # pythran export fft(complex []) 5 | 6 | import numpy as np 7 | 8 | 9 | def fft(x): 10 | return np.fft(x) 11 | -------------------------------------------------------------------------------- /pyodide/packages/aiowinreg/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: aiowinreg 3 | version: '0.0.1' 4 | source: 5 | url: https://files.pythonhosted.org/packages/27/29/d57c971f5ae9cfdddce7b7bdcbba0e1ce15f40c120e6b6dc9783bb481e3d/aiowinreg-0.0.1.tar.gz 6 | test: 7 | imports: 8 | - aiowinreg -------------------------------------------------------------------------------- /pyodide/packages/asn1crypto/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: asn1crypto 3 | version: '0.24.0' 4 | source: 5 | url: https://files.pythonhosted.org/packages/fc/f1/8db7daa71f414ddabfa056c4ef792e1461ff655c2ae2928a2b675bfed6b4/asn1crypto-0.24.0.tar.gz 6 | test: 7 | imports: 8 | - asn1crypto -------------------------------------------------------------------------------- /pyodide/src/jsimport.h: -------------------------------------------------------------------------------- 1 | #ifndef JSIMPORT_H 2 | #define JSIMPORT_H 3 | 4 | /** Support "from js import …" from Python. */ 5 | 6 | #include 7 | 8 | /** Install the import hook to support "from js import …". */ 9 | int 10 | JsImport_init(); 11 | 12 | #endif /* JSIMPORT_H */ 13 | -------------------------------------------------------------------------------- /pyodide/src/sitecustomize.py: -------------------------------------------------------------------------------- 1 | """ 2 | Pyodide-specific startup code that's always run at Python startup. 3 | """ 4 | 5 | # We weren't invoked at the commandline, but set some commandline arguments as 6 | # if we were anyway. Helps many of the CPython tests pass. 7 | import sys 8 | sys.argv = ['pyodide'] 9 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/large_decimal_list.py: -------------------------------------------------------------------------------- 1 | # setup: from decimal import Decimal ; A = [Decimal('2.1') for i in range(1000)] ; B = [Decimal('3.2') for i in range(1000)] # noqa 2 | # run: large_decimal_list(A, B) 3 | 4 | 5 | def large_decimal_list(A, B): 6 | return [a * b for a, b in zip(A, B)] 7 | -------------------------------------------------------------------------------- /pyodide/packages/py/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: py 3 | version: 1.5.4 4 | 5 | source: 6 | url: https://pypi.io/packages/source/p/py/py-1.5.4.tar.gz 7 | sha256: 3fd59af7435864e1a243790d322d763925431213b6b8529c6ca71081ace3bbf7 8 | 9 | 10 | test: 11 | imports: 12 | - py 13 | - py.code 14 | -------------------------------------------------------------------------------- /pyodide/src/runpython.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNPYTHON_H 2 | #define RUNPYTHON_H 3 | 4 | /** The primary entry point function that runs Python code. 5 | */ 6 | 7 | int 8 | runpython_init_js(); 9 | 10 | int 11 | runpython_init_py(); 12 | 13 | int 14 | runpython_finalize_js(); 15 | 16 | #endif /* RUNPYTHON_H */ 17 | -------------------------------------------------------------------------------- /pyodide/packages/pluggy/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: pluggy 3 | version: 0.7.1 4 | 5 | source: 6 | url: https://pypi.io/packages/source/p/pluggy/pluggy-0.7.1.tar.gz 7 | sha256: 95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1 8 | 9 | 10 | test: 11 | imports: 12 | - pluggy 13 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/rosen.py: -------------------------------------------------------------------------------- 1 | # setup: import numpy as np; r = np.arange(1000000, dtype=float) 2 | # run: rosen(r) 3 | import numpy as np 4 | 5 | # pythran export rosen(float[]) 6 | 7 | 8 | def rosen(x): 9 | t0 = 100 * (x[1:] - x[:-1] ** 2) ** 2 10 | t1 = (1 - x[:-1]) ** 2 11 | return np.sum(t0 + t1) 12 | -------------------------------------------------------------------------------- /pyodide/docs/rootdir.rst: -------------------------------------------------------------------------------- 1 | .. This rST file provides a way to easily add Markdown files 2 | which are located in the root directory of the repo. 3 | 4 | About the Project 5 | ================= 6 | 7 | .. mdinclude:: ../README.md 8 | 9 | .. mdinclude:: ../CONTRIBUTING.md 10 | 11 | .. mdinclude:: ../CODE-OF-CONDUCT.md 12 | -------------------------------------------------------------------------------- /pyodide/packages/joblib/patches/use-setuptools.patch: -------------------------------------------------------------------------------- 1 | diff --git a/setup.py b/setup.py 2 | index 134db18..f705b28 100755 3 | --- a/setup.py 4 | +++ b/setup.py 5 | @@ -1,6 +1,6 @@ 6 | #!/usr/bin/env python 7 | 8 | -from distutils.core import setup 9 | +from setuptools import setup 10 | import sys 11 | 12 | import joblib 13 | -------------------------------------------------------------------------------- /pyodide/packages/cycler/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: cycler 3 | version: 0.10.0 4 | 5 | source: 6 | url: https://files.pythonhosted.org/packages/c2/4b/137dea450d6e1e3d474e1d873cd1d4f7d3beed7e0dc973b06e8e10d32488/cycler-0.10.0.tar.gz 7 | md5: 4cb42917ac5007d1cdff6cccfe2d016b 8 | 9 | test: 10 | imports: 11 | - cycler 12 | -------------------------------------------------------------------------------- /pyodide/packages/atomicwrites/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: atomicwrites 3 | version: 1.1.5 4 | 5 | source: 6 | url: https://pypi.io/packages/source/a/atomicwrites/atomicwrites-1.1.5.tar.gz 7 | sha256: 240831ea22da9ab882b551b31d4225591e5e447a68c5e188db5b89ca1d487585 8 | 9 | 10 | test: 11 | imports: 12 | - atomicwrites 13 | -------------------------------------------------------------------------------- /pyodide/packages/nltk/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: nltk 3 | version: '3.4' 4 | source: 5 | sha256: 286f6797204ffdb52525a1d21ec0a221ec68b8e3fa4f2d25f412ac8e63c70e8d 6 | url: https://files.pythonhosted.org/packages/6f/ed/9c755d357d33bc1931e157f537721efb5b88d2c583fe593cc09603076cc3/nltk-3.4.zip 7 | test: 8 | imports: 9 | - nltk 10 | -------------------------------------------------------------------------------- /pyodide/bin/pyodide: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # get the absolute path to the root directory 4 | ROOTDIR=$(python3 -c 'import pathlib, sys; \ 5 | print(pathlib.Path(sys.argv[1]).resolve().parents[1])' \ 6 | "${BASH_SOURCE[0]}") 7 | 8 | export PYTHONPATH="${PYTHONPATH}:${ROOTDIR}" 9 | python3 -m pyodide_build "$@" 10 | -------------------------------------------------------------------------------- /pyodide/packages/Jinja2/test_jinja2.py: -------------------------------------------------------------------------------- 1 | def test_jinja2(selenium): 2 | selenium.load_package("Jinja2") 3 | selenium.run(""" 4 | import jinja2 5 | 6 | template = jinja2.Template('Hello {{ name }}!') 7 | """) 8 | content = selenium.run("""template.render(name='Zach')""") 9 | assert content == 'Hello Zach!' 10 | -------------------------------------------------------------------------------- /pyodide/packages/kiwisolver/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: kiwisolver 3 | version: 1.0.1 4 | 5 | source: 6 | url: https://files.pythonhosted.org/packages/31/60/494fcce70d60a598c32ee00e71542e52e27c978e5f8219fae0d4ac6e2864/kiwisolver-1.0.1.tar.gz 7 | md5: e2a1718b837e2cd001f7c06934616fcd 8 | 9 | test: 10 | imports: 11 | - kiwisolver 12 | -------------------------------------------------------------------------------- /pyodide/packages/minikerberos/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: minikerberos 3 | version: '0.0.11' 4 | source: 5 | url: https://files.pythonhosted.org/packages/ba/bd/8f04644bc1c6d4cf669984ea57fd01e3ff84cf8b5756793a9e9804794c74/minikerberos-0.0.11.tar.gz 6 | requirements: 7 | run: 8 | - asn1crypto 9 | test: 10 | imports: 11 | - minikerberos -------------------------------------------------------------------------------- /pyodide/packages/more-itertools/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: more-itertools 3 | version: 4.3.0 4 | 5 | source: 6 | url: https://pypi.io/packages/source/m/more-itertools/more-itertools-4.3.0.tar.gz 7 | sha256: c476b5d3a34e12d40130bc2f935028b5f636df8f372dc2c1c01dc19681b2039e 8 | 9 | 10 | test: 11 | imports: 12 | - more_itertools 13 | -------------------------------------------------------------------------------- /pyodide/packages/nose/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: nose 3 | version: 1.3.7 4 | 5 | source: 6 | url: https://pypi.io/packages/source/n/nose/nose-1.3.7.tar.gz 7 | sha256: f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98 8 | 9 | requirements: 10 | run: 11 | - setuptools 12 | 13 | test: 14 | imports: 15 | - nose 16 | -------------------------------------------------------------------------------- /pyodide/packages/distlib/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: distlib 3 | version: 0.2.8 4 | source: 5 | sha256: 57977cd7d9ea27986ec62f425630e4ddb42efe651ff80bc58ed8dbc3c7c21f19 6 | url: https://files.pythonhosted.org/packages/d4/81/ae64653802eceb93f5c33d882f4ea1290bb77ba165ac78d1dfa39e860ea9/distlib-0.2.8.zip 7 | test: 8 | imports: 9 | - distlib 10 | -------------------------------------------------------------------------------- /pyodide/packages/Pygments/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: Pygments 3 | version: 2.3.1 4 | source: 5 | sha256: 5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a 6 | url: https://files.pythonhosted.org/packages/64/69/413708eaf3a64a6abb8972644e0f20891a55e621c6759e2c3f3891e05d63/Pygments-2.3.1.tar.gz 7 | test: 8 | imports: 9 | - pygments 10 | -------------------------------------------------------------------------------- /pyodide/packages/docutils/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: docutils 3 | version: '0.14' 4 | source: 5 | sha256: 51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274 6 | url: https://files.pythonhosted.org/packages/84/f4/5771e41fdf52aabebbadecc9381d11dea0fa34e4759b4071244fa094804c/docutils-0.14.tar.gz 7 | test: 8 | imports: 9 | - docutils 10 | -------------------------------------------------------------------------------- /pyodide/packages/soupsieve/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: soupsieve 3 | version: '1.8' 4 | source: 5 | sha256: eaed742b48b1f3e2d45ba6f79401b2ed5dc33b2123dfe216adb90d4bfa0ade26 6 | url: https://files.pythonhosted.org/packages/0c/52/e9088bb9b96e2d39fc3b33fcda5b4fde9d71473536ac660a1ca9a0958a2f/soupsieve-1.8.tar.gz 7 | test: 8 | imports: 9 | - soupsieve 10 | -------------------------------------------------------------------------------- /pyodide/packages/MarkupSafe/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: MarkupSafe 3 | version: 1.1.1 4 | source: 5 | sha256: 29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b 6 | url: https://files.pythonhosted.org/packages/b9/2e/64db92e53b86efccfaea71321f597fa2e1b2bd3853d8ce658568f7a13094/MarkupSafe-1.1.1.tar.gz 7 | test: 8 | imports: 9 | - markupsafe 10 | -------------------------------------------------------------------------------- /pyodide/packages/attrs/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: attrs 3 | version: 18.1.0 4 | 5 | source: 6 | url: https://pypi.io/packages/source/a/attrs/attrs-18.1.0.tar.gz 7 | sha256: e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b 8 | 9 | patches: 10 | - patches/use-dummy-threading.patch 11 | 12 | 13 | test: 14 | imports: 15 | - attr 16 | -------------------------------------------------------------------------------- /pyodide/packages/mpmath/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: mpmath 3 | version: 1.1.0 4 | 5 | source: 6 | sha256: fc17abe05fbab3382b61a123c398508183406fa132e0223874578e20946499f6 7 | url: 'https://files.pythonhosted.org/packages/ca/63/3384ebb3b51af9610086b23ea976e6d27d6d97bf140a76a365bd77a3eb32/mpmath-1.1.0.tar.gz' 8 | 9 | test: 10 | imports: 11 | - mpmath 12 | -------------------------------------------------------------------------------- /pyodide/packages/decorator/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: decorator 3 | version: 4.3.0 4 | 5 | source: 6 | url: https://files.pythonhosted.org/packages/6f/24/15a229626c775aae5806312f6bf1e2a73785be3402c0acdec5dbddd8c11e/decorator-4.3.0.tar.gz 7 | sha256: c39efa13fbdeb4506c476c9b3babf6a718da943dab7811c206005a4a956c080c 8 | 9 | test: 10 | imports: 11 | - decorator -------------------------------------------------------------------------------- /pyodide/packages/pypykatz/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: pypykatz 3 | version: '0.2.2' 4 | source: 5 | url: https://files.pythonhosted.org/packages/98/06/92650d9710fb1fc7345d5977fda45c8d0a56c02d599132aaffbceb0b328c/pypykatz-0.2.2.tar.gz 6 | requirements: 7 | run: 8 | - minidump 9 | - minikerberos 10 | - aiowinreg 11 | test: 12 | imports: 13 | - pypykatz -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/reverse_cumsum.py: -------------------------------------------------------------------------------- 1 | # http://stackoverflow.com/questions/16541618/perform-a-reverse-cumulative-sum-on-a-numpy-array 2 | # pythran export reverse_cumsum(float[]) 3 | # setup: import numpy as np ; r = np.random.rand(1000000) 4 | # run: reverse_cumsum(r) 5 | import numpy as np 6 | 7 | 8 | def reverse_cumsum(x): 9 | return np.cumsum(x[::-1])[::-1] 10 | -------------------------------------------------------------------------------- /pyodide/packages/biopython/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: biopython 3 | version: '1.73' 4 | 5 | source: 6 | url: https://files.pythonhosted.org/packages/7a/4a/0d4381a60b6e942c6772b01cfb931196f1a9c33910cc43fbd4faccbd7d9f/biopython-1.73.tar.gz 7 | sha256: 70c5cc27dc61c23d18bb33b6d38d70edc4b926033aea3b7434737c731c94a5e0 8 | 9 | test: 10 | imports: 11 | - Bio 12 | 13 | -------------------------------------------------------------------------------- /pyodide/packages/webencodings/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: webencodings 3 | version: 0.5.1 4 | source: 5 | sha256: b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923 6 | url: https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz 7 | test: 8 | imports: 9 | - webencodings 10 | -------------------------------------------------------------------------------- /pyodide/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | charset = utf-8 7 | indent_size = 2 8 | indent_style = space 9 | trim_trailing_whitespace = true 10 | 11 | [**.py] 12 | indent_size = 4 13 | 14 | [tools/*] 15 | indent_size = 4 16 | 17 | [Makefile] 18 | indent_style = tab 19 | 20 | [**.patch] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/l2norm.py: -------------------------------------------------------------------------------- 1 | # http://stackoverflow.com/questions/7741878/how-to-apply-numpy-linalg-norm-to-each-row-of-a-matrix/7741976#7741976 2 | # setup: import numpy as np ; N = 1000; x = np.random.rand(N,N) 3 | # run: l2norm(x) 4 | 5 | # pythran export l2norm(float64[][]) 6 | import numpy as np 7 | 8 | 9 | def l2norm(x): 10 | return np.sqrt(np.einsum('ij,ij->i', x, x)) 11 | -------------------------------------------------------------------------------- /pyodide/cpython/patches/zlib/include_unistd.patch: -------------------------------------------------------------------------------- 1 | diff -u zlib-1.2.11-orig/gzguts.h zlib-1.2.11/gzguts.h 2 | --- a/gzguts.h 3 | +++ b/gzguts.h 4 | @@ -3,6 +3,8 @@ 5 | * For conditions of distribution and use, see copyright notice in zlib.h 6 | */ 7 | 8 | +#include 9 | + 10 | #ifdef _LARGEFILE64_SOURCE 11 | # ifndef _LARGEFILE_SOURCE 12 | # define _LARGEFILE_SOURCE 1 13 | -------------------------------------------------------------------------------- /pyodide/packages/Makefile: -------------------------------------------------------------------------------- 1 | PYODIDE_ROOT=$(abspath ..) 2 | include ../Makefile.envs 3 | 4 | all: deps 5 | ../bin/pyodide buildall . ../build \ 6 | --package_abi=$(PYODIDE_PACKAGE_ABI) --ldflags="$(SIDE_LDFLAGS)" --host=$(HOSTPYTHONROOT) --target=$(TARGETPYTHONROOT) 7 | deps: 8 | # Install build dependencies 9 | $(HOSTPYTHON) -m pip install Cython Tempita 10 | 11 | clean: 12 | rm -rf ./*/build 13 | -------------------------------------------------------------------------------- /pyodide/packages/joblib/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: joblib 3 | version: "0.11" 4 | 5 | source: 6 | url: https://pypi.io/packages/source/j/joblib/joblib-0.11.tar.gz 7 | sha256: 7b8fd56df36d9731a83729395ccb85a3b401f62a96255deb1a77220c00ed4085 8 | 9 | patches: 10 | - patches/use-setuptools.patch 11 | - patches/ctypes-import.patch 12 | 13 | test: 14 | imports: 15 | - joblib 16 | -------------------------------------------------------------------------------- /pyodide/.gitignore: -------------------------------------------------------------------------------- 1 | *.bc 2 | *.a 3 | *.o 4 | *.pyc 5 | .patched 6 | .built 7 | .packaged 8 | .pytest_cache/ 9 | __pycache__ 10 | geckodriver.log 11 | firefox/ 12 | .vscode 13 | 14 | build 15 | downloads 16 | host 17 | installs 18 | ccache 19 | 20 | /root/ 21 | /build/ 22 | 23 | /emsdk/emsdk 24 | 25 | /six/six-1.11.0 26 | /lz4/lz4-1.8.3 27 | CLAPACK/CLAPACK-WA 28 | CLAPACK/clapack.tgz 29 | *.egg-info/ 30 | -------------------------------------------------------------------------------- /pyodide/packages/pyparsing/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: pyparsing 3 | version: 2.2.0 4 | 5 | source: 6 | url: https://files.pythonhosted.org/packages/3c/ec/a94f8cf7274ea60b5413df054f82a8980523efd712ec55a59e7c3357cf7c/pyparsing-2.2.0.tar.gz 7 | md5: 0214e42d63af850256962b6744c948d9 8 | 9 | patches: 10 | - patches/dummy_threading.patch 11 | 12 | test: 13 | imports: 14 | - pyparsing 15 | -------------------------------------------------------------------------------- /pyodide/packages/sympy/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: sympy 3 | version: '1.3' 4 | 5 | source: 6 | sha256: e1319b556207a3758a0efebae14e5e52c648fc1db8975953b05fff12b6871b54 7 | url: 'https://files.pythonhosted.org/packages/dd/f6/ed485ff22efdd7b371d0dbbf6d77ad61c3b3b7e0815a83c89cbb38ce35de/sympy-1.3.tar.gz' 8 | 9 | requirements: 10 | run: 11 | - mpmath 12 | 13 | test: 14 | imports: 15 | - sympy 16 | -------------------------------------------------------------------------------- /pyodide/packages/Jinja2/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: Jinja2 3 | version: '2.10' 4 | 5 | source: 6 | sha256: f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4 7 | url: https://files.pythonhosted.org/packages/56/e6/332789f295cf22308386cf5bbd1f4e00ed11484299c5d7383378cf48ba47/Jinja2-2.10.tar.gz 8 | 9 | requirements: 10 | run: 11 | - MarkupSafe 12 | 13 | test: 14 | imports: 15 | - jinja2 16 | -------------------------------------------------------------------------------- /pyodide/packages/beautifulsoup4/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: beautifulsoup4 3 | version: 4.7.1 4 | source: 5 | sha256: 945065979fb8529dd2f37dbb58f00b661bdbcbebf954f93b32fdf5263ef35348 6 | url: https://files.pythonhosted.org/packages/80/f2/f6aca7f1b209bb9a7ef069d68813b091c8c3620642b568dac4eb0e507748/beautifulsoup4-4.7.1.tar.gz 7 | requirements: 8 | run: 9 | - soupsieve 10 | test: 11 | imports: 12 | - bs4 13 | -------------------------------------------------------------------------------- /pyodide/packages/bleach/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: bleach 3 | version: 3.1.0 4 | source: 5 | sha256: 3fdf7f77adcf649c9911387df51254b813185e32b2c6619f690b593a617e19fa 6 | url: https://files.pythonhosted.org/packages/78/5a/0df03e8735cd9c75167528299c738702437589b9c71a849489d00ffa82e8/bleach-3.1.0.tar.gz 7 | requirements: 8 | run: 9 | - setuptools 10 | - webencodings 11 | test: 12 | imports: 13 | - bleach 14 | -------------------------------------------------------------------------------- /pyodide/packages/python-dateutil/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: python-dateutil 3 | version: 2.7.2 4 | 5 | source: 6 | url: https://files.pythonhosted.org/packages/c5/39/4da7c2dbc4f023fba5fb2325febcadf0d0ce0efdc8bd12083a0f65d20653/python-dateutil-2.7.2.tar.gz 7 | md5: 03a08c8bcf0a2b29f1cd21b9de4d12fb 8 | 9 | patches: 10 | - patches/dummy-thread-lock.patch 11 | 12 | test: 13 | imports: 14 | - dateutil 15 | -------------------------------------------------------------------------------- /pyodide/packages/pytz/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: pytz 3 | version: '2018.4' 4 | 5 | source: 6 | url: https://files.pythonhosted.org/packages/10/76/52efda4ef98e7544321fd8d5d512e11739c1df18b0649551aeccfb1c8376/pytz-2018.4.tar.gz 7 | sha256: c06425302f2cf668f1bba7a0a03f3c1d34d4ebeef2c72003da308b3947c7f749 8 | 9 | patches: 10 | - patches/dummy-threading.patch 11 | 12 | test: 13 | imports: 14 | - pytz 15 | -------------------------------------------------------------------------------- /pyodide/src/pyproxy.h: -------------------------------------------------------------------------------- 1 | #ifndef PYPROXY_H 2 | #define PYPROXY_H 3 | 4 | /** Makes Python objects usable from Javascript. 5 | */ 6 | 7 | // This implements the Javascript Proxy handler interface as defined here: 8 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy 9 | 10 | int 11 | pyproxy_new(int obj); 12 | 13 | int 14 | pyproxy_init(); 15 | 16 | #endif /* PYPROXY_H */ 17 | -------------------------------------------------------------------------------- /pyodide/packages/micropip/micropip/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | 5 | setup( 6 | name='micropip', 7 | version='0.1', 8 | description='A small version of pip for running in pyodide', 9 | author='Michael Droettboom', 10 | author_email='mdroettboom@mozilla.com', 11 | url='https://github.com/iodide-project/pyodide', 12 | py_modules=['micropip'], 13 | ) 14 | -------------------------------------------------------------------------------- /pyodide/packages/mne/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: mne 3 | version: 0.17.2 4 | 5 | source: 6 | sha256: 2f40d52a8e3899359c4ecc156642cf772a8aacea206187d139bb0ab864c4b363 7 | url: https://files.pythonhosted.org/packages/68/97/fc6be75f8cc9b3f79b7c2558a45b61c6c7d02da20182f0db01ac239858be/mne-0.17.2.tar.gz 8 | 9 | requirements: 10 | run: 11 | - numpy 12 | - scipy 13 | 14 | test: 15 | imports: 16 | - mne 17 | -------------------------------------------------------------------------------- /pyodide/packages/html5lib/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: html5lib 3 | version: 1.0.1 4 | 5 | source: 6 | sha256: 66cb0dcfdbbc4f9c3ba1a63fdb511ffdbd4f513b2b6d81b80cd26ce6b3fb3736 7 | url: https://files.pythonhosted.org/packages/85/3e/cf449cf1b5004e87510b9368e7a5f1acd8831c2d6691edd3c62a0823f98f/html5lib-1.0.1.tar.gz 8 | 9 | requirements: 10 | run: 11 | - webencodings 12 | 13 | test: 14 | imports: 15 | - html5lib 16 | -------------------------------------------------------------------------------- /pyodide/test/test_bz2.py: -------------------------------------------------------------------------------- 1 | def test_bz2(selenium): 2 | selenium.run(""" 3 | import bz2 4 | 5 | text = "Hello test test test test this is a test test test" 6 | some_compressed_bytes = bz2.compress(text.encode('utf-8')) 7 | assert some_compressed_bytes != text 8 | decompressed_bytes = bz2.decompress(some_compressed_bytes) 9 | assert decompressed_bytes.decode('utf-8') == text 10 | """) 11 | -------------------------------------------------------------------------------- /pyodide/cpython/patches/no_af_vsock.patch: -------------------------------------------------------------------------------- 1 | diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h 2 | index fdb4e871ce..c990003ff3 100644 3 | --- a/Modules/socketmodule.h 4 | +++ b/Modules/socketmodule.h 5 | @@ -144,6 +144,8 @@ typedef int socklen_t; 6 | extern "C" { 7 | #endif 8 | 9 | +#undef AF_VSOCK 10 | + 11 | /* Python module and C API name */ 12 | #define PySocket_MODULE_NAME "_socket" 13 | #define PySocket_CAPI_NAME "CAPI" 14 | -------------------------------------------------------------------------------- /pyodide/run_docker: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PYODIDE_DOCKER_PORT=${PYODIDE_DOCKER_PORT:-"8000"} 4 | PYODIDE_SYSTEM_PORT=${PYODIDE_SYSTEM_PORT:-"8000"} 5 | PYODIDE_DOCKER_IMAGE=${PYODIDE_DOCKER_IMAGE:-"iodide/pyodide-env:0.3.1"} 6 | 7 | exec docker run \ 8 | -p $PYODIDE_SYSTEM_PORT:$PYODIDE_DOCKER_PORT \ 9 | -it --rm \ 10 | -v $PWD:/src \ 11 | --user root -e NB_UID=$UID -e NB_GID=$GID \ 12 | ${PYODIDE_DOCKER_IMAGE} \ 13 | /bin/bash 14 | -------------------------------------------------------------------------------- /pyodide/.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | sphinx: 9 | configuration: docs/conf.py 10 | 11 | formats: all 12 | 13 | # Optionally set the version of Python and requirements required to build your docs 14 | python: 15 | version: 3.7 16 | install: 17 | - requirements: docs/requirements-doc.txt 18 | -------------------------------------------------------------------------------- /pyodide/packages/matplotlib/patches/hardcoded_font_cache.patch: -------------------------------------------------------------------------------- 1 | --- a/lib/matplotlib/font_manager.py 2018-06-01 14:26:50.000683915 -0400 2 | +++ b/lib/matplotlib/font_manager.py 2018-06-01 14:27:16.803726101 -0400 3 | @@ -1431,7 +1431,7 @@ 4 | else: 5 | _fmcache = None 6 | 7 | - cachedir = get_cachedir() 8 | + cachedir = os.path.dirname(__file__) 9 | if cachedir is not None: 10 | _fmcache = os.path.join(cachedir, 'fontList.json') 11 | 12 | -------------------------------------------------------------------------------- /pyodide/src/webbrowser.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | """ 4 | An implementation of the standard library webbrowser module to open webpages. 5 | Since we're already running a webbrowser, it's really simple... 6 | """ 7 | 8 | 9 | def open(url, new=0, autoraise=True): 10 | from js import window 11 | window.open(url, "_blank") 12 | 13 | 14 | def open_new(url): 15 | return open(url, 1) 16 | 17 | 18 | def open_new_tab(url): 19 | return open(url, 2) 20 | -------------------------------------------------------------------------------- /pyodide/packages/setuptools/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: setuptools 3 | version: 40.0.0 4 | 5 | source: 6 | url: https://pypi.io/packages/source/s/setuptools/setuptools-40.0.0.zip 7 | sha256: 012adb8e25fbfd64c652e99e7bab58799a3aaf05d39ab38561f69190a909015f 8 | 9 | patches: 10 | - patches/remove-ctypes.patch 11 | 12 | requirements: 13 | run: 14 | - pyparsing 15 | 16 | test: 17 | imports: 18 | - setuptools 19 | - easy_install 20 | - pkg_resources 21 | -------------------------------------------------------------------------------- /pyodide/emsdk/clean_for_dist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | find . -name "*.o" -type f -delete 4 | find . -name "*.a" -type f -delete 5 | find -type d -name .git -prune -exec rm -rf {} \; 6 | find -type d -name CMakeFiles -prune -exec rm -rf {} \; 7 | rm -rf emsdk/emscripten/incoming/tests 8 | rm -rf emsdk/clang/fastcomp/src 9 | rm -rf emsdk/zips 10 | rm -rf emsdk/binaryen/master/test 11 | rm -rf emsdk/.emscripten_cache 12 | rm emsdk/.emscripten_cache.lock 13 | rm emsdk/.emscripten_sanity 14 | -------------------------------------------------------------------------------- /pyodide/packages/networkx/test_networkx.py: -------------------------------------------------------------------------------- 1 | def test_networkx_basicgraph(selenium_standalone, request): 2 | selenium = selenium_standalone 3 | selenium.load_package(['networkx']) 4 | cmd = """ 5 | import networkx as nx 6 | 7 | G = nx.Graph() 8 | G.add_nodes_from([1,2,3]) 9 | G.add_edges_from([(1,2), (1,3)]) 10 | 11 | assert G.number_of_nodes() == 3 12 | assert G.number_of_edges() == 2 13 | """ 14 | 15 | selenium.run(cmd) 16 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/create_grid.py: -------------------------------------------------------------------------------- 1 | # http://stackoverflow.com/questions/13815719/creating-grid-with-numpy-performance 2 | # pythran export create_grid(float []) 3 | # setup: import numpy as np ; N = 800 ; x = np.arange(0,1,1./N) 4 | # run: create_grid(x) 5 | import numpy as np 6 | 7 | 8 | def create_grid(x): 9 | N = x.shape[0] 10 | z = np.zeros((N, N, 3)) 11 | z[:, :, 0] = x.reshape(-1, 1) 12 | z[:, :, 1] = x 13 | fast_grid = z.reshape(N * N, 3) 14 | return fast_grid 15 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/vibr_energy.py: -------------------------------------------------------------------------------- 1 | # from: http://stackoverflow.com/questions/17112550/python-and-numba-for-vectorized-functions # noqa 2 | # setup: import numpy as np ; N = 100000 ; a, b, c = np.random.rand(N), np.random.rand(N), np.random.rand(N) # noqa 3 | # run: vibr_energy(a, b, c) 4 | 5 | # pythran export vibr_energy(float64[], float64[], float64[]) 6 | import numpy 7 | 8 | 9 | def vibr_energy(harmonic, anharmonic, i): 10 | return numpy.exp(-harmonic * i - anharmonic * (i ** 2)) 11 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/repeating.py: -------------------------------------------------------------------------------- 1 | # http://stackoverflow.com/questions/14553331/how-to-improve-numpy-performance-in-this-short-code 2 | # pythran export repeating(float[], int) 3 | # setup: import numpy as np ; a = np.random.rand(10000) 4 | # run: repeating(a, 20) 5 | 6 | import numpy as np 7 | 8 | 9 | def repeating(x, nvar_y): 10 | nvar_x = x.shape[0] 11 | y = np.empty(nvar_x * (1 + nvar_y)) 12 | y[0:nvar_x] = x[0:nvar_x] 13 | y[nvar_x:] = np.repeat(x, nvar_y) 14 | return y 15 | -------------------------------------------------------------------------------- /pyodide/src/python2js_buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef PYTHON2JS_BUFFER_H 2 | #define PYTHON2JS_BUFFER_H 3 | 4 | /** Utilities to convert Python buffer objects to Javascript. 5 | */ 6 | 7 | #include 8 | 9 | /** Convert a Python buffer object to a Javascript object. 10 | * 11 | * \param The Python object 12 | * \return The Javascript object -- might be an Error object in the case of an 13 | * exception. 14 | */ 15 | int 16 | _python2js_buffer(PyObject* x); 17 | 18 | #endif /* PYTHON2JS_BUFFER_H */ 19 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/cronbach.py: -------------------------------------------------------------------------------- 1 | # http://stackoverflow.com/questions/20799403/improving-performance-of-cronbach-alpha-code-python-numpy 2 | # pythran export cronbach(float [][]) 3 | # setup: import numpy as np ; N = 600 ; items = np.random.rand(N,N) 4 | # run: cronbach(items) 5 | 6 | 7 | def cronbach(itemscores): 8 | itemvars = itemscores.var(axis=1, ddof=1) 9 | tscores = itemscores.sum(axis=0) 10 | nitems = len(itemscores) 11 | return nitems / (nitems - 1) * (1 - itemvars.sum() / tscores.var(ddof=1)) 12 | -------------------------------------------------------------------------------- /pyodide/packages/pandas/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: pandas 3 | version: 0.23.4 4 | 5 | source: 6 | url: https://files.pythonhosted.org/packages/e9/ad/5e92ba493eff96055a23b0a1323a9a803af71ec859ae3243ced86fcbd0a4/pandas-0.23.4.tar.gz 7 | sha256: 5b24ca47acf69222e82530e89111dd9d14f9b970ab2cd3a1c2c78f0c4fbba4f4 8 | 9 | build: 10 | cflags: -Wno-implicit-function-declaration 11 | 12 | requirements: 13 | run: 14 | - numpy 15 | - python-dateutil 16 | - pytz 17 | 18 | test: 19 | imports: 20 | - pandas 21 | -------------------------------------------------------------------------------- /pyodide/packages/attrs/patches/use-dummy-threading.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/attr/_make.py b/src/attr/_make.py 2 | index fc44611..f60016e 100644 3 | --- a/src/attr/_make.py 4 | +++ b/src/attr/_make.py 5 | @@ -3,7 +3,10 @@ from __future__ import absolute_import, division, print_function 6 | import hashlib 7 | import linecache 8 | import sys 9 | -import threading 10 | +try: 11 | + import threading 12 | +except ImportError: 13 | + import dummy_threading as threading 14 | import warnings 15 | 16 | from operator import itemgetter 17 | -------------------------------------------------------------------------------- /pyodide/packages/numpy/patches/dont-include-execinfo.patch: -------------------------------------------------------------------------------- 1 | diff --git a/numpy/core/src/multiarray/temp_elide.c b/numpy/core/src/multiarray/temp_elide.c 2 | index e5175f162..13850b18b 100644 3 | --- a/numpy/core/src/multiarray/temp_elide.c 4 | +++ b/numpy/core/src/multiarray/temp_elide.c 5 | @@ -82,9 +82,9 @@ 6 | * during in-place operations 7 | */ 8 | #define NPY_MIN_ELIDE_BYTES (32) 9 | +#include 10 | #endif 11 | #include 12 | -#include 13 | 14 | /* 15 | * linear search pointer in table 16 | -------------------------------------------------------------------------------- /pyodide/test/src/test_pyodide.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from pathlib import Path 3 | from textwrap import dedent 4 | 5 | sys.path.append(str(Path(__file__).parents[2] / 'src')) 6 | 7 | from pyodide import find_imports # noqa: E402 8 | 9 | 10 | def test_find_imports(): 11 | 12 | res = find_imports(dedent(""" 13 | import six 14 | import numpy as np 15 | from scipy import sparse 16 | import matplotlib.pyplot as plt 17 | """)) 18 | assert set(res) == {'numpy', 'scipy', 'six', 'matplotlib'} 19 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/log_likelihood.py: -------------------------------------------------------------------------------- 1 | # setup: import numpy as np ; N = 100000 ; a = np.random.random(N); b = 0.1; c =1.1 # noqa 2 | # run: log_likelihood(a, b, c) 3 | # from: http://arogozhnikov.github.io/2015/09/08/SpeedBenchmarks.html 4 | import numpy 5 | 6 | # pythran export log_likelihood(float64[], float64, float64) 7 | 8 | 9 | def log_likelihood(data, mean, sigma): 10 | s = (data - mean) ** 2 / (2 * (sigma ** 2)) 11 | pdfs = numpy.exp(- s) 12 | pdfs /= numpy.sqrt(2 * numpy.pi) * sigma 13 | return numpy.log(pdfs).sum() 14 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/multiple_sum.py: -------------------------------------------------------------------------------- 1 | # from http://stackoverflow.com/questions/77999777799977/numpy-vs-cython-speed 2 | # pythran export multiple_sum(float[][]) 3 | # setup: import numpy as np ; r = np.random.rand(100,100) 4 | # run: multiple_sum(r) 5 | import numpy as np 6 | 7 | 8 | def multiple_sum(array): 9 | 10 | rows = array.shape[0] 11 | cols = array.shape[1] 12 | 13 | out = np.zeros((rows, cols)) 14 | 15 | for row in range(0, rows): 16 | out[row, :] = np.sum(array - array[row, :], 0) 17 | 18 | return out 19 | -------------------------------------------------------------------------------- /pyodide/packages/pytest/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: pytest 3 | version: 3.6.3 4 | 5 | source: 6 | url: https://files.pythonhosted.org/packages/55/50/399419c03c39bf41faa7cbd5a8976c076037b2d76adf2535610919806d67/pytest-3.6.3.tar.gz 7 | md5: 8ca6124a3a80f9555c50f5c09056ea02 8 | 9 | patches: 10 | - patches/named-tmp-and-rm-dup2.patch 11 | 12 | requirements: 13 | run: 14 | - atomicwrites 15 | - attrs 16 | - more-itertools 17 | - pluggy 18 | - py 19 | - setuptools 20 | 21 | test: 22 | imports: 23 | - pytest 24 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/allpairs_distances_loops.py: -------------------------------------------------------------------------------- 1 | # setup: import numpy as np ; N = 50 ; X, Y = np.random.randn(30,N), np.random.randn(20,N) # noqa 2 | # run: allpairs_distances_loops(X, Y) 3 | 4 | # pythran export allpairs_distances_loops(float64[][], float64[][]) 5 | import numpy as np 6 | 7 | 8 | def allpairs_distances_loops(X, Y): 9 | result = np.zeros((X.shape[0], Y.shape[0]), X.dtype) 10 | for i in range(X.shape[0]): 11 | for j in range(Y.shape[0]): 12 | result[i, j] = np.sum((X[i, :] - Y[j, :]) ** 2) 13 | return result 14 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/grouping.py: -------------------------------------------------------------------------------- 1 | # http://stackoverflow.com/questions/4651683/numpy-grouping-using-itertools-groupby-performance 2 | # setup: import numpy as np ; N = 350000 ; values = np.array(np.random.randint(0,3298,size=N),dtype='u4') ; values.sort() # noqa 3 | # run: grouping(values) 4 | 5 | # pythran export grouping(uint32 []) 6 | 7 | 8 | def grouping(values): 9 | import numpy as np 10 | diff = np.concatenate(([1], np.diff(values))) 11 | idx = np.concatenate((np.where(diff)[0], [len(values)])) 12 | return values[idx[:-1]], np.diff(idx) 13 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/smoothing.py: -------------------------------------------------------------------------------- 1 | # setup: import numpy as np ; N = 1000 ; a = np.arange(0,1,N) 2 | # run: smoothing(a, .4) 3 | # from: http://www.parakeetpython.com/ 4 | 5 | # pythran export smoothing(float[], float) 6 | 7 | 8 | def smoothing(x, alpha): 9 | """ 10 | Exponential smoothing of a time series 11 | For x = 10**6 floats 12 | - Python runtime: 9 seconds 13 | - Parakeet runtime: .01 seconds 14 | """ 15 | s = x.copy() 16 | for i in range(1, len(x)): 17 | s[i] = alpha * x[i] + (1 - alpha) * s[i - 1] 18 | return s 19 | -------------------------------------------------------------------------------- /pyodide/packages/matplotlib/patches/force_malloc_free.patch: -------------------------------------------------------------------------------- 1 | diff -ur matplotlib-2.2.2/src/_png.cpp host/matplotlib-2.2.2/src/_png.cpp 2 | --- matplotlib-2.2.2/src/_png.cpp 2018-03-17 14:03:23.000000000 -0400 3 | +++ host/matplotlib-2.2.2/src/_png.cpp 2018-05-16 17:37:38.065033586 -0400 4 | @@ -774,6 +774,10 @@ 5 | INITERROR; 6 | } 7 | 8 | + volatile long x; 9 | + x = (long)malloc(0); 10 | + free((void*)x); 11 | + 12 | import_array(); 13 | 14 | if (PyModule_AddIntConstant(m, "PNG_FILTER_NONE", PNG_FILTER_NONE) || 15 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/specialconvolve.py: -------------------------------------------------------------------------------- 1 | # from: http://stackoverflow.com/questions/2196693/improving-numpy-performance 2 | # pythran export specialconvolve(uint32 [][]) 3 | # setup: import numpy as np ; r = np.arange(100*10000, dtype=np.uint32).reshape(1000,1000) # noqa 4 | # run: specialconvolve(r) 5 | 6 | 7 | def specialconvolve(a): 8 | # sorry, you must pad the input yourself 9 | rowconvol = a[1:-1, :] + a[:-2, :] + a[2:, :] 10 | colconvol = rowconvol[:, 1:-1] + rowconvol[:, :-2] + \ 11 | rowconvol[:, 2:] - 9 * a[1:-1, 1:-1] 12 | return colconvol 13 | -------------------------------------------------------------------------------- /pyodide/packages/numpy/patches/disable-maybe-uninitialized.patch: -------------------------------------------------------------------------------- 1 | diff --git a/numpy/linalg/umath_linalg.c.src b/numpy/linalg/umath_linalg.c.src 2 | index 36b99b522..7c2d21189 100644 3 | --- a/numpy/linalg/umath_linalg.c.src 4 | +++ b/numpy/linalg/umath_linalg.c.src 5 | @@ -797,7 +797,6 @@ update_pointers(npy_uint8** bases, ptrdiff_t* offsets, size_t count) 6 | positives with this warning 7 | */ 8 | #pragma GCC diagnostic push 9 | -#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 10 | 11 | /* 12 | ***************************************************************************** 13 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/allpairs_distances.py: -------------------------------------------------------------------------------- 1 | # setup: import numpy as np ; N = 50 ; X, Y = np.random.randn(100,N), np.random.randn(40,N) # noqa 2 | # run: allpairs_distances(X, Y) 3 | 4 | # pythran export allpairs_distances(float64[][], float64[][]) 5 | import numpy as np 6 | 7 | 8 | def allpairs_distances(A, B): 9 | """ This returns the euclidean distances squared 10 | dist2(x, y) = dot(x, x) - 2 * dot(x, y) + dot(y, y) 11 | """ 12 | A2 = np.einsum('ij,ij->i', A, A) 13 | B2 = np.einsum('ij,ij->i', B, B) 14 | return A2[:, None] + B2[None, :] - 2 * np.dot(A, B.T) 15 | -------------------------------------------------------------------------------- /pyodide/packages/joblib/patches/ctypes-import.patch: -------------------------------------------------------------------------------- 1 | diff --git a/joblib/backports.py b/joblib/backports.py 2 | index 7dd3df1..a49ef78 100644 3 | --- a/joblib/backports.py 4 | +++ b/joblib/backports.py 5 | @@ -3,7 +3,6 @@ Backports of fixes for joblib dependencies 6 | """ 7 | import os 8 | import time 9 | -import ctypes 10 | import sys 11 | 12 | from distutils.version import LooseVersion 13 | @@ -34,6 +33,8 @@ except ImportError: 14 | 15 | if os.name == 'nt': 16 | error_access_denied = 5 17 | + import ctypes 18 | + 19 | try: 20 | from os import replace 21 | except ImportError: 22 | -------------------------------------------------------------------------------- /pyodide/packages/pyparsing/patches/dummy_threading.patch: -------------------------------------------------------------------------------- 1 | diff -ur pyparsing-2.2.0/pyparsing.py pyparsing-2.2.0.bak/pyparsing.py 2 | --- pyparsing-2.2.0/pyparsing.py 2017-03-05 21:06:06.000000000 -0500 3 | +++ pyparsing-2.2.0.bak/pyparsing.py 2018-05-17 11:25:17.960270391 -0400 4 | @@ -80,7 +80,10 @@ 5 | try: 6 | from _thread import RLock 7 | except ImportError: 8 | - from threading import RLock 9 | + try: 10 | + from threading import RLock 11 | + except ImportError: 12 | + from dummy_threading import RLock 13 | 14 | try: 15 | from collections import OrderedDict as _OrderedDict 16 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/pairwise_loop.py: -------------------------------------------------------------------------------- 1 | # from: http://jakevdp.github.com/blog/2012/08/24/numba-vs-cython/ 2 | # setup: import numpy as np ; X = np.linspace(0,10,200).reshape(20,10) 3 | # run: pairwise_loop(X) 4 | 5 | # pythran export pairwise_loop(float [][]) 6 | 7 | import numpy as np 8 | 9 | 10 | def pairwise_loop(X): 11 | M, N = X.shape 12 | D = np.empty((M, M)) 13 | for i in range(M): 14 | for j in range(M): 15 | d = 0.0 16 | for k in range(N): 17 | tmp = X[i, k] - X[j, k] 18 | d += tmp * tmp 19 | D[i, j] = np.sqrt(d) 20 | return D 21 | -------------------------------------------------------------------------------- /pyodide/cpython/patches/dont-test-undecodable-filenames.patch: -------------------------------------------------------------------------------- 1 | diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py 2 | index ddcd2cc387..f422f2feb6 100644 3 | --- a/Lib/test/support/__init__.py 4 | +++ b/Lib/test/support/__init__.py 5 | @@ -880,6 +880,8 @@ if os.name == 'nt': 6 | 'Unicode filename tests may not be effective' 7 | % (TESTFN_UNENCODABLE, TESTFN_ENCODING)) 8 | TESTFN_UNENCODABLE = None 9 | +elif sys.platform == 'emscripten': 10 | + pass 11 | # Mac OS X denies unencodable filenames (invalid utf-8) 12 | elif sys.platform != 'darwin': 13 | try: 14 | -------------------------------------------------------------------------------- /pyodide/src/js2python.h: -------------------------------------------------------------------------------- 1 | #ifndef JS2PYTHON_H 2 | #define JS2PYTHON_H 3 | 4 | /** 5 | * Utilities to convert Javascript objects to Python objects. 6 | */ 7 | 8 | #include 9 | 10 | /** Convert a Javascript object to a Python object. 11 | * \param x The Javascript object. 12 | * \return The Python object. New reference. If NULL, a Python exception 13 | * occurred during the conversion, and the Python exception API should be 14 | * used to obtain the exception. 15 | */ 16 | PyObject* 17 | js2python(int x); 18 | 19 | /** Initialize any global variables used by this module. */ 20 | int 21 | js2python_init(); 22 | 23 | #endif /* JS2PYTHON_H */ 24 | -------------------------------------------------------------------------------- /pyodide/docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SOURCEDIR = . 8 | BUILDDIR = _build 9 | 10 | # Put it first so that "make" without argument is like "make help". 11 | help: 12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 13 | 14 | .PHONY: help Makefile 15 | 16 | # Catch-all target: route all unknown targets to Sphinx using the new 17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 18 | %: Makefile 19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/check_mask.py: -------------------------------------------------------------------------------- 1 | # setup: n=100 ; import numpy; db = numpy.random.randint(2, size=(n, 4), dtype='bool') # noqa 2 | # run: check_mask(db) 3 | # from: 4 | # http://stackoverflow.com/questions/34500913/numba-slower-for-numpy-bitwise-and-on-boolean-arrays 5 | 6 | # pythran export check_mask(bool[][]) 7 | import numpy as np 8 | 9 | 10 | def check_mask(db, mask=[1, 0, 1]): 11 | out = np.zeros(db.shape[0], dtype=bool) 12 | for idx, line in enumerate(db): 13 | target, vector = line[0], line[1:] 14 | if (mask == np.bitwise_and(mask, vector)).all(): 15 | if target == 1: 16 | out[idx] = 1 17 | return out 18 | -------------------------------------------------------------------------------- /pyodide/packages/pytz/patches/dummy-threading.patch: -------------------------------------------------------------------------------- 1 | diff -ru pytz-2018.4.orig/pytz/lazy.py pytz-2018.4/pytz/lazy.py 2 | --- pytz-2018.4.orig/pytz/lazy.py 2018-04-24 15:47:46.293980100 -0400 3 | +++ pytz-2018.4/pytz/lazy.py 2018-04-24 15:56:06.281648286 -0400 4 | @@ -1,4 +1,7 @@ 5 | -from threading import RLock 6 | +try: 7 | + from threading import RLock 8 | +except (ImportError, ModuleNotFoundError): 9 | + from dummy_threading import RLock 10 | try: 11 | from collections.abc import Mapping as DictMixin 12 | except ImportError: # Python < 3.3 13 | Binary files pytz-2018.4.orig/pytz/__pycache__/lazy.cpython-36.pyc and pytz-2018.4/pytz/__pycache__/lazy.cpython-36.pyc differ 14 | -------------------------------------------------------------------------------- /pyodide/pyodide_build/_fixes.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | 4 | # Temporary fix from https://github.com/SeleniumHQ/selenium/pull/6480 5 | # to avoid ConnectionError in selenium 6 | 7 | def _selenium_is_connectable(port, host="localhost"): 8 | """ 9 | Tries to connect to the server at port to see if it is running. 10 | :Args: 11 | - port - The port to connect. 12 | """ 13 | socket_ = None 14 | try: 15 | socket_ = socket.create_connection((host, port), 1) 16 | result = True 17 | except (socket.error, ConnectionError): 18 | result = False 19 | finally: 20 | if socket_: 21 | socket_.close() 22 | return result 23 | -------------------------------------------------------------------------------- /pyodide/cpython/patches/disable-set_inheritable.patch: -------------------------------------------------------------------------------- 1 | diff --git a/Python/fileutils.c b/Python/fileutils.c 2 | index 35869c81ac..1af4ead7f5 100644 3 | --- a/Python/fileutils.c 4 | +++ b/Python/fileutils.c 5 | @@ -964,6 +964,9 @@ _Py_get_inheritable(int fd) 6 | static int 7 | set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) 8 | { 9 | +#ifdef EMSCRIPTEN 10 | + return 0; 11 | +#else 12 | #ifdef MS_WINDOWS 13 | HANDLE handle; 14 | DWORD flags; 15 | @@ -1080,6 +1083,7 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) 16 | } 17 | return 0; 18 | #endif 19 | +#endif 20 | } 21 | 22 | /* Make the file descriptor non-inheritable. 23 | -------------------------------------------------------------------------------- /pyodide/docs/README.md: -------------------------------------------------------------------------------- 1 | # Pyodide documentation 2 | 3 | ## Using Pyodide 4 | 5 | - [Using Pyodide directly from Javascript](using_pyodide_from_javascript.md) 6 | - [Using Pyodide from a web worker](using_pyodide_from_webworker.md) 7 | - [Using Pyodide from Iodide](using_pyodide_from_iodide.md) 8 | - [Installing packages from PyPI](pypi.md) 9 | - [Type conversions](type_conversions.md): describes how data types are shared between Python and Javascript 10 | - [API Reference](api_reference.md) 11 | 12 | ## Developing Pyodide 13 | 14 | - [Making new packages](new_packages.md) 15 | - [Development instructions](../README.md) 16 | - [Contributing](../CONTRIBUTING.md) 17 | - [Code of Conduct](../CODE-OF-CONDUCT.md) 18 | -------------------------------------------------------------------------------- /pyodide/src/python2js.h: -------------------------------------------------------------------------------- 1 | #ifndef PYTHON2JS_H 2 | #define PYTHON2JS_H 3 | 4 | /** Utilities to convert Python objects to Javascript. 5 | */ 6 | 7 | #include 8 | 9 | /** Convert the active Python exception into a Javascript Error object. 10 | * \return A Javascript Error object 11 | */ 12 | int 13 | pythonexc2js(); 14 | 15 | /** Convert a Python object to a Javascript object. 16 | * \param The Python object 17 | * \return The Javascript object -- might be an Error object in the case of an 18 | * exception. 19 | */ 20 | int 21 | python2js(PyObject* x); 22 | 23 | /** Set up the global state for this module. 24 | */ 25 | int 26 | python2js_init(); 27 | 28 | #endif /* PYTHON2JS_H */ 29 | -------------------------------------------------------------------------------- /pyodide/emsdk/patches/num_params.patch: -------------------------------------------------------------------------------- 1 | --- a/emsdk/binaryen/tag-1.38.30/src/passes/FuncCastEmulation.cpp 2019-04-03 11:30:13.556074729 -0400 2 | +++ b/emsdk/binaryen/tag-1.38.30/src/passes/FuncCastEmulation.cpp 2019-04-03 11:30:32.817143862 -0400 3 | @@ -39,7 +39,7 @@ 4 | // This should be enough for everybody. (As described above, we need this 5 | // to match when dynamically linking, and also dynamic linking is why we 6 | // can't just detect this automatically in the module we see.) 7 | -static const int NUM_PARAMS = 16; 8 | +static const int NUM_PARAMS = 61; // needed by scipy.odr._odrpack 9 | 10 | // Converts a value to the ABI type of i64. 11 | static Expression* toABI(Expression* value, Module* module) { 12 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/hasting.py: -------------------------------------------------------------------------------- 1 | # from: http://wiki.scipy.org/Cookbook/Theoretical_Ecology/Hastings_and_Powell 2 | # setup: import numpy as np ; y = np.random.rand(3) ; args = np.random.rand(7) 3 | # run: hasting(y, *args) 4 | 5 | # pythran export hasting(float [], float, float, float, float, float, 6 | # float, float) 7 | import numpy as np 8 | 9 | 10 | def hasting(y, t, a1, a2, b1, b2, d1, d2): 11 | yprime = np.empty((3,)) 12 | yprime[0] = y[0] * (1. - y[0]) - a1 * y[0] * y[1] / (1. + b1 * y[0]) 13 | yprime[1] = a1 * y[0] * y[1] / (1. + b1 * y[0]) - \ 14 | a2 * y[1] * y[2] / (1. + b2 * y[1]) - d1 * y[1] 15 | yprime[2] = a2 * y[1] * y[2] / (1. + b2 * y[1]) - d2 * y[2] 16 | return yprime 17 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/diffusion.py: -------------------------------------------------------------------------------- 1 | # setup: import numpy as np;lx,ly=(2**6,2**6);u=np.zeros([lx,ly],dtype=np.double);u[lx//2,ly//2]=1000.0;tempU=np.zeros([lx,ly],dtype=np.double) # noqa 2 | # run: diffusion(u,tempU,100) 3 | 4 | # pythran export diffusion(float [][], float [][], int) 5 | 6 | 7 | def diffusion(u, tempU, iterNum): 8 | """ 9 | Apply Numpy matrix for the Forward-Euler Approximation 10 | """ 11 | mu = .1 12 | 13 | for n in range(iterNum): 14 | tempU[1:-1, 1:-1] = u[1:-1, 1:-1] + mu * ( 15 | u[2:, 1:-1] - 2 * u[1:-1, 1:-1] + u[0:-2, 1:-1] + 16 | u[1:-1, 2:] - 2 * u[1:-1, 1:-1] + u[1:-1, 0:-2]) 17 | u[:, :] = tempU[:, :] 18 | tempU[:, :] = 0.0 19 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/lstsqr.py: -------------------------------------------------------------------------------- 1 | # setup: import numpy as np ; N = 500000 ; X, Y = np.random.rand(N), np.random.rand(N) # noqa 2 | # run: lstsqr(X, Y) 3 | # from: 4 | # http://nbviewer.ipython.org/github/rasbt/One-Python-benchmark-per-day/blob/master/ipython_nbs/day10_fortran_lstsqr.ipynb 5 | 6 | # pythran export lstsqr(float[], float[]) 7 | import numpy as np 8 | 9 | 10 | def lstsqr(x, y): 11 | """ Computes the least-squares solution to a linear matrix equation. """ 12 | x_avg = np.average(x) 13 | y_avg = np.average(y) 14 | dx = x - x_avg 15 | var_x = np.sum(dx**2) 16 | cov_xy = np.sum(dx * (y - y_avg)) 17 | slope = cov_xy / var_x 18 | y_interc = y_avg - slope * x_avg 19 | return (slope, y_interc) 20 | -------------------------------------------------------------------------------- /pyodide/src/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /pyodide/packages/numpy/patches/fix-install-with-skip-build.patch: -------------------------------------------------------------------------------- 1 | diff --git a/numpy/distutils/command/install_clib.py b/numpy/distutils/command/install_clib.py 2 | index 662aa00bd..6f51e22ca 100644 3 | --- a/numpy/distutils/command/install_clib.py 4 | +++ b/numpy/distutils/command/install_clib.py 5 | @@ -20,6 +20,9 @@ class install_clib(Command): 6 | def run (self): 7 | build_clib_cmd = get_cmd("build_clib") 8 | build_dir = build_clib_cmd.build_clib 9 | + if build_dir is None: 10 | + build_clib_cmd.finalize_options() 11 | + build_dir = build_clib_cmd.build_clib 12 | 13 | # We need the compiler to get the library name -> filename association 14 | if not build_clib_cmd.compiler: 15 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/arc_distance.py: -------------------------------------------------------------------------------- 1 | # setup: N = 5000 ; import numpy as np ; t0, p0, t1, p1 = np.random.randn(N), np.random.randn(N), np.random.randn(N), np.random.randn(N) # noqa 2 | # run: arc_distance(t0, p0, t1, p1) 3 | 4 | # pythran export arc_distance(float64 [], float64[], float64[], float64[]) 5 | 6 | import numpy as np 7 | 8 | 9 | def arc_distance(theta_1, phi_1, theta_2, phi_2): 10 | """ 11 | Calculates the pairwise arc distance between all points in vector a and b. 12 | """ 13 | temp = (np.sin((theta_2 - theta_1) / 2)**2 + np.cos(theta_1) 14 | * np.cos(theta_2) * np.sin((phi_2 - phi_1) / 2)**2) 15 | distance_matrix = 2 * (np.arctan2(np.sqrt(temp), np.sqrt(1 - temp))) 16 | return distance_matrix 17 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/evolve.py: -------------------------------------------------------------------------------- 1 | # setup: import numpy as np ; grid_shape = (512, 512) ; grid = np.zeros(grid_shape) ; block_low = int(grid_shape[0] * .4) ; block_high = int(grid_shape[0] * .5) ; grid[block_low:block_high, block_low:block_high] = 0.005 # noqa 2 | # run: evolve(grid, 0.1) 3 | # from: High Performance Python by Micha Gorelick and Ian Ozsvald, 4 | # http://shop.oreilly.com/product/0636920028963.do 5 | 6 | # pythran export evolve(float64[][], float) 7 | 8 | import numpy as np 9 | 10 | 11 | def laplacian(grid): 12 | return (np.roll(grid, +1, 0) + np.roll(grid, -1, 0) 13 | + np.roll(grid, +1, 1) + np.roll(grid, -1, 1) - 4 * grid) 14 | 15 | 16 | def evolve(grid, dt, D=1): 17 | return grid + dt * D * laplacian(grid) 18 | -------------------------------------------------------------------------------- /pyodide/packages/numpy/patches/use-local-blas-lapack.patch: -------------------------------------------------------------------------------- 1 | diff --git a/numpy/distutils/system_info.py b/numpy/distutils/system_info.py 2 | old mode 100644 3 | new mode 100755 4 | index bea120cf9..5b2ccb2c1 5 | --- a/numpy/distutils/system_info.py 6 | +++ b/numpy/distutils/system_info.py 7 | @@ -406,8 +406,8 @@ def get_info(name, notfound_action=0): 8 | 'numeric': Numeric_info, 9 | 'numarray': numarray_info, 10 | 'numerix': numerix_info, 11 | - 'lapack_opt': lapack_opt_info, 12 | - 'blas_opt': blas_opt_info, 13 | + 'lapack_opt': lapack_src_info, 14 | + 'blas_opt': blas_src_info, 15 | 'boost_python': boost_python_info, 16 | 'agg2': agg2_info, 17 | 'wx': wx_info, 18 | -------------------------------------------------------------------------------- /pyodide/test/test_testing.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | 3 | 4 | def test_pytest(selenium): 5 | selenium.load_package(['pytest', 'numpy', 'nose']) 6 | 7 | selenium.run( 8 | """ 9 | from pathlib import Path 10 | import os 11 | import numpy 12 | import pytest 13 | 14 | base_dir = Path(numpy.__file__).parent / "core" / "tests" 15 | """) 16 | 17 | selenium.run("pytest.main([base_dir / 'test_api.py'])") 18 | 19 | logs = '\n'.join(selenium.logs) 20 | assert 'INTERNALERROR' not in logs 21 | 22 | 23 | def test_web_server_secondary(selenium, web_server_secondary): 24 | host, port, logs = web_server_secondary 25 | assert pathlib.Path(logs).exists() 26 | assert selenium.server_port != port 27 | -------------------------------------------------------------------------------- /pyodide/packages/scikit-learn/patches/use-site-joblib.patch: -------------------------------------------------------------------------------- 1 | commit 55cfffe8243d7d85dc6f8d14f045cee8a4e8b0ae 2 | Author: Roman Yurchak 3 | Date: Mon Dec 3 22:09:46 2018 +0100 4 | 5 | Use site joblib 6 | 7 | diff --git a/sklearn/utils/_joblib.py b/sklearn/utils/_joblib.py 8 | index c3df15e91..b9f218ef1 100644 9 | --- a/sklearn/utils/_joblib.py 10 | +++ b/sklearn/utils/_joblib.py 11 | @@ -5,7 +5,7 @@ import os as _os 12 | import warnings as _warnings 13 | 14 | # An environment variable to use the site joblib 15 | -if _os.environ.get('SKLEARN_SITE_JOBLIB', False): 16 | +if True: 17 | with _warnings.catch_warnings(): 18 | _warnings.simplefilter("ignore") 19 | # joblib imports may raise DeprecationWarning on certain Python 20 | -------------------------------------------------------------------------------- /pyodide/lz4/Makefile: -------------------------------------------------------------------------------- 1 | PYODIDE_ROOT=$(abspath ..) 2 | include ../Makefile.envs 3 | 4 | LZ4VERSION=1.8.3 5 | 6 | ROOT=$(abspath .) 7 | 8 | SRC=$(ROOT)/lz4-$(LZ4VERSION) 9 | TARBALL=$(ROOT)/downloads/lz4-$(LZ4VERSION).tgz 10 | URL=https://github.com/lz4/lz4/archive/v$(LZ4VERSION).tar.gz 11 | 12 | 13 | all: $(SRC)/lib/liblz4.a 14 | 15 | 16 | clean: 17 | -rm -fr downloads 18 | -rm -fr $(SRC) 19 | 20 | 21 | $(TARBALL): 22 | [ -d $(ROOT)/downloads ] || mkdir $(ROOT)/downloads 23 | wget -q -O $@ $(URL) 24 | # md5sum --quiet --check checksums || (rm $@; false) 25 | 26 | 27 | $(SRC)/Makefile: $(TARBALL) 28 | tar -C . -xf $(TARBALL) 29 | touch $(SRC)/Makefile 30 | 31 | 32 | $(SRC)/lib/liblz4.a: $(SRC)/Makefile 33 | ( \ 34 | cd $(SRC) ; \ 35 | emmake make ; \ 36 | ) 37 | -------------------------------------------------------------------------------- /pyodide/jedi/Makefile: -------------------------------------------------------------------------------- 1 | PYODIDE_ROOT=$(abspath ..) 2 | include ../Makefile.envs 3 | 4 | JEDIVERSION=0.15.1 5 | 6 | ROOT=$(abspath .) 7 | 8 | SRC=$(ROOT)/jedi-$(JEDIVERSION) 9 | BUILD=$(SRC)/build/lib/jedi 10 | TARBALL=$(ROOT)/downloads/jedi-$(JEDIVERSION).tar.gz 11 | URL=https://files.pythonhosted.org/packages/85/03/cd5a6e44a5753b4d539288d9d1f9645caac889c17dd2950292a8818f86b2/jedi-$(JEDIVERSION).tar.gz 12 | 13 | 14 | all: $(SRC)/setup.py 15 | 16 | 17 | clean: 18 | -rm -fr downloads 19 | -rm -fr $(SRC) 20 | 21 | 22 | $(TARBALL): 23 | [ -d $(ROOT)/downloads ] || mkdir $(ROOT)/downloads 24 | wget -q -O $@ $(URL) 25 | sha256sum --quiet --check checksums || (rm $@; false) 26 | 27 | 28 | $(SRC)/setup.py: $(TARBALL) 29 | tar -C . -xf $(TARBALL) 30 | touch $(SRC)/setup.py 31 | -------------------------------------------------------------------------------- /pyodide/parso/Makefile: -------------------------------------------------------------------------------- 1 | PYODIDE_ROOT=$(abspath ..) 2 | include ../Makefile.envs 3 | 4 | PARSOVERSION=0.5.1 5 | 6 | ROOT=$(abspath .) 7 | 8 | SRC=$(ROOT)/parso-$(PARSOVERSION) 9 | BUILD=$(SRC)/build/lib/parso 10 | TARBALL=$(ROOT)/downloads/parso-$(PARSOVERSION).tar.gz 11 | URL=https://files.pythonhosted.org/packages/21/40/615957db4d178b7504c87b1a5b85fa5945b0b4fa5f5a845e31fc7aad6018/parso-$(PARSOVERSION).tar.gz 12 | 13 | 14 | all: $(SRC)/setup.py 15 | 16 | 17 | clean: 18 | -rm -fr downloads 19 | -rm -fr $(SRC) 20 | 21 | 22 | $(TARBALL): 23 | [ -d $(ROOT)/downloads ] || mkdir $(ROOT)/downloads 24 | wget -q -O $@ $(URL) 25 | sha256sum --quiet --check checksums || (rm $@; false) 26 | 27 | 28 | $(SRC)/setup.py: $(TARBALL) 29 | tar -C . -xf $(TARBALL) 30 | touch $(SRC)/setup.py 31 | -------------------------------------------------------------------------------- /pyodide/packages/numpy/patches/force_malloc.patch: -------------------------------------------------------------------------------- 1 | diff --git a/numpy/fft/fftpack_litemodule.c b/numpy/fft/fftpack_litemodule.c 2 | index dfa0d211b..0bdf709c5 100644 3 | --- a/numpy/fft/fftpack_litemodule.c 4 | +++ b/numpy/fft/fftpack_litemodule.c 5 | @@ -328,6 +328,8 @@ static struct PyModuleDef moduledef = { 6 | }; 7 | #endif 8 | 9 | +static volatile int *_dummy_malloc; 10 | + 11 | /* Initialization function for the module */ 12 | #if PY_MAJOR_VERSION >= 3 13 | #define RETVAL m 14 | @@ -349,6 +351,10 @@ initfftpack_lite(void) 15 | (PyObject*)NULL,PYTHON_API_VERSION); 16 | #endif 17 | 18 | + _dummy_malloc = malloc(sizeof(int)); 19 | + *_dummy_malloc = 1; 20 | + free((void *)_dummy_malloc); 21 | + 22 | /* Import the array object */ 23 | import_array(); 24 | 25 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/harris.py: -------------------------------------------------------------------------------- 1 | # from: parakeet testbed 2 | # setup: import numpy as np ; M, N = 512, 512 ; I = np.random.randn(M,N) 3 | # run: harris(I) 4 | 5 | # pythran export harris(float64[][]) 6 | 7 | 8 | def harris(I): 9 | m, n = I.shape 10 | dx = (I[1:, :] - I[:m - 1, :])[:, 1:] 11 | dy = (I[:, 1:] - I[:, :n - 1])[1:, :] 12 | 13 | # 14 | # At each point we build a matrix 15 | # of derivative products 16 | # M = 17 | # | A = dx^2 C = dx * dy | 18 | # | C = dy * dx B = dy * dy | 19 | # 20 | # and the score at that point is: 21 | # det(M) - k*trace(M)^2 22 | # 23 | A = dx * dx 24 | B = dy * dy 25 | C = dx * dy 26 | tr = A + B 27 | det = A * B - C * C 28 | k = 0.05 29 | return det - k * tr * tr 30 | -------------------------------------------------------------------------------- /pyodide/packages/numpy/patches/fix-longdouble.patch: -------------------------------------------------------------------------------- 1 | diff --git a/numpy/core/src/npymath/npy_math_complex.c.src b/numpy/core/src/npymath/npy_math_complex.c.src 2 | index cf427dad8..6c9f1c37e 100644 3 | --- a/numpy/core/src/npymath/npy_math_complex.c.src 4 | +++ b/numpy/core/src/npymath/npy_math_complex.c.src 5 | @@ -1522,10 +1522,9 @@ _sum_squares@c@(@type@ x, @type@ y) 6 | #if @precision@ == 1 7 | const npy_float SQRT_MIN = 1.0842022e-19f; 8 | #endif 9 | -#if @precision@ == 2 10 | +#if @precision@ == 2 || NPY_SIZEOF_LONGDOUBLE < 16 11 | const npy_double SQRT_MIN = 1.4916681462400413e-154; /* sqrt(DBL_MIN) */ 12 | -#endif 13 | -#if @precision@ == 3 14 | +#elif @precision@ == 3 15 | #if NPY_SIZEOF_LONGDOUBLE == NPY_SIZEOF_DOUBLE 16 | const npy_longdouble SQRT_MIN = 1.4916681462400413e-154; /* sqrt(DBL_MIN) */ 17 | #else 18 | -------------------------------------------------------------------------------- /pyodide/packages/scikit-learn/test_scikit-learn.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | def test_scikit_learn(selenium_standalone, request): 5 | selenium = selenium_standalone 6 | if selenium.browser == 'chrome': 7 | request.applymarker(pytest.mark.xfail( 8 | run=False, reason='chrome not supported')) 9 | selenium.load_package("scikit-learn") 10 | assert selenium.run(""" 11 | import numpy as np 12 | import sklearn 13 | from sklearn.linear_model import LogisticRegression 14 | 15 | rng = np.random.RandomState(42) 16 | X = rng.rand(100, 20) 17 | y = rng.randint(5, size=100) 18 | 19 | estimator = LogisticRegression(solver='liblinear') 20 | estimator.fit(X, y) 21 | print(estimator.predict(X)) 22 | estimator.score(X, y) 23 | """) > 0 24 | -------------------------------------------------------------------------------- /http_server.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #test on python 3.4 ,python of lower version has different module organization. 3 | import http.server 4 | from http.server import HTTPServer, BaseHTTPRequestHandler 5 | import socketserver 6 | 7 | PORT = 8000 8 | 9 | Handler = http.server.SimpleHTTPRequestHandler 10 | 11 | Handler.extensions_map={ 12 | '.manifest': 'text/cache-manifest', 13 | '.html': 'text/html', 14 | '.png': 'image/png', 15 | '.jpg': 'image/jpg', 16 | '.svg': 'image/svg+xml', 17 | '.css': 'text/css', 18 | '.js': 'application/x-javascript', 19 | '.wasm': 'application/wasm', 20 | '': 'application/octet-stream', # Default 21 | } 22 | 23 | httpd = socketserver.TCPServer(("", PORT), Handler) 24 | 25 | print("serving at port", PORT) 26 | httpd.serve_forever() 27 | -------------------------------------------------------------------------------- /pyodide/cpython/pyconfig.undefs.h: -------------------------------------------------------------------------------- 1 | #undef HAVE_EPOLL 2 | #undef HAVE_EPOLL_CREATE1 3 | #undef HAVE_LINUX_VM_SOCKETS_H 4 | #undef HAVE_SOCKETPAIR 5 | #undef HAVE_UTIMENSAT 6 | #undef HAVE_SIGACTION 7 | 8 | /* Untested syscalls in emscripten */ 9 | #undef HAVE_OPENAT 10 | #undef HAVE_MKDIRAT 11 | #undef HAVE_FCHOWNAT 12 | #undef HAVE_RENAMEAT 13 | #undef HAVE_LINKAT 14 | #undef HAVE_SYMLINKAT 15 | #undef HAVE_READLINKAT 16 | #undef HAVE_FCHMODAT 17 | #undef HAVE_DUP3 18 | 19 | /* Syscalls not implemented in emscripten */ 20 | #undef HAVE_PREADV 21 | #undef HAVE_PWRITEV 22 | #undef HAVE_PIPE2 23 | #undef HAVE_NICE 24 | 25 | /* Syscalls that resulted in a segfault */ 26 | #undef HAVE_UTIMENSAT 27 | #undef HAVE_SYS_SOCKET_H 28 | #undef HAVE_SYS_IOCTL_H 29 | 30 | /* Unsupported functionality */ 31 | #undef HAVE_PTHREAD_H 32 | 33 | #define CONFIG_32 34 | #define ANSI 35 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/hyantes.py: -------------------------------------------------------------------------------- 1 | # setup: import numpy ; a = numpy.array([ [i/10., i/10., i/20.] for i in range(44440)], dtype=numpy.double) # noqa 2 | # run: hyantes(0, 0, 90, 90, 1, 100, 80, 80, a) 3 | 4 | # pythran export hyantes(float, float, float, float, float, float, int, 5 | # int, float[][]) 6 | import numpy as np 7 | 8 | 9 | def hyantes(xmin, ymin, xmax, ymax, step, range_, range_x, range_y, t): 10 | X, Y = t.shape 11 | pt = np.zeros((X, Y)) 12 | for i in range(X): 13 | for j in range(Y): 14 | for k in t: 15 | tmp = (6368. * np.arccos(np.cos(xmin + step * i) 16 | * np.cos(k[0]) * np.cos((ymin + step * j) - k[1]) 17 | + np.sin(xmin + step * i) * np.sin(k[0]))) 18 | if tmp < range_: 19 | pt[i, j] += k[2] / (1 + tmp) 20 | return pt 21 | -------------------------------------------------------------------------------- /pyodide/packages/numpy/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: numpy 3 | version: 1.15.1 4 | 5 | source: 6 | url: https://files.pythonhosted.org/packages/65/ab/4dfcc20234fae12ee40c714b98077d6e3a10652496bd1488fa4828529b22/numpy-1.15.1.zip 7 | sha256: 7b9e37f194f8bcdca8e9e6af92e2cbad79e360542effc2dd6b98d63955d8d8a3 8 | 9 | patches: 10 | - patches/add-emscripten-cpu.patch 11 | - patches/disable-maybe-uninitialized.patch 12 | - patches/dont-include-execinfo.patch 13 | - patches/fix-longdouble.patch 14 | - patches/fix-static-init-of-nditer-pywrap.patch 15 | - patches/force_malloc.patch 16 | - patches/init-alloc-cache.patch 17 | - patches/use-local-blas-lapack.patch 18 | - patches/fix-install-with-skip-build.patch 19 | 20 | build: 21 | skip_host: False 22 | cflags: -include math.h -I../../config 23 | 24 | 25 | test: 26 | imports: 27 | - numpy 28 | -------------------------------------------------------------------------------- /pyodide/test/test_sqlite3.py: -------------------------------------------------------------------------------- 1 | def test_sqlite3(selenium): 2 | content = selenium.run(""" 3 | import sqlite3 4 | 5 | with sqlite3.connect(':memory:') as conn: 6 | c = conn.cursor() 7 | c.execute(''' 8 | CREATE TABLE people ( 9 | first_name VARCHAR, 10 | last_name VARCHAR 11 | ) 12 | ''') 13 | c.execute("INSERT INTO people VALUES ('John', 'Doe')") 14 | c.execute("INSERT INTO people VALUES ('Jane', 'Smith')") 15 | c.execute("INSERT INTO people VALUES ('Michael', 'Jordan')") 16 | c.execute("SELECT * FROM people") 17 | """) 18 | content = selenium.run("c.fetchall()") 19 | assert len(content) == 3 20 | assert content[0][0] == 'John' 21 | assert content[1][0] == 'Jane' 22 | assert content[2][0] == 'Michael' 23 | -------------------------------------------------------------------------------- /pyodide/pyodide_build/common.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | 4 | ROOTDIR = Path(__file__).parents[1].resolve() / 'tools' 5 | HOSTPYTHON = ROOTDIR / '..' / 'cpython' / 'build' / '3.7.0' / 'host' 6 | TARGETPYTHON = ROOTDIR / '..' / 'cpython' / 'installs' / 'python-3.7.0' 7 | DEFAULTCFLAGS = '' 8 | DEFAULTLDFLAGS = ' '.join([ 9 | '-O3', 10 | '-s', "BINARYEN_METHOD='native-wasm'", 11 | '-Werror', 12 | '-s', 'EMULATED_FUNCTION_POINTERS=1', 13 | '-s', 'EMULATE_FUNCTION_POINTER_CASTS=1', 14 | '-s', 'SIDE_MODULE=1', 15 | '-s', 'WASM=1', 16 | '--memory-init-file', '0' 17 | ]) 18 | 19 | 20 | def parse_package(package): 21 | # Import yaml here because pywasmcross needs to run in the built native 22 | # Python, which won't have PyYAML 23 | import yaml 24 | # TODO: Validate against a schema 25 | with open(package) as fd: 26 | return yaml.load(fd) 27 | -------------------------------------------------------------------------------- /pyodide/packages/micropip/test_micropip.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | 4 | def test_install_simple(selenium_standalone): 5 | selenium_standalone.run("import os") 6 | selenium_standalone.load_package("micropip") 7 | selenium_standalone.run("import micropip") 8 | selenium_standalone.run("micropip.install('snowballstemmer')") 9 | 10 | for i in range(10): 11 | if selenium_standalone.run( 12 | "os.path.exists" 13 | "('/lib/python3.6/site-packages/snowballstemmer')" 14 | ): 15 | break 16 | else: 17 | time.sleep(1) 18 | 19 | selenium_standalone.run("import snowballstemmer") 20 | selenium_standalone.run("stemmer = snowballstemmer.stemmer('english')") 21 | assert selenium_standalone.run( 22 | "stemmer.stemWords('go going goes gone'.split())") == [ 23 | 'go', 'go', 'goe', 'gone' 24 | ] 25 | -------------------------------------------------------------------------------- /pyodide/src/pyimport.c: -------------------------------------------------------------------------------- 1 | #include "pyimport.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "python2js.h" 7 | 8 | extern PyObject* globals; 9 | 10 | int 11 | _pyimport(char* name) 12 | { 13 | PyObject* pyname = PyUnicode_FromString(name); 14 | PyObject* pyval = PyDict_GetItem(globals, pyname); 15 | if (pyval == NULL) { 16 | Py_DECREF(pyname); 17 | return pythonexc2js(); 18 | } 19 | 20 | Py_DECREF(pyname); 21 | int idval = python2js(pyval); 22 | return idval; 23 | } 24 | 25 | EM_JS(int, pyimport_init, (), { 26 | Module.pyimport = function(name) 27 | { 28 | var pyname = allocate(intArrayFromString(name), 'i8', ALLOC_NORMAL); 29 | var idresult = Module.__pyimport(pyname); 30 | jsresult = Module.hiwire_get_value(idresult); 31 | Module.hiwire_decref(idresult); 32 | _free(pyname); 33 | return jsresult; 34 | }; 35 | 36 | return 0; 37 | }); 38 | -------------------------------------------------------------------------------- /pyodide/docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /pyodide/packages/numpy/patches/fix-static-init-of-nditer-pywrap.patch: -------------------------------------------------------------------------------- 1 | diff --git a/numpy/core/src/multiarray/nditer_pywrap.c b/numpy/core/src/multiarray/nditer_pywrap.c 2 | index 0d318178f..2d3de0247 100644 3 | --- a/numpy/core/src/multiarray/nditer_pywrap.c 4 | +++ b/numpy/core/src/multiarray/nditer_pywrap.c 5 | @@ -2481,7 +2481,7 @@ NPY_NO_EXPORT PyTypeObject NpyIter_Type = { 6 | 0, /* tp_iter */ 7 | (iternextfunc)npyiter_next, /* tp_iternext */ 8 | npyiter_methods, /* tp_methods */ 9 | - npyiter_members, /* tp_members */ 10 | + 0, /* tp_members */ 11 | npyiter_getsets, /* tp_getset */ 12 | 0, /* tp_base */ 13 | 0, /* tp_dict */ 14 | -------------------------------------------------------------------------------- /pyodide/six/Makefile: -------------------------------------------------------------------------------- 1 | PYODIDE_ROOT=$(abspath ..) 2 | include ../Makefile.envs 3 | 4 | SIXVERSION=1.11.0 5 | 6 | ROOT=$(abspath .) 7 | 8 | SRC=$(ROOT)/six-$(SIXVERSION) 9 | BUILD=$(SRC)/build/lib/six 10 | TARBALL=$(ROOT)/downloads/six-$(SIXVERSION).tgz 11 | URL=https://files.pythonhosted.org/packages/16/d8/bc6316cf98419719bd59c91742194c111b6f2e85abac88e496adefaf7afe/six-1.11.0.tar.gz 12 | 13 | 14 | all: $(BUILD)/__init__.py 15 | 16 | 17 | clean: 18 | -rm -fr downloads 19 | -rm -fr $(SRC) 20 | 21 | 22 | $(TARBALL): 23 | [ -d $(ROOT)/downloads ] || mkdir $(ROOT)/downloads 24 | wget -q -O $@ $(URL) 25 | md5sum --quiet --check checksums || (rm $@; false) 26 | 27 | 28 | $(SRC)/setup.py: $(TARBALL) 29 | tar -C . -xf $(TARBALL) 30 | touch $(SRC)/setup.py 31 | 32 | 33 | $(BUILD)/__init__.py: $(SRC)/setup.py 34 | ( \ 35 | cd $(SRC) ; \ 36 | $(HOSTPYTHON) setup.py build ; \ 37 | touch build/lib/six.py \ 38 | ) 39 | -------------------------------------------------------------------------------- /pyodide/src/webworker.js: -------------------------------------------------------------------------------- 1 | self.languagePluginUrl = '{{DEPLOY}}' 2 | importScripts('./pyodide.js') 3 | 4 | var onmessage = function(e) { // eslint-disable-line no-unused-vars 5 | languagePluginLoader.then(() => { 6 | const data = e.data; 7 | const keys = Object.keys(data); 8 | for (let key of keys) { 9 | if (key !== 'python') { 10 | // Keys other than python must be arguments for the python script. 11 | // Set them on self, so that `from js import key` works. 12 | self[key] = data[key]; 13 | } 14 | } 15 | 16 | self.pyodide.runPythonAsync(data.python, () => {}) 17 | .then((results) => { self.postMessage({results}); }) 18 | .catch((err) => { 19 | // if you prefer messages with the error 20 | self.postMessage({error : err.message}); 21 | // if you prefer onerror events 22 | // setTimeout(() => { throw err; }); 23 | }); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /pyodide/CLAPACK/Makefile: -------------------------------------------------------------------------------- 1 | PYODIDE_ROOT=$(abspath ..) 2 | include ../Makefile.envs 3 | 4 | CLAPACK_VERSION=3.2.1 5 | 6 | ROOT=$(abspath .) 7 | 8 | SRC=$(ROOT)/CLAPACK-WA 9 | 10 | 11 | all: $(SRC)/lapack_WA.bc 12 | 13 | clean: 14 | rm -rf CLAPACK-WA 15 | 16 | $(SRC)/lapack_WA.bc: $(SRC)/Makefile 17 | # We build BLAS/LAPACK only for target. 18 | # On host we include -LCLAPACK-WA path which has no effect on host. 19 | # On target it gets rewritten by pywasmcross to the full patch of 20 | # blas_WA.bc, lapack_WA.bc which are linked statically in scipy 21 | # in each module that needs them. 22 | emmake make -C CLAPACK-WA/ 23 | 24 | 25 | $(SRC)/Makefile: 26 | wget -q -O clapack.tgz http://www.netlib.org/clapack/clapack.tgz 27 | md5sum --quiet --check checksums || (rm -f clapack.tgz; false) 28 | tar xzf clapack.tgz 29 | rm -rf $(SRC) 30 | mv CLAPACK-$(CLAPACK_VERSION) $(SRC) 31 | ( \ 32 | cd $(SRC); \ 33 | (cat ../patches/*.patch | patch -p1) \ 34 | ) 35 | -------------------------------------------------------------------------------- /pyodide/packages/nltk/test_nltk.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | def test_nltk_edit_distance(selenium): 5 | selenium.load_package('nltk') 6 | selenium.run('import nltk') 7 | edit_distance = selenium.run("nltk.edit_distance('foo', 'food')") 8 | assert edit_distance == 1 9 | 10 | 11 | def test_nltk_jaccard_distance(selenium): 12 | selenium.load_package('nltk') 13 | selenium.run('import nltk') 14 | jaccard_distance = selenium.run(""" 15 | nltk.jaccard_distance(set('mapping'), set('mappings')) 16 | """) 17 | assert jaccard_distance == pytest.approx(0.1428571) 18 | 19 | 20 | def test_nltk_ngrams(selenium): 21 | selenium.load_package('nltk') 22 | selenium.run('import nltk') 23 | ngrams = selenium.run("list(nltk.ngrams('master', n=3))") 24 | assert len(ngrams) == 4 25 | assert ngrams[0] == ['m', 'a', 's'] 26 | assert ngrams[1] == ['a', 's', 't'] 27 | assert ngrams[2] == ['s', 't', 'e'] 28 | assert ngrams[3] == ['t', 'e', 'r'] 29 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/julia.py: -------------------------------------------------------------------------------- 1 | # setup: N=10 2 | # run: julia(1., 1., N, 1.5, 10., 1e4) 3 | 4 | # pythran export julia(float, float, int, float, float, float) 5 | import numpy as np 6 | 7 | 8 | def kernel(zr, zi, cr, ci, lim, cutoff): 9 | ''' Computes the number of iterations `n` such that 10 | |z_n| > `lim`, where `z_n = z_{n-1}**2 + c`. 11 | ''' 12 | count = 0 13 | while ((zr * zr + zi * zi) < (lim * lim)) and count < cutoff: 14 | zr, zi = zr * zr - zi * zi + cr, 2 * zr * zi + ci 15 | count += 1 16 | return count 17 | 18 | 19 | def julia(cr, ci, N, bound=1.5, lim=1000., cutoff=1e6): 20 | ''' Pure Python calculation of the Julia set for a given `c`. No NumPy 21 | array operations are used. 22 | ''' 23 | julia = np.empty((N, N), np.uint32) 24 | grid_x = np.linspace(-bound, bound, N) 25 | for i, x in enumerate(grid_x): 26 | for j, y in enumerate(grid_x): 27 | julia[i, j] = kernel(x, y, cr, ci, lim, cutoff) 28 | return julia 29 | -------------------------------------------------------------------------------- /pyodide/src/jsproxy.h: -------------------------------------------------------------------------------- 1 | #ifndef JSPROXY_H 2 | #define JSPROXY_H 3 | 4 | /** A Python object that a Javascript object inside. Used for any non-standard 5 | * data types that are passed from Javascript to Python. 6 | */ 7 | 8 | #include 9 | 10 | /** Make a new JsProxy. 11 | * \param v The Javascript object. 12 | * \return The Python object wrapping the Javascript object. 13 | */ 14 | PyObject* 15 | JsProxy_cnew(int v); 16 | 17 | /** Check if a Python object is a JsProxy object. 18 | * \param x The Python object 19 | * \return 1 if the object is a JsProxy object. 20 | */ 21 | int 22 | JsProxy_Check(PyObject* x); 23 | 24 | /** Grab the underlying Javascript object from the JsProxy object. 25 | * \param x The JsProxy object. Must confirm that it is a JsProxy object using 26 | * JsProxy_Check. \return The Javascript object. 27 | */ 28 | int 29 | JsProxy_AsJs(PyObject* x); 30 | 31 | /** Initialize global state for the JsProxy functionality. */ 32 | int 33 | JsProxy_init(); 34 | 35 | #endif /* JSPROXY_H */ 36 | -------------------------------------------------------------------------------- /pyodide/pyodide_build/__main__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import argparse 3 | 4 | from . import buildall 5 | from . import buildpkg 6 | from . import pywasmcross 7 | from . import serve 8 | from . import mkpkg 9 | 10 | 11 | def main(): 12 | main_parser = argparse.ArgumentParser(prog='pyodide') 13 | subparsers = main_parser.add_subparsers(help='action') 14 | 15 | for command_name, module in (("buildpkg", buildpkg), 16 | ("buildall", buildall), 17 | ("pywasmcross", pywasmcross), 18 | ("serve", serve), 19 | ("mkpkg", mkpkg)): 20 | parser = module.make_parser(subparsers.add_parser(command_name)) 21 | parser.set_defaults(func=module.main) 22 | 23 | args = main_parser.parse_args() 24 | if hasattr(args, 'func'): 25 | # run the selected action 26 | args.func(args) 27 | else: 28 | main_parser.print_help() 29 | 30 | 31 | if __name__ == '__main__': 32 | main() 33 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/slowparts.py: -------------------------------------------------------------------------------- 1 | # from: https://groups.google.com/forum/#!topic/parakeet-python/p-flp2kdE4U 2 | # setup: import numpy as np ;d = 10 ;re = 5 ;params = (d, re, np.ones((2*d, d+1, re)), np.ones((d, d+1, re)), np.ones((d, 2*d)), np.ones((d, 2*d)), np.ones((d+1, re, d)), np.ones((d+1, re, d)), 1) # noqa 3 | # run: slowparts(*params) 4 | 5 | # pythran export slowparts(int, int, float [][][], float [][][], float 6 | # [][], float [][], float [][][], float [][][], int) 7 | from numpy import zeros, power, tanh 8 | 9 | 10 | def slowparts(d, re, preDz, preWz, SRW, RSW, yxV, xyU, resid): 11 | """ computes the linear algebra intensive part of the gradients of the grae 12 | """ 13 | def fprime(x): return 1 - power(tanh(x), 2) 14 | 15 | partialDU = zeros((d + 1, re, 2 * d, d)) 16 | for k in range(2 * d): 17 | for i in range(d): 18 | partialDU[:, :, k, i] = ( 19 | fprime(preDz[k]) * fprime(preWz[i]) 20 | * (SRW[i, k] + RSW[i, k]) * yxV[:, :, i]) 21 | 22 | return partialDU 23 | -------------------------------------------------------------------------------- /pyodide/emsdk/Makefile: -------------------------------------------------------------------------------- 1 | PYODIDE_ROOT=$(abspath ..) 2 | include ../Makefile.envs 3 | 4 | all: emsdk/.complete 5 | 6 | # We hack the CPU_CORES, because if you use all of the cores on Circle-CI, you 7 | # run out of memory. 8 | 9 | emsdk/.complete: 10 | if [ -d emsdk ]; then rm -rf emsdk; fi 11 | git clone https://github.com/juj/emsdk.git 12 | sed -i -e "s#CPU_CORES = max(multiprocessing.cpu_count()-1, 1)#CPU_CORES = 3#g" emsdk/emsdk 13 | ( \ 14 | cd emsdk && \ 15 | ./emsdk install --build=Release sdk-tag-$(EMSCRIPTEN_VERSION)-64bit binaryen-tag-$(EMSCRIPTEN_VERSION)-64bit && \ 16 | cd .. && \ 17 | (cat patches/*.patch | patch -p1) && \ 18 | cd emsdk/binaryen/tag-$(EMSCRIPTEN_VERSION)_64bit_binaryen/ && \ 19 | make && \ 20 | cd ../../.. && \ 21 | cd emsdk/clang/tag-e$(EMSCRIPTEN_VERSION)/build_tag-e$(EMSCRIPTEN_VERSION)_64/ && \ 22 | make && \ 23 | cd ../../.. && \ 24 | ./emsdk activate --embedded --build=Release sdk-tag-$(EMSCRIPTEN_VERSION)-64bit binaryen-tag-$(EMSCRIPTEN_VERSION)-64bit && \ 25 | touch .complete \ 26 | ) 27 | 28 | clean: 29 | rm -rf emsdk 30 | -------------------------------------------------------------------------------- /pyodide/benchmark/plot_benchmark.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | import json 4 | import sys 5 | 6 | plt.rcdefaults() 7 | fig, ax = plt.subplots(constrained_layout=True, figsize=(8, 8)) 8 | 9 | with open(sys.argv[-2]) as fp: 10 | content = json.load(fp) 11 | 12 | results = [] 13 | for k, v in content.items(): 14 | results.append((k, v['firefox'] / v['native'], v['chrome'] / v['native'])) 15 | results.sort(key=lambda x: x[1], reverse=True) 16 | 17 | names = [x[0] for x in results] 18 | firefox = [x[1] for x in results] 19 | chrome = [x[2] for x in results] 20 | 21 | width = 0.35 22 | y_pos = np.arange(len(results)) 23 | ax.barh(y_pos, firefox, width, color='#ff9400', label='firefox') 24 | ax.barh(y_pos + width, chrome, width, color='#45a1ff', label='chrome') 25 | ax.set_yticks(y_pos + width / 2) 26 | ax.set_yticklabels(names) 27 | ax.invert_yaxis() 28 | ax.set_xlabel('Slowdown factor (WebAssembly:Native)') 29 | ax.set_title('Python benchmarks') 30 | ax.axvline(1.0, color='red') 31 | ax.grid(axis='x') 32 | ax.legend(loc='lower right') 33 | 34 | plt.savefig(sys.argv[-1]) 35 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/local_maxima.py: -------------------------------------------------------------------------------- 1 | # https://github.com/iskandr/parakeet/blob/master/benchmarks/nd_local_maxima.py 2 | # setup: import numpy as np ; shape = (3,2,3,2) ; x = np.arange(36, dtype=np.float64).reshape(*shape) # noqa 3 | # run: local_maxima(x) 4 | 5 | # pythran export local_maxima(float [][][][]) 6 | import numpy as np 7 | 8 | 9 | def wrap(pos, offset, bound): 10 | return (pos + offset) % bound 11 | 12 | 13 | def clamp(pos, offset, bound): 14 | return min(bound - 1, max(0, pos + offset)) 15 | 16 | 17 | def reflect(pos, offset, bound): 18 | idx = pos + offset 19 | return min(2 * (bound - 1) - idx, max(idx, -idx)) 20 | 21 | 22 | def local_maxima(data, mode=wrap): 23 | wsize = data.shape 24 | result = np.ones(data.shape, bool) 25 | for pos in np.ndindex(data.shape): 26 | myval = data[pos] 27 | for offset in np.ndindex(wsize): 28 | neighbor_idx = tuple(mode(p, o - w // 2, w) 29 | for (p, o, w) in zip(pos, offset, wsize)) 30 | result[pos] &= (data[neighbor_idx] <= myval) 31 | return result 32 | -------------------------------------------------------------------------------- /pyodide/packages/scipy/test_scipy.py: -------------------------------------------------------------------------------- 1 | from textwrap import dedent 2 | 3 | import pytest 4 | 5 | 6 | def test_scipy_linalg(selenium_standalone, request): 7 | selenium = selenium_standalone 8 | 9 | if selenium.browser == 'chrome': 10 | request.applymarker(pytest.mark.xfail( 11 | run=False, reason='chrome not supported')) 12 | 13 | selenium.load_package("scipy") 14 | cmd = dedent(r""" 15 | import numpy as np 16 | import scipy as sp 17 | import scipy.linalg 18 | from numpy.testing import assert_allclose 19 | 20 | N = 10 21 | X = np.random.RandomState(42).rand(N, N) 22 | 23 | X_inv = scipy.linalg.inv(X) 24 | 25 | res = X.dot(X_inv) 26 | 27 | assert_allclose(res, np.identity(N), 28 | rtol=1e-07, atol=1e-9) 29 | """) 30 | 31 | selenium.run(cmd) 32 | 33 | 34 | def test_brentq(selenium_standalone): 35 | selenium_standalone.load_package("scipy") 36 | selenium_standalone.run("from scipy.optimize import brentq") 37 | selenium_standalone.run("brentq(lambda x: x, -1, 1)") 38 | -------------------------------------------------------------------------------- /pyodide/packages/numpy/config/_numpyconfig.h: -------------------------------------------------------------------------------- 1 | #define NPY_HAVE_ENDIAN_H 1 2 | #define NPY_SIZEOF_SHORT 2 3 | #define NPY_SIZEOF_INT 4 4 | #define NPY_SIZEOF_LONG 4 5 | #define NPY_SIZEOF_FLOAT 4 6 | #define NPY_SIZEOF_COMPLEX_FLOAT 8 7 | #define NPY_SIZEOF_DOUBLE 8 8 | #define NPY_SIZEOF_COMPLEX_DOUBLE 16 9 | #define NPY_SIZEOF_LONGDOUBLE 8 10 | #define NPY_SIZEOF_COMPLEX_LONGDOUBLE 16 11 | #define NPY_SIZEOF_PY_INTPTR_T 4 12 | #define NPY_SIZEOF_OFF_T 4 13 | #define NPY_SIZEOF_PY_LONG_LONG 8 14 | #define NPY_SIZEOF_LONGLONG 8 15 | #define NPY_NO_SMP 0 16 | #define NPY_HAVE_DECL_ISNAN 17 | #define NPY_HAVE_DECL_ISINF 18 | #define NPY_HAVE_DECL_ISFINITE 19 | #define NPY_HAVE_DECL_SIGNBIT 20 | #define NPY_USE_C99_COMPLEX 1 21 | #define NPY_HAVE_COMPLEX_DOUBLE 1 22 | #define NPY_HAVE_COMPLEX_FLOAT 1 23 | #define NPY_HAVE_COMPLEX_LONG_DOUBLE 1 24 | #define NPY_RELAXED_STRIDES_CHECKING 1 25 | #define NPY_USE_C99_FORMATS 1 26 | #define NPY_VISIBILITY_HIDDEN __attribute__((visibility("hidden"))) 27 | #define NPY_ABI_VERSION 0x01000009 28 | #define NPY_API_VERSION 0x0000000C 29 | 30 | #ifndef __STDC_FORMAT_MACROS 31 | #define __STDC_FORMAT_MACROS 1 32 | #endif 33 | -------------------------------------------------------------------------------- /pyodide/packages/scipy/patches/disable_scipy_stats_mvn.patch: -------------------------------------------------------------------------------- 1 | commit d6740caa7400105a578ace74f8c25bbb3434178c 2 | Author: Roman Yurchak 3 | Date: Wed Oct 10 14:47:12 2018 +0200 4 | 5 | Disable scipy.stats.mvn 6 | 7 | diff --git a/scipy/stats/kde.py b/scipy/stats/kde.py 8 | index 7c702a038..8b0ab0254 100644 9 | --- a/scipy/stats/kde.py 10 | +++ b/scipy/stats/kde.py 11 | @@ -32,7 +32,10 @@ import numpy as np 12 | from numpy.random import randint, multivariate_normal 13 | 14 | # Local imports. 15 | -from . import mvn 16 | +try: 17 | + from . import mvn 18 | +except ImportError: 19 | + mvn = None 20 | 21 | 22 | __all__ = ['gaussian_kde'] 23 | diff --git a/scipy/stats/setup.py b/scipy/stats/setup.py 24 | index f1a02df4e..7366ec12d 100755 25 | --- a/scipy/stats/setup.py 26 | +++ b/scipy/stats/setup.py 27 | @@ -32,9 +32,9 @@ def configuration(parent_package='',top_path=None): 28 | ) 29 | 30 | # add mvn module 31 | - config.add_extension('mvn', 32 | - sources=['mvn.pyf','mvndst.f'], 33 | - ) 34 | + #config.add_extension('mvn', 35 | + # sources=['mvn.pyf','mvndst.f'], 36 | + #) 37 | 38 | return config 39 | 40 | -------------------------------------------------------------------------------- /pyodide/test/make_test_list.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generate a list of test modules in the CPython distribution. 3 | """ 4 | 5 | import os 6 | from pathlib import Path 7 | 8 | 9 | TEST_DIR = (Path(__file__).parent 10 | / "cpython/build/3.7.0/host/lib/python3.7/test") 11 | 12 | 13 | def collect_tests(base_dir): 14 | """Collect CPython unit tests""" 15 | # Note: this functionality is somewhat equivalent to pytest test 16 | # collection. 17 | tests = [] 18 | 19 | for root, dirs, files in os.walk(base_dir): 20 | root = Path(root).relative_to(base_dir) 21 | 22 | if str(root) == '.': 23 | root = '' 24 | else: 25 | root = '.'.join(str(root).split('/')) + '.' 26 | 27 | for filename in files: 28 | filename = Path(filename) 29 | if str(filename).startswith("test_") and filename.suffix == ".py": 30 | tests.append(root + filename.stem) 31 | 32 | tests.sort() 33 | return tests 34 | 35 | 36 | if __name__ == '__main__': 37 | tests = collect_tests(TEST_DIR) 38 | with open("python_tests.txt", "w") as fp: 39 | for test in tests: 40 | fp.write(test + '\n') 41 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/mandel.py: -------------------------------------------------------------------------------- 1 | # setup: import numpy as np; image = np.zeros((64, 32), dtype = np.uint8) 2 | # run: mandel(-2.0, 1.0, -1.0, 1.0, image, 20) 3 | 4 | # pythran export mandel(float, float, float, float, uint8[][], int) 5 | 6 | 7 | def kernel(x, y, max_iters): 8 | """ 9 | Given the real and imaginary parts of a complex number, 10 | determine if it is a candidate for membership in the Mandelbrot 11 | set given a fixed number of iterations. 12 | """ 13 | c = complex(x, y) 14 | z = 0.0j 15 | for i in range(max_iters): 16 | z = z * z + c 17 | if (z.real * z.real + z.imag * z.imag) >= 4: 18 | return i 19 | 20 | return max_iters 21 | 22 | 23 | def mandel(min_x, max_x, min_y, max_y, image, iters): 24 | height = image.shape[0] 25 | width = image.shape[1] 26 | 27 | pixel_size_x = (max_x - min_x) / width 28 | pixel_size_y = (max_y - min_y) / height 29 | 30 | for x in range(width): 31 | real = min_x + x * pixel_size_x 32 | for y in range(height): 33 | imag = min_y + y * pixel_size_y 34 | color = kernel(real, imag, iters) 35 | image[y, x] = color 36 | -------------------------------------------------------------------------------- /pyodide/packages/matplotlib/test_matplotlib.py: -------------------------------------------------------------------------------- 1 | def test_matplotlib(selenium_standalone): 2 | selenium = selenium_standalone 3 | selenium.load_package("matplotlib") 4 | selenium.run("from matplotlib import pyplot as plt") 5 | selenium.run("plt.figure()") 6 | selenium.run("plt.plot([1,2,3])") 7 | selenium.run("plt.show()") 8 | 9 | 10 | def test_svg(selenium): 11 | selenium.load_package("matplotlib") 12 | selenium.run("from matplotlib import pyplot as plt") 13 | selenium.run("plt.figure()") 14 | selenium.run("x = plt.plot([1,2,3])") 15 | selenium.run("import io") 16 | selenium.run("fd = io.BytesIO()") 17 | selenium.run("plt.savefig(fd, format='svg')") 18 | content = selenium.run("fd.getvalue().decode('utf8')") 19 | assert len(content) == 15752 20 | assert content.startswith(" 2 | #include 3 | 4 | #include "hiwire.h" 5 | #include "js2python.h" 6 | #include "jsimport.h" 7 | #include "jsproxy.h" 8 | #include "pyimport.h" 9 | #include "pyproxy.h" 10 | #include "python2js.h" 11 | #include "runpython.h" 12 | 13 | int 14 | main(int argc, char** argv) 15 | { 16 | hiwire_setup(); 17 | 18 | setenv("PYTHONHOME", "/", 0); 19 | 20 | Py_InitializeEx(0); 21 | 22 | // This doesn't seem to work anymore, but I'm keeping it for good measure 23 | // anyway The effective way to turn this off is below: setting 24 | // sys.done_write_bytecode = True 25 | setenv("PYTHONDONTWRITEBYTECODE", "1", 0); 26 | 27 | PyObject* sys = PyImport_ImportModule("sys"); 28 | if (sys == NULL) { 29 | return 1; 30 | } 31 | if (PyObject_SetAttrString(sys, "dont_write_bytecode", Py_True)) { 32 | return 1; 33 | } 34 | Py_DECREF(sys); 35 | 36 | if (js2python_init() || JsImport_init() || JsProxy_init() || 37 | pyimport_init() || pyproxy_init() || python2js_init() || 38 | runpython_init_js() || runpython_init_py() || runpython_finalize_js()) { 39 | return 1; 40 | } 41 | 42 | printf("Python initialization complete\n"); 43 | 44 | emscripten_exit_with_live_runtime(); 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /pyodide/packages/numpy/patches/add-emscripten-cpu.patch: -------------------------------------------------------------------------------- 1 | diff --git a/numpy/core/include/numpy/npy_cpu.h b/numpy/core/include/numpy/npy_cpu.h 2 | index 5edd8f42e..31560eac3 100644 3 | --- a/numpy/core/include/numpy/npy_cpu.h 4 | +++ b/numpy/core/include/numpy/npy_cpu.h 5 | @@ -102,6 +102,8 @@ 6 | #define NPY_CPU_ARCEB 7 | #elif defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64 8 | #define NPY_CPU_RISCV64 9 | +#elif defined(__EMSCRIPTEN__) 10 | + #define NPY_CPU_EMSCRIPTEN 11 | #else 12 | #error Unknown CPU, please report this to numpy maintainers with \ 13 | information about your platform (OS, CPU and compiler) 14 | diff --git a/numpy/core/include/numpy/npy_endian.h b/numpy/core/include/numpy/npy_endian.h 15 | index 649bdb0a6..ec2f6eda5 100644 16 | --- a/numpy/core/include/numpy/npy_endian.h 17 | +++ b/numpy/core/include/numpy/npy_endian.h 18 | @@ -47,7 +47,8 @@ 19 | || defined(NPY_CPU_MIPSEL) \ 20 | || defined(NPY_CPU_PPC64LE) \ 21 | || defined(NPY_CPU_ARCEL) \ 22 | - || defined(NPY_CPU_RISCV64) 23 | + || defined(NPY_CPU_RISCV64) \ 24 | + || defined(NPY_CPU_EMSCRIPTEN) 25 | #define NPY_BYTE_ORDER NPY_LITTLE_ENDIAN 26 | #elif defined(NPY_CPU_PPC) \ 27 | || defined(NPY_CPU_SPARC) \ 28 | -------------------------------------------------------------------------------- /pyodide/packages/joblib/test_joblib.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | def test_joblib_numpy_pickle(selenium, request): 5 | if selenium.browser == 'chrome': 6 | request.applymarker(pytest.mark.xfail( 7 | run=False, reason='chrome not supported')) 8 | selenium.load_package(['numpy', 'joblib']) 9 | selenium.run(""" 10 | import joblib 11 | import numpy as np 12 | from numpy.testing import assert_array_equal 13 | 14 | X = np.ones(10) 15 | 16 | file_path = "./X.pkl" 17 | 18 | joblib.dump(X, file_path) 19 | 20 | X2 = joblib.load(file_path) 21 | 22 | assert_array_equal(X, X2)""") 23 | 24 | 25 | def test_joblib_parallel(selenium): 26 | selenium.load_package(['numpy', 'joblib']) 27 | selenium.clean_logs() 28 | selenium.run(""" 29 | from math import sqrt 30 | from joblib import Parallel, delayed 31 | 32 | # check that the default multiprocessing backend 33 | # gracefully reduces to n_jobs=1 34 | res = Parallel(n_jobs=2)(delayed(sqrt)(i ** 2) 35 | for i in range(10)) 36 | assert res == [sqrt(i ** 2) for i in range(10)] 37 | 38 | # check threading backend 39 | Parallel(n_jobs=2, backend='threading')( 40 | delayed(sqrt)(i ** 2) for i in range(10)) 41 | """) 42 | -------------------------------------------------------------------------------- /pyodide/packages/setuptools/patches/remove-ctypes.patch: -------------------------------------------------------------------------------- 1 | diff --git a/setuptools/glibc.py b/setuptools/glibc.py 2 | index a134591c..c31fc78a 100644 3 | --- a/setuptools/glibc.py 4 | +++ b/setuptools/glibc.py 5 | @@ -2,13 +2,13 @@ 6 | # https://github.com/pypa/pip/blob/8f4f15a5a95d7d5b511ceaee9ed261176c181970/src/pip/_internal/utils/glibc.py 7 | from __future__ import absolute_import 8 | 9 | -import ctypes 10 | import re 11 | import warnings 12 | 13 | 14 | def glibc_version_string(): 15 | "Returns glibc version string, or None if not using glibc." 16 | + import ctypes 17 | 18 | # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen 19 | # manpage says, "If filename is NULL, then the returned handle is for the 20 | diff --git a/setuptools/windows_support.py b/setuptools/windows_support.py 21 | index cb977cff..1ca64fbb 100644 22 | --- a/setuptools/windows_support.py 23 | +++ b/setuptools/windows_support.py 24 | @@ -1,5 +1,4 @@ 25 | import platform 26 | -import ctypes 27 | 28 | 29 | def windows_only(func): 30 | @@ -17,6 +16,7 @@ def hide_file(path): 31 | 32 | `path` must be text. 33 | """ 34 | + import ctypes 35 | __import__('ctypes.wintypes') 36 | SetFileAttributes = ctypes.windll.kernel32.SetFileAttributesW 37 | SetFileAttributes.argtypes = ctypes.wintypes.LPWSTR, ctypes.wintypes.DWORD 38 | -------------------------------------------------------------------------------- /pyodide/test/largish.json.cgi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import json 4 | import random 5 | import sys 6 | 7 | random.seed(0) 8 | 9 | columns = [ 10 | ('column0', lambda: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'), 11 | ('column1', lambda: random.choice([ 12 | 'notification-interval-longer', 'notification-interval-short', 'control'])), 13 | ('column2', lambda: random.choice([True, False])), 14 | ('column3', lambda: random.randint(0, 4)), 15 | ('column4', lambda: random.randint(0, 4)), 16 | ('column5', lambda: random.randint(0, 4)), 17 | ('column6', lambda: random.randint(0, 4)), 18 | ('column7', lambda: random.randint(0, 4)) 19 | ] 20 | 21 | N_ROWS = 91746 # the output JSON size will be ~15 MB/10k rows 22 | 23 | 24 | class StreamDict(dict): 25 | """ 26 | To serialize to JSON, we create an iterable object that inherits from a 27 | known supported object type: dict. 28 | """ 29 | def __init__(self, generator): 30 | self.generator = generator 31 | 32 | def items(self): 33 | for i in range(N_ROWS): 34 | yield i, self.generator() 35 | 36 | def __len__(self): 37 | return 1 38 | 39 | 40 | data = {} 41 | for name, generator in columns: 42 | data[name] = StreamDict(generator) 43 | 44 | 45 | print("Content-Type: application/json") 46 | print() 47 | json.dump(data, sys.stdout) 48 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/periodic_dist.py: -------------------------------------------------------------------------------- 1 | # setup: import numpy as np ; N = 20 ; x = y = z = np.arange(0., N, 0.1) ; L = 4 ; periodic = True # noqa 2 | # run: periodic_dist(x, x, x, L,periodic, periodic, periodic) 3 | 4 | # pythran export periodic_dist(float [], float[], float[], int, bool, 5 | # bool, bool) 6 | import numpy as np 7 | 8 | 9 | def periodic_dist(x, y, z, L, periodicX, periodicY, periodicZ): 10 | """Computes distances between all particles and places the result 11 | in a matrix such that the ij th matrix entry corresponds to the 12 | distance between particle i and j""" 13 | N = len(x) 14 | xtemp = np.tile(x, (N, 1)) 15 | dx = xtemp - xtemp.T 16 | ytemp = np.tile(y, (N, 1)) 17 | dy = ytemp - ytemp.T 18 | ztemp = np.tile(z, (N, 1)) 19 | dz = ztemp - ztemp.T 20 | 21 | # Particles 'feel' each other across the periodic boundaries 22 | if periodicX: 23 | dx[dx > L / 2] = dx[dx > L / 2] - L 24 | dx[dx < -L / 2] = dx[dx < -L / 2] + L 25 | 26 | if periodicY: 27 | dy[dy > L / 2] = dy[dy > L / 2] - L 28 | dy[dy < -L / 2] = dy[dy < -L / 2] + L 29 | 30 | if periodicZ: 31 | dz[dz > L / 2] = dz[dz > L / 2] - L 32 | dz[dz < -L / 2] = dz[dz < -L / 2] + L 33 | 34 | # Total Distances 35 | d = np.sqrt(dx**2 + dy**2 + dz**2) 36 | 37 | # Mark zero entries with negative 1 to avoid divergences 38 | d[d == 0] = -1 39 | 40 | return d, dx, dy, dz 41 | -------------------------------------------------------------------------------- /pyodide/packages/numpy/test_numpy.py: -------------------------------------------------------------------------------- 1 | def test_numpy(selenium): 2 | selenium.load_package("numpy") 3 | selenium.run("import numpy") 4 | selenium.run("x = numpy.ones((32, 64))") 5 | assert selenium.run_js("return pyodide.pyimport('x').length == 32") 6 | for i in range(32): 7 | assert selenium.run_js( 8 | f"return pyodide.pyimport('x')[{i}].length == 64" 9 | ) 10 | for j in range(64): 11 | assert selenium.run_js( 12 | f"return pyodide.pyimport('x')[{i}][{j}] == 1" 13 | ) 14 | 15 | 16 | def test_typed_arrays(selenium): 17 | selenium.load_package("numpy") 18 | selenium.run("import numpy") 19 | for (jstype, npytype) in ( 20 | ('Int8Array', 'int8'), 21 | ('Uint8Array', 'uint8'), 22 | ('Uint8ClampedArray', 'uint8'), 23 | ('Int16Array', 'int16'), 24 | ('Uint16Array', 'uint16'), 25 | ('Int32Array', 'int32'), 26 | ('Uint32Array', 'uint32'), 27 | ('Float32Array', 'float32'), 28 | ('Float64Array', 'float64')): 29 | print(jstype, npytype) 30 | selenium.run_js( 31 | f'window.array = new {jstype}([1, 2, 3, 4]);\n') 32 | assert selenium.run( 33 | 'from js import array\n' 34 | 'npyarray = numpy.asarray(array)\n' 35 | f'npyarray.dtype.name == "{npytype}" ' 36 | 'and npyarray == [1, 2, 3, 4]') 37 | -------------------------------------------------------------------------------- /pyodide/packages/matplotlib/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: matplotlib 3 | version: 2.2.3 4 | 5 | source: 6 | url: https://files.pythonhosted.org/packages/eb/a0/31b6ba00bc4dcbc06f0b80d1ad6119a9cc3081ecb04a00117f6c1ca3a084/matplotlib-2.2.3.tar.gz 7 | sha256: 7355bf757ecacd5f0ac9dd9523c8e1a1103faadf8d33c22664178e17533f8ce5 8 | 9 | patches: 10 | - patches/font_name_encoding.patch 11 | - patches/force_malloc_free.patch 12 | - patches/hardcoded_font_cache.patch 13 | - patches/reduce_cpp_exceptions.patch 14 | - patches/reduce-imports.patch 15 | 16 | extras: 17 | - 18 | - src/wasm_backend.py 19 | - lib/matplotlib/backends/wasm_backend.py 20 | - 21 | - src/setup.cfg 22 | - ./setup.cfg 23 | 24 | build: 25 | cflags: -s USE_FREETYPE=1 -s USE_LIBPNG=1 -s USE_ZLIB=1 26 | ldflags: ../../../../emsdk/emsdk/.emscripten_cache/asmjs/libpng.bc 27 | post: | 28 | wget -O $SITEPACKAGES/matplotlib/mpl-data/fonts/ttf/Humor-Sans.ttf http://antiyawn.com/uploads/Humor-Sans-1.0.ttf 29 | rm -rf $SITEPACKAGES/matplotlib/backends/qt_editor 30 | rm -rf $SITEPACKAGES/matplotlib/backends/web_backend 31 | rm -rf $SITEPACKAGES/sphinxext 32 | cp $PKGDIR/src/fontList.json $SITEPACKAGES/matplotlib 33 | 34 | requirements: 35 | run: 36 | - cycler 37 | - kiwisolver 38 | - numpy 39 | - pyparsing 40 | - python-dateutil 41 | - pytz 42 | 43 | test: 44 | imports: 45 | - matplotlib 46 | - mpl_toolkits 47 | -------------------------------------------------------------------------------- /pyodide/packages/scipy/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: scipy 3 | version: 0.17.1 4 | 5 | source: 6 | # We can't use the version from PyPi as it includes Cythonized files 7 | # generated with an older Cython that does not support Python 3.7 8 | # This requires, 9 | # pip install Cython Tempita 10 | # on the host for the build 11 | url: https://github.com/scipy/scipy/archive/v0.17.1.tar.gz 12 | sha256: bf22383d9e2526ffdc53a6c7d3d66dab45a86291ed35d8e281bd1a5d2c34187b 13 | 14 | patches: 15 | # these patches can be found as commits in 16 | # https://github.com/rth/scipy/tree/0.17.1-pyodide 17 | # on top of the v0.17.1 tag 18 | - patches/fix-blas.patch 19 | - patches/fix-build-gcc5-a80460.patch 20 | - patches/force_malloc.patch 21 | - patches/disable_scipy_stats_mvn.patch 22 | - patches/skip-fortran-fails-to-link.patch 23 | - patches/dummy_threading.patch 24 | - patches/skip_ellip_harm_2_pyx_ctypes.patch 25 | 26 | build: 27 | cflags: -I../../../../CLAPACK/CLAPACK-WA/INCLUDE -Wno-implicit-function-declaration 28 | cxxflags: 29 | 30 | requirements: 31 | run: 32 | - numpy 33 | 34 | test: 35 | imports: 36 | - scipy 37 | - scipy.cluster 38 | - scipy.constants 39 | - scipy.fftpack 40 | - scipy.odr 41 | - scipy.sparse 42 | - scipy.interpolate 43 | - scipy.integrate 44 | - scipy.linalg 45 | - scipy.misc 46 | - scipy.ndimage 47 | - scipy.spatial 48 | - scipy.special 49 | -------------------------------------------------------------------------------- /pyodide/docs/pypi.md: -------------------------------------------------------------------------------- 1 | # Installing packages from PyPI 2 | 3 | Pyodide has experimental support for installing pure Python wheels from PyPI. 4 | 5 | **IMPORTANT:** Since the packages hosted at `files.pythonhosted.org` don't 6 | support CORS requests, we use a CORS proxy at `cors-anywhere.herokuapp.com` to 7 | get package contents. This makes a man-in-the-middle attack on the package 8 | contents possible. However, this threat is minimized by the fact that the 9 | integrity of each package is checked using a hash obtained directly from 10 | `pypi.org`. We hope to have this improved in the future, but for now, understand 11 | the risks and don't use any sensitive data with the packages installed using 12 | this method. 13 | 14 | For use in Iodide: 15 | 16 | ``` 17 | %% py 18 | import micropip 19 | micropip.install('snowballstemmer') 20 | 21 | # Iodide implicitly waits for the promise to resolve when the packages have finished 22 | # installing... 23 | 24 | %% py 25 | import snowballstemmer 26 | snowballstemmer.stemmer('english') 27 | stemmer.stemWords('go goes going gone'.split()) 28 | ``` 29 | 30 | For use outside of Iodide (just Python), you can use the `then` method on the 31 | `Promise` that `micropip.install` returns to do work once the packages have 32 | finished loading: 33 | 34 | ``` 35 | def do_work(*args): 36 | import snowballstemmer 37 | snowballstemmer.stemmer('english') 38 | stemmer.stemWords('go goes going gone'.split()) 39 | 40 | import micropip 41 | micropip.install('snowballstemmer').then(do_work) 42 | ``` 43 | -------------------------------------------------------------------------------- /pyodide/packages/networkx/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: networkx 3 | version: '2.2' 4 | 5 | source: 6 | url: https://files.pythonhosted.org/packages/f3/f4/7e20ef40b118478191cec0b58c3192f822cace858c19505c7670961b76b2/networkx-2.2.zip 7 | sha256: 45e56f7ab6fe81652fb4bc9f44faddb0e9025f469f602df14e3b2551c2ea5c8b 8 | 9 | requirements: 10 | run: 11 | - decorator 12 | - setuptools 13 | # Upstream NetworkX has these as "soft" dependencies, but it's more 14 | # convenient to have them come in automatically. 15 | - matplotlib 16 | - numpy 17 | 18 | test: 19 | imports: 20 | - networkx 21 | - networkx.algorithms 22 | - networkx.algorithms.approximation 23 | - networkx.algorithms.assortativity 24 | - networkx.algorithms.bipartite 25 | - networkx.algorithms.centrality 26 | - networkx.algorithms.chordal 27 | - networkx.algorithms.coloring 28 | - networkx.algorithms.community 29 | - networkx.algorithms.components 30 | - networkx.algorithms.connectivity 31 | - networkx.algorithms.flow 32 | - networkx.algorithms.isomorphism 33 | - networkx.algorithms.link_analysis 34 | - networkx.algorithms.node_classification 35 | - networkx.algorithms.operators 36 | - networkx.algorithms.shortest_paths 37 | - networkx.algorithms.traversal 38 | - networkx.algorithms.tree 39 | - networkx.classes 40 | - networkx.drawing 41 | - networkx.generators 42 | - networkx.linalg 43 | - networkx.readwrite 44 | - networkx.readwrite.json_graph 45 | - networkx.utils 46 | -------------------------------------------------------------------------------- /pyodide/Makefile.envs: -------------------------------------------------------------------------------- 1 | export EMSCRIPTEN_VERSION = 1.38.30 2 | 3 | export PATH := $(PYODIDE_ROOT)/ccache:$(PYODIDE_ROOT)/emsdk/emsdk:$(PYODIDE_ROOT)/emsdk/emsdk/clang/tag-e$(EMSCRIPTEN_VERSION)/build_tag-e$(EMSCRIPTEN_VERSION)_64/bin:$(PYODIDE_ROOT)/emsdk/emsdk/node/8.9.1_64bit/bin:$(PYODIDE_ROOT)/emsdk/emsdk/emscripten/tag-$(EMSCRIPTEN_VERSION):$(PYODIDE_ROOT)/emsdk/emsdk/binaryen/tag-$(EMSCRIPTEN_VERSION)_64bit_binaryen/bin:$(PATH) 4 | 5 | export EMSDK = $(PYODIDE_ROOT)/emsdk/emsdk 6 | export EM_CONFIG = $(PYODIDE_ROOT)/emsdk/emsdk/.emscripten 7 | export EM_CACHE = $(PYODIDE_ROOT)/emsdk/emsdk/.emscripten_cache 8 | export EMSCRIPTEN = $(PYODIDE_ROOT)/emsdk/emsdk/emscripten/tag-$(EMSCRIPTEN_VERSION) 9 | export BINARYEN_ROOT = $(PYODIDE_ROOT)/emsdk/emsdk/binaryen/tag-$(EMSCRIPTEN_VERSION)_64bit_binaryen 10 | 11 | export PYVERSION=3.7.0 12 | export PYMINOR=$(basename $(PYVERSION)) 13 | export HOSTPYTHONROOT=$(PYODIDE_ROOT)/cpython/build/$(PYVERSION)/host 14 | export HOSTPYTHON=$(HOSTPYTHONROOT)/bin/python3 15 | export TARGETPYTHONROOT=$(PYODIDE_ROOT)/cpython/installs/python-$(PYVERSION) 16 | export PYTHONINCLUDE=$(PYODIDE_ROOT)/cpython/installs/python-$(PYVERSION)/include/python$(PYMINOR) 17 | 18 | export PYODIDE_PACKAGE_ABI=1 19 | 20 | export SIDE_LDFLAGS=\ 21 | -O3 \ 22 | -s "BINARYEN_METHOD='native-wasm'" \ 23 | -Werror \ 24 | -s EMULATED_FUNCTION_POINTERS=1 \ 25 | -s EMULATE_FUNCTION_POINTER_CASTS=1 \ 26 | -s SIDE_MODULE=1 \ 27 | -s WASM=1 \ 28 | -s "BINARYEN_TRAP_MODE='clamp'" \ 29 | --memory-init-file 0 \ 30 | -s LINKABLE=1 \ 31 | -s EXPORT_ALL=1 32 | -------------------------------------------------------------------------------- /pyodide/packages/numpy/patches/init-alloc-cache.patch: -------------------------------------------------------------------------------- 1 | diff --git a/numpy/core/src/multiarray/alloc.c b/numpy/core/src/multiarray/alloc.c 2 | index f8305d115..369a14012 100644 3 | --- a/numpy/core/src/multiarray/alloc.c 4 | +++ b/numpy/core/src/multiarray/alloc.c 5 | @@ -277,3 +277,9 @@ PyDataMem_RENEW(void *ptr, size_t size) 6 | } 7 | return result; 8 | } 9 | + 10 | +NPY_NO_EXPORT void npy_init_cache() { 11 | + memset(datacache, 0, sizeof(cache_bucket) * NBUCKETS); 12 | + memset(dimcache, 0, sizeof(cache_bucket) * NBUCKETS_DIM); 13 | + _PyDataMem_eventhook = NULL; 14 | +} 15 | diff --git a/numpy/core/src/multiarray/alloc.h b/numpy/core/src/multiarray/alloc.h 16 | index 2b69efc35..10069503d 100644 17 | --- a/numpy/core/src/multiarray/alloc.h 18 | +++ b/numpy/core/src/multiarray/alloc.h 19 | @@ -33,4 +33,7 @@ npy_free_cache_dim_array(PyArrayObject * arr) 20 | npy_free_cache_dim(PyArray_DIMS(arr), PyArray_NDIM(arr)); 21 | } 22 | 23 | +NPY_NO_EXPORT void 24 | +npy_init_cache(void); 25 | + 26 | #endif 27 | diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c 28 | index 8e7352e4f..a713679e8 100644 29 | --- a/numpy/core/src/multiarray/multiarraymodule.c 30 | +++ b/numpy/core/src/multiarray/multiarraymodule.c 31 | @@ -4747,6 +4747,8 @@ PyMODINIT_FUNC initmultiarray(void) { 32 | goto err; 33 | } 34 | 35 | + npy_init_cache(); 36 | + 37 | #if defined(MS_WIN64) && defined(__GNUC__) 38 | PyErr_WarnEx(PyExc_Warning, 39 | "Numpy built with MINGW-W64 on Windows 64 bits is experimental, " \ 40 | -------------------------------------------------------------------------------- /pyodide/emsdk/patches/dynCall_so.patch: -------------------------------------------------------------------------------- 1 | diff --git a/emsdk/emscripten/tag-1.38.30/src/support.js b//emsdk/emscripten/tag-1.38.30/src/support.js 2 | index 8e1df8e82..4d07d6bef 100644 3 | --- a/emsdk/emscripten/tag-1.38.30/src/support.js 4 | +++ b/emsdk/emscripten/tag-1.38.30/src/support.js 5 | @@ -437,7 +437,18 @@ function loadWebAssemblyModule(binary, flags) { 6 | // present in the dynamic library but not in the main JS, 7 | // and the dynamic library cannot provide JS for it. Use 8 | // the generic "X" invoke for it. 9 | - return env[prop] = invoke_X; 10 | + var dynCallName = 'dynCall_' + prop.slice(7); 11 | + return env[prop] = function() { 12 | + var sp = stackSave(); 13 | + try { 14 | + var args = Array.prototype.slice.call(arguments); 15 | + return Module[dynCallName].apply(null, args); 16 | + } catch(e) { 17 | + stackRestore(sp); 18 | + if (typeof e !== 'number' && e !== 'longjmp') throw e; 19 | + Module["setThrew"](1, 0); 20 | + } 21 | + } 22 | } 23 | // if not a global, then a function - call it indirectly 24 | return env[prop] = function() { 25 | @@ -502,6 +513,11 @@ function loadWebAssemblyModule(binary, flags) { 26 | } 27 | #endif 28 | } 29 | + if (e.startsWith("dynCall_")) { 30 | + if (!Module.hasOwnProperty(e)) { 31 | + Module[e] = value; 32 | + } 33 | + } 34 | exports[e] = value; 35 | } 36 | // initialize the module 37 | -------------------------------------------------------------------------------- /pyodide/packages/scikit-learn/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: scikit-learn 3 | version: 0.20.1 4 | 5 | source: 6 | url: https://github.com/scikit-learn/scikit-learn/archive/0.20.1.tar.gz 7 | sha256: 618feea121c59a52ea459d6af7bc179344ca345775b04bd60e96740e9df75960 8 | 9 | patches: 10 | - patches/use-site-joblib.patch 11 | 12 | build: 13 | cflags: -Wno-implicit-function-declaration 14 | 15 | requirements: 16 | run: 17 | - numpy 18 | - scipy 19 | - joblib 20 | 21 | test: 22 | imports: 23 | - sklearn 24 | - sklearn.calibration 25 | - sklearn.cluster 26 | - sklearn.compose 27 | - sklearn.covariance 28 | - sklearn.cross_decomposition 29 | - sklearn.datasets 30 | - sklearn.decomposition 31 | - sklearn.discriminant_analysis 32 | - sklearn.dummy 33 | - sklearn.ensemble 34 | - sklearn.exceptions 35 | - sklearn.externals 36 | - sklearn.feature_extraction 37 | - sklearn.feature_selection 38 | - sklearn.gaussian_process 39 | - sklearn.impute 40 | - sklearn.isotonic 41 | - sklearn.kernel_approximation 42 | - sklearn.kernel_ridge 43 | - sklearn.linear_model 44 | - sklearn.manifold 45 | - sklearn.metrics 46 | - sklearn.mixture 47 | - sklearn.model_selection 48 | - sklearn.multiclass 49 | - sklearn.multioutput 50 | - sklearn.naive_bayes 51 | - sklearn.neighbors 52 | - sklearn.neural_network 53 | - sklearn.pipeline 54 | - sklearn.preprocessing 55 | - sklearn.random_projection 56 | - sklearn.semi_supervised 57 | - sklearn.svm 58 | - sklearn.tree 59 | - sklearn.utils 60 | -------------------------------------------------------------------------------- /pyodide/pyodide_build/serve.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import argparse 4 | import http.server 5 | import socketserver 6 | import pathlib 7 | 8 | TEST_PATH = pathlib.Path(__file__).parents[0].resolve() 9 | BUILD_PATH = TEST_PATH / '..' / 'build' 10 | 11 | 12 | class Handler(http.server.SimpleHTTPRequestHandler): 13 | def end_headers(self): 14 | self.send_header('Access-Control-Allow-Origin', '*') 15 | super().end_headers() 16 | 17 | 18 | Handler.extensions_map['.wasm'] = 'application/wasm' 19 | 20 | 21 | def make_parser(parser): 22 | parser.description = ('Start a server with the supplied ' 23 | 'build_dir and port.') 24 | parser.add_argument('--build_dir', action='store', type=str, 25 | default=BUILD_PATH, help='set the build directory') 26 | parser.add_argument('--port', action='store', type=int, 27 | default=8000, help='set the PORT number') 28 | return parser 29 | 30 | 31 | def server(port): 32 | httpd = socketserver.TCPServer(('', port), Handler) 33 | return httpd 34 | 35 | 36 | def main(args): 37 | build_dir = args.build_dir 38 | port = args.port 39 | httpd = server(port) 40 | os.chdir(build_dir) 41 | print("serving from {0} at localhost:".format(build_dir) + str(port)) 42 | try: 43 | httpd.serve_forever() 44 | except KeyboardInterrupt: 45 | print("\n...shutting down http server") 46 | httpd.shutdown() 47 | sys.exit() 48 | 49 | 50 | if __name__ == "__main__": 51 | parser = make_parser(argparse.ArgumentParser()) 52 | args = parser.parse_args() 53 | main(args) 54 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/wave.py: -------------------------------------------------------------------------------- 1 | # from https://github.com/sklam/numba-example-wavephysics 2 | # setup: N=100 3 | # run: wave(N) 4 | import numpy as np 5 | 6 | 7 | def physics(masspoints, dt, plunk, which): 8 | ppos = masspoints[1] 9 | cpos = masspoints[0] 10 | N = cpos.shape[0] 11 | # apply hooke's law 12 | HOOKE_K = 2100000. 13 | DAMPING = 0.0001 14 | MASS = .01 15 | 16 | force = np.zeros((N, 2)) 17 | for i in range(1, N): 18 | dx, dy = cpos[i] - cpos[i - 1] 19 | dist = np.sqrt(dx**2 + dy**2) 20 | assert dist != 0 21 | fmag = -HOOKE_K * dist 22 | cosine = dx / dist 23 | sine = dy / dist 24 | fvec = np.array([fmag * cosine, fmag * sine]) 25 | force[i - 1] -= fvec 26 | force[i] += fvec 27 | 28 | force[0] = force[-1] = 0, 0 29 | force[which][1] += plunk 30 | accel = force / MASS 31 | 32 | # verlet integration 33 | npos = (2 - DAMPING) * cpos - (1 - DAMPING) * ppos + accel * (dt**2) 34 | 35 | masspoints[1] = cpos 36 | masspoints[0] = npos 37 | 38 | # pythran export wave(int) 39 | 40 | 41 | def wave(PARTICLE_COUNT): 42 | SUBDIVISION = 300 43 | FRAMERATE = 60 44 | count = PARTICLE_COUNT 45 | width, height = 1200, 400 46 | 47 | masspoints = np.empty((2, count, 2), np.float64) 48 | initpos = np.zeros(count, np.float64) 49 | for i in range(1, count): 50 | initpos[i] = initpos[i - 1] + float(width) / count 51 | masspoints[:, :, 0] = initpos 52 | masspoints[:, :, 1] = height / 2 53 | f = 15 54 | plunk_pos = count // 2 55 | physics(masspoints, 1. / (SUBDIVISION * FRAMERATE), f, plunk_pos) 56 | return masspoints[0, count // 2] 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /pyodide/packages/scipy/patches/fix-build-gcc5-a80460.patch: -------------------------------------------------------------------------------- 1 | commit a80460f1b45035d34575866e6394107396ac62e2 2 | Author: Michael Danilov 3 | Date: Thu Apr 20 18:08:39 2017 +0200 4 | 5 | Fix build with GCC5. 6 | 7 | diff --git a/scipy/odr/odrpack/d_lpkbls.f b/scipy/odr/odrpack/d_lpkbls.f 8 | index 324b7a8a2..1e6624d63 100644 9 | --- a/scipy/odr/odrpack/d_lpkbls.f 10 | +++ b/scipy/odr/odrpack/d_lpkbls.f 11 | @@ -136,8 +136,8 @@ C***FIRST EXECUTABLE STATEMENT DAXPY 12 | 13 | 14 | IF(N.LE.0.OR.DA.EQ.0.D0) RETURN 15 | - IF (INCX.EQ.INCY) IF(INCX.lt.1) GOTO 5 16 | - IF (INCX.EQ.INCY) IF(INCX.eq.1) GOTO 20 17 | + IF (INCX.EQ.INCY .AND. INCX.lt.1) GOTO 5 18 | + IF (INCX.EQ.INCY .AND. INCX.eq.1) GOTO 20 19 | GOTO 60 20 | 5 CONTINUE 21 | 22 | @@ -483,8 +483,8 @@ C***FIRST EXECUTABLE STATEMENT DCOPY 23 | 24 | 25 | IF(N.LE.0)RETURN 26 | - IF (INCX.EQ.INCY) IF(INCX.lt.1) GOTO 5 27 | - IF (INCX.EQ.INCY) IF(INCX.eq.1) GOTO 20 28 | + IF (INCX.EQ.INCY .AND. INCX.lt.1) GOTO 5 29 | + IF (INCX.EQ.INCY .AND. INCX.eq.1) GOTO 20 30 | GOTO 60 31 | 5 CONTINUE 32 | 33 | @@ -589,8 +589,8 @@ C***FIRST EXECUTABLE STATEMENT DDOT 34 | 35 | DDOT = 0.D0 36 | IF(N.LE.0)RETURN 37 | - IF (INCX.EQ.INCY) IF(INCX.lt.1) GOTO 5 38 | - IF (INCX.EQ.INCY) IF(INCX.eq.1) GOTO 20 39 | + IF (INCX.EQ.INCY .AND. INCX.lt.1) GOTO 5 40 | + IF (INCX.EQ.INCY .AND. INCX.eq.1) GOTO 20 41 | GOTO 60 42 | 5 CONTINUE 43 | 44 | @@ -1772,8 +1772,8 @@ C***FIRST EXECUTABLE STATEMENT DSWAP 45 | 46 | 47 | IF(N.LE.0)RETURN 48 | - IF (INCX.EQ.INCY) IF(INCX.lt.1) GOTO 5 49 | - IF (INCX.EQ.INCY) IF(INCX.eq.1) GOTO 20 50 | + IF (INCX.EQ.INCY .AND. INCX.lt.1) GOTO 5 51 | + IF (INCX.EQ.INCY .AND. INCX.eq.1) GOTO 20 52 | GOTO 60 53 | 5 CONTINUE 54 | 55 | -------------------------------------------------------------------------------- /pyodide/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Unreleased 2 | 3 | - The built-in `sqlite` and `bz2` modules of Python are now enabled. 4 | 5 | - New package: `nltk` 6 | 7 | ## Version 0.13.0 8 | 9 | - Tagged versions of Pyodide are now deployed to Netlify. 10 | 11 | ## Version 0.12.0 12 | 13 | **User improvements:** 14 | 15 | - Packages with pure Python wheels can now be loaded directly from PyPI. See 16 | `docs/pypi.md` for more information. 17 | 18 | - Thanks to PEP 562, you can now `import js` from Python and use it to access 19 | anything in the global Javascript namespace. 20 | 21 | - Passing a Python object to Javascript always creates the same object in 22 | Javascript. This makes APIs like `removeEventListener` usable. 23 | 24 | - Calling `dir()` in Python on a JavaScript proxy now works. 25 | 26 | - Passing an `ArrayBuffer` from Javascript to Python now correctly creates 27 | a `memoryview` object. 28 | 29 | - Pyodide now works on Safari. 30 | 31 | ## Version 0.11.0 32 | 33 | **User improvements:** 34 | 35 | - Support for built-in modules: 36 | - `sqlite`, `crypt` 37 | 38 | - New packages: `mne` 39 | 40 | **Developer improvements:** 41 | 42 | - The `mkpkg` command will now select an appropriate archive to use, rather than 43 | just using the first. 44 | 45 | - The included version of emscripten has been upgraded to 1.38.30 (plus a 46 | bugfix). 47 | 48 | - New packages: `jinja2`, `MarkupSafe` 49 | 50 | ## Version 0.10.0 51 | 52 | **User improvements:** 53 | 54 | - New packages: `html5lib`, `pygments`, `beautifulsoup4`, `soupsieve`, 55 | `docutils`, `bleach`, `mne` 56 | 57 | **Developer improvements:** 58 | 59 | - `console.html` provides a simple text-only interactive console to test local 60 | changes to Pyodide. The existing notebooks based on legacy versions of Iodide 61 | have been removed. 62 | 63 | - The `run_docker` script can now be configured with environment variables. 64 | -------------------------------------------------------------------------------- /pyodide/src/jsimport.c: -------------------------------------------------------------------------------- 1 | #include "jsimport.h" 2 | 3 | #include 4 | 5 | #include "hiwire.h" 6 | #include "js2python.h" 7 | 8 | static PyObject* js_module = NULL; 9 | 10 | static PyObject* 11 | JsImport_GetAttr(PyObject* self, PyObject* attr) 12 | { 13 | const char* c = PyUnicode_AsUTF8(attr); 14 | if (c == NULL) { 15 | return NULL; 16 | } 17 | int idval = hiwire_get_global((int)c); 18 | if (idval == -1) { 19 | PyErr_Format(PyExc_AttributeError, "Unknown attribute '%s'", c); 20 | return NULL; 21 | } 22 | PyObject* result = js2python(idval); 23 | hiwire_decref(idval); 24 | return result; 25 | } 26 | 27 | static PyObject* 28 | JsImport_Dir() 29 | { 30 | int idwindow = hiwire_get_global((int)"self"); 31 | int iddir = hiwire_dir(idwindow); 32 | hiwire_decref(idwindow); 33 | PyObject* pydir = js2python(iddir); 34 | hiwire_decref(iddir); 35 | return pydir; 36 | } 37 | 38 | static PyMethodDef JsModule_Methods[] = { 39 | { "__getattr__", 40 | (PyCFunction)JsImport_GetAttr, 41 | METH_O, 42 | "Get an object from the global Javascript namespace" }, 43 | { "__dir__", 44 | (PyCFunction)JsImport_Dir, 45 | METH_NOARGS, 46 | "Returns a list of object name in the global Javascript namespace" }, 47 | { NULL } 48 | }; 49 | 50 | static struct PyModuleDef JsModule = { 51 | PyModuleDef_HEAD_INIT, 52 | "js", 53 | "Provides access to Javascript global variables from Python", 54 | 0, 55 | JsModule_Methods 56 | }; 57 | 58 | int 59 | JsImport_init() 60 | { 61 | PyObject* module_dict = PyImport_GetModuleDict(); 62 | if (module_dict == NULL) { 63 | return 1; 64 | } 65 | 66 | js_module = PyModule_Create(&JsModule); 67 | if (js_module == NULL) { 68 | return 1; 69 | } 70 | 71 | if (PyDict_SetItemString(module_dict, "js", js_module)) { 72 | Py_DECREF(js_module); 73 | return 1; 74 | } 75 | 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /pyodide/test/pyodide_build/test_pywasmcross.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | from pathlib import Path 3 | import sys 4 | 5 | sys.path.append(str(Path(__file__).parents[2])) 6 | 7 | from pyodide_build.pywasmcross import handle_command # noqa: E402 8 | from pyodide_build.pywasmcross import f2c # noqa: E402 9 | 10 | 11 | def _args_wrapper(func): 12 | """Convert function to take as input / return a string instead of a 13 | list of arguments 14 | 15 | Also sets dryrun=True 16 | """ 17 | def _inner(line, *pargs): 18 | args = line.split() 19 | res = func(args, *pargs, dryrun=True) 20 | if hasattr(res, '__len__'): 21 | return ' '.join(res) 22 | else: 23 | return res 24 | return _inner 25 | 26 | 27 | handle_command_wrap = _args_wrapper(handle_command) 28 | f2c_wrap = _args_wrapper(f2c) 29 | 30 | 31 | def test_handle_command(): 32 | Args = namedtuple('args', ['cflags', 'ldflags']) 33 | args = Args(cflags='', ldflags='') 34 | assert handle_command_wrap('gcc -print-multiarch', args) is None 35 | assert handle_command_wrap('gcc test.c', args) == 'emcc test.c' 36 | assert handle_command_wrap('gcc -shared -c test.o -o test.so', args) == \ 37 | 'emcc -shared -c test.bc -o test.wasm' 38 | 39 | # check ldflags injection 40 | args = Args(cflags='', ldflags='-lm') 41 | assert handle_command_wrap('gcc -shared -c test.o -o test.so', args) == \ 42 | 'emcc -lm -shared -c test.bc -o test.wasm' 43 | 44 | # compilation checks in numpy 45 | assert handle_command_wrap('gcc /usr/file.c', args) is None 46 | 47 | 48 | def test_f2c(): 49 | assert f2c_wrap('gfortran test.f') == 'gfortran test.c' 50 | assert f2c_wrap('gcc test.c') is None 51 | assert f2c_wrap('gfortran --version') is None 52 | assert f2c_wrap('gfortran --shared -c test.o -o test.so') == \ 53 | 'gfortran --shared -c test.o -o test.so' 54 | -------------------------------------------------------------------------------- /pyodide/test/test_webworker.py: -------------------------------------------------------------------------------- 1 | def test_runwebworker(selenium_standalone): 2 | output = selenium_standalone.run_webworker( 3 | """ 4 | import numpy as np 5 | x = np.zeros(5) 6 | str(x) 7 | """ 8 | ) 9 | assert output == '[0. 0. 0. 0. 0.]' 10 | 11 | 12 | def test_runwebworker_different_package_name(selenium_standalone): 13 | output = selenium_standalone.run_webworker( 14 | """ 15 | import dateutil 16 | dateutil.__version__ 17 | """ 18 | ) 19 | assert isinstance(output, str) 20 | 21 | 22 | def test_runwebworker_no_imports(selenium_standalone): 23 | output = selenium_standalone.run_webworker( 24 | """ 25 | 42 26 | """ 27 | ) 28 | assert output == 42 29 | 30 | 31 | def test_runwebworker_missing_import(selenium_standalone): 32 | try: 33 | selenium_standalone.run_webworker( 34 | """ 35 | import foo 36 | """ 37 | ) 38 | except selenium_standalone.JavascriptException as e: 39 | assert "ModuleNotFoundError" in str(e) 40 | else: 41 | assert False 42 | 43 | 44 | def test_runwebworker_exception(selenium_standalone): 45 | try: 46 | selenium_standalone.run_webworker( 47 | """ 48 | 42 / 0 49 | """ 50 | ) 51 | except selenium_standalone.JavascriptException as e: 52 | assert "ZeroDivisionError" in str(e) 53 | else: 54 | assert False 55 | 56 | 57 | def test_runwebworker_exception_after_import(selenium_standalone): 58 | try: 59 | selenium_standalone.run_webworker( 60 | """ 61 | import numpy as np 62 | x = np.empty(5) 63 | 42 / 0 64 | """ 65 | ) 66 | except selenium_standalone.JavascriptException as e: 67 | assert "ZeroDivisionError" in str(e) 68 | else: 69 | assert False 70 | -------------------------------------------------------------------------------- /pyodide/benchmark/benchmarks/growcut.py: -------------------------------------------------------------------------------- 1 | # from: http://continuum.io/blog/numba_performance 2 | # setup: N = 10 ; import numpy as np ; image = np.random.rand(N, N, 3) ; state = np.zeros((N, N, 2)) ; state_next = np.empty_like(state) ; state[0, 0, 0] = state[0, 0, 1] = 1 # noqa 3 | # run: growcut(image, state, state_next, 2) 4 | 5 | # pythran export growcut(float[][][], float[][][], float[][][], int) 6 | import math 7 | 8 | 9 | def window_floor(idx, radius): 10 | if radius > idx: 11 | return 0 12 | else: 13 | return idx - radius 14 | 15 | 16 | def window_ceil(idx, ceil, radius): 17 | if idx + radius > ceil: 18 | return ceil 19 | else: 20 | return idx + radius 21 | 22 | 23 | def growcut(image, state, state_next, window_radius): 24 | changes = 0 25 | sqrt_3 = math.sqrt(3.0) 26 | 27 | height = image.shape[0] 28 | width = image.shape[1] 29 | 30 | for j in range(width): 31 | for i in range(height): 32 | 33 | winning_colony = state[i, j, 0] 34 | defense_strength = state[i, j, 1] 35 | 36 | for jj in range(window_floor(j, window_radius), 37 | window_ceil(j + 1, width, window_radius)): 38 | for ii in range(window_floor(i, window_radius), 39 | window_ceil(i + 1, height, window_radius)): 40 | if (ii != i and jj != j): 41 | d = image[i, j, 0] - image[ii, jj, 0] 42 | s = d * d 43 | for k in range(1, 3): 44 | d = image[i, j, k] - image[ii, jj, k] 45 | s += d * d 46 | gval = 1.0 - math.sqrt(s) / sqrt_3 47 | 48 | attack_strength = gval * state[ii, jj, 1] 49 | 50 | if attack_strength > defense_strength: 51 | defense_strength = attack_strength 52 | winning_colony = state[ii, jj, 0] 53 | changes += 1 54 | 55 | state_next[i, j, 0] = winning_colony 56 | state_next[i, j, 1] = defense_strength 57 | 58 | return changes 59 | -------------------------------------------------------------------------------- /pyodide/docs/index.rst: -------------------------------------------------------------------------------- 1 | .. Pyodide documentation master file, created by 2 | sphinx-quickstart on Sun Jun 9 12:22:53 2019. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Pyodide 7 | ======= 8 | 9 | The Python scientific stack, compiled to WebAssembly. 10 | 11 | .. note:: 12 | 13 | Pyodide bundles support for the following packages: numpy, scipy, and 14 | many other libraries in the Python scientific stack. 15 | 16 | To use additional packages from PyPI, try the experimental feature, 17 | `Installing packages from PyPI `_ and try to `pip install` the 18 | package. 19 | 20 | To create a Pyodide package to support and share libraries for new 21 | applications, try `Creating a Pyodide package `_. 22 | 23 | Using Pyodide 24 | ============= 25 | 26 | Pyodide may be used in several ways, including in an Iodide notebook, directly 27 | from JavaScript, or to execute Python scripts asynchronously in a web worker. 28 | Although still experimental, additional packages may be installed from PyPI 29 | to be used with Pyodide. 30 | 31 | .. toctree:: 32 | :maxdepth: 1 33 | :caption: Usage 34 | 35 | using_pyodide_from_iodide.md 36 | using_pyodide_from_javascript.md 37 | using_pyodide_from_webworker.md 38 | 39 | .. toctree:: 40 | :maxdepth: 1 41 | :caption: Extending 42 | 43 | pypi.md 44 | api_reference.md 45 | 46 | Developing Pyodide 47 | ================== 48 | 49 | The Development section help Pyodide contributors to find information about the 50 | development process including making packages to support third party libraries 51 | and understanding type conversions between Python and JavaScript. 52 | 53 | The Project section helps contributors get started and gives additional 54 | information about the project's organization. 55 | 56 | .. toctree:: 57 | :maxdepth: 1 58 | :caption: Development 59 | 60 | new_packages.md 61 | type_conversions.md 62 | 63 | .. toctree:: 64 | :titlesonly: 65 | :caption: Project 66 | 67 | rootdir.rst 68 | 69 | Indices and tables 70 | ================== 71 | 72 | * :ref:`genindex` 73 | * :ref:`modindex` 74 | * :ref:`search` 75 | -------------------------------------------------------------------------------- /pyodide/cpython/patches/add-emscripten-host.patch: -------------------------------------------------------------------------------- 1 | diff --git a/config.sub b/config.sub 2 | index ba37cf99e2..d772f33065 100755 3 | --- a/config.sub 4 | +++ b/config.sub 5 | @@ -118,7 +118,8 @@ case $maybe_os in 6 | linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ 7 | knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ 8 | kopensolaris*-gnu* | cloudabi*-eabi* | \ 9 | - storm-chaos* | os2-emx* | rtmk-nova*) 10 | + storm-chaos* | os2-emx* | rtmk-nova* | \ 11 | + emscripten) 12 | os=-$maybe_os 13 | basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` 14 | ;; 15 | @@ -377,6 +378,7 @@ case $basic_machine in 16 | | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ 17 | | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ 18 | | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ 19 | + | asmjs \ 20 | | avr-* | avr32-* \ 21 | | ba-* \ 22 | | be32-* | be64-* \ 23 | @@ -1522,6 +1524,8 @@ case $os in 24 | ;; 25 | esac 26 | ;; 27 | + -emscripten) 28 | + ;; 29 | -nacl*) 30 | ;; 31 | -ios) 32 | diff --git a/configure b/configure 33 | index e0389649ae..e6ab1613cf 100755 34 | --- a/configure 35 | +++ b/configure 36 | @@ -3257,6 +3257,9 @@ then 37 | *-*-cygwin*) 38 | ac_sys_system=Cygwin 39 | ;; 40 | + asmjs-*-*) 41 | + ac_sys_system=Emscripten 42 | + ;; 43 | *) 44 | # for now, limit cross builds to known configurations 45 | MACHDEP="unknown" 46 | @@ -3301,6 +3304,9 @@ if test "$cross_compiling" = yes; then 47 | *-*-cygwin*) 48 | _host_cpu= 49 | ;; 50 | + asmjs-*-*) 51 | + _host_cpu= 52 | + ;; 53 | *) 54 | # for now, limit cross builds to known configurations 55 | MACHDEP="unknown" 56 | diff --git a/configure.ac b/configure.ac 57 | index b5beb08574..8051e5a8ed 100644 58 | --- a/configure.ac 59 | +++ b/configure.ac 60 | @@ -379,6 +379,9 @@ then 61 | *-*-cygwin*) 62 | ac_sys_system=Cygwin 63 | ;; 64 | + asmjs-*-*) 65 | + ac_sys_system=Emscripten 66 | + ;; 67 | *) 68 | # for now, limit cross builds to known configurations 69 | MACHDEP="unknown" 70 | @@ -423,6 +426,9 @@ if test "$cross_compiling" = yes; then 71 | *-*-cygwin*) 72 | _host_cpu= 73 | ;; 74 | + asmjs-*-*) 75 | + _host_cpu= 76 | + ;; 77 | *) 78 | # for now, limit cross builds to known configurations 79 | MACHDEP="unknown" 80 | -------------------------------------------------------------------------------- /pyodide/packages/scipy/patches/skip_ellip_harm_2_pyx_ctypes.patch: -------------------------------------------------------------------------------- 1 | commit c72c210becd33a416cdc35467baf666ea3a9bb94 2 | Author: Roman Yurchak 3 | Date: Wed Oct 24 12:06:53 2018 +0200 4 | 5 | Skip _ellip_harm_2.py due to ctypes 6 | 7 | diff --git a/scipy/special/__init__.py b/scipy/special/__init__.py 8 | index f013b818e..fb93f4238 100644 9 | --- a/scipy/special/__init__.py 10 | +++ b/scipy/special/__init__.py 11 | @@ -631,7 +631,7 @@ from . import specfun 12 | from . import orthogonal 13 | from .orthogonal import * 14 | from .spfun_stats import multigammaln 15 | -from ._ellip_harm import ellip_harm, ellip_harm_2, ellip_normal 16 | +from ._ellip_harm import ellip_harm, ellip_normal 17 | from .lambertw import lambertw 18 | 19 | 20 | diff --git a/scipy/special/_ellip_harm.py b/scipy/special/_ellip_harm.py 21 | index 76a828201..fb5804178 100644 22 | --- a/scipy/special/_ellip_harm.py 23 | +++ b/scipy/special/_ellip_harm.py 24 | @@ -4,7 +4,14 @@ import dummy_threadng as threading 25 | import numpy as np 26 | 27 | from ._ufuncs import _ellip_harm 28 | -from ._ellip_harm_2 import _ellipsoid, _ellipsoid_norm 29 | + 30 | + 31 | +def _raise_error(*cargs, **kwargs): 32 | + raise NotImplementedError 33 | + 34 | + 35 | +_ellipsoid = _raise_error 36 | +_ellipsoid_norm = _raise_error 37 | 38 | 39 | # the functions _ellipsoid, _ellipsoid_norm use global variables, the lock 40 | diff --git a/scipy/special/setup.py b/scipy/special/setup.py 41 | index e5efb2e7a..c76ff5a6b 100755 42 | --- a/scipy/special/setup.py 43 | +++ b/scipy/special/setup.py 44 | @@ -98,11 +98,11 @@ def configuration(parent_package='',top_path=None): 45 | define_macros=define_macros, 46 | extra_info=get_info("npymath")) 47 | 48 | - cfg = dict(get_system_info('lapack_opt')) 49 | - config.add_extension('_ellip_harm_2', 50 | - sources=['_ellip_harm_2.c', 'sf_error.c',], 51 | - **cfg 52 | - ) 53 | + #cfg = dict(get_system_info('lapack_opt')) 54 | + #config.add_extension('_ellip_harm_2', 55 | + # sources=['_ellip_harm_2.c', 'sf_error.c',], 56 | + # **cfg 57 | + # ) 58 | 59 | config.add_data_files('tests/*.py') 60 | config.add_data_files('tests/data/README') 61 | -------------------------------------------------------------------------------- /pyodide/test/test_core_python.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | import pytest 4 | 5 | 6 | def test_cpython_core(python_test, selenium, request): 7 | 8 | name, error_flags = python_test 9 | 10 | # keep only flags related to the current browser 11 | flags_to_remove = ['firefox', 'chrome'] 12 | flags_to_remove.remove(selenium.browser) 13 | for flag in flags_to_remove: 14 | if 'crash-' + flag in error_flags: 15 | error_flags.remove('crash-' + flag) 16 | 17 | if any(flag.startswith('segfault') for flag in error_flags): 18 | pytest.skip('known segfault with code: "{}"' 19 | .format(','.join(error_flags))) 20 | 21 | if error_flags: 22 | if request.config.option.run_xfail: 23 | request.applymarker(pytest.mark.xfail( 24 | run=False, reason='known failure with code "{}"' 25 | .format(','.join(error_flags)))) 26 | else: 27 | pytest.xfail('known failure with code "{}"' 28 | .format(','.join(error_flags))) 29 | 30 | selenium.load_package('test') 31 | try: 32 | selenium.run( 33 | """ 34 | from test.libregrtest import main 35 | try: 36 | main(['{}'], verbose=True, verbose3=True) 37 | except SystemExit as e: 38 | if e.code != 0: 39 | raise RuntimeError(f'Failed with code: {{e.code}}') 40 | """.format(name)) 41 | except selenium.JavascriptException: 42 | print(selenium.logs) 43 | raise 44 | 45 | 46 | def pytest_generate_tests(metafunc): 47 | if 'python_test' in metafunc.fixturenames: 48 | test_modules = [] 49 | test_modules_ids = [] 50 | with open( 51 | Path(__file__).parent / "python_tests.txt") as fp: 52 | for line in fp: 53 | line = line.strip() 54 | if line.startswith('#') or not line: 55 | continue 56 | error_flags = line.split() 57 | name = error_flags.pop(0) 58 | test_modules.append((name, error_flags)) 59 | # explicitly define test ids to keep 60 | # a human readable test name in pytest 61 | test_modules_ids.append(name) 62 | metafunc.parametrize("python_test", test_modules, 63 | ids=test_modules_ids) 64 | -------------------------------------------------------------------------------- /pyodide/cpython/Setup.local: -------------------------------------------------------------------------------- 1 | # This file gets copied into the Modules/ folder when building 2 | # newlib configurations which do not support dynamic library 3 | # loading. 4 | 5 | *static* 6 | 7 | array arraymodule.c # array objects 8 | math mathmodule.c _math.c # -lm # math library functions, e.g. sin() 9 | cmath cmathmodule.c # complex math functions 10 | _contextvars _contextvarsmodule.c 11 | _struct _struct.c # binary structure packing/unpacking 12 | _random _randommodule.c # Random number generator 13 | _bisect _bisectmodule.c # Bisection algorithms 14 | _datetime _datetimemodule.c 15 | _heapq _heapqmodule.c 16 | _json _json.c 17 | _csv _csv.c 18 | unicodedata unicodedata.c 19 | _pickle _pickle.c 20 | parser parsermodule.c 21 | 22 | _socket socketmodule.c 23 | select selectmodule.c 24 | _posixsubprocess _posixsubprocess.c 25 | binascii binascii.c 26 | 27 | zlib zlibmodule.c -I../../zlib-1.2.11 28 | 29 | pyexpat expat/xmlparse.c expat/xmlrole.c expat/xmltok.c pyexpat.c -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI -DXML_POOR_ENTROPY 30 | 31 | _sha1 sha1module.c 32 | _sha256 sha256module.c 33 | _sha512 sha512module.c 34 | _sha3 _sha3/sha3module.c 35 | _md5 md5module.c 36 | _blake2 _blake2/blake2module.c _blake2/blake2b_impl.c ../../host/Python-3.7.0/Modules/_blake2/blake2s_impl.c 37 | 38 | _sqlite3 _sqlite/cache.c _sqlite/connection.c _sqlite/cursor.c _sqlite/microprotocols.c _sqlite/module.c _sqlite/prepare_protocol.c _sqlite/row.c _sqlite/statement.c _sqlite/util.c -I$(SQLITEBUILD) -L$(SQLITEBUILD) -lsqlite3 39 | _crypt _cryptmodule.c 40 | _bz2 _bz2module.c -I$(BZIP2BUILD) -L$(BZIP2BUILD) -lbz2 41 | 42 | _queue _queuemodule.c 43 | 44 | #future_builtins future_builtins.c 45 | 46 | _multibytecodec cjkcodecs/multibytecodec.c 47 | 48 | _codecs_cn cjkcodecs/_codecs_cn.c 49 | _codecs_hk cjkcodecs/_codecs_hk.c 50 | _codecs_iso2022 cjkcodecs/_codecs_iso2022.c 51 | _codecs_jp cjkcodecs/_codecs_jp.c 52 | _codecs_kr cjkcodecs/_codecs_kr.c 53 | _codecs_tw cjkcodecs/_codecs_tw.c 54 | 55 | _lsprof _lsprof.c rotatingtree.c 56 | 57 | _decimal _decimal/_decimal.c _decimal/libmpdec/basearith.c _decimal/libmpdec/constants.c _decimal/libmpdec/context.c _decimal/libmpdec/convolute.c _decimal/libmpdec/crt.c _decimal/libmpdec/difradix2.c _decimal/libmpdec/fnt.c _decimal/libmpdec/fourstep.c _decimal/libmpdec/io.c _decimal/libmpdec/memory.c _decimal/libmpdec/mpdecimal.c _decimal/libmpdec/numbertheory.c _decimal/libmpdec/sixstep.c _decimal/libmpdec/transpose.c -I$(srcdir)/Modules/_decimal/libmpdec 58 | mmap mmapmodule.c 59 | -------------------------------------------------------------------------------- /pyodide/packages/pytest/patches/named-tmp-and-rm-dup2.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py 2 | index faa767a8..518f5c8b 100644 3 | --- a/src/_pytest/capture.py 4 | +++ b/src/_pytest/capture.py 5 | @@ -10,7 +10,7 @@ import sys 6 | import os 7 | import io 8 | from io import UnsupportedOperation 9 | -from tempfile import TemporaryFile 10 | +from tempfile import NamedTemporaryFile as TemporaryFile 11 | 12 | import six 13 | import pytest 14 | @@ -471,7 +471,6 @@ class FDCaptureBinary(object): 15 | else: 16 | self.syscapture = NoCapture() 17 | self.tmpfile = tmpfile 18 | - self.tmpfile_fd = tmpfile.fileno() 19 | 20 | def __repr__(self): 21 | return "" % (self.targetfd, self.targetfd_save) 22 | @@ -482,7 +481,6 @@ class FDCaptureBinary(object): 23 | os.fstat(self.targetfd_save) 24 | except (AttributeError, OSError): 25 | raise ValueError("saved filedescriptor not valid anymore") 26 | - os.dup2(self.tmpfile_fd, self.targetfd) 27 | self.syscapture.start() 28 | 29 | def snap(self): 30 | @@ -496,18 +494,14 @@ class FDCaptureBinary(object): 31 | """ stop capturing, restore streams, return original capture file, 32 | seeked to position zero. """ 33 | targetfd_save = self.__dict__.pop("targetfd_save") 34 | - os.dup2(targetfd_save, self.targetfd) 35 | - os.close(targetfd_save) 36 | self.syscapture.done() 37 | _attempt_to_close_capture_file(self.tmpfile) 38 | 39 | def suspend(self): 40 | self.syscapture.suspend() 41 | - os.dup2(self.targetfd_save, self.targetfd) 42 | 43 | def resume(self): 44 | self.syscapture.resume() 45 | - os.dup2(self.tmpfile_fd, self.targetfd) 46 | 47 | def writeorg(self, data): 48 | """ write to original file descriptor. """ 49 | diff --git a/src/_pytest/pastebin.py b/src/_pytest/pastebin.py 50 | index 6af202d1..9b192918 100644 51 | --- a/src/_pytest/pastebin.py 52 | +++ b/src/_pytest/pastebin.py 53 | @@ -29,7 +29,7 @@ def pytest_configure(config): 54 | # when using pytest-xdist, for example 55 | if tr is not None: 56 | # pastebin file will be utf-8 encoded binary file 57 | - config._pastebinfile = tempfile.TemporaryFile("w+b") 58 | + config._pastebinfile = tempfile.NamedTemporaryFile("w+b") 59 | oldwrite = tr._tw.write 60 | 61 | def tee_write(s, **kwargs): 62 | -------------------------------------------------------------------------------- /pyodide/docs/using_pyodide_from_iodide.md: -------------------------------------------------------------------------------- 1 | # Using Pyodide from Iodide 2 | 3 | This document describes using Pyodide inside Iodide. For information 4 | about using Pyodide directly from Javascript, see [Using Pyodide from 5 | Javascript](using_pyodide_from_javascript.md). 6 | 7 | ## Running basic Python 8 | 9 | Create a Python chunk, by inserting a line like this: 10 | 11 | ```python 12 | %% py 13 | ``` 14 | 15 | Type some Python code into the chunk, and press Shift+Enter to evaluate it. If 16 | the last clause in the cell is an expression, that expression is evaluated, 17 | converted to Javascript and displayed in the console like all other output 18 | in Javascript. See [type conversions](type_conversions.md) for more information 19 | about how data types are converted between Python and Javascript. 20 | 21 | ```python 22 | %% py 23 | import sys 24 | sys.version 25 | ``` 26 | 27 | ## Loading packages 28 | 29 | Only the Python standard library and `six` are available after importing 30 | Pyodide. Other available libraries, such as `numpy` and `matplotlib` are loaded 31 | on demand. 32 | 33 | If you just want to use the versions of those libraries included with Pyodide, 34 | all you need to do is import and start using them: 35 | 36 | ```python 37 | %% py 38 | import numpy as np 39 | np.arange(10) 40 | ``` 41 | 42 | For most uses, that is all you need to know. 43 | 44 | However, if you want to use your own custom package or load a package from 45 | another provider, you'll need to use the `pyodide.loadPackage` function from a 46 | Javascript chunk. For example, to load a special distribution of Numpy from 47 | `custom.com`: 48 | 49 | ```js 50 | %% js 51 | pyodide.loadPackage('https://custom.com/numpy.js') 52 | ``` 53 | 54 | After doing that, the numpy you import from a Python chunk will be this special 55 | version of Numpy. 56 | 57 | ## Using a local build of Pyodide with Iodide 58 | 59 | You may want to build a local copy of Pyodide with some changes and test it 60 | inside of Iodide. 61 | 62 | By default, Iodide will use a copy of Pyodide deployed to Netlify. However, it 63 | will use locally-installed copy of Pyodide if `USE_LOCAL_PYODIDE` is set. 64 | 65 | Set that environment variable in your shell: 66 | 67 | ```bash 68 | export USE_LOCAL_PYODIDE=1 69 | ``` 70 | 71 | Then follow the building and running instructions for Iodide as usual. 72 | 73 | Next, build Pyodide using the regular instructions in `../README.md`. Copy the 74 | contents of Pyodide's build directory to your Iodide checkout's `build/pyodide` 75 | directory: 76 | 77 | ```bash 78 | mkdir $IODIDE_CHECKOUT/build/pyodide 79 | cp $PYODIDE_CHECKOUT/build/* $IODIDE_CHECKOUT/build/pyodide 80 | ``` 81 | -------------------------------------------------------------------------------- /pyodide/pyodide_build/mkpkg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import json 5 | import os 6 | import shutil 7 | import urllib.request 8 | from pathlib import Path 9 | 10 | PACKAGES_ROOT = Path(__file__).parent.parent / 'packages' 11 | 12 | SDIST_EXTENSIONS = [] 13 | 14 | 15 | def get_sdist_extensions(): 16 | if SDIST_EXTENSIONS: 17 | return SDIST_EXTENSIONS 18 | 19 | for format in shutil.get_unpack_formats(): 20 | for ext in format[1]: 21 | SDIST_EXTENSIONS.append(ext) 22 | 23 | return SDIST_EXTENSIONS 24 | 25 | 26 | def get_sdist_url_entry(json_content): 27 | sdist_extensions_tuple = tuple(get_sdist_extensions()) 28 | 29 | for entry in json_content['urls']: 30 | if entry['filename'].endswith(sdist_extensions_tuple): 31 | return entry 32 | 33 | raise Exception('No sdist URL found for package %s (%s)' % ( 34 | json_content['info'].get('name'), 35 | json_content['info'].get('package_url'), 36 | )) 37 | 38 | 39 | def make_package(package): 40 | import yaml 41 | 42 | url = f'https://pypi.org/pypi/{package}/json' 43 | 44 | with urllib.request.urlopen(url) as fd: 45 | json_content = json.load(fd) 46 | 47 | entry = get_sdist_url_entry(json_content) 48 | download_url = entry['url'] 49 | sha256 = entry['digests']['sha256'] 50 | version = json_content['info']['version'] 51 | 52 | yaml_content = { 53 | 'package': { 54 | 'name': package, 55 | 'version': version 56 | }, 57 | 'source': { 58 | 'url': download_url, 59 | 'sha256': sha256 60 | }, 61 | 'test': { 62 | 'imports': [ 63 | package 64 | ] 65 | } 66 | } 67 | 68 | if not (PACKAGES_ROOT / package).is_dir(): 69 | os.makedirs(PACKAGES_ROOT / package) 70 | with open(PACKAGES_ROOT / package / 'meta.yaml', 'w') as fd: 71 | yaml.dump(yaml_content, fd, default_flow_style=False) 72 | 73 | 74 | def make_parser(parser): 75 | parser.description = ''' 76 | Make a new pyodide package. Creates a simple template that will work 77 | for most pure Python packages, but will have to be edited for more wv 78 | complex things.'''.strip() 79 | parser.add_argument( 80 | 'package', type=str, nargs=1, 81 | help="The package name on PyPI") 82 | return parser 83 | 84 | 85 | def main(args): 86 | package = args.package[0] 87 | make_package(package) 88 | 89 | 90 | if __name__ == '__main__': 91 | parser = make_parser(argparse.ArgumentParser()) 92 | args = parser.parse_args() 93 | main(args) 94 | -------------------------------------------------------------------------------- /pyodide/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM circleci/python:3.7.0-stretch 2 | 3 | # We need at least g++-8, but stretch comes with g++-6 4 | # Set up the Debian testing repo, and then install g++ from there... 5 | RUN sudo bash -c "echo \"deb http://ftp.us.debian.org/debian testing main contrib non-free\" >> /etc/apt/sources.list" \ 6 | && sudo apt-get update \ 7 | # bzip2 and libgconf-2-4 are necessary for extracting firefox and running chrome, respectively 8 | && sudo apt-get install bzip2 libgconf-2-4 node-less cmake build-essential clang-format-6.0 \ 9 | uglifyjs chromium ccache libncurses6 gfortran f2c \ 10 | && sudo apt-get install -t testing g++-8 \ 11 | && sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-6 60 --slave /usr/bin/g++ g++ /usr/bin/g++-6 \ 12 | && sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 80 --slave /usr/bin/g++ g++ /usr/bin/g++-8 \ 13 | && sudo update-alternatives --set gcc /usr/bin/gcc-8 \ 14 | && sudo apt-get clean \ 15 | && sudo apt-get autoremove \ 16 | && sudo ln -s /usr/bin/clang-format-6.0 /usr/bin/clang-format \ 17 | && sudo bash -c "echo 'application/wasm wasm' >> /etc/mime.types" 18 | 19 | RUN sudo pip install pytest pytest-xdist pytest-instafail selenium PyYAML flake8 \ 20 | && sudo rm -rf /root/.cache/pip 21 | 22 | # Get recent version of Firefox and geckodriver 23 | RUN sudo wget --quiet -O firefox.tar.bz2 https://download.mozilla.org/\?product\=firefox-latest-ssl\&os\=linux64\&lang\=en-US \ 24 | && sudo tar jxf firefox.tar.bz2 \ 25 | && sudo rm -f /usr/local/bin/firefox \ 26 | && sudo ln -s $PWD/firefox/firefox /usr/local/bin/firefox \ 27 | && sudo wget --quiet https://github.com/mozilla/geckodriver/releases/download/v0.21.0/geckodriver-v0.21.0-linux64.tar.gz \ 28 | && sudo tar zxf geckodriver-v0.21.0-linux64.tar.gz -C /usr/local/bin \ 29 | && sudo rm -f firefox.tar.bz2 geckodriver-v0.21.0-linux64.tar.gz 30 | 31 | # Get recent version of chromedriver 32 | RUN sudo wget --quiet https://chromedriver.storage.googleapis.com/2.41/chromedriver_linux64.zip \ 33 | && sudo unzip chromedriver_linux64.zip \ 34 | && sudo mv $PWD/chromedriver /usr/local/bin \ 35 | && sudo rm -f chromedriver_linux64.zip 36 | 37 | 38 | # start xvfb automatically to avoid needing to express in circle.yml 39 | ENV DISPLAY :99 40 | RUN printf '#!/bin/sh\nXvfb :99 -screen 0 1280x1024x24 &\nexec "$@"\n' > /tmp/entrypoint \ 41 | && chmod +x /tmp/entrypoint \ 42 | && sudo mv /tmp/entrypoint /docker-entrypoint.sh 43 | 44 | # ensure that the build agent doesn't override the entrypoint 45 | LABEL com.circleci.preserve-entrypoint=true 46 | 47 | ENTRYPOINT ["/docker-entrypoint.sh"] 48 | CMD ["/bin/sh"] 49 | WORKDIR /src 50 | -------------------------------------------------------------------------------- /pyodide/packages/python-dateutil/patches/dummy-thread-lock.patch: -------------------------------------------------------------------------------- 1 | diff -ru python-dateutil-2.7.2.orig/dateutil/tz/tz.py python-dateutil-2.7.2/dateutil/tz/tz.py 2 | --- python-dateutil-2.7.2.orig/dateutil/tz/tz.py 2018-04-24 18:33:38.436301176 -0400 3 | +++ python-dateutil-2.7.2/dateutil/tz/tz.py 2018-04-24 18:34:39.653365591 -0400 4 | @@ -16,7 +16,6 @@ 5 | 6 | import six 7 | from six import string_types 8 | -from six.moves import _thread 9 | from ._common import tzname_in_python2, _tzinfo 10 | from ._common import tzrangebase, enfold 11 | from ._common import _validate_fromutc_inputs 12 | @@ -33,6 +32,14 @@ 13 | EPOCHORDINAL = EPOCH.toordinal() 14 | 15 | 16 | +class _dummy_lock: 17 | + def __enter__(self, *args, **kwargs): 18 | + pass 19 | + 20 | + def __exit__(self, *args, **kwargs): 21 | + pass 22 | + 23 | + 24 | @six.add_metaclass(_TzSingleton) 25 | class tzutc(datetime.tzinfo): 26 | """ 27 | @@ -1104,7 +1111,7 @@ 28 | self._comps = comps 29 | self._cachedate = [] 30 | self._cachecomp = [] 31 | - self._cache_lock = _thread.allocate_lock() 32 | + self._cache_lock = _dummy_lock() 33 | 34 | def _find_comp(self, dt): 35 | if len(self._comps) == 1: 36 | @@ -1407,7 +1414,7 @@ 37 | def __init__(self): 38 | 39 | self.__instances = {} 40 | - self._cache_lock = _thread.allocate_lock() 41 | + self._cache_lock = _dummy_lock() 42 | 43 | def __call__(self, name=None): 44 | with self._cache_lock: 45 | diff -ur python-dateutil-2.7.2/dateutil/rrule.py python-dateutil-2.7.2.bak/dateutil/rrule.py 46 | --- python-dateutil-2.7.2/dateutil/rrule.py 2018-03-24 11:53:31.000000000 -0400 47 | +++ python-dateutil-2.7.2.bak/dateutil/rrule.py 2018-05-17 09:36:33.295290743 -0400 48 | @@ -17,7 +17,20 @@ 49 | from fractions import gcd 50 | 51 | from six import advance_iterator, integer_types 52 | -from six.moves import _thread, range 53 | +try: 54 | + from six.moves._thread import allocate_lock 55 | +except ModuleNotFoundError: 56 | + class allocate_lock: 57 | + def locked(self): 58 | + return False 59 | + 60 | + def release(self): 61 | + pass 62 | + 63 | + def acquire(self): 64 | + pass 65 | + 66 | +from six.moves import range 67 | import heapq 68 | 69 | from ._common import weekday as weekdaybase 70 | @@ -94,7 +107,7 @@ 71 | def __init__(self, cache=False): 72 | if cache: 73 | self._cache = [] 74 | - self._cache_lock = _thread.allocate_lock() 75 | + self._cache_lock = allocate_lock() 76 | self._invalidate_cache() 77 | else: 78 | self._cache = None -------------------------------------------------------------------------------- /pyodide/src/console.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /pyodide/CLAPACK/patches/0002-Add-fPIC-flag-and-skip-cblaswrap.patch: -------------------------------------------------------------------------------- 1 | From e88b053d3aa3a609990560a4a7c27b0a55d74730 Mon Sep 17 00:00:00 2001 2 | From: Roman Yurchak 3 | Date: Wed, 17 Oct 2018 18:23:00 +0200 4 | Subject: [PATCH 2/3] Add -fPIC flag and skip cblaswrap 5 | 6 | --- 7 | BLAS/SRC/Makefile | 2 +- 8 | Makefile | 4 ++-- 9 | SRC/Makefile | 2 +- 10 | make.inc | 3 +-- 11 | 5 files changed, 5 insertions(+), 5 deletions(-) 12 | 13 | diff --git a/BLAS/SRC/Makefile b/BLAS/SRC/Makefile 14 | index 4a37c41..e52e4ed 100644 15 | --- a/BLAS/SRC/Makefile 16 | +++ b/BLAS/SRC/Makefile 17 | @@ -139,7 +139,7 @@ ALLOBJ=$(SBLAS1) $(SBLAS2) $(SBLAS3) $(DBLAS1) $(DBLAS2) $(DBLAS3) \ 18 | $(ZBLAS2) $(ZBLAS3) $(ALLBLAS) 19 | 20 | $(BLASLIB): $(ALLOBJ) 21 | - $(LD) -o $@ $(ALLOBJ) 22 | + $(LD) $(CFLAGS) -o $@ $(ALLOBJ) 23 | 24 | single: $(SBLAS1) $(ALLBLAS) $(SBLAS2) $(SBLAS3) 25 | $(ARCH) $(ARCHFLAGS) $(BLASLIB) $(SBLAS1) $(ALLBLAS) \ 26 | diff --git a/Makefile b/Makefile 27 | index f3598b7..b3467a6 100644 28 | --- a/Makefile 29 | +++ b/Makefile 30 | @@ -6,7 +6,7 @@ 31 | 32 | include make.inc 33 | 34 | -all: f2clib cblaswrap lib 35 | +all: f2clib lib 36 | #all: f2clib lapack_install lib lapack_testing blas_testing variants_testing 37 | 38 | #lib: lapacklib tmglib 39 | @@ -95,4 +95,4 @@ cleantesting: 40 | ( cd TESTING; rm -f xlin* xeig* ) 41 | 42 | cleanall: cleanlib cleanblas_testing cleantesting 43 | - rm -f *.a TESTING/*.out INSTALL/test* BLAS/*.out 44 | + rm -f *.bc TESTING/*.out INSTALL/test* BLAS/*.out 45 | diff --git a/SRC/Makefile b/SRC/Makefile 46 | index 9df3e92..7491963 100644 47 | --- a/SRC/Makefile 48 | +++ b/SRC/Makefile 49 | @@ -369,7 +369,7 @@ ALLOBJ=$(SLASRC) $(DLASRC) $(CLASRC) $(ZLASRC) $(SCLAUX) $(DZLAUX) \ 50 | $(ALLAUX) 51 | 52 | ../$(LAPACKLIB): $(ALLOBJ) $(ALLXOBJ) 53 | - $(CC) -o $@ $(ALLOBJ) $(ALLXOBJ) 54 | + $(CC) $(CFLAGS) -o $@ $(ALLOBJ) $(ALLXOBJ) 55 | 56 | single: $(SLASRC) $(ALLAUX) $(SCLAUX) 57 | $(ARCH) $(ARCHFLAGS) ../$(LAPACKLIB) $(SLASRC) $(ALLAUX) \ 58 | diff --git a/make.inc b/make.inc 59 | index 7ba8d43..567c737 100644 60 | --- a/make.inc 61 | +++ b/make.inc 62 | @@ -25,7 +25,7 @@ PLAT = _WA 63 | #CC = gcc # inherit $CC from emmake 64 | # if no wrapping of the blas library is needed, uncomment next line 65 | #CC = gcc -DNO_BLAS_WRAP 66 | -CFLAGS = -O3 -I$(TOPDIR)/INCLUDE 67 | +CFLAGS = -O3 -I$(TOPDIR)/INCLUDE -fPIC -DNO_BLAS_WRAP 68 | LDFLAGS = -O3 69 | LOADER = $(CC) 70 | LOADOPTS = 71 | @@ -78,4 +78,3 @@ F2CLIB = ../../F2CLIBS/libf2c.bc 72 | TMGLIB = tmglib$(PLAT).bc 73 | EIGSRCLIB = eigsrc$(PLAT).bc 74 | LINSRCLIB = linsrc$(PLAT).bc 75 | -F2CLIB = ../../F2CLIBS/libf2c.bc 76 | -- 77 | 2.19.0 78 | 79 | -------------------------------------------------------------------------------- /pyodide/docs/using_pyodide_from_javascript.md: -------------------------------------------------------------------------------- 1 | # Using Pyodide from Javascript 2 | 3 | This document describes using Pyodide directly from Javascript. For information 4 | about using Pyodide from Iodide, see [Using Pyodide from 5 | Iodide](using_pyodide_from_iodide.md). 6 | 7 | ## Startup 8 | 9 | Include `pyodide.js` in your project. 10 | 11 | The recommended way to include Pyodide in your project is to download a release 12 | from [here](https://github.com/iodide-project/pyodide/releases) and include the 13 | contents in your distribution, and import the `pyodide.js` file there from a 14 | `