Skip to content

Commit 420ae56

Browse files
authored
Merge pull request #215 from lucasimi/develop
Improved CI
2 parents e1d0cd3 + b7a8fd7 commit 420ae56

12 files changed

Lines changed: 133 additions & 37 deletions

File tree

.flake8

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[flake8]
2+
max-line-length = 88
3+
extend-ignore = E203, W503
4+
exclude =
5+
docs

.github/workflows/test-bench.yml

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,61 @@ name: test-bench
33
on:
44
push:
55
branches:
6-
- develop
7-
- main
6+
- main
7+
pull_request:
8+
branches:
9+
- main
810

911
jobs:
10-
test-bench-job:
12+
test-bench-matrix-job:
1113
runs-on: ubuntu-latest
14+
strategy:
15+
matrix:
16+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
17+
include:
18+
- python-version: 3.8
19+
allow-failure: false
20+
- python-version: 3.9
21+
allow-failure: false
22+
- python-version: 3.10
23+
allow-failure: false
24+
- python-version: 3.11
25+
allow-failure: false
26+
- python-version: 3.12
27+
allow-failure: false
28+
- python-version: 3.13
29+
allow-failure: false
30+
continue-on-error: ${{ matrix.allow-failure }}
31+
name: Python ${{ matrix.python-version }} bench tests
32+
1233
steps:
1334
- name: Check out repository code
1435
uses: actions/checkout@v4
36+
37+
- name: Cache pip
38+
uses: actions/cache@v4
39+
with:
40+
path: ~/.cache/pip
41+
key: ${{ runner.os }}-pip-${{ hashFiles('pyproject.toml') }}
42+
restore-keys: |
43+
${{ runner.os }}-pip-
44+
1545
- name: Install Python
1646
uses: actions/setup-python@v5
1747
with:
18-
python-version: '3.10'
48+
python-version: ${{ matrix.python-version }}
49+
1950
- name: Install dependencies
2051
run: |
2152
python -m pip install -e .[dev]
53+
2254
- name: Run benchmarks
2355
run: |
2456
python -m unittest discover -s tests -p 'test_bench_*.py'
57+
58+
test-bench-job:
59+
needs: test-bench-matrix-job
60+
runs-on: ubuntu-latest
61+
steps:
62+
- name: test-bench-job
63+
run: echo "All bench tests passed."

.github/workflows/test-unit.yml

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,68 @@ name: test-unit
22

33
on:
44
push:
5-
branches:
6-
- develop
7-
- main
5+
branches:
6+
- '**'
7+
pull_request:
8+
branches:
9+
- '**'
810

911
jobs:
10-
test-unit-job:
11-
runs-on: ubuntu-latest
12+
test-unit-matrix-job:
13+
runs-on: ubuntu-22.04
14+
strategy:
15+
matrix:
16+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
17+
include:
18+
- python-version: 3.8
19+
allow-failure: false
20+
- python-version: 3.9
21+
allow-failure: false
22+
- python-version: 3.10
23+
allow-failure: false
24+
- python-version: 3.11
25+
allow-failure: false
26+
- python-version: 3.12
27+
allow-failure: false
28+
- python-version: 3.13
29+
allow-failure: false
30+
continue-on-error: ${{ matrix.allow-failure }}
31+
name: Python ${{ matrix.python-version }} unit tests
32+
1233
steps:
1334
- name: Check out repository code
1435
uses: actions/checkout@v4
36+
37+
- name: Cache pip
38+
uses: actions/cache@v4
39+
with:
40+
path: ~/.cache/pip
41+
key: ${{ runner.os }}-pip-${{ hashFiles('pyproject.toml') }}
42+
restore-keys: |
43+
${{ runner.os }}-pip-
44+
1545
- name: Install Python
1646
uses: actions/setup-python@v5
1747
with:
18-
python-version: '3.10'
48+
python-version: ${{ matrix.python-version }}
49+
1950
- name: Install dependencies
2051
run: |
2152
python -m pip install -e .[dev]
53+
2254
- name: Run tests and code coverage
2355
run: |
2456
coverage run --source=src -m unittest discover -s tests -p 'test_unit_*.py'
2557
coverage report -m
58+
2659
- name: Upload coverage reports to Codecov
2760
uses: codecov/codecov-action@v4
2861
env:
2962
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
63+
64+
test-unit-job:
65+
needs: test-unit-matrix-job
66+
runs-on: ubuntu-latest
67+
steps:
68+
- name: test-unit-job
69+
run: echo "All unit tests passed."

