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
93 changes: 93 additions & 0 deletions .github/actions/wait-for-pypi-version/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
name: 'Wait for PyPI version'
description: 'Wait for a specific package version to become available on PyPI or TestPyPI'
inputs:
repository:
description: 'PyPI repository type: "pypi" or "testpypi"'
required: true
package:
description: 'Package name'
required: true
version:
description: 'Package version to wait for'
required: true
max_attempts:
description: 'Maximum number of retry attempts'
required: false
default: '30'
wait_seconds:
description: 'Seconds to wait between attempts'
required: false
default: '10'

runs:
using: composite
steps:
- name: Install requests
shell: bash
run: |
python -m pip install --upgrade pip
pip install requests

- name: Wait for version to be available
shell: python
env:
REPOSITORY: ${{ inputs.repository }}
PACKAGE: ${{ inputs.package }}
VERSION: ${{ inputs.version }}
MAX_ATTEMPTS: ${{ inputs.max_attempts }}
WAIT_SECONDS: ${{ inputs.wait_seconds }}
run: |
import os
import sys
import time

import requests

repository = os.environ["REPOSITORY"].strip().lower()
package = os.environ["PACKAGE"]
version = os.environ["VERSION"]
max_attempts = int(os.environ.get("MAX_ATTEMPTS", "30"))
wait_seconds = int(os.environ.get("WAIT_SECONDS", "10"))

if repository == "testpypi":
api_url = f"https://test.pypi.org/pypi/{package}/json"
repo_name = "TestPyPI"
elif repository == "pypi":
api_url = f"https://pypi.org/pypi/{package}/json"
repo_name = "PyPI"
else:
print(
f"ERROR: repository must be 'pypi' or 'testpypi', got {repository!r}",
file=sys.stderr,
)
sys.exit(1)

for attempt in range(max_attempts):
try:
r = requests.get(api_url, timeout=10)
r.raise_for_status()
data = r.json()
versions = data.get("releases", {})
keys = list(versions.keys())
print("Available versions:", keys[-10:]) # Show last 10 versions
if version in versions:
print(f"✓ Version {version} is available on {repo_name}")
print(f"Version {version} is now available on {repo_name}")
sys.exit(0)
print(f"✗ Version {version} is NOT available on {repo_name}")
except Exception as e:
print(f"Error checking version: {e}")

current = attempt + 1
print(
f"Attempt {current}/{max_attempts}: Version {version} not yet available "
f"on {repo_name}, waiting {wait_seconds} seconds..."
)
time.sleep(wait_seconds)

print(
f"ERROR: Version {version} did not become available on {repo_name} "
f"after {max_attempts} attempts",
file=sys.stderr,
)
sys.exit(1)
205 changes: 183 additions & 22 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,47 +8,208 @@
types:
- published

concurrency:
group: "${{ github.ref }}-${{ github.head_ref }}-${{ github.workflow }}"
cancel-in-progress: false

defaults:
run:
shell: bash -l {0}

