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
55 changes: 55 additions & 0 deletions .github/scripts/check_dist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import argparse
from email.parser import BytesParser
from pathlib import Path, PurePosixPath
import tarfile
import zipfile


def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument("dist", nargs="+", type=Path)
parser.add_argument("--tag")
return parser.parse_args()


def archive_names(path):
if path.suffix == ".whl":
with zipfile.ZipFile(path) as archive:
return archive.namelist()
with tarfile.open(path) as archive:
return archive.getnames()


def wheel_version(path):
with zipfile.ZipFile(path) as archive:
metadata = next(
name for name in archive.namelist() if name.endswith(".dist-info/METADATA")
)
message = BytesParser().parsebytes(archive.read(metadata))
return message["Version"]


def main():
args = parse_args()
wheels = [path for path in args.dist if path.suffix == ".whl"]
sdists = [path for path in args.dist if path.name.endswith(".tar.gz")]
if len(wheels) != 1 or len(sdists) != 1:
raise SystemExit("Expected exactly one wheel and one sdist")

for path in args.dist:
for name in archive_names(path):
parts = PurePosixPath(name).parts
if "examples" in parts or "test" in parts:
raise SystemExit(f"Unexpected path in {path.name}: {name}")

version = wheel_version(wheels[0])
if f"-{version}.tar.gz" not in sdists[0].name:
raise SystemExit("Wheel and sdist versions do not match")
if args.tag is not None and args.tag.removeprefix("v") != version:
raise SystemExit(f"Tag {args.tag!r} does not match package version {version!r}")

print(f"Validated GeoTorch {version} wheel and sdist")


if __name__ == "__main__":
main()
128 changes: 89 additions & 39 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,52 +1,102 @@
name: build
name: CI

on:
push:
branches: [ master ]
branches: [master]
pull_request:
branches: [ '*' ]

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
build:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.14"
cache: pip
- run: python -m pip install --upgrade pip
- run: python -m pip install ".[dev]"
- run: black --check --diff .
- run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics

linux:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- python: "3.10"
torch: "torch==2.6.*"
- python: "3.12"
torch: "torch"
- python: "3.14"
torch: "torch"
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: ${{ matrix.python }}
cache: pip
- run: python -m pip install --upgrade pip
- run: python -m pip install "${{ matrix.torch }}" pytest pytest-xdist
- run: python -m pip install --no-deps -e .
- run: python -m pytest -s --tb=short -n32 test

os-smoke:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
python-version: [3.6, 3.7, 3.8]
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.13"
cache: pip
- run: python -m pip install --upgrade pip
- run: python -m pip install ".[test]"
- run: python -m pytest -s --tb=short -n32 test

coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.14"
cache: pip
- run: python -m pip install --upgrade pip
- run: python -m pip install ".[test]" pytest-cov
- run: python -m pytest -s --tb=short -n32 --cov=geotorch --cov-report=xml test
- uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
with:
token: ${{ secrets.CODECOV_TOKEN }}

package:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies others
if: ${{ matrix.os != 'windows-latest' }}
run: |
python -m pip install --upgrade pip
pip install .[dev]

# Windows is treated differently, as PyTorch is not uploaded to Pypi atm
- name: Install dependencies windows
if: ${{ matrix.os == 'windows-latest' }}
run: |
python -m pip install --upgrade pip
pip install torch===1.10.0+cpu -f https://download.pytorch.org/whl/torch_stable.html
pip install .[dev]

- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=12 --max-line-length=127 --statistics

- name: Lint with Black
run: |
black --check --diff .

