From 644869b0dce0baf54e168ad6ed504ba851534706 Mon Sep 17 00:00:00 2001 From: kngwyu Date: Fri, 11 Oct 2024 01:48:20 +0900 Subject: [PATCH] Use uv instead of nox and pip-tools --- .github/workflows/tests.yml | 12 ++-- .gitignore | 1 + Makefile | 32 ++++++++++ noxfile.py | 119 ------------------------------------ pyproject.toml | 12 +++- requirements/bench.in | 3 - requirements/cuda11.in | 2 - requirements/cuda12.in | 2 - requirements/format.in | 2 - requirements/jupyter.in | 12 ---- requirements/lint.in | 2 - requirements/scripts.in | 3 - requirements/smoke.in | 4 -- requirements/tests.in | 2 - setup-jupterlab | 16 ----- src/emevo/analysis/tree.py | 4 +- tests/test_tree.py | 8 +-- 17 files changed, 54 insertions(+), 182 deletions(-) create mode 100644 Makefile delete mode 100644 noxfile.py delete mode 100644 requirements/bench.in delete mode 100644 requirements/cuda11.in delete mode 100644 requirements/cuda12.in delete mode 100644 requirements/format.in delete mode 100644 requirements/jupyter.in delete mode 100644 requirements/lint.in delete mode 100644 requirements/scripts.in delete mode 100644 requirements/smoke.in delete mode 100644 requirements/tests.in delete mode 100755 setup-jupterlab diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f463c723..b5728ebd 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,11 +29,9 @@ jobs: - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - - name: Update pip and install nox - run: | - pip install --upgrade pip - pip install nox - - name: Run pip compile - run: nox --session=compile + - name: Install uv + run: pip install uv + - name: Sync + run: make sync - name: Run tests - run: nox --session=${{ matrix.nox }} --python=${{ matrix.python }} + run: make test diff --git a/.gitignore b/.gitignore index 3203e0fa..7094808c 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ pyrightconfig.json *.eqx *.parquet *.npz +uv.lock diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..0533248b --- /dev/null +++ b/Makefile @@ -0,0 +1,32 @@ +.PHONY: test lint + +CUDA_AVAILABLE := $(shell command -v nvcc >/dev/null 2>&1 && echo 1 || echo 0) + +test: + uv run pytest + +lint: + uvx ruff check + uvx black src/emevo tests --check + uvx isort src/emevo tests --check + + +format: + uvx black src/emevo tests + uvx isort src/emevo tests + + +publish: + uv build + uvx twine upload dist/* + + +sync: +ifeq ($(CUDA_AVAILABLE),1) + uv sync --extra=analysis --extra=cuda12 +else + uv sync --extra=analysis +endif + + +all: test lint diff --git a/noxfile.py b/noxfile.py deleted file mode 100644 index 9518f9f6..00000000 --- a/noxfile.py +++ /dev/null @@ -1,119 +0,0 @@ -from __future__ import annotations - -import pathlib -import shutil -import subprocess - -import nox - -SOURCES = ["src/emevo", "tests", "smoke-tests", "experiments", "scripts"] - - -def _sync(session: nox.Session, requirements: str) -> None: - if ( - not session._runner.global_config.no_install - or session._runner.global_config.install_only - ): - session.install("pip-tools") - session.run("pip-sync", requirements) - - -@nox.session(reuse_venv=True) -def compile(session: nox.Session) -> None: - session.install("pip-tools") - requirements_dir = pathlib.Path("requirements") - has_cuda = shutil.which("ptxas") is not None - if has_cuda: - nvcc_out = subprocess.run(["nvcc", "--version"], capture_output=True) - is_cuda_12 = "cuda_12" in nvcc_out.stdout.decode("utf-8") - else: - nvcc_out = "" - is_cuda_12 = False - - def _run_pip_compile(in_file: str, out_name: str) -> None: - # If -k {out_name} is given, skip compiling - if "-k" in session.posargs and out_name not in session.posargs: - return - - out_file = f"requirements/{out_name}.txt" - args = ["pip-compile"] - if has_cuda and out_name not in ["format", "lint"]: - if is_cuda_12: - args.append("requirements/cuda12.in") - else: - args.append("requirements/cuda11.in") - args += [ - in_file, - "--output-file", - out_file, - "--resolver=backtracking", - ] - if "--upgrade" in session.posargs: - args.append("--upgrade") - session.run(*args) - - for path in requirements_dir.glob("*.in"): - if "cuda" not in path.stem: - _run_pip_compile(path.as_posix(), path.stem) - - -@nox.session(reuse_venv=True) -def bench(session: nox.Session) -> None: - _sync(session, "requirements/bench.txt") - session.run("pytest", "benches", *session.posargs) - - -@nox.session(reuse_venv=True) -def format(session: nox.Session) -> None: - _sync(session, "requirements/format.txt") - session.run("black", *SOURCES) - session.run("isort", *SOURCES) - - -@nox.session(reuse_venv=True, python=["3.10", "3.11", "3.12"]) -def lint(session: nox.Session) -> None: - _sync(session, "requirements/lint.txt") - session.run("ruff", "check", *SOURCES) - session.run("black", *SOURCES, "--check") - session.run("isort", *SOURCES, "--check") - - -@nox.session(reuse_venv=True) -def lab(session: nox.Session) -> None: - _sync(session, "requirements/jupyter.txt") - session.run("python", "-m", "ipykernel", "install", "--user", "--name", "emevo-lab") - session.run("jupyter", "lab", *session.posargs) - - -@nox.session(reuse_venv=True) -def ipython(session: nox.Session) -> None: - _sync(session, "requirements/jupyter.txt") - session.run("python", "-m", "IPython") - - -@nox.session(reuse_venv=True) -def script(session: nox.Session) -> None: - """Run scripts""" - _sync(session, "requirements/scripts.txt") - DEFAULT = "scripts/plot_bd_models.py" - if 0 < len(session.posargs) and session.posargs[0].endswith(".py"): - session.run("python", *session.posargs) - else: - session.run("python", DEFAULT, *session.posargs) - - -@nox.session(reuse_venv=True) -def smoke(session: nox.Session) -> None: - """Run smoke tests""" - _sync(session, "requirements/smoke.txt") - DEFAULT = "smoke-tests/circle_loop.py" - if 0 < len(session.posargs) and session.posargs[0].endswith(".py"): - session.run("python", *session.posargs) - else: - session.run("python", DEFAULT, *session.posargs) - - -@nox.session(reuse_venv=True, python=["3.10", "3.11", "3.12"]) -def tests(session: nox.Session) -> None: - _sync(session, "requirements/tests.txt") - session.run("pytest", "tests", *session.posargs) diff --git a/pyproject.toml b/pyproject.toml index 4a83353d..9ea82e08 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,8 +38,10 @@ analysis = [ "matplotlib >= 3.0", "networkx >= 3.0", "polars >= 0.20", - "PySide6 >= 6.5", ] +# Meta feature to install CUDA12 jax +cuda12 = ["jax[cuda12]"] +widget = ["PySide6 >= 6.5"] video = ["imageio-ffmpeg >= 0.4"] [project.readme] @@ -76,4 +78,10 @@ ignore = ["B905"] # For typer "experiments/*.py" = ["B008", "UP006", "UP007"] "smoke-tests/*.py" = ["B008", "UP006", "UP007"] -"scripts/*.py" = ["UP006", "UP035", "UP007"] \ No newline at end of file +"scripts/*.py" = ["UP006", "UP035", "UP007"] + + +[tool.uv] +dev-dependencies = [ + "pytest>=8.3.3", +] diff --git a/requirements/bench.in b/requirements/bench.in deleted file mode 100644 index 3e3a2f82..00000000 --- a/requirements/bench.in +++ /dev/null @@ -1,3 +0,0 @@ --e . -pygal -pytest-benchmark \ No newline at end of file diff --git a/requirements/cuda11.in b/requirements/cuda11.in deleted file mode 100644 index d4160109..00000000 --- a/requirements/cuda11.in +++ /dev/null @@ -1,2 +0,0 @@ ---find-links https://storage.googleapis.com/jax-releases/jax_cuda_releases.html -jax[cuda11_pip] \ No newline at end of file diff --git a/requirements/cuda12.in b/requirements/cuda12.in deleted file mode 100644 index a7bd282b..00000000 --- a/requirements/cuda12.in +++ /dev/null @@ -1,2 +0,0 @@ ---find-links https://storage.googleapis.com/jax-releases/jax_cuda_releases.html -jax[cuda12_pip] \ No newline at end of file diff --git a/requirements/format.in b/requirements/format.in deleted file mode 100644 index 3cfb3fc0..00000000 --- a/requirements/format.in +++ /dev/null @@ -1,2 +0,0 @@ -black -isort \ No newline at end of file diff --git a/requirements/jupyter.in b/requirements/jupyter.in deleted file mode 100644 index 9c8766dd..00000000 --- a/requirements/jupyter.in +++ /dev/null @@ -1,12 +0,0 @@ --r format.in --e .[analysis,video] -celluloid -ipympl -ipywidgets -jupyterlab -jupyterlab_code_formatter -jupyterlab-lsp -matplotlib -polars -pygraphviz -seaborn \ No newline at end of file diff --git a/requirements/lint.in b/requirements/lint.in deleted file mode 100644 index ca5245f0..00000000 --- a/requirements/lint.in +++ /dev/null @@ -1,2 +0,0 @@ --r format.in -ruff \ No newline at end of file diff --git a/requirements/scripts.in b/requirements/scripts.in deleted file mode 100644 index fdd6aec5..00000000 --- a/requirements/scripts.in +++ /dev/null @@ -1,3 +0,0 @@ --e . -matplotlib -typer \ No newline at end of file diff --git a/requirements/smoke.in b/requirements/smoke.in deleted file mode 100644 index 05545803..00000000 --- a/requirements/smoke.in +++ /dev/null @@ -1,4 +0,0 @@ --e .[video] -py-spy # for profiling -tqdm -typer \ No newline at end of file diff --git a/requirements/tests.in b/requirements/tests.in deleted file mode 100644 index cc4db9b8..00000000 --- a/requirements/tests.in +++ /dev/null @@ -1,2 +0,0 @@ --e .[analysis] -pytest \ No newline at end of file diff --git a/setup-jupterlab b/setup-jupterlab deleted file mode 100755 index 6f0c23e3..00000000 --- a/setup-jupterlab +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -set -eo pipefail - -if [[ ! -d .lab-venv ]]; then - mkdir .lab-venv - python3 -m venv .lab-venv -fi - -if [[ ! -f requirements/jupyter.txt ]]; then - nox -s compile -- -k jupyter -fi - -source .lab-venv/bin/activate -pip install pip-tools -pip-sync requirements/jupyter.txt -python -m ipykernel install --user --name emevo-lab diff --git a/src/emevo/analysis/tree.py b/src/emevo/analysis/tree.py index 48de360b..70036724 100644 --- a/src/emevo/analysis/tree.py +++ b/src/emevo/analysis/tree.py @@ -63,7 +63,7 @@ def parent(self) -> Node | None: @functools.cached_property def n_total_children(self) -> int: total = 0 - for child, _ in self.children: + for child in self.children: total += 1 + child.n_total_children return total @@ -87,7 +87,7 @@ def traverse( ) -> Iterable[Node]: if include_self and preorder: yield self - for child, _ in self.children: + for child in self.children: yield from child.traverse(preorder) if include_self and not preorder: yield self diff --git a/tests/test_tree.py b/tests/test_tree.py index 9fbe2e5f..cac2c476 100644 --- a/tests/test_tree.py +++ b/tests/test_tree.py @@ -22,7 +22,7 @@ def treedef() -> list[tuple[int, int]]: def test_from_iter(treedef: list[tuple[int, int]]) -> None: - tree = Tree.from_iter(treedef) + tree = Tree.from_iter(treedef, root_idx=-1) preorder = list(map(operator.attrgetter("index"), tree.traverse(preorder=True))) assert preorder == [0, 1, 3, 4, 5, 8, 9, 2, 6, 7] postorder = list(map(operator.attrgetter("index"), tree.traverse(preorder=False))) @@ -33,7 +33,7 @@ def test_from_iter(treedef: list[tuple[int, int]]) -> None: def test_split(treedef: list[tuple[int, int]]) -> None: tree = Tree.from_iter(treedef) sp1 = tree.split(min_group_size=3) - assert len(sp1) == 10 + assert len(sp1) == 4 assert sp1[0] == 0 for idx in [1, 3, 4]: assert sp1[idx] == 1 @@ -43,7 +43,7 @@ def test_split(treedef: list[tuple[int, int]]) -> None: assert sp1[idx] == 3 sp2 = tree.split(min_group_size=4) - assert len(sp2) == 10 + assert len(sp2) == 4 for idx in [0, 2, 6, 7]: assert sp2[idx] == 0 for idx in [1, 3, 4, 5, 8, 9]: @@ -63,7 +63,7 @@ def test_multilabel_split(treedef: list[tuple[int, int]]) -> None: def test_from_table() -> None: table = pq.read_table(ASSET_DIR.joinpath("profile_and_rewards.parquet")) tree = Tree.from_table(table, 20) - for root, _ in tree.root.children: + for root in tree.root.children: assert root.index < 10 assert root.birth_time is not None for node in root.traverse():