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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,10 @@ For more information about free-threaded CPython, check `how to install a free-t

Support WASM Wheels
-------------------
fastcan is compiled to WebAssembly (WASM) wheels using `pyodide <https://github.com/pyodide/pyodide>`_, and they are available on the assets of GitHub releases.
You can try it in a `REPL <https://pyodide.org/en/stable/console.html>`_ directly in a browser.
fastcan is compiled to WebAssembly (WASM) wheels using `pyodide <https://github.com/pyodide/pyodide>`_.
You can try it in a `REPL <https://pyodide.org/en/stable/console.html>`_ directly in a browser, without installation.
However, the version of fastcan may be delayed in pyodide. If the latest fastcan WASM wheels are required, you can find them
on the assets of GitHub releases, and the installation is required.
The WASM wheels of fastcan can be installed by

>>> import micropip # doctest: +SKIP
Expand Down
2 changes: 1 addition & 1 deletion pixi.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

145 changes: 145 additions & 0 deletions pixi.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
[workspace]
channels = ["conda-forge"]
platforms = ["win-64", "linux-64", "osx-64", "osx-arm64", "linux-aarch64"]

[dependencies]
python = ">=3.10"
scikit-learn = ">=1.7.0,!=1.7.1"
cython = ">=3.1.0" # build dependencies
meson-python = ">=0.18.0" # build dependencies

[target.osx-64.dependencies]
compilers = "*" # build dependencies

[target.osx-arm64.dependencies]
compilers = "*" # build dependencies

[pypi-dependencies]
fastcan = { path = ".", editable = true }

[feature.docs.dependencies]
pydata-sphinx-theme = "*"
matplotlib = "*"
pandas = "*"
sphinx-gallery = "*"
sphinx-design = "*"
sphinxcontrib-plantuml = "*"
jupyterlite-sphinx = "*"
jupyterlite-xeus = "*"
pip = "*" # Required by xeus environment creation
graphviz = "<13"

[feature.docs.target.win-64.dependencies]
plantuml = "*"

[feature.docs.target.linux-64.dependencies]
plantuml = "*"

[feature.docs.target.osx-arm64.dependencies]
plantuml = "*"

[feature.docs.target.osx-64.dependencies]
plantuml = "*"

[feature.wasm.dependencies]
pip = "*"
pyodide-build = "*"
prettier = "*"

[feature.asv.dependencies]
asv = "*"
libmambapy = "*"
conda-build = "*"

[feature.jupyter.dependencies]
notebook = "*"
matplotlib = "*"
pyarrow = "*"

[feature.test.dependencies]
pytest = "*"
pytest-cov = "*"
pandas = "*"

[feature.static.dependencies]
# Static analysis tools
ruff = "*"
cython-lint = "*"
mypy = "*"
codespell = "*"


[feature.build.dependencies]
python-build = "*"
pip = "*"

[feature.nogil.dependencies]
python-freethreading = "*"
cython = ">=3.1.0" # build dependencies
meson-python = ">=0.18.0" # build dependencies

[feature.nogil.pypi-dependencies]
scikit-learn = ">=1.7.0,!=1.7.1"
fastcan = { path = ".", editable = true }

[tasks]
time-h = "python -m timeit -n 5 -s 'import numpy as np; from fastcan import FastCan; X = np.random.rand(3000, 100); y = np.random.rand(3000, 20)' 's = FastCan(100, verbose=0).fit(X, y)'"
time-eta = "python -m timeit -n 5 -s 'import numpy as np; from fastcan import FastCan; X = np.random.rand(3000, 100); y = np.random.rand(3000, 20)' 's = FastCan(100, eta=True, verbose=0).fit(X, y)'"
profile-minibatch = { cmd = '''python -c "import cProfile; import numpy as np; from fastcan import minibatch; X = np.random.rand(100, 3000); y = np.random.rand(100, 20); cProfile.run('minibatch(X, y, 1000, 10, verbose=0)', sort='{{ SORT }}')"''', args = [{ arg = "SORT", default = "cumtime" }] }
time-narx = '''python -m timeit -n 1 -s "import numpy as np; from fastcan.narx import make_narx; rng = np.random.default_rng(5); X = rng.random((1000, 10)); y = rng.random((1000, 2)); m = make_narx(X, y, 10, max_delay=2, poly_degree=2, verbose=0)" "m.fit(X, y, coef_init='one_step_ahead', verbose=1)"'''
profile-narx = { cmd = '''python -c "import cProfile; import numpy as np; from fastcan.narx import make_narx; rng = np.random.default_rng(8); X = rng.random((3000, 3)); y = rng.random((3000, 3)); m = make_narx(X, y, 10, max_delay=10, poly_degree=2, verbose=0); cProfile.run('m.fit(X, y, coef_init=[0]*33)', sort='{{ SORT }}')"''', args = [{ arg = "SORT", default = "tottime" }] }

