Skip to content

Commit 3fe0467

Browse files
authored
Merge pull request #281 from iiasa/ci/uv
Update CI and code quality
2 parents c782c30 + a43feb4 commit 3fe0467

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+358
-232
lines changed

.github/workflows/pytest-snapshots.yaml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ concurrency:
1414
cancel-in-progress: true
1515

1616
env:
17-
gams: "43.4.1"
18-
python: "3.12"
17+
gams-version: 43.4.1
18+
python-version: "3.13"
1919
upstream: main
2020

2121
jobs:
@@ -35,15 +35,15 @@ jobs:
3535
with:
3636
lfs: true
3737

38-
- uses: actions/setup-python@v5
38+
- name: Set up uv, Python
39+
uses: astral-sh/setup-uv@v5
3940
with:
41+
cache-dependency-glob: "**/pyproject.toml"
4042
python-version: ${{ env.python }}
41-
cache: pip
42-
cache-dependency-path: "**/pyproject.toml"
4343

4444
- uses: iiasa/actions/setup-gams@main
4545
with:
46-
version: ${{ env.gams }}
46+
version: ${{ env.gams-version }}
4747
license: ${{ secrets.GAMS_LICENSE }}
4848

4949
- uses: ts-graphviz/setup-graphviz@v2
@@ -59,12 +59,12 @@ jobs:
5959
# for open PRs), temporarily uncomment, add, or edit lines below
6060
# as needed. DO NOT merge such changes to `main`.
6161
run: |
62-
# pip install --upgrade "genno @ git+https://github.com/khaeru/genno.git@main"
63-
pip install --upgrade "ixmp @ git+https://github.com/iiasa/ixmp.git@${{ env.upstream }}"
64-
# pip install --upgrade "message-ix @ git+https://github.com/iiasa/message_ix.git@${{ env.upstream }}"
65-
pip install --upgrade "message-ix @ git+https://github.com/iiasa/message_ix.git@issue/723"
62+
# uv pip install --upgrade "genno @ git+https://github.com/khaeru/genno.git@main"
63+
uv pip install --upgrade "ixmp @ git+https://github.com/iiasa/ixmp.git@${{ env.upstream }}"
64+
# uv pip install --upgrade "message-ix @ git+https://github.com/iiasa/message_ix.git@${{ env.upstream }}"
65+
uv pip install --upgrade "message-ix @ git+https://github.com/iiasa/message_ix.git@issue/723"
6666
67-
pip install .[docs,tests] dask[dataframe]
67+
uv pip install .[docs,tests] dask[dataframe]
6868
6969
- name: Configure local data path
7070
run: |

.github/workflows/pytest.yaml

Lines changed: 58 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,47 @@
11
name: Test
22

33
on:
4-
pull_request:
5-
branches: [ main , "migrate**"]
4+
# Uncomment this entry only to debug the workflow
5+
# pull_request:
6+
# branches: [ main ]
7+
pull_request_target:
8+
branches: [ main, "migrate**" ]
9+
types: [ labeled, opened, reopened, synchronize ]
610
schedule:
7-
# 05:00 UTC = 06:00 CET = 07:00 CEST
8-
- cron: "0 5 * * *"
11+
- cron: "0 5 * * *" # = 06:00 CET = 07:00 CEST
912

1013
# Cancel previous runs that have not completed
1114
concurrency:
1215
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
1316
cancel-in-progress: true
1417

18+
defaults:
19+
run:
20+
shell: bash
21+
22+
env:
23+
gams-version: 43.4.1
24+
label: "safe to test"
25+
python-version: "3.13"
26+
1527
jobs:
28+
check:
29+
name: check permissions
30+
runs-on: ubuntu-latest
31+
steps:
32+
- if: >
33+
!(
34+
github.event_name == 'schedule'
35+
|| github.repository == github.event.pull_request.head.repo.full_name
36+
|| contains(github.event.pull_request.labels.*.name, env.label)
37+
)
38+
run: |
39+
echo "Pytest workflow will not run for branch in fork without label \`${{ env.label }}\`." >>$GITHUB_STEP_SUMMARY
40+
exit 1
41+
1642
warm-lfs-cache:
43+
needs: check
44+
1745
strategy:
1846
matrix:
1947
os: [ macos-13, macos-latest, ubuntu-latest, windows-latest ]
@@ -73,23 +101,23 @@ jobs:
73101
- name: Check out message-ix-models
74102
uses: francisbilham11/action-cached-lfs-checkout@v3
75103

76-
- uses: actions/setup-python@v5
104+
- name: Set up uv, Python
105+
uses: astral-sh/setup-uv@v5
77106
with:
107+
cache-dependency-glob: "**/pyproject.toml"
78108
python-version: ${{ matrix.version.python }}
79-
cache: pip
80-
cache-dependency-path: "**/pyproject.toml"
81109

