Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
c45f750
fix: Fix groupby() call for pandas 3.0 (#1596)
mgrabovsky Mar 4, 2026
a21ba06
Update users.md (#1597)
gincrement Mar 4, 2026
2e22ebd
Fix statistics map transmission flows with bus_carrier and add groupb…
FabianHofmann Mar 4, 2026
a163622
Add configurable numerical tolerance for consistency checks
FabianHofmann Mar 9, 2026
19f7360
Revert "Add configurable numerical tolerance for consistency checks" …
FabianHofmann Mar 9, 2026
28a27ef
Deprecate get_strongly_meshed_buses and expose meshed_thresholds (#1591)
FabianHofmann Mar 9, 2026
a6f29d0
Add configurable numerical tolerance for consistency checks (#1609)
FabianHofmann Mar 10, 2026
70f7280
Fix minor ruff checks (#1612)
FabianHofmann Mar 11, 2026
e6138c2
plot: maps: fix pandas dtype error for pandas 3.x (#1613)
maurerle Mar 16, 2026
c0461dc
Update Canada Energy Regulator references in users.md (#1625)
pz-max Mar 20, 2026
d744302
Fix port number parsing in consistency check (#1619)
mgrabovsky Mar 20, 2026
6f177c6
Handle p_set for Store (#1623)
Irieo Mar 23, 2026
eed8d8d
Fix `optimize_security_constrained` not supporting MultiIndex `branch…
keeganmjgreen Mar 26, 2026
8f2f01e
Added GBpower to model list (#1639)
LukasFrankenQ Mar 26, 2026
8d10871
Minor improvement to GH-1631 test (#1640)
keeganmjgreen Mar 27, 2026
c27dd09
Add model and user ucsusa (#1638)
gincrement Mar 27, 2026
fceb755
Fix NetworkCollection statistics for networks with different snapshot…
FabianHofmann Mar 27, 2026
825070c
Add operational limit example (#1630)
brynpickering Mar 30, 2026
b7c5258
build(deps): bump the github-actions group with 4 updates (#1643)
dependabot[bot] Apr 1, 2026
c06804b
Fix market_value and get_operation for multi-port components (#1614)
FabianHofmann Apr 1, 2026
3dcd508
Add pandas3 tests (#1617)
maurerle Apr 3, 2026
44b267f
[pre-commit.ci] pre-commit autoupdate (#1648)
pre-commit-ci[bot] Apr 7, 2026
50bcbb8
fix: pin xarray<2026.4, drop netcdf4 pin (#1655)
lkstrp Apr 16, 2026
7e8ca86
fix: allow groupby="name" in NetworkCollection statistics (#1653)
lkstrp Apr 21, 2026
33b634e
Apply investment_period_weightings to cost statistics (#1646)
FabianHofmann Apr 21, 2026
d25fee3
ci: release workflow simplification and move example networks to buck…
lkstrp Apr 21, 2026
c066669
fix: suppress spurious warnings during network export (#1659)
FabianHofmann Apr 21, 2026
2e0ab1f
chore: update docs deps (#1649)
lkstrp Apr 21, 2026
437287b
prepare release `v1.2.0`
lkstrp Apr 22, 2026
6bffa6a
fix: regression of n.statistics.transmission with bus_carrier (#1662)
coroa Apr 25, 2026
9cfc3f7
build(deps): bump softprops/action-gh-release from 2 to 3 in the gith…
dependabot[bot] May 4, 2026
b3fc372
fix: clear stale dynamic attributes on n.add(overwrite=True) (#1666)
darsh-mishr May 4, 2026
3816d0e
Update README.md (#1670)
gincrement May 6, 2026
6f9ca55
fix: mypy type checks (#1673)
lkstrp May 7, 2026
0d21e2c
New user+model ftdt py psa ar (#1674)
gincrement May 8, 2026
936e6f5
ci: update Pixi version to v0.68.1 (#1676)
lkstrp May 15, 2026
e69d8d0
New user+model canmet energy pypsa canada (#1678)
gincrement May 18, 2026
a84ca7d
Add AI contribution guidelines (#1672)
euronion May 18, 2026
f4837b6
fix: use `latest` fallback to prevent race in release pipeline (#1660)
lkstrp May 18, 2026
e194e6c
fix: ramp limit constraint leaking p_nom of other generators on non-a…
darsh-mishr May 18, 2026
a2d7e58
prepare release `v1.2.1`
lkstrp May 19, 2026
3f3813e
ci: fix release workflow
lkstrp May 19, 2026
c755767
fix: capacity bounds for infinite non-extendables (#1683)
FabianHofmann May 21, 2026
933eb06
docs: fix interactive map plot (#1679)
lkstrp May 21, 2026
decd92e
docs: update deps (#1680)
lkstrp May 21, 2026
0ad709f
include -1 * sign for loads in define_nodal_balance_constraint (#1685)
gugrimm May 21, 2026
1e53ce6
deps: lift xarray<2026.4 cap, bump linopy>=0.7.0 (#1686)
MaykThewessen May 22, 2026
0ff4da8
prepare release `v1.2.2`
lkstrp May 25, 2026
fbd3ed5
build(deps): bump prefix-dev/setup-pixi from 0.9.5 to 0.9.6 in the gi…
dependabot[bot] Jun 1, 2026
30e4ed0
feat: drop empty dim name in mga (#1708)
FabianHofmann Jun 1, 2026
1f58b00
Use standard removeprefix function (#1717)
mgrabovsky Jun 4, 2026
46aa7ed
fix: avoid redundant interactive bar legend (#1710)
william-xue Jun 9, 2026
7e8bac7
fix: do not delete solver model from test fixture (compat linopy v0.8…
FabianHofmann Jun 11, 2026
7f1f118
fix: keep dynamic results of components added after previous assignme…
lkstrp Jun 12, 2026
c4ae1b8
fix: optimize() now honours static `p_set` on Generator/StorageUnit/S…
darsh-mishr Jun 12, 2026
19460ac
prepare release `v1.2.3`
lkstrp Jun 12, 2026
2cfd464
fix: pytest 9 compatibility (#1744)
lkstrp Jun 22, 2026
c1f96e7
fix: preserve snapshot index name on dynamic data when setting again …
lkstrp Jun 22, 2026
d195b1d
fix process docs on committable + extendable (#1734)
FabianHofmann Jun 22, 2026
4862865
Doc: Process capacity/cost refer to internal power p (#1747)
FabianHofmann Jun 23, 2026
fc6c805
use importlib.resources for package-internal files (#1720)
fneum Jun 23, 2026
b35744a
chore: fill in copyright placeholder (#1748)
lkstrp Jun 23, 2026
bbc6f63
clearify docs on transformer electrical parameters (#1750)
FabianHofmann Jun 24, 2026
241b8dd
Text correction in imperfect competition example (#1751)
Irieo Jun 25, 2026
719f9d8
fix: ensure upper clipping of min_pu in time segmentation (#1752)
FabianHofmann Jun 25, 2026
260e9b2
fix(io): coerce Arrow-backed strings on import (closes #1585) (#1687)
MaykThewessen Jun 25, 2026
3df3b0a
fix: avoid KeyError in (l)pf when a sub-network lacks a branch type (…
FabianHofmann Jun 25, 2026
3c4b61a
Reset inter-temporal constraints at investment-period boundaries (#1746)
FabianHofmann Jun 26, 2026
5140b4b
fix: warn when standard type overrides manual branch impedances (#1759)
FabianHofmann Jun 26, 2026
85a8ce6
fix(io): correct shunt susceptance sign on pandapower import (#1758)
FabianHofmann Jun 26, 2026
d225cc6
docs: clarify Transformer tap_position is absolute, relative to tap_n…
FabianHofmann Jun 26, 2026
bd10a99
fix: validate list `suffix` in n.add and n.remove and fix Series/Data…
darsh-mishr Jun 26, 2026
2de575b
fix: support netCDF export under pandas>=3 future.infer_string (#1762)
lkstrp Jun 27, 2026
541db77
fix: resolve statistics plotting issues (#1721)
FabianHofmann Jun 27, 2026
fb425cb
prepare release `v1.2.4`
lkstrp Jun 27, 2026
5793d19
fix: deterministic edge order in n.graph() (#1764)
FabianHofmann Jun 30, 2026
a8ff2a0
fix(docs): use thread pool in GSA example for cross-platform builds (…
FabianHofmann Jun 30, 2026
9bfd031
Apply seasonal line ratings to s_max_pu without modifying s_nom
claude Jun 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ body:
Thanks for taking the time to fill out this bug report!
Please do not post usage questions here. Ask them on the [PyPSA Discord server](https://discord.gg/AnuJBk23FU).

Please write this issue description yourself. Any potentially verbose AI-generated content should be marked. See [Contributing guidelines](https://docs.pypsa.org/latest/contributing/contributing/).

- type: checkboxes
id: checks
attributes:
Expand Down
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ assignees: ''

<!-- Please do not post usage questions here. Ask them on the PyPSA Discord server: https://discord.gg/AnuJBk23FU -->

<!-- Please write this issue description yourself. Any potentially verbose AI-generated content should be marked. See Contributing guidelines: https://docs.pypsa.org/latest/contributing/contributing/ -->

## Describe the feature you'd like to see

*Please give a clear and concise description and provide context why the feature would be useful.*
Expand Down
1 change: 1 addition & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ Closes # (if applicable).
- [ ] Code changes are sufficiently documented; i.e. new functions contain docstrings and further explanations may be given in `docs`.
- [ ] Unit tests for new features were added (if applicable).
- [ ] A note for the release notes `docs/release-notes.md` of the upcoming release is included.
- [ ] PR description is written by me. Any potentially verbose AI-generated content is marked (see [Contributing guidelines](https://docs.pypsa.org/latest/contributing/contributing/)).
- [ ] I consent to the release of this PR's code under the MIT license.
179 changes: 70 additions & 109 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,136 +9,97 @@ on:
tags:
- v*.*.*

env:
PREPARATION_COMMIT: '[github-actions.ci] prepare release ${{ github.ref_name }}'

jobs:
check-preparation:
name: Check if release is prepared
publish-examples:
name: Publish example networks to bucket
runs-on: ubuntu-latest
outputs:
prepared: ${{ steps.validate.outputs.prepared }}
steps:
- uses: actions/checkout@v6

- name: Validate commit message
id: validate
run: |
# Check if last commit is the expected commit message
COMMIT_MESSAGE=$(git log -1 --pretty=%B)
echo "Expected: '${{ env.PREPARATION_COMMIT }}'"
echo "Received: '$COMMIT_MESSAGE'"

prepared="false"
if [[ "$COMMIT_MESSAGE" == "${{ env.PREPARATION_COMMIT }}" ]]; then
prepared="true"
fi

echo "prepared=$prepared" >> $GITHUB_OUTPUT

prepare-release:
name: Prepare release
needs: [check-preparation]
if: ${{ needs.check-preparation.outputs.prepared == 'false' }}
runs-on: ubuntu-latest
steps:
- name: Generate token for PyPSA Bot
id: generate-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.PYPSA_BOT_ID }}
private-key: ${{ secrets.PYPSA_BOT_PRIVATE_KEY }}

- uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Find the branch for commit/ tag
run: |
branch=$(git branch -r --points-at ${{ github.sha }} | grep -v 'HEAD' | head -n 1 | sed 's|origin/||' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
echo "Branch found: $branch"
echo "BRANCH_NAME=$branch" >> $GITHUB_ENV

- uses: actions/checkout@v6
with:
fetch-depth: 0
ref: ${{ env.BRANCH_NAME }}
token: ${{ steps.generate-token.outputs.token }}

# Start of preparation script

- uses: actions/setup-python@v6
with:
python-version: 3.12

- name: Install packages
run: |
python -m pip install uv
uv pip install --system toml
uv pip install --system setuptools_scm
uv pip install --system boto3
uv pip install --system .

- name: Update CITATION.cff
- name: Publish example networks to S3
env:
AWS_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_KEY }}
S3_ENDPOINT_URL: ${{ vars.S3_ENDPOINT_URL }}
S3_BUCKET: ${{ vars.S3_BUCKET }}
S3_EXAMPLES_PREFIX: ${{ vars.S3_EXAMPLES_PREFIX }}
RELEASE_TAG: ${{ github.ref_name }}
run: |
import re
from setuptools_scm import get_version

version = get_version()

with open('CITATION.cff', 'r') as file:
cff_content = file.read()
cff_content = open('CITATION.cff', 'r').read()

updated_cff_content = re.sub(r"(?<=version: ).+(?= #)",version,cff_content,flags=re.MULTILINE)

with open('CITATION.cff', 'w') as file:
file.write(updated_cff_content)
shell: python
import os
from pathlib import Path

- name: Update example notebooks
run: |
import boto3
import pypsa
# ac-dc-meshed
n = pypsa.Network("examples/networks/ac-dc-meshed/ac-dc-meshed")
n.export_to_csv_folder("examples/networks/ac-dc-meshed/ac-dc-meshed")
n.export_to_netcdf("examples/networks/ac-dc-meshed/ac-dc-meshed.nc")
# storage-hvdc
n = pypsa.Network("examples/networks/storage-hvdc/storage-hvdc")
n.export_to_csv_folder("examples/networks/storage-hvdc/storage-hvdc")
n.export_to_netcdf("examples/networks/storage-hvdc/storage-hvdc.nc")
# scigrid-de
n = pypsa.Network("examples/networks/scigrid-de/scigrid-de")
n.export_to_csv_folder("examples/networks/scigrid-de/scigrid-de")
n.export_to_netcdf("examples/networks/scigrid-de/scigrid-de.nc")
# model-energy
n = pypsa.Network("examples/networks/model-energy/model-energy")
n.export_to_csv_folder("examples/networks/model-energy/model-energy")
n.export_to_netcdf("examples/networks/model-energy/model-energy.nc")
# stochastic-network
n = pypsa.Network("examples/networks/stochastic-network/stochastic-network.nc")
n.export_to_netcdf("examples/networks/stochastic-network/stochastic-network.nc")
shell: python

# End of preparation script

- name: Remove previous tag
run: |
git tag -d ${{ github.ref_name }}
git push origin --delete ${{ github.ref_name }}
tag = os.environ["RELEASE_TAG"]
assert tag.startswith("v"), f"unexpected release tag: {tag!r}"
version_base = tag[1:]

endpoint_url = os.environ["S3_ENDPOINT_URL"]
bucket = os.environ["S3_BUCKET"]
base_prefix = os.environ["S3_EXAMPLES_PREFIX"]

client = boto3.client("s3", endpoint_url=endpoint_url)

examples = [
"ac_dc_meshed",
"storage_hvdc",
"scigrid_de",
"model_energy",
"stochastic_network",
"carbon_management",
]

tmp = Path("/tmp/pypsa-examples")
tmp.mkdir(exist_ok=True)

# Upload examples to versioned prefix
for name in examples:
n = getattr(pypsa.examples, name)()
local = tmp / f"{name}.nc"
n.export_to_netcdf(str(local))
key = f"{base_prefix}/v{version_base}/{name}.nc"
client.upload_file(
str(local),
bucket,
key,
ExtraArgs={"ACL": "public-read", "ContentType": "application/x-netcdf"},
)
print(f"uploaded {key}")

# Repoint latest/ to new version
for name in examples:
src_key = f"{base_prefix}/v{version_base}/{name}.nc"
dst_key = f"{base_prefix}/latest/{name}.nc"
client.copy_object(
Bucket=bucket,
CopySource={"Bucket": bucket, "Key": src_key},
Key=dst_key,
ACL="public-read",
ContentType="application/x-netcdf",
MetadataDirective="REPLACE",
)
print(f"repointed {dst_key} -> {src_key}")
shell: python

- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v7
with:
branch: ${{ env.BRANCH_NAME }}
commit_message: '${{ env.PREPARATION_COMMIT }}'
tagging_message: '${{ github.ref_name }}' # add tag again
push_options: '${{ github.ref_name }}'
add_options: '-u' # Never add untracked files
test:
needs: [publish-examples]
uses: ./.github/workflows/test.yml
secrets: inherit

build:
name: Build and verify package
needs: [check-preparation]
if: ${{ needs.check-preparation.outputs.prepared == 'true' }}
needs: [test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
Expand All @@ -150,7 +111,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: softprops/action-gh-release@v2
- uses: softprops/action-gh-release@v3
with:
body: |
Revised release notes are available in the [documentation](https://docs.pypsa.org/latest/release-notes/).
Expand Down
9 changes: 6 additions & 3 deletions .github/workflows/test-models.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
steps:
- uses: actions/checkout@v6

- uses: dorny/paths-filter@v3
- uses: dorny/paths-filter@v4
id: filter
with:
filters: |
Expand Down Expand Up @@ -82,9 +82,9 @@ jobs:

- name: Setup Pixi
if: steps.filter.outputs.src == 'true' || github.event_name == 'schedule'
uses: prefix-dev/setup-pixi@v0.9.4
uses: prefix-dev/setup-pixi@v0.9.6
with:
pixi-version: v0.59.0
pixi-version: v0.68.1
cache: true
# Do not cache in branches
cache-write: ${{ github.event_name == 'push' && github.ref_name == 'main' }}
Expand Down Expand Up @@ -120,7 +120,10 @@ jobs:
- name: Install package from ref
if: (steps.filter.outputs.src == 'true' || github.event_name == 'schedule') && env.pinned == 'false'
run: |
# Allow upgrading internal packages without exclude-newer cap
sed -i '/^exclude-newer\s*=/d' pixi.toml
pixi remove ${{ env.PACKAGE_NAME }}
pixi upgrade linopy
pixi add --pypi --git https://github.com/${{ github.repository }}.git ${{ github.event.repository.name }} --rev ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}

- name: Run snakemake test workflows
Expand Down
78 changes: 64 additions & 14 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ on:
branches: ["*"]
schedule:
- cron: "0 5 * * *"
workflow_call:

# Cancel any in-progress runs when a new run is triggered
concurrency:
Expand Down Expand Up @@ -53,6 +54,10 @@ jobs:
api: new_api
- os: windows-latest
api: new_api
include:
- python-version: '3.13'
os: ubuntu-latest
api: pandas3

env:
MPLBACKEND: Agg # https://github.com/orgs/community/discussions/26434
Expand Down Expand Up @@ -95,35 +100,35 @@ jobs:
uv sync --extra dev --no-install-project
uv pip install "$(ls dist/*.whl)"

- name: Install pandas 3
if: matrix.api == 'pandas3'
run: uv pip install 'pandas>=3.0'

- name: Run unit tests (old API)
if: matrix.api == 'default'
run: >
uv run pytest --mpl --mpl-generate-summary=html --mpl-results-path=mpl-results
uv run pytest
--cov=pypsa --junitxml=junit.xml -o junit_family=legacy
&& uv run coverage xml

- name: Run unit tests (pandas 3)
if: matrix.api == 'pandas3'
run: >
uv run --no-sync pytest
--cov=pypsa --junitxml=junit.xml -o junit_family=legacy
&& uv run --no-sync coverage xml

- name: Run unit tests (new API)
if: matrix.api == 'new_api'
run: >
uv run pytest
--new-components-api
--mpl --mpl-generate-summary=html --mpl-results-path=mpl-results
--cov=pypsa --junitxml=junit.xml -o junit_family=legacy
&& uv run coverage xml

- name: Upload artifacts
if: matrix.api == 'default' && matrix.os == 'macos-latest' && matrix.python-version == '3.13'
uses: actions/upload-artifact@v7
with:
name: results-plotting
path: |
mpl-results
retention-days: 14
if-no-files-found: ignore

- name: Upload code coverage report
if: ${{ !cancelled() }}
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@v6
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: >
Expand All @@ -143,6 +148,51 @@ jobs:
python${{ matrix.python-version }},
api-${{ matrix.api }}

test-plots:
# Run the matplotlib image-comparison tests once, on a single instance.
# Baselines are generated on Linux; see test/test_statistics_plot.py.
name: Test plots
needs: [build]
runs-on: ubuntu-latest
env:
MPLBACKEND: Agg # https://github.com/orgs/community/discussions/26434
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # Needed for setuptools_scm

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

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

- name: Install package and dependencies
run: |
python -m pip install uv
uv sync --all-extras --no-install-project
uv pip install "$(ls dist/*.whl)"

- name: Run image comparison tests
run: >
uv run pytest --run-plot-tests -m mpl_image_compare
--mpl --mpl-generate-summary=html --mpl-results-path=mpl-results

- name: Upload artifacts
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v7
with:
name: results-plotting
path: |
mpl-results
retention-days: 14
if-no-files-found: ignore

check-docs:
name: Check docs
needs: [build]
Expand Down Expand Up @@ -179,7 +229,7 @@ jobs:

- name: Upload code coverage report
if: ${{ !cancelled() }}
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@v6
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: >
Expand Down
Loading
Loading