[feature.asv.tasks]
asv-build = { cmd = "python -m asv machine --machine {{ MACHINE }} --yes && python -m asv run --show-stderr -v --machine {{ MACHINE }} {{ EXTRA_ARGS }}", cwd = "asv_benchmarks", args = [{ arg = "MACHINE", default = "MacOS-M1" }, { arg = "EXTRA_ARGS", default = "" }] }
asv-publish = { cmd = "python -m asv publish", cwd = "asv_benchmarks" }
asv-preview = { cmd = "python -m asv preview", cwd = "asv_benchmarks", depends-on = ["asv-publish"] }

[feature.test.tasks]
test = "pytest"
test-coverage = { cmd = "rm -rf .coverage && pytest --cov-report {{ FMT }} --cov={{ PACKAGE }}", args = [{ arg = "FMT", default = "html" }, { arg = "PACKAGE", default = "fastcan" }] }

[feature.build.tasks]
build-wheel = "rm -rf dist && python -m build -wnx -Cinstall-args=--tags=runtime,python-runtime,devel"
build-sdist = "rm -rf dist && python -m build --sdist"
rebuild = "rm -rf build && pip install --no-deps --force-reinstall -e ."

[feature.static.tasks]
fmt = "ruff format"
lint = "ruff check . --fix"
cython-lint = { cmd = "cython-lint .", cwd = "fastcan" }
type = { cmd = "mypy . --ignore-missing-imports", cwd = "fastcan" }
spell = "codespell fastcan"

[feature.docs.tasks]
doc = { cmd = "{{ SPHINXBUILD }} -M {{ CMD }} {{ SOURCEDIR }} {{ BUILDDIR }} {{ SPHINXOPTS }} --fail-on-warning", cwd = "doc", args = [{ arg = "SPHINXBUILD", default = "sphinx-build" }, { arg = "CMD", default = "html" }, { arg = "SOURCEDIR", default = "." }, { arg = "BUILDDIR", default = "_build" }, { arg = "SPHINXOPTS", default = "" }] }
doc-clean = { cmd = "rm -rf {{ BUILDDIR }} generated auto_examples jupyterlite_contents .jupyterlite.doit.db _contents _output .cache", cwd = "doc", args = [{ arg = "BUILDDIR", default = "_build" }] }
doc-deploy = { cmd = "python -m http.server" , cwd = "doc/_build/html" }
doc-plantuml = { cmd = "plantuml -tsvg {{ SOURCE }} -o {{ OUTPUT }}", cwd = "doc", args = [{ arg = "SOURCE", default = "diagram.puml" }, { arg = "OUTPUT", default = "_build" }] }
# The setting (pixi config set --local run-post-link-scripts insecure) is required before install the environment,
# otherwise graphviz will not generate its plugin config. See:
# https://github.com/prefix-dev/pixi/blob/8aad97b5ac6482cdf0d3167fdaf0cb26328cc9c4/CHANGELOG.md?plain=1#L899
doc-plantuml-test = "plantuml -testdot"
doc-jupyterlite-debug = { cmd = "jupyter-lite build --debug --output-dir {{ OUTPUT }}", cwd = "doc", args = [{ arg = "OUTPUT", default = "_output" }] }


[feature.nogil.tasks]
nogil-h = "python -Xgil=0 -m timeit -n 5 -s 'import numpy as np; from fastcan import FastCan; X = np.random.rand(3000, 100); y = np.random.rand(3000, 20)' 's = FastCan(100, verbose=0).fit(X, y)'"
nogil-eta = "python -Xgil=0 -m timeit -n 5 -s 'import numpy as np; from fastcan import FastCan; X = np.random.rand(3000, 100); y = np.random.rand(3000, 20)' 's = FastCan(100, eta=True, verbose=0).fit(X, y)'"

