Skip to content

Commit a0c03a5

Browse files
authored
Modernize the repo to support newer PyTorch versions (#49)
* Modernize for PyTorch 2.6 * Modernize package metadata and builds * Modernize continuous integration * Publish releases through PyPI trusted publishing * Use stable equivalent scalar expressions * Reduce tensor temporaries in manifold operations
1 parent 85e517a commit a0c03a5

39 files changed

Lines changed: 590 additions & 1052 deletions

‎.github/scripts/check_dist.py‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import argparse
2+
from email.parser import BytesParser
3+
from pathlib import Path, PurePosixPath
4+
import tarfile
5+
import zipfile
6+
7+
8+
def parse_args():
9+
parser = argparse.ArgumentParser()
10+
parser.add_argument("dist", nargs="+", type=Path)
11+
parser.add_argument("--tag")
12+
return parser.parse_args()
13+
14+
15+
def archive_names(path):
16+
if path.suffix == ".whl":
17+
with zipfile.ZipFile(path) as archive:
18+
return archive.namelist()
19+
with tarfile.open(path) as archive:
20+
return archive.getnames()
21+
22+
23+
def wheel_version(path):
24+
with zipfile.ZipFile(path) as archive:
25+
metadata = next(
26+
name for name in archive.namelist() if name.endswith(".dist-info/METADATA")
27+
)
28+
message = BytesParser().parsebytes(archive.read(metadata))
29+
return message["Version"]
30+
31+
32+
def main():
33+
args = parse_args()
34+
wheels = [path for path in args.dist if path.suffix == ".whl"]
35+
sdists = [path for path in args.dist if path.name.endswith(".tar.gz")]
36+
if len(wheels) != 1 or len(sdists) != 1:
37+
raise SystemExit("Expected exactly one wheel and one sdist")
38+
39+
for path in args.dist:
40+
for name in archive_names(path):
41+
parts = PurePosixPath(name).parts
42+
if "examples" in parts or "test" in parts:
43+
raise SystemExit(f"Unexpected path in {path.name}: {name}")
44+
45+
version = wheel_version(wheels[0])
46+
if f"-{version}.tar.gz" not in sdists[0].name:
47+
raise SystemExit("Wheel and sdist versions do not match")
48+
if args.tag is not None and args.tag.removeprefix("v") != version:
49+
raise SystemExit(f"Tag {args.tag!r} does not match package version {version!r}")
50+
51+
print(f"Validated GeoTorch {version} wheel and sdist")
52+
53+
54+
if __name__ == "__main__":
55+
main()

‎.github/workflows/build.yml‎

Lines changed: 89 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,102 @@
1-
name: build
1+
name: CI
22

33
on:
44
push:
5-
branches: [ master ]
5+
branches: [master]
66
pull_request:
7-
branches: [ '*' ]
7+
8+
concurrency:
9+
group: ci-${{ github.workflow }}-${{ github.ref }}
10+
cancel-in-progress: true
11+
12+
permissions:
13+
contents: read
814

915
jobs:
10-
build:
16+
lint:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
20+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
21+
with:
22+
python-version: "3.14"
23+
cache: pip
24+
- run: python -m pip install --upgrade pip
25+
- run: python -m pip install ".[dev]"
26+
- run: black --check --diff .
27+
- run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
28+
29+
linux:
30+
runs-on: ubuntu-latest
31+
strategy:
32+
fail-fast: false
33+
matrix:
34+
include:
35+
- python: "3.10"
36+
torch: "torch==2.6.*"
37+
- python: "3.12"
38+
torch: "torch"
39+
- python: "3.14"
40+
torch: "torch"
41+
steps:
42+
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
43+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
44+
with:
45+
python-version: ${{ matrix.python }}
46+
cache: pip
47+
- run: python -m pip install --upgrade pip
48+
- run: python -m pip install "${{ matrix.torch }}" pytest pytest-xdist
49+
- run: python -m pip install --no-deps -e .
50+
- run: python -m pytest -s --tb=short -n32 test
1151

52+
os-smoke:
1253
runs-on: ${{ matrix.os }}
1354
strategy:
55+
fail-fast: false
1456
matrix:
15-
python-version: [3.6, 3.7, 3.8]
1657
os: [ubuntu-latest, macos-latest, windows-latest]
58+
steps:
59+
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
60+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
61+
with:
62+
python-version: "3.13"
63+
cache: pip
64+
- run: python -m pip install --upgrade pip
65+
- run: python -m pip install ".[test]"
66+
- run: python -m pytest -s --tb=short -n32 test
67+
68+
coverage:
69+
runs-on: ubuntu-latest
70+
steps:
71+
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
72+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
73+
with:
74+
python-version: "3.14"
75+
cache: pip
76+
- run: python -m pip install --upgrade pip
77+
- run: python -m pip install ".[test]" pytest-cov
78+
- run: python -m pytest -s --tb=short -n32 --cov=geotorch --cov-report=xml test
79+
- uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
80+
with:
81+
token: ${{ secrets.CODECOV_TOKEN }}
1782

83+
package:
84+
runs-on: ubuntu-latest
1885
steps:
19-
- uses: actions/checkout@v2
20-
- name: Set up Python ${{ matrix.python-version }}
21-
uses: actions/setup-python@v2
22-
with:
23-
python-version: ${{ matrix.python-version }}
24-
25-
- name: Install dependencies others
26-
if: ${{ matrix.os != 'windows-latest' }}
27-
run: |
28-
python -m pip install --upgrade pip
29-
pip install .[dev]
30-
31-
# Windows is treated differently, as PyTorch is not uploaded to Pypi atm
32-
- name: Install dependencies windows
33-
if: ${{ matrix.os == 'windows-latest' }}
34-
run: |
35-
python -m pip install --upgrade pip
36-
pip install torch===1.10.0+cpu -f https://download.pytorch.org/whl/torch_stable.html
37-
pip install .[dev]
38-
39-
- name: Lint with flake8
40-
run: |
41-
# stop the build if there are Python syntax errors or undefined names
42-
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
43-
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
44-
flake8 . --count --exit-zero --max-complexity=12 --max-line-length=127 --statistics
45-
46-
- name: Lint with Black
47-
run: |
48-
black --check --diff .
49-
50-
- name: Test with pytest
51-
run: |
52-
pytest test
86+
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
87+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
88+
with:
89+
python-version: "3.14"
90+
cache: pip
91+
- run: python -m pip install --upgrade pip
92+
- run: python -m pip install build pytest pytest-xdist torch twine
93+
- run: python -m build
94+
- run: python -m twine check dist/*
95+
- run: python .github/scripts/check_dist.py dist/*
96+
- name: Test installed wheel
97+
run: |
98+
python -m venv --system-site-packages /tmp/geotorch-wheel
99+
/tmp/geotorch-wheel/bin/python -m pip install --no-deps dist/*.whl
100+
cp -R test /tmp/geotorch-tests
101+
cd /tmp
102+
/tmp/geotorch-wheel/bin/python -m pytest -s --tb=short -n32 geotorch-tests

‎.github/workflows/coverage.yml‎

Lines changed: 0 additions & 35 deletions
This file was deleted.

‎.github/workflows/pypi.yml‎

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,54 @@
1-
name: Upload Python Package
1+
name: Publish to PyPI
22

33
on:
44
release:
5-
types: [created]
5+
types: [published]
6+
7+
permissions:
8+
contents: read
69

710
jobs:
8-
deploy:
11+
build:
12+
if: github.event.release.prerelease == false
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
16+
with:
17+
fetch-depth: 0
18+
ref: ${{ github.event.release.tag_name }}
19+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
20+
with:
21+
python-version: "3.14"
22+
cache: pip
23+
- name: Verify release source
24+
env:
25+
RELEASE_TAG: ${{ github.event.release.tag_name }}
26+
run: |
27+
test "$(git rev-parse HEAD)" = "$(git rev-list -n 1 "$RELEASE_TAG")"
28+
- run: python -m pip install --upgrade pip
29+
- run: python -m pip install build twine
30+
- run: python -m build
31+
- run: python -m twine check dist/*
32+
- name: Verify release artifacts
33+
env:
34+
RELEASE_TAG: ${{ github.event.release.tag_name }}
35+
run: python .github/scripts/check_dist.py --tag "$RELEASE_TAG" dist/*
36+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
37+
with:
38+
name: distributions
39+
path: dist/*
40+
if-no-files-found: error
41+
42+
publish:
43+
if: github.event.release.prerelease == false
44+
needs: build
945
runs-on: ubuntu-latest
46+
environment: pypi
47+
permissions:
48+
id-token: write
1049
steps:
11-
- uses: actions/checkout@v2
12-
- name: Set up Python 3.x
13-
uses: actions/setup-python@v2
14-
with:
15-
python-version: '3.x'
16-
- name: Install dependencies
17-
run: |
18-
python -m pip install --upgrade pip
19-
pip install setuptools wheel twine
20-
- name: Build and publish
21-
env:
22-
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
23-
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
24-
run: |
25-
python setup.py sdist bdist_wheel
26-
twine upload dist/*
50+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
51+
with:
52+
name: distributions
53+
path: dist
54+
- uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0

‎.readthedocs.yml‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
version: 2
22

3+
build:
4+
os: ubuntu-24.04
5+
tools:
6+
python: "3.13"
7+
8+
sphinx:
9+
configuration: docs/source/conf.py
10+
311
python:
4-
version: 3.7
512
install:
613
- method: pip
714
path: .

‎MANIFEST.in‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
prune examples
2+
prune test

‎README.rst‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,10 @@ You may try GeoTorch installing it as
136136

137137
.. code:: bash
138138
139-
pip install git+https://github.com/Lezcano/geotorch/
139+
pip install geotorch
140140
141-
GeoTorch is tested in Linux, Mac, and Windows environments for Python >= 3.6 and supports PyTorch >= 1.9
141+
GeoTorch supports Python >= 3.10 and PyTorch >= 2.6. It is tested on Linux,
142+
macOS, and Windows.
142143

143144
Sharing Weights, Parametrizations, and Normalizing Flows
144145
--------------------------------------------------------
@@ -147,12 +148,14 @@ If one wants to use a parametrized tensor in different places in their model, or
147148

148149
.. code:: python
149150
150-
with geotorch.parametrize.cached():
151+
from torch.nn.utils import parametrize
152+
153+
with parametrize.cached():
151154
logits = model(input_)
152155
153156
Of course, this ``with`` statement may be used simply inside the forward function where the parametrized layer is used several times.
154157

155-
These ideas fall in the context of parametrized optimization, where one wraps a tensor ``X`` with a function ``f``, and rather than using ``X``, uses ``f(X)``. Particular examples of this idea are pruning, weight normalization, and spectral normalization among others. This repository implements a framework to approach this kind of problems. This framework was accepted to core PyTorch 1.8. It can be found under `torch.nn.utils.parametrize`_ and `torch.nn.utils.parametrizations`_. When using PyTorch 1.10 or higher, the native PyTorch functions are used within GeoTorch. In this case, the user can interact with the parametrizations in GeoTorch using the PyTorch functions.
158+
These ideas fall in the context of parametrized optimization, where one wraps a tensor ``X`` with a function ``f``, and rather than using ``X``, uses ``f(X)``. Particular examples of this idea are pruning, weight normalization, and spectral normalization among others.
156159

157160
As every space in GeoTorch is, at its core, a map from a flat space into a manifold, the tools implemented here also serve as a building block in normalizing flows. Using a factorized space such as |low|_ it is direct to compute the determinant of the transformation it defines, as we have direct access to the singular values of the layer.
158161

@@ -208,8 +211,8 @@ Please cite the following work if you found GeoTorch useful. This paper exposes
208211
}
209212
210213
211-
.. |Build| image:: https://github.com/lezcano/geotorch/workflows/Build/badge.svg
212-
:target: https://github.com/lezcano/geotorch/workflows/Build/badge.svg
214+
.. |Build| image:: https://github.com/lezcano/geotorch/actions/workflows/build.yml/badge.svg
215+
:target: https://github.com/lezcano/geotorch/actions/workflows/build.yml
213216
:alt: Build
214217
.. |Docs| image:: https://readthedocs.org/projects/geotorch/badge/?version=latest
215218
:target: https://geotorch.readthedocs.io/en/latest/?badge=latest
@@ -226,8 +229,6 @@ Please cite the following work if you found GeoTorch useful. This paper exposes
226229
.. _here: https://github.com/Lezcano/geotorch/blob/master/examples/copying_problem.py#L16
227230
.. _torch.nn.utils.parametrize: https://pytorch.org/docs/stable/generated/torch.nn.utils.parametrize.register_parametrization.html
228231
.. _torch.nn.utils.parametrizations: https://pytorch.org/docs/stable/generated/torch.nn.utils.parametrizations.orthogonal.html
229-
.. _geotorch/parametrize.py: https://github.com/Lezcano/geotorch/blob/master/geotorch/parametrize.py
230232
.. _examples/sequential_mnist.py: https://github.com/Lezcano/geotorch/blob/master/examples/sequential_mnist.py
231233
.. _examples/copying_problem.py: https://github.com/Lezcano/geotorch/blob/master/examples/copying_problem.py
232234
.. _examples/parametrisations.ipynb: https://github.com/Lezcano/geotorch/blob/master/examples/parametrisations.ipynb
233-

‎docs/README.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ To make the documentation you can run
66
make html
77
```
88

9-
To generate the docs from the GeoTorch source excluding the `parametrize.py` file, run
9+
To generate the docs from the GeoTorch source, run
1010

1111
```
12-
SPHINX_APIDOC_OPTIONS=members sphinx-apidoc -o ./source ../geotorch ../geotorch/parametrize.py
12+
SPHINX_APIDOC_OPTIONS=members sphinx-apidoc -o ./source ../geotorch
1313
```
1414

1515
To check the spelling

0 commit comments

Comments
 (0)