82110
- uses: iiasa/actions/setup-gams@main
83111
with:
84-
version: 43.4.1
112+
version: ${{ env.gams-version }}
85113
license: ${{ secrets.GAMS_LICENSE }}
86114

87115
- uses: ts-graphviz/setup-graphviz@v2
88116
# Work around ts-graphviz/setup-graphviz#630
89-
if: ${{ matrix.os != 'macos-13' }}
117+
if: matrix.os != 'macos-13'
90118

91119
- name: Determine extra dependencies
92-
id: extra-deps
120+
id: dependencies
93121
run : |
94122
from os import environ
95123
from pathlib import Path
@@ -110,42 +138,36 @@ jobs:
110138
- name: Install packages and dependencies
111139
# By default, install:
112140
# - ixmp, message_ix: from GitHub branches/tags per matrix.version.upstream (above)
113-
# - other dependencies including genno: from PyPI.
141+
# - other dependencies: from PyPI.
114142
#
115-
# To test against unreleased code (on `main`, or other branches
116-
# for open PRs), temporarily uncomment, add, or edit lines below
117-
# as needed. DO NOT merge such changes to `main`.
143+
# To test against unreleased code (on `main`, or other branches for open PRs),
144+
# temporarily edit or add lines below as needed. DO NOT merge such changes to `main`.
118145
run: |
119-
pip install --upgrade "ixmp @ git+https://github.com/iiasa/ixmp.git@${{ matrix.version.upstream }}"
120-
pip install --upgrade "message-ix @ git+https://github.com/iiasa/message_ix.git@${{ matrix.version.upstream }}"
121-
122-
pip install .[docs,tests] ${{ steps.extra-deps.outputs.value }}
123-
124-
# TEMPORARY With Python 3.13 pyam-iamc resolves to 1.3.1, which in turn
125-
# limits pint < 0.17. Override.
126-
pip install --upgrade pint
146+
uv pip install --upgrade \
147+
${{ steps.dependencies.outputs.value }} \
148+
"ixmp @ git+https://github.com/iiasa/ixmp.git@${{ matrix.version.upstream }}" \
149+
"message-ix @ git+https://github.com/iiasa/message_ix.git@${{ matrix.version.upstream }}" \
150+
.[docs,tests]
127151
128152
- name: Configure local data path
129153
run: |
130154
mkdir -p message-local-data/cache
131155
mix-models config set "message local data" "$(realpath message-local-data)"
132156
mix-models config show
133-
shell: bash
134157
135158
- name: Run test suite using pytest
136159
run: |
137160
pytest message_ix_models \
138161
-m "not (ece_db or snapshot)" \
139-
-rA --verbose --color=yes --durations=20 \
162+
--color=yes --durations=20 -rA --verbose \
140163
--cov-report=term-missing --cov-report=xml \
141164
--numprocesses=auto \
142165
--local-cache --jvmargs="-Xmx6G"
143-
shell: bash
144166
145167
- name: Upload test coverage to Codecov.io
146168
uses: codecov/codecov-action@v5
147169
with:
148-
token: ${{ secrets.CODECOV_TOKEN }} # required
170+
token: ${{ secrets.CODECOV_TOKEN }} # Required
149171

150172
pre-commit:
151173
name: Code quality
@@ -154,12 +176,13 @@ jobs:
154176

155177
steps:
156178
- uses: actions/checkout@v4
157-
- uses: actions/setup-python@v5
158-
with: { python-version: "3.13" }
159-
160-
- name: Force recreation of pre-commit virtual environment for mypy
161-
if: github.event_name == 'schedule' # Comment this line to run on a PR
162-
run: gh cache list -L 999 | cut -f2 | grep pre-commit | xargs -I{} gh cache delete "{}" || true
163-
env: { GH_TOKEN: "${{ github.token }}" }
164-
165-
- uses: pre-commit/[email protected]
179+
- uses: astral-sh/setup-uv@v5
180+
with:
181+
cache-dependency-glob: "**/pyproject.toml"
182+
python-version: ${{ env.python-version }}
183+
- uses: actions/cache@v4
184+
with:
185+
path: ~/.cache/pre-commit
186+
key: pre-commit|${{ env.UV_PYTHON }}|${{ hashFiles('.pre-commit-config.yaml') }}
187+
lookup-only: ${{ github.event_name == 'schedule' }} # Set 'true' to recreate cache
188+
- run: uvx pre-commit run --all-files --color=always --show-diff-on-failure