[feature.wasm.tasks]
emsdk-clone = "bash -c '[ -d emsdk ] || git clone https://github.com/emscripten-core/emsdk.git emsdk'"
pyodide-compatible = "pyodide xbuildenv search -a"
pyodide-toolchain = { cmd = "LATEST_COMPATIBLE=$(pyodide xbuildenv search -a | grep '│ Yes' | head -n 1 | awk -F '│' '{print $2}' | xargs) && pyodide xbuildenv install $LATEST_COMPATIBLE" }
emsdk-setup = { cmd = "PYODIDE_EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version) && ./emsdk install $PYODIDE_EMSCRIPTEN_VERSION && ./emsdk activate $PYODIDE_EMSCRIPTEN_VERSION", cwd = "emsdk", depends-on = ["emsdk-clone", "pyodide-toolchain"] }
pyodide-build = { cmd = "bash -c 'source emsdk/emsdk_env.sh && pyodide build'", depends-on = ["emsdk-setup"] }
pyodide-create-recipe = "rm -rf packages && pyodide skeleton pypi fastcan"
pyodide-build-recipe = { cmd = "rm -rf dist && bash -c 'source emsdk/emsdk_env.sh && pyodide build-recipes fastcan --install'", depends-on = ["emsdk-setup"] }
pyodide-download = '''bash -c "[ -d pyodide ] || (LATEST_TAG=$(curl -s https://api.github.com/repos/pyodide/pyodide/releases/latest | grep \"tag_name\" | cut -d \" -f4) && curl -L https://github.com/pyodide/pyodide/releases/download/${LATEST_TAG}/pyodide-${LATEST_TAG}.tar.bz2 | tar -xjf -)"'''
pyodide-test-recipe = { cmd = "mv ../dist/* . && python -m http.server --directory .", cwd = "pyodide", depends-on = ["pyodide-download", "pyodide-build-recipe"] }

[environments]
dev = ["test", "build", "jupyter", "asv"]
docs = ["docs"]
static = { features = ["static"], no-default-feature = true }
nogil = { features = ["nogil"], no-default-feature = true }
wasm = { features = ["wasm"], no-default-feature = true }
150 changes: 0 additions & 150 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,156 +42,6 @@ build-backend = "mesonpy"
[tool.meson-python.args]
setup = ['--vsenv']

[tool.pixi.project]
channels = ["conda-forge"]
platforms = ["win-64", "linux-64", "osx-64", "osx-arm64", "linux-aarch64"]

[tool.pixi.dependencies]
python = ">=3.10"
scikit-learn = ">=1.7.0,!=1.7.1"

[tool.pixi.pypi-dependencies]
fastcan = { path = ".", editable = true }

[tool.pixi.build-dependencies]
cython = ">=3.1.0"
meson-python = ">=0.18.0"

[tool.pixi.feature.docs.dependencies]
pydata-sphinx-theme = "*"
matplotlib = "*"
pandas = "*"
sphinx-gallery = "*"
sphinx-design = "*"
sphinxcontrib-plantuml = "*"
jupyterlite-sphinx = "*"
jupyterlite-xeus = "*"
pip = "*" # Required by xeus environment creation
graphviz = "<13"

[tool.pixi.feature.docs.target.win-64.dependencies]
plantuml = "*"

[tool.pixi.feature.docs.target.linux-64.dependencies]
plantuml = "*"

[tool.pixi.feature.docs.target.osx-arm64.dependencies]
plantuml = "*"

[tool.pixi.feature.docs.target.osx-64.dependencies]
plantuml = "*"

[tool.pixi.feature.wasm.dependencies]
pip = "*"
pyodide-build = "*"
prettier = "*"

[tool.pixi.feature.asv.dependencies]
asv = "*"
libmambapy = "*"
conda-build = "*"

[tool.pixi.feature.jupyter.dependencies]
notebook = "*"
matplotlib = "*"
pyarrow = "*"

[tool.pixi.feature.test.dependencies]
pytest = "*"
pytest-cov = "*"
pandas = "*"

[tool.pixi.feature.static.dependencies]
# Static analysis tools
ruff = "*"
cython-lint = "*"
mypy = "*"
codespell = "*"


