Spaces:
Running
Running
MilesCranmer
commited on
Commit
•
24a4349
1
Parent(s):
673e8d5
Test that we can use development version of backend
Browse files- .github/workflows/CI.yml +21 -0
- pysr/_cli/main.py +5 -2
- pysr/test/__init__.py +2 -0
- pysr/test/generate_dev_juliapkg.py +17 -0
- pysr/test/test_dev.py +55 -0
- pysr/test/test_dev_pysr.dockerfile +57 -0
.github/workflows/CI.yml
CHANGED
@@ -94,6 +94,27 @@ jobs:
|
|
94 |
COVERALLS_PARALLEL: true
|
95 |
run: coveralls --service=github
|
96 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
conda_test:
|
98 |
runs-on: ${{ matrix.os }}
|
99 |
defaults:
|
|
|
94 |
COVERALLS_PARALLEL: true
|
95 |
run: coveralls --service=github
|
96 |
|
97 |
+
dev_install:
|
98 |
+
runs-on: ${{ matrix.os }}
|
99 |
+
strategy:
|
100 |
+
matrix:
|
101 |
+
os: ['ubuntu-latest']
|
102 |
+
python-version: ['3.11']
|
103 |
+
julia-version: ['1']
|
104 |
+
include:
|
105 |
+
- os: ubuntu-latest
|
106 |
+
python-version: '3.7'
|
107 |
+
julia-version: '1.6'
|
108 |
+
steps:
|
109 |
+
- uses: actions/checkout@v4
|
110 |
+
- uses: actions/setup-python@v5
|
111 |
+
- name: "Install PySR"
|
112 |
+
run: |
|
113 |
+
python -m pip install --upgrade pip
|
114 |
+
pip install .
|
115 |
+
- name: "Run development test"
|
116 |
+
run: PYSR_TEST_JULIA_VERSION=${{ matrix.julia-version }} PYSR_TEST_PYTHON_VERSION=${{ matrix.python-version }} python -m pysr test dev
|
117 |
+
|
118 |
conda_test:
|
119 |
runs-on: ${{ matrix.os }}
|
120 |
defaults:
|
pysr/_cli/main.py
CHANGED
@@ -5,6 +5,7 @@ import click
|
|
5 |
from ..test import (
|
6 |
get_runtests_cli,
|
7 |
runtests,
|
|
|
8 |
runtests_jax,
|
9 |
runtests_startup,
|
10 |
runtests_torch,
|
@@ -44,7 +45,7 @@ def _install(julia_project, quiet, precompile):
|
|
44 |
)
|
45 |
|
46 |
|
47 |
-
TEST_OPTIONS = {"main", "jax", "torch", "cli", "startup"}
|
48 |
|
49 |
|
50 |
@pysr.command("test")
|
@@ -52,7 +53,7 @@ TEST_OPTIONS = {"main", "jax", "torch", "cli", "startup"}
|
|
52 |
def _tests(tests):
|
53 |
"""Run parts of the PySR test suite.
|
54 |
|
55 |
-
Choose from main, jax, torch, cli, and startup. You can give multiple tests, separated by commas.
|
56 |
"""
|
57 |
for test in tests.split(","):
|
58 |
if test == "main":
|
@@ -64,6 +65,8 @@ def _tests(tests):
|
|
64 |
elif test == "cli":
|
65 |
runtests_cli = get_runtests_cli()
|
66 |
runtests_cli()
|
|
|
|
|
67 |
elif test == "startup":
|
68 |
runtests_startup()
|
69 |
else:
|
|
|
5 |
from ..test import (
|
6 |
get_runtests_cli,
|
7 |
runtests,
|
8 |
+
runtests_dev,
|
9 |
runtests_jax,
|
10 |
runtests_startup,
|
11 |
runtests_torch,
|
|
|
45 |
)
|
46 |
|
47 |
|
48 |
+
TEST_OPTIONS = {"main", "jax", "torch", "cli", "dev", "startup"}
|
49 |
|
50 |
|
51 |
@pysr.command("test")
|
|
|
53 |
def _tests(tests):
|
54 |
"""Run parts of the PySR test suite.
|
55 |
|
56 |
+
Choose from main, jax, torch, cli, dev, and startup. You can give multiple tests, separated by commas.
|
57 |
"""
|
58 |
for test in tests.split(","):
|
59 |
if test == "main":
|
|
|
65 |
elif test == "cli":
|
66 |
runtests_cli = get_runtests_cli()
|
67 |
runtests_cli()
|
68 |
+
elif test == "dev":
|
69 |
+
runtests_dev()
|
70 |
elif test == "startup":
|
71 |
runtests_startup()
|
72 |
else:
|
pysr/test/__init__.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
from .test import runtests
|
2 |
from .test_cli import get_runtests as get_runtests_cli
|
|
|
3 |
from .test_jax import runtests as runtests_jax
|
4 |
from .test_startup import runtests as runtests_startup
|
5 |
from .test_torch import runtests as runtests_torch
|
@@ -10,4 +11,5 @@ __all__ = [
|
|
10 |
"runtests_torch",
|
11 |
"get_runtests_cli",
|
12 |
"runtests_startup",
|
|
|
13 |
]
|
|
|
1 |
from .test import runtests
|
2 |
from .test_cli import get_runtests as get_runtests_cli
|
3 |
+
from .test_dev import runtests as runtests_dev
|
4 |
from .test_jax import runtests as runtests_jax
|
5 |
from .test_startup import runtests as runtests_startup
|
6 |
from .test_torch import runtests as runtests_torch
|
|
|
11 |
"runtests_torch",
|
12 |
"get_runtests_cli",
|
13 |
"runtests_startup",
|
14 |
+
"runtests_dev",
|
15 |
]
|
pysr/test/generate_dev_juliapkg.py
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Example call:
|
2 |
+
## python3 generate_dev_juliapkg.py /pysr/pysr/juliapkg.json /srjl
|
3 |
+
import json
|
4 |
+
import sys
|
5 |
+
|
6 |
+
juliapkg_json = sys.argv[1]
|
7 |
+
path_to_srjl = sys.argv[2]
|
8 |
+
|
9 |
+
with open(juliapkg_json, "r") as f:
|
10 |
+
juliapkg = json.load(f)
|
11 |
+
|
12 |
+
del juliapkg["packages"]["SymbolicRegression"]["version"]
|
13 |
+
juliapkg["packages"]["SymbolicRegression"]["path"] = path_to_srjl
|
14 |
+
juliapkg["packages"]["SymbolicRegression"]["dev"] = True
|
15 |
+
|
16 |
+
with open(juliapkg_json, "w") as f:
|
17 |
+
json.dump(juliapkg, f, indent=4)
|
pysr/test/test_dev.py
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import subprocess
|
3 |
+
import unittest
|
4 |
+
from pathlib import Path
|
5 |
+
|
6 |
+
|
7 |
+
class TestDev(unittest.TestCase):
|
8 |
+
def test_simple_change_to_backend(self):
|
9 |
+
"""Test that we can use a development version of SymbolicRegression.jl"""
|
10 |
+
PYSR_TEST_JULIA_VERSION = os.environ.get("PYSR_TEST_JULIA_VERSION", "1.6")
|
11 |
+
PYSR_TEST_PYTHON_VERSION = os.environ.get("PYSR_TEST_PYTHON_VERSION", "3.9")
|
12 |
+
build_result = subprocess.run(
|
13 |
+
[
|
14 |
+
"docker",
|
15 |
+
"build",
|
16 |
+
"-t",
|
17 |
+
"pysr-dev",
|
18 |
+
"--build-arg",
|
19 |
+
f"JLVERSION={PYSR_TEST_JULIA_VERSION}",
|
20 |
+
"--build-arg",
|
21 |
+
f"PYVERSION={PYSR_TEST_PYTHON_VERSION}",
|
22 |
+
"-f",
|
23 |
+
"pysr/test/test_dev_pysr.dockerfile",
|
24 |
+
".",
|
25 |
+
],
|
26 |
+
env=os.environ,
|
27 |
+
cwd=Path(__file__).parent.parent.parent,
|
28 |
+
universal_newlines=True,
|
29 |
+
)
|
30 |
+
self.assertEqual(build_result.returncode, 0)
|
31 |
+
test_result = subprocess.run(
|
32 |
+
[
|
33 |
+
"docker",
|
34 |
+
"run",
|
35 |
+
"--rm",
|
36 |
+
"pysr-dev",
|
37 |
+
"python3",
|
38 |
+
"-c",
|
39 |
+
"from pysr import SymbolicRegression as SR; print(SR.__test_function())",
|
40 |
+
],
|
41 |
+
stdout=subprocess.PIPE,
|
42 |
+
stderr=subprocess.PIPE,
|
43 |
+
env=os.environ,
|
44 |
+
cwd=Path(__file__).parent.parent.parent,
|
45 |
+
)
|
46 |
+
self.assertEqual(test_result.returncode, 0)
|
47 |
+
self.assertEqual(test_result.stdout.decode("utf-8").strip(), "2.3")
|
48 |
+
|
49 |
+
|
50 |
+
def runtests():
|
51 |
+
suite = unittest.TestSuite()
|
52 |
+
loader = unittest.TestLoader()
|
53 |
+
suite.addTests(loader.loadTestsFromTestCase(TestDev))
|
54 |
+
runner = unittest.TextTestRunner()
|
55 |
+
return runner.run(suite)
|
pysr/test/test_dev_pysr.dockerfile
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# This dockerfile simulates a user installation that
|
2 |
+
# tries to manually edit SymbolicRegression.jl and
|
3 |
+
# use it from PySR.
|
4 |
+
|
5 |
+
ARG JLVERSION=1.9.4
|
6 |
+
ARG PYVERSION=3.11.6
|
7 |
+
ARG BASE_IMAGE=bullseye
|
8 |
+
|
9 |
+
FROM julia:${JLVERSION}-${BASE_IMAGE} AS jl
|
10 |
+
FROM python:${PYVERSION}-${BASE_IMAGE}
|
11 |
+
|
12 |
+
# Merge Julia image:
|
13 |
+
COPY --from=jl /usr/local/julia /usr/local/julia
|
14 |
+
ENV PATH="/usr/local/julia/bin:${PATH}"
|
15 |
+
|
16 |
+
WORKDIR /pysr
|
17 |
+
|
18 |
+
# Caches install (https://stackoverflow.com/questions/25305788/how-to-avoid-reinstalling-packages-when-building-docker-image-for-python-project)
|
19 |
+
ADD ./requirements.txt /pysr/requirements.txt
|
20 |
+
RUN pip3 install --no-cache-dir -r /pysr/requirements.txt
|
21 |
+
|
22 |
+
# Install PySR:
|
23 |
+
# We do a minimal copy so it doesn't need to rerun at every file change:
|
24 |
+
ADD ./pyproject.toml /pysr/pyproject.toml
|
25 |
+
ADD ./setup.py /pysr/setup.py
|
26 |
+
|
27 |
+
RUN mkdir /pysr/pysr
|
28 |
+
ADD ./pysr/*.py /pysr/pysr/
|
29 |
+
ADD ./pysr/juliapkg.json /pysr/pysr/juliapkg.json
|
30 |
+
|
31 |
+
RUN mkdir /pysr/pysr/_cli
|
32 |
+
ADD ./pysr/_cli/*.py /pysr/pysr/_cli/
|
33 |
+
|
34 |
+
RUN mkdir /pysr/pysr/test
|
35 |
+
|
36 |
+
RUN pip3 install --no-cache-dir .
|
37 |
+
|
38 |
+
# Now, we create a custom version of SymbolicRegression.jl
|
39 |
+
# First, we get the version from juliapkg.json:
|
40 |
+
RUN python3 -c 'import json; print(json.load(open("/pysr/pysr/juliapkg.json", "r"))["packages"]["SymbolicRegression"]["version"])' > /pysr/sr_version
|
41 |
+
|
42 |
+
# Remove any = or ^ or ~ from the version:
|
43 |
+
RUN cat /pysr/sr_version | sed 's/[\^=~]//g' > /pysr/sr_version_processed
|
44 |
+
|
45 |
+
# Now, we check out the version of SymbolicRegression.jl that PySR is using:
|
46 |
+
RUN git clone -b "v$(cat /pysr/sr_version_processed)" --single-branch https://github.com/MilesCranmer/SymbolicRegression.jl /srjl
|
47 |
+
|
48 |
+
# Edit SymbolicRegression.jl to create a new function.
|
49 |
+
# We want to put this function immediately after `module SymbolicRegression`:
|
50 |
+
RUN sed -i 's/module SymbolicRegression/module SymbolicRegression\n__test_function() = 2.3/' /srjl/src/SymbolicRegression.jl
|
51 |
+
|
52 |
+
# Edit PySR to use the custom version of SymbolicRegression.jl:
|
53 |
+
ADD ./pysr/test/generate_dev_juliapkg.py /generate_dev_juliapkg.py
|
54 |
+
RUN python3 /generate_dev_juliapkg.py /pysr/pysr/juliapkg.json /srjl
|
55 |
+
|
56 |
+
# Precompile
|
57 |
+
RUN python3 -c 'import pysr'
|