CONTRIBUTING.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ structures are welcome but must first be discussed in an issue, especially when
3030
it comes to performance critical parts. Please include supporting theoretical
3131
or experimental evidence for such contributions.
3232

33+
NB: Contributions from bots or fully automated AI agents are discouraged and
34+
will be discarded.
35+
3336
Follow these steps to contribute:
3437

3538
1. **Fork the Repository**.
@@ -108,12 +111,21 @@ removed whenever required by a new jump in major version.
108111
### Code Style
109112
110113
We follow [PEP 8](https://peps.python.org/pep-0008/) for Python code style.
111-
You can run a linter to check your code:
114+
You can run a linter to check your code. The dev dependencies of **tda-mapper**
115+
include `flake8`, `black` and `isort` to help you manage code style.
112116
113117
```bash
114118
flake8
115119
```
116120
121+
```bash
122+
black .
123+
```
124+
125+
```bash
126+
isort .
127+
```
128+
117129
### Documentation
118130
119131
Ensure that new features and APIs are documented in the code and that
@@ -123,6 +135,7 @@ To build the documentation locally:
123135
124136
```bash
125137
cd docs
138+
make clean
126139
make html
127140
```
128141

benchmarks/benchmark.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,14 @@ def run_gm(X, n, p):
7474
cover=gm.CubicalCover(n_intervals=n, overlap_frac=p),
7575
clusterer=TrivialEstimator(),
7676
)
77-
mapper_graph = pipe.fit_transform(X)
77+
pipe.fit_transform(X)
7878
t1 = time.time()
7979
return t1 - t0
8080

8181