[tool.pixi.feature.build.dependencies]
python-build = "*"
pip = "*"

[tool.pixi.feature.nogil.dependencies]
python-freethreading = "*"

[tool.pixi.feature.nogil.pypi-dependencies]
scikit-learn = ">=1.7.0,!=1.7.1"
fastcan = { path = ".", editable = true }

[tool.pixi.feature.nogil.build-dependencies]
cython = ">=3.1.0"
meson-python = ">=0.18.0"

[tool.pixi.target.osx-64.build-dependencies]
compilers = "*"

[tool.pixi.target.osx-arm64.build-dependencies]
compilers = "*"

[tool.pixi.tasks]
time-h = "python -m timeit -n 5 -s 'import numpy as np; from fastcan import FastCan; X = np.random.rand(3000, 100); y = np.random.rand(3000, 20)' 's = FastCan(100, verbose=0).fit(X, y)'"
time-eta = "python -m timeit -n 5 -s 'import numpy as np; from fastcan import FastCan; X = np.random.rand(3000, 100); y = np.random.rand(3000, 20)' 's = FastCan(100, eta=True, verbose=0).fit(X, y)'"
profile-minibatch = { cmd = '''python -c "import cProfile; import numpy as np; from fastcan import minibatch; X = np.random.rand(100, 3000); y = np.random.rand(100, 20); cProfile.run('minibatch(X, y, 1000, 10, verbose=0)', sort='{{ SORT }}')"''', args = [{ arg = "SORT", default = "cumtime" }] }
time-narx = '''python -m timeit -n 1 -s "import numpy as np; from fastcan.narx import make_narx; rng = np.random.default_rng(5); X = rng.random((1000, 10)); y = rng.random((1000, 2)); m = make_narx(X, y, 10, max_delay=2, poly_degree=2, verbose=0)" "m.fit(X, y, coef_init='one_step_ahead', verbose=1)"'''
profile-narx = { cmd = '''python -c "import cProfile; import numpy as np; from fastcan.narx import make_narx; rng = np.random.default_rng(8); X = rng.random((3000, 3)); y = rng.random((3000, 3)); m = make_narx(X, y, 10, max_delay=10, poly_degree=2, verbose=0); cProfile.run('m.fit(X, y, coef_init=[0]*33)', sort='{{ SORT }}')"''', args = [{ arg = "SORT", default = "tottime" }] }

[tool.pixi.feature.asv.tasks]
asv-build = { cmd = "python -m asv machine --machine {{ MACHINE }} --yes && python -m asv run --show-stderr -v --machine {{ MACHINE }} {{ EXTRA_ARGS }}", cwd = "asv_benchmarks", args = [{ arg = "MACHINE", default = "MacOS-M1" }, { arg = "EXTRA_ARGS", default = "" }] }
asv-publish = { cmd = "python -m asv publish", cwd = "asv_benchmarks" }
asv-preview = { cmd = "python -m asv preview", cwd = "asv_benchmarks", depends-on = ["asv-publish"] }

[tool.pixi.feature.test.tasks]
test = "pytest"
test-coverage = { cmd = "rm -rf .coverage && pytest --cov-report {{ FMT }} --cov={{ PACKAGE }}", args = [{ arg = "FMT", default = "html" }, { arg = "PACKAGE", default = "fastcan" }] }

[tool.pixi.feature.build.tasks]
build-wheel = "rm -rf dist && python -m build -wnx -Cinstall-args=--tags=runtime,python-runtime,devel"
build-sdist = "rm -rf dist && python -m build --sdist"
rebuild = "rm -rf build && pip install --no-deps --force-reinstall -e ."

[tool.pixi.feature.static.tasks]
fmt = "ruff format"
lint = "ruff check . --fix"
cython-lint = { cmd = "cython-lint .", cwd = "fastcan" }
type = { cmd = "mypy . --ignore-missing-imports", cwd = "fastcan" }
spell = "codespell fastcan"

