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
13 changes: 6 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@ ShapePipe is not a stand-alone library: it needs system tools (Source Extractor,
PSFEx, WeightWatcher), MPI, and a specific scientific-Python stack. The supported
way to get all of that is the container.

- **Dependencies** are declared in `pyproject.toml`, **pinned to exact versions**
and kept current by **Renovate** (see `renovate.json`). ShapePipe ships as a
container, not a published library, so there are no downstream installers to
keep flexible — pinning is what lets Renovate honor a supply-chain
release-age delay before a new release is adopted (it can't hold `uv` back to
an aged version through a floor range). `uv.lock` is the reproducible manifest
generated by `uv` (never hand-edited). System-level tools live in the
- **Dependencies** are declared in `pyproject.toml` as **floor ranges**; exact
versions live in `uv.lock`, the reproducible manifest generated by `uv`
(never hand-edited). **Renovate** keeps the lock current (see
`renovate.json`): uv's resolver owns version selection, so cross-package
constraints resolve jointly instead of failing update PRs. Bump a floor only
when the code actually requires the newer API. System-level tools live in the
`Dockerfile`.
- **Images** publish to `ghcr.io/cosmostat/shapepipe` on every push to an
integration branch, in two targets:
Expand Down
61 changes: 30 additions & 31 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,38 @@ authors = [
license = "MIT"
license-files = ["LICENSE"]
requires-python = ">=3.12"
# Dependencies are PINNED to exact versions and kept current by Renovate (see
# renovate.json). shapepipe ships as a container, not a published library, so
# there are no downstream installers to keep flexible — pinning is what lets
# Renovate honor a supply-chain release-age delay before adopting a new release
# (it can't hold uv back to an aged version through a floor range;
# renovatebot/renovate#41624). `uv.lock` is the reproducible manifest generated
# by uv (never hand-edited).
# Dependencies use FLOOR RANGES; exact versions live in `uv.lock`, the
# reproducible manifest generated by uv (never hand-edited). Renovate updates
# the lock (rangeStrategy=update-lockfile, see renovate.json), so uv's resolver
# owns version selection — cross-package constraints (e.g. numba capping numpy)
# are resolved jointly instead of failing update PRs. Bump a floor only when
# the code actually requires the newer API.
dependencies = [
"astropy==7.2.0", # major 6 → 7
"astropy>=7.0", # major 6 → 7
"astroquery",
"canfar",
"cs_util>=0.2.1",
"galsim==2.8.4",
"galsim>=2.8",
"h5py",
"joblib==1.5.3",
"matplotlib==3.10.9",
"mccd==1.2.4",
"modopt==1.7.2",
"mpi4py==4.1.2",
"numba==0.65.1", # numpy 2 support
"numpy==2.4.6", # major 1 → 2
"pandas==3.0.3", # major 2 → 3
"joblib>=1.4",
"matplotlib>=3.10",
"mccd>=1.2.4",
"modopt>=1.6",
"mpi4py>=4.1.2",
"numba>=0.59", # numpy 2 support
"numpy>=2.4.6", # major 1 → 2
"pandas>=3.0.3", # major 2 → 3
"python-dateutil",
"python-pysap==0.3.0",
"python-pysap>=0.3",
"PyQt5",
"pyqtgraph",
"reproject==0.19.0",
"sf_tools==2.0.4",
"skaha==1.7.0",
"sqlitedict==2.1.0",
"reproject>=0.19",
"sf_tools>=2.0.4",
"skaha>=1.7",
"sqlitedict>=2.0",
"termcolor",
"tqdm==4.68.1",
"vos==3.6.4",
"tqdm>=4.68.1",
"vos>=3.6",
"ngmix>=2.4",
]

Expand All @@ -57,9 +56,9 @@ doc = [
"sphinx-book-theme"
]
jupyter = [
"ipython==9.14.1",
"jupyterlab==4.5.9",
"snakemake==9.22.0",
"ipython>=9.14.1",
"jupyterlab>=4.5.9",
"snakemake>=9.22.0",
]
lint = [
"ruff",
Expand All @@ -69,9 +68,9 @@ release = [
"twine",
]
test = [
"hypothesis==6.155.2",
"pytest==9.1.1",
"pytest-cov==7.1.0",
"hypothesis>=6.155.2",
"pytest>=8.3",
"pytest-cov>=5.0",
]
fitsio = ["fitsio"]
dev = ["shapepipe[doc,jupyter,lint,release,test,fitsio]"]
Expand Down Expand Up @@ -99,7 +98,7 @@ cs_util = { git = "https://github.com/CosmoStat/cs_util", branch = "develop" }
# Declaring a build backend makes shapepipe an installed package (not a uv
# "virtual" project), so `uv sync` / `pip install -e .` put it on the path
# rather than only its dependencies.
requires = ["setuptools==82.0.1"]
requires = ["setuptools>=61"]
build-backend = "setuptools.build_meta"

[tool.setuptools]
Expand Down
17 changes: 4 additions & 13 deletions renovate.json
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"description": [
"Low-noise dependency updates with mild supply-chain hygiene, layered on the Mend org config.",
"Pins: ShapePipe ships as a container, not a PyPI library, so per the Renovate dependency-pinning doc we pin app dependencies exactly. The pins are written directly in pyproject.toml (== versions), so nothing depends on rangeStrategy resolution against the org config; the packageRule (scoped to PyPI, leaving git-sourced deps like ngmix/cs_util alone) just keeps future deps pinned. Exact pins are also what lets minimumReleaseAge work with uv (renovatebot/renovate#41624).",
"Python base-image bumps (3.12 -> 3.14 rides as 'minor' in Renovate's python versioning) never automerge — a Python upgrade gets human eyes.",
"Noise: all non-major updates grouped into one weekly PR that automerges when CI (full suite in the container) is green; majors surface individually for review; lockFileMaintenance refreshes transitive deps.",
"minimumReleaseAge=7 days: supply-chain detection window, sized per the Renovate docs' automerge guidance and Astral's uv guide."
"Low-noise dependency updates; uv owns version resolution. pyproject keeps floor ranges and Renovate uses the org default rangeStrategy=update-lockfile, so `uv lock` picks versions jointly — cross-package conflicts (e.g. numba capping numpy) resolve silently instead of failing the batch, and un-stick themselves when upstream catches up. No minimumReleaseAge: it is unenforceable with uv resolution (renovatebot/renovate#41624 forced exact pins, which forced manual conflict caps); CI running the full suite in the container is the automerge gate.",
"Noise: all non-major updates grouped into one weekly PR that automerges when CI is green; majors surface individually; lockFileMaintenance refreshes transitive deps weekly.",
"python is guarded: Renovate classes base-image bumps like 3.12 -> 3.14 as 'minor', so it gets its own PR and never automerges — a Python upgrade gets human eyes without holding the weekly batch hostage."
],
"extends": ["config:recommended", "group:allNonMajor", "schedule:weekly"],
"minimumReleaseAge": "7 days",
"lockFileMaintenance": { "enabled": true },
"packageRules": [
{ "matchDatasources": ["pypi"], "rangeStrategy": "pin" },
{ "matchUpdateTypes": ["minor", "patch", "pin", "digest"], "automerge": true },
{ "matchPackageNames": ["python"], "automerge": false },
{
"matchPackageNames": ["numpy"],
"allowedVersions": "<2.5",
"description": "numba 0.65.1 caps numpy<2.5; a grouped pin bump to 2.5.0 makes uv lock unsatisfiable and fails the whole batch. Drop this rule when numba supports numpy 2.5."
}
{ "matchPackageNames": ["python"], "groupName": "python", "automerge": false }
]
}
46 changes: 23 additions & 23 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.