- name: Test with pytest
run: |
pytest test
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.14"
cache: pip
- run: python -m pip install --upgrade pip
- run: python -m pip install build pytest pytest-xdist torch twine
- run: python -m build
- run: python -m twine check dist/*
- run: python .github/scripts/check_dist.py dist/*
- name: Test installed wheel
run: |
python -m venv --system-site-packages /tmp/geotorch-wheel
/tmp/geotorch-wheel/bin/python -m pip install --no-deps dist/*.whl
cp -R test /tmp/geotorch-tests
cd /tmp
/tmp/geotorch-wheel/bin/python -m pytest -s --tb=short -n32 geotorch-tests
35 changes: 0 additions & 35 deletions .github/workflows/coverage.yml

This file was deleted.

66 changes: 47 additions & 19 deletions .github/workflows/pypi.yml
Original file line number Diff line number Diff line change
@@ -1,26 +1,54 @@
name: Upload Python Package
name: Publish to PyPI

on:
release:
types: [created]
types: [published]

permissions:
contents: read

jobs:
deploy:
build:
if: github.event.release.prerelease == false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
fetch-depth: 0
ref: ${{ github.event.release.tag_name }}
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.14"
cache: pip
- name: Verify release source
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
test "$(git rev-parse HEAD)" = "$(git rev-list -n 1 "$RELEASE_TAG")"
- run: python -m pip install --upgrade pip
- run: python -m pip install build twine
- run: python -m build
- run: python -m twine check dist/*
- name: Verify release artifacts
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: python .github/scripts/check_dist.py --tag "$RELEASE_TAG" dist/*
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: distributions
path: dist/*
if-no-files-found: error

publish:
if: github.event.release.prerelease == false
needs: build
runs-on: ubuntu-latest
environment: pypi
permissions:
id-token: write
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.x
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
python setup.py sdist bdist_wheel
twine upload dist/*
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: distributions
path: dist
- uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
9 changes: 8 additions & 1 deletion .readthedocs.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
version: 2

build:
os: ubuntu-24.04
tools:
python: "3.13"

sphinx:
configuration: docs/source/conf.py

python:
version: 3.7
install:
- method: pip
path: .
Expand Down
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
prune examples
prune test
17 changes: 9 additions & 8 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,10 @@ You may try GeoTorch installing it as

.. code:: bash

pip install git+https://github.com/Lezcano/geotorch/
pip install geotorch

GeoTorch is tested in Linux, Mac, and Windows environments for Python >= 3.6 and supports PyTorch >= 1.9
GeoTorch supports Python >= 3.10 and PyTorch >= 2.6. It is tested on Linux,
macOS, and Windows.

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

.. code:: python

with geotorch.parametrize.cached():
from torch.nn.utils import parametrize

with parametrize.cached():
logits = model(input_)

Of course, this ``with`` statement may be used simply inside the forward function where the parametrized layer is used several times.

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.
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.

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.

Expand Down Expand Up @@ -208,8 +211,8 @@ Please cite the following work if you found GeoTorch useful. This paper exposes
}


.. |Build| image:: https://github.com/lezcano/geotorch/workflows/Build/badge.svg
:target: https://github.com/lezcano/geotorch/workflows/Build/badge.svg
.. |Build| image:: https://github.com/lezcano/geotorch/actions/workflows/build.yml/badge.svg
:target: https://github.com/lezcano/geotorch/actions/workflows/build.yml
:alt: Build
.. |Docs| image:: https://readthedocs.org/projects/geotorch/badge/?version=latest
:target: https://geotorch.readthedocs.io/en/latest/?badge=latest
Expand All @@ -226,8 +229,6 @@ Please cite the following work if you found GeoTorch useful. This paper exposes
.. _here: https://github.com/Lezcano/geotorch/blob/master/examples/copying_problem.py#L16
.. _torch.nn.utils.parametrize: https://pytorch.org/docs/stable/generated/torch.nn.utils.parametrize.register_parametrization.html
.. _torch.nn.utils.parametrizations: https://pytorch.org/docs/stable/generated/torch.nn.utils.parametrizations.orthogonal.html
.. _geotorch/parametrize.py: https://github.com/Lezcano/geotorch/blob/master/geotorch/parametrize.py
.. _examples/sequential_mnist.py: https://github.com/Lezcano/geotorch/blob/master/examples/sequential_mnist.py
.. _examples/copying_problem.py: https://github.com/Lezcano/geotorch/blob/master/examples/copying_problem.py
.. _examples/parametrisations.ipynb: https://github.com/Lezcano/geotorch/blob/master/examples/parametrisations.ipynb

4 changes: 2 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ To make the documentation you can run
make html
```

To generate the docs from the GeoTorch source excluding the `parametrize.py` file, run
To generate the docs from the GeoTorch source, run

```
SPHINX_APIDOC_OPTIONS=members sphinx-apidoc -o ./source ../geotorch ../geotorch/parametrize.py
SPHINX_APIDOC_OPTIONS=members sphinx-apidoc -o ./source ../geotorch
```

To check the spelling
Expand Down
Loading
Loading