[tool.pixi.feature.docs.tasks]
doc = { cmd = "{{ SPHINXBUILD }} -M {{ CMD }} {{ SOURCEDIR }} {{ BUILDDIR }} {{ SPHINXOPTS }} --fail-on-warning", cwd = "doc", args = [{ arg = "SPHINXBUILD", default = "sphinx-build" }, { arg = "CMD", default = "html" }, { arg = "SOURCEDIR", default = "." }, { arg = "BUILDDIR", default = "_build" }, { arg = "SPHINXOPTS", default = "" }] }
doc-clean = { cmd = "rm -rf {{ BUILDDIR }} generated auto_examples jupyterlite_contents .jupyterlite.doit.db _contents _output .cache", cwd = "doc", args = [{ arg = "BUILDDIR", default = "_build" }] }
doc-deploy = { cmd = "python -m http.server" , cwd = "doc/_build/html" }
doc-plantuml = { cmd = "plantuml -tsvg {{ SOURCE }} -o {{ OUTPUT }}", cwd = "doc", args = [{ arg = "SOURCE", default = "diagram.puml" }, { arg = "OUTPUT", default = "_build" }] }
# The setting (pixi config set --local run-post-link-scripts insecure) is required before install the environment,
# otherwise graphviz will not generate its plugin config. See:
# https://github.com/prefix-dev/pixi/blob/8aad97b5ac6482cdf0d3167fdaf0cb26328cc9c4/CHANGELOG.md?plain=1#L899
doc-plantuml-test = "plantuml -testdot"
doc-jupyterlite-debug = { cmd = "jupyter-lite build --debug --output-dir {{ OUTPUT }}", cwd = "doc", args = [{ arg = "OUTPUT", default = "_output" }] }


[tool.pixi.feature.nogil.tasks]
nogil-h = "python -Xgil=0 -m timeit -n 5 -s 'import numpy as np; from fastcan import FastCan; X = np.random.rand(3000, 100); y = np.random.rand(3000, 20)' 's = FastCan(100, verbose=0).fit(X, y)'"
nogil-eta = "python -Xgil=0 -m timeit -n 5 -s 'import numpy as np; from fastcan import FastCan; X = np.random.rand(3000, 100); y = np.random.rand(3000, 20)' 's = FastCan(100, eta=True, verbose=0).fit(X, y)'"

[tool.pixi.feature.wasm.tasks]
emsdk-clone = "bash -c '[ -d emsdk ] || git clone https://github.com/emscripten-core/emsdk.git emsdk'"
pyodide-compatible = "pyodide xbuildenv search -a"
pyodide-toolchain = { cmd = "LATEST_COMPATIBLE=$(pyodide xbuildenv search -a | grep '│ Yes' | head -n 1 | awk -F '│' '{print $2}' | xargs) && pyodide xbuildenv install $LATEST_COMPATIBLE" }
emsdk-setup = { cmd = "PYODIDE_EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version) && ./emsdk install $PYODIDE_EMSCRIPTEN_VERSION && ./emsdk activate $PYODIDE_EMSCRIPTEN_VERSION", cwd = "emsdk", depends-on = ["emsdk-clone", "pyodide-toolchain"] }
pyodide-build = { cmd = "bash -c 'source emsdk/emsdk_env.sh && pyodide build'", depends-on = ["emsdk-setup"] }
pyodide-create-recipe = "rm -rf packages && pyodide skeleton pypi fastcan"
pyodide-build-recipe = { cmd = "rm -rf dist && bash -c 'source emsdk/emsdk_env.sh && pyodide build-recipes fastcan --install'", depends-on = ["emsdk-setup"] }
pyodide-download = '''bash -c "[ -d pyodide ] || (LATEST_TAG=$(curl -s https://api.github.com/repos/pyodide/pyodide/releases/latest | grep \"tag_name\" | cut -d \" -f4) && curl -L https://github.com/pyodide/pyodide/releases/download/${LATEST_TAG}/pyodide-${LATEST_TAG}.tar.bz2 | tar -xjf -)"'''
pyodide-test-recipe = { cmd = "mv ../dist/* . && python -m http.server --directory .", cwd = "pyodide", depends-on = ["pyodide-download", "pyodide-build-recipe"] }

[tool.pixi.environments]
dev = ["test", "build", "jupyter", "asv"]
docs = ["docs"]
static = { features = ["static"], no-default-feature = true }
nogil = { features = ["nogil"], no-default-feature = true }
wasm = { features = ["wasm"], no-default-feature = true }

[tool.pytest.ini_options]
testpaths = [
"./tests",
Expand Down