8282
def run_tm(X, n, p):
8383
t0 = time.time()
84-
mapper_graph = tm.core.MapperAlgorithm(
84+
tm.core.MapperAlgorithm(
8585
cover=tm.cover.CubicalCover(
8686
n_intervals=n,
8787
overlap_frac=p,
@@ -99,7 +99,7 @@ def run_tm(X, n, p):
9999
def run_km(X, n, p):
100100
t0 = time.time()
101101
mapper = km.KeplerMapper(verbose=0)
102-
graph = mapper.map(
102+
mapper.map(
103103
lens=X,
104104
X=X,
105105
cover=km.Cover(n_cubes=n, perc_overlap=p),

docs/source/notebooks/digits.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
from sklearn.datasets import load_digits
4545
from sklearn.decomposition import PCA
4646

47-
from tdamapper.clustering import FailSafeClustering
4847
from tdamapper.cover import CubicalCover
4948
from tdamapper.learn import MapperAlgorithm
5049
from tdamapper.plot import MapperPlot

pyproject.toml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ classifiers = [
2020
"License :: OSI Approved :: Apache Software License",
2121
"Programming Language :: Python",
2222
"Programming Language :: Python :: 3",
23+
"Programming Language :: Python :: 3.8",
24+
"Programming Language :: Python :: 3.9",
25+
"Programming Language :: Python :: 3.10",
26+
"Programming Language :: Python :: 3.11",
27+
"Programming Language :: Python :: 3.12",
28+
"Programming Language :: Python :: 3.13",
2329
"Operating System :: OS Independent",
2430
]
2531
keywords = ["tda", "mapper", "topology", "topological data analysis"]
@@ -28,21 +34,21 @@ dependencies = [
2834
"matplotlib>=3.3.4,<4.0.0",
2935
"networkx>=2.5,<3.0.0",
3036
"igraph>=0.11.8,<0.12.0",
31-
"numba>=0.54,<0.60",
37+
"numba>=0.54,<0.62",
3238
"pyvis>=0.3.2,<0.4.0",
3339
"plotly>=6.0.1,<7.0.0",
3440
"joblib>=1.4.2,<2.0.0",
3541
]
36-
requires-python = ">=3.6"
42+
requires-python = ">=3.8"
3743

3844
[project.optional-dependencies]
3945
dev = [
4046
"coverage[toml]",
4147
"pandas",
4248
"scikit-learn<1.6.0",
43-
"flake8",
4449
"black[jupyter]",
45-
"isort"
50+
"isort",
51+
"flake8",
4652
]
4753

4854
[project.urls]
@@ -80,4 +86,3 @@ include_trailing_comma = true
8086
force_grid_wrap = 0
8187
combine_as_imports = true
8288
skip = ["venv", ".venv", "build", "dist"]
83-

tests/test_bench_cover.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,16 @@ def cover(self, vpt, X, r):
3838

3939
def run_bench(self, X, r, dist, vp, **kwargs):
4040
XX = np.array([[i] + [xi for xi in x] for i, x in enumerate(X)])
41-
d = lambda x, y: dist(x[1:], y[1:])
4241
t0 = time.time()
43-
vpt = vp(XX, metric=d, **kwargs)
42+
vpt = vp(XX, metric=lambda x, y: dist(x[1:], y[1:]), **kwargs)
4443
list(self.cover(vpt, XX, r))
4544
t1 = time.time()
4645
self.logger.info(f"time: {t1 - t0}")
4746

4847
def test_cover_random(self):
4948
for r in [1.0, 10.0, 100.0]:
5049
for n in [100, 1000, 10000]:
51-
self.logger.info(f"============ Cover Bench Random ==========")
50+
self.logger.info("============ Cover Bench Random ==========")
5251
self.logger.info(f"[n: {n}, r: {r}]")
5352
X = dataset(num=n)
5453
self.logger.info(">>>>>>> HVPT >>>>>>")
@@ -66,7 +65,7 @@ def test_cover_digits(self):
6665
X, _ = load_digits(return_X_y=True)
6766
# X = PCA(n_components=3).fit_transform(X)
6867
for r in [1.0, 10.0, 100.0]:
69-
self.logger.info(f"======= Cover Bench Digits =======")
68+
self.logger.info("======= Cover Bench Digits =======")
7069
self.logger.info(f"[r: {r}]")
7170
self.logger.info(">>>>>>> HVPT >>>>>>")
7271
self.run_bench(X, r, dist, HVPT, leaf_radius=r, pivoting="random")

tests/test_bench_vptree.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,14 @@ def _test_ball_search_naive(self, data, name):
7777
d(np.array([0.0]), np.array([0.0])) # jit-compile numba
7878
t0 = time()
7979
for val in data:
80-
neigh = [x for x in data if d(val, x) <= self.eps]
80+
[x for x in data if d(val, x) <= self.eps]
8181
t1 = time()
8282
self.logger.info(f"{name}: {t1 - t0}")
8383

8484
def _test_ball_search(self, data, name, vpt):
8585
t0 = time()
8686
for val in data:
87-
neigh = vpt.ball_search(val, self.eps)
87+
vpt.ball_search(val, self.eps)
8888
t1 = time()
8989
self.logger.info(f"{name}: {t1 - t0}")
9090

@@ -94,13 +94,13 @@ def _test_knn_search_naive(self, data, name):
9494
t0 = time()
9595
for val in data:
9696
data.sort(key=lambda x: d(x, val))
97-
neigh = [x for x in data[: self.k]]
97+
[x for x in data[: self.k]]
9898
t1 = time()
9999
self.logger.info(f"{name}: {t1 - t0}")
100100

101101
def _test_knn_search(self, data, name, vpt):
102102
t0 = time()
103103
for val in data:
104-
neigh = vpt.knn_search(val, self.k)
104+
vpt.knn_search(val, self.k)
105105
t1 = time()
106106
self.logger.info(f"{name}: {t1 - t0}")

tests/test_unit_learn.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,11 @@
22

33
import networkx as nx
44
import numpy as np
5-
from sklearn.cluster import DBSCAN
65
from sklearn.utils.estimator_checks import check_estimator
76

87
from tdamapper.core import TrivialClustering, TrivialCover
98
from tdamapper.cover import BallCover
10-
from tdamapper.learn import (
11-
MapperAlgorithm,
12-
MapperClustering,
13-
)
9+
from tdamapper.learn import MapperAlgorithm, MapperClustering
1410

1511

1612
def euclidean(x, y):

0 commit comments

Comments
 (0)