.pre-commit-config.yaml

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,19 @@
11
repos:
2-
- repo: local
2+
- repo: https://github.com/pre-commit/mirrors-mypy
3+
rev: v1.14.1
34
hooks:
45
- id: mypy
5-
name: mypy
6-
always_run: true
7-
require_serial: true
86
pass_filenames: false
9-
10-
language: python
11-
entry: bash -c ". ${PRE_COMMIT_MYPY_VENV:-/dev/null}/bin/activate 2>/dev/null; mypy $0 $@; python -m pip list"
127
additional_dependencies:
13-
- mypy >= 1.13.0
8+
- "ixmp @ git+https://github.com/iiasa/ixmp.git@main"
9+
- "message-ix @ git+https://github.com/iiasa/message_ix.git@main"
1410
- plotnine
1511
- pytest
1612
- sdmx1
1713
- types-PyYAML
1814
- types-tqdm
19-
- "ixmp @ git+https://github.com/iiasa/ixmp.git@main"
20-
- "message-ix @ git+https://github.com/iiasa/message_ix.git@main"
21-
args: ["."]
2215
- repo: https://github.com/astral-sh/ruff-pre-commit
23-
rev: v0.7.4
16+
rev: v0.9.1
2417
hooks:
2518
- id: ruff
2619
- id: ruff-format

doc/conf.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ def local_inv(name: str, *parts: str) -> Optional[str]:
184184
spec = find_spec(name)
185185
if spec and spec.origin:
186186
return str(Path(spec.origin).parents[1].joinpath(*parts, "objects.inv"))
187+
else:
188+
return None
187189

188190

189191
# For message-data, see: https://docs.readthedocs.io/en/stable/guides/intersphinx.html#intersphinx-with-private-projects

message_ix_models/model/material/material_demand/material_demand_calc.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def read_timer_pop(
100100
datapath: str | Path, material: Literal["cement", "steel", "aluminum"]
101101
):
102102
df_population = pd.read_excel(
103-
f'{datapath}/{material_data[material]["dir"]}{material_data[material]["file"]}',
103+
f"{datapath}/{material_data[material]['dir']}{material_data[material]['file']}",
104104
sheet_name="Timer_POP",
105105
skiprows=[0, 1, 2, 30],
106106
nrows=26,
@@ -119,7 +119,7 @@ def read_timer_gdp(
119119
):
120120
# Read GDP per capita data
121121
df_gdp = pd.read_excel(
122-
f'{datapath}/{material_data[material]["dir"]}{material_data[material]["file"]}',
122+
f"{datapath}/{material_data[material]['dir']}{material_data[material]['file']}",
123123
sheet_name="Timer_GDPCAP",
124124
skiprows=[0, 1, 2, 30],
125125
nrows=26,
@@ -195,7 +195,7 @@ def read_hist_mat_demand(material: Literal["cement", "steel", "aluminum"]):
195195
if material == "aluminum":
196196
df_raw_cons = (
197197
pd.read_excel(
198-
f'{datapath}/{material_data[material]["dir"]}{material_data[material]["file"]}',
198+
f"{datapath}/{material_data[material]['dir']}{material_data[material]['file']}",
199199
sheet_name="final_table",
200200
nrows=378,
201201
)
@@ -213,7 +213,7 @@ def read_hist_mat_demand(material: Literal["cement", "steel", "aluminum"]):
213213
)
214214
elif material == "steel":
215215
df_raw_cons = pd.read_excel(
216-
f'{datapath}/{material_data[material]["dir"]}{material_data[material]["file"]}',
216+
f"{datapath}/{material_data[material]['dir']}{material_data[material]['file']}",
217217
sheet_name="Consumption regions",
218218
nrows=26,
219219
)
@@ -246,7 +246,7 @@ def read_hist_mat_demand(material: Literal["cement", "steel", "aluminum"]):
246246
)
247247
elif material == "cement":
248248
df_raw_cons = pd.read_excel(
249-
f'{datapath}/{material_data[material]["dir"]}{material_data[material]["file"]}',
249+
f"{datapath}/{material_data[material]['dir']}{material_data[material]['file']}",
250250
sheet_name="Regions",
251251
skiprows=122,
252252
nrows=26,
@@ -358,7 +358,7 @@ def derive_demand(
358358

359359
# get base year demand of material
360360
df_base_demand = read_base_demand(
361-
f'{datapath}/{material_data[material]["dir"]}/demand_{material}.yaml'
361+
f"{datapath}/{material_data[material]['dir']}/demand_{material}.yaml"
362362
)
363363

364364
# get historical data (material consumption, pop, gdp)

message_ix_models/model/transport/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ def share_constraints(c: Computer, k_fe: "genno.Key", k_ue: "genno.Key") -> None
373373
)
374374

375375
# Transform ue-share values to the expected format
376-
base = c.full_key("ue::share")
376+
base = Key(c.full_key("ue::share"))
377377
for kind, (label, groupby) in product(
378378
("lo", "up"),
379379
(

message_ix_models/model/transport/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ def get_cl_scenario() -> "Codelist":
441441
as_ = read("IIASA_ECE:AGENCIES")
442442
cl_ssp_2024 = read("ICONICS:SSP(2024)")
443443

444-
cl = common.Codelist(
444+
cl: "common.Codelist" = common.Codelist(
445445
id="CL_TRANSPORT_SCENARIO", maintainer=as_["IIASA_ECE"], version="1.0.0"
446446
)
447447

0 commit comments

Comments
 (0)