jobs:
testpypi_push:
build:
name: Build package
if: github.repository == 'MDAnalysis/PathSimAnalysis'
runs-on: ubuntu-latest
outputs:
version: ${{ steps.extract-version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 0
fetch-tags: true

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.11"

- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install "setuptools>=61.2,<81" build twine

- name: Build package (wheel and sdist)
run: python -m build

- name: Check package
run: twine check dist/*

- name: Extract package version
id: extract-version
run: |
WHEEL_FILE=$(ls dist/*.whl)
VERSION=$(basename "$WHEEL_FILE" | sed -n 's/pathsimanalysis-\([^-]*\)-.*/\1/p')
if [ -z "$VERSION" ]; then
pip install "$WHEEL_FILE" --quiet
VERSION=$(python -c "import pathsimanalysis; print(pathsimanalysis.__version__)")
pip uninstall -y pathsimanalysis --quiet
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Extracted version: $VERSION"

- name: Upload dist files
uses: actions/upload-artifact@v7
with:
name: dist-files
path: dist/
retention-days: 1

test-pytest:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
Comment on lines +21 to +69
name: Run tests
if: github.repository == 'MDAnalysis/PathSimAnalysis'
runs-on: ubuntu-latest
needs: build
steps:
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.11"

- name: Download dist files
uses: actions/download-artifact@v8
with:
name: dist-files
path: dist/

- name: Install wheel with test extras
run: |
python -m pip install --upgrade pip
WHEEL_FILE=$(ls dist/*.whl)
pip install "${WHEEL_FILE}[test]"

- name: Test import
run: |
python -c "import pathsimanalysis; print(f'Package {pathsimanalysis.__version__} imported successfully')"

- name: Run tests
run: pytest -v --pyargs pathsimanalysis.tests

deploy-testpypi:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
Comment on lines +70 to +99
name: Deploy to TestPyPI
if: |
github.repository == 'MDAnalysis/PathSimAnalysis' &&
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/'))
runs-on: ubuntu-latest
needs: [build, test-pytest]
environment:
name: deploy
url: https://test.pypi.org/p/pathsimanalysis
permissions:
id-token: write
if: |
github.repository == 'MDAnalysis/PathSimAnalysis' &&
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/'))
name: Build, upload and test pure Python wheels to TestPyPi
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v7
- name: Download dist files
uses: actions/download-artifact@v8
with:
name: dist-files
path: dist/

- name: testpypi_deploy
uses: MDAnalysis/pypi-deployment@main
- name: Publish to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
test_submission: true
tests: true
test_deps: 'pytest MDAnalysisTests'
package_name: 'pathsimanalysis'
repository-url: https://test.pypi.org/legacy/
verbose: true
skip-existing: true

pypi_push:
deploy-pypi:
name: Deploy to PyPI
if: |
github.repository == 'MDAnalysis/PathSimAnalysis' &&
(github.event_name == 'release' && github.event.action == 'published')
runs-on: ubuntu-latest
needs: [build, test-pytest]
environment:
name: deploy
url: https://pypi.org/p/pathsimanalysis
permissions:
id-token: write
steps:
- name: Download dist files
uses: actions/download-artifact@v8
with:
name: dist-files
path: dist/

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1

test-deployed-testpypi:
name: Test deployed package (TestPyPI)
if: |
github.repository == 'MDAnalysis/PathSimAnalysis' &&
(github.event_name == 'release' && github.event.action == 'published')
name: Build, upload and test pure Python wheels to PyPi
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/'))
runs-on: ubuntu-latest
needs: [build, deploy-testpypi]
steps:
- name: Checkout repository for actions
uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.11"

- name: Wait for version to be available on TestPyPI
uses: ./.github/actions/wait-for-pypi-version
with:
repository: testpypi
package: pathsimanalysis
version: ${{ needs.build.outputs.version }}

- name: Install from TestPyPI
run: |
python -m pip install --upgrade pip
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ "pathsimanalysis[test]==${{ needs.build.outputs.version }}"

- name: Test import
run: |
python -c "import pathsimanalysis; print(f'Package {pathsimanalysis.__version__} imported successfully from TestPyPI')"

- name: Run tests
run: pytest -v --pyargs pathsimanalysis.tests

test-deployed-pypi:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
Comment on lines +148 to +182
name: Test deployed package (PyPI)
if: |
github.repository == 'MDAnalysis/PathSimAnalysis' &&
(github.event_name == 'release' && github.event.action == 'published')
runs-on: ubuntu-latest
needs: [build, deploy-pypi]
steps:
- uses: actions/checkout@v7
- name: Checkout repository for actions
uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.11"

- name: pypi_deploy
uses: MDAnalysis/pypi-deployment@main
- name: Wait for version to be available on PyPI
uses: ./.github/actions/wait-for-pypi-version
with:
package_name: 'pathsimanalysis'
tests: false
repository: pypi
package: pathsimanalysis
version: ${{ needs.build.outputs.version }}

- name: Install from PyPI
run: |
python -m pip install --upgrade pip
pip install "pathsimanalysis[test]==${{ needs.build.outputs.version }}"

- name: Test import
run: |
python -c "import pathsimanalysis; print(f'Package {pathsimanalysis.__version__} imported successfully from PyPI')"

- name: Run tests
run: pytest -v --pyargs pathsimanalysis.tests

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
Comment on lines +183 to +215
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ The rules for this file:
* accompany each entry with github issue/PR number (Issue #xyz)
-->

## [1.2.1] -- 2026-07-23

### Authors
- orbeckst

### Changed
- In accordance with SPEC0 the minimum Python version has been
raised to v3.11 (PR #36)
- Officially supports Python 3.11 - 3.14

## [1.2.0] -- 2024-11-22

### Authors
Expand Down
11 changes: 5 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ build-backend = "setuptools.build_meta"
[project]
name = "pathsimanalysis"
description = "Calculates the geometric similarity of molecular dynamics trajectories using path metrics such as the Hausdorff and Fréchet distances."
license = {file = "LICENSE" }
license = "LGPL-2.1-or-later"
license-files = ["LICENSE"]
authors = [
{name = "MDAnalysis", email = "mdanalysis@numfocus.org"},
]
Expand All @@ -19,7 +20,6 @@ classifiers = [
"Development Status :: 6 - Mature",
"Environment :: Console",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)",
"Programming Language :: C",
"Programming Language :: Python",
"Programming Language :: Python :: 3.11",
Expand All @@ -30,7 +30,7 @@ classifiers = [
"Topic :: Software Development :: Libraries :: Python Modules",
]
readme = "README.md"
requires-python = ">=3.10"
requires-python = ">=3.11"
dependencies = [
"MDAnalysis>=2.1.0",
"scipy>=1.5.0",
Expand All @@ -51,11 +51,11 @@ test = [
"pytest>=6.0",
"pytest-xdist>=2.5",
"pytest-cov>=3.0",
"MDAnalysisTests>=2.0.0",
"MDAnalysisTests>=2.1.0",
]
doc = [
"sphinx",
"sphinx_rtd_theme",
"mdanalysis-sphinx-theme",
]

[project.urls]
Expand All @@ -73,7 +73,6 @@ testpaths = [

[tool.black]
line-length = 80
extend-exclude = "versioneer.py"

[tool.versioningit]
default-version = "1+unknown"
Expand Down
Loading