Skip to content

Adjust upstream versions #356

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
May 28, 2025
13 changes: 6 additions & 7 deletions .github/workflows/pytest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,22 +98,22 @@ jobs:
# - Latest supported Python version for those or other dependencies.
# Minimum version given in pyproject.toml + earlier version of Python
# For this job only, the oldest version of Python supported by message-ix-models
- { upstream: v3.7.0, python: "3.9" } # Released 2023-05-17
- { upstream: v3.8.0, python: "3.12" } # 2024-01-12
- { upstream: v3.9.0, python: "3.13" } # 2024-06-04
# Latest released version + latest released Python
- { upstream: v3.8.0, python: "3.9" } # Released 2024-01-12
- { upstream: v3.9.0, python: "3.13" } # 2024-06-04
- { upstream: v3.10.0, python: "3.13" } # 2025-02-21
# Latest released version + latest released Python
- { upstream: v3.11.0, python: "3.13" } # 2025-05-27
# Development version + latest released Python
- { upstream: main, python: "3.13" }
- { upstream: main, python: "3.13" }

exclude:
# Specific version combinations that are invalid / not to be used
# These versions of ixmp are not able locate the arm64 GAMS API binaries
- { os: macos-latest, version: { upstream: v3.7.0 }}
- { os: macos-latest, version: { upstream: v3.8.0 }}
- { os: macos-latest, version: { upstream: v3.9.0 }}
# Redundant with macos-latest
- { os: macos-13, version: { upstream: v3.10.0 }}
- { os: macos-13, version: { upstream: v3.11.0 }}
- { os: macos-13, version: { upstream: main }}

fail-fast: false
Expand Down Expand Up @@ -171,7 +171,6 @@ jobs:
if version_string != "main":
v, result = parse(version_string), []
for condition, dependency in (
(v <= Version("v3.7.0"), "genno < 1.25"), # Upstream versions < 3.8.0 import genno.computations, removed in 1.25.0 (#156)
(v < Version("v3.9.0"), "pytest == 8.0.0"), # Upstream versions < 3.9.0 use a hook argument removed in pytest 8.1.0 (#155)
):
result.extend([f'"{dependency}"'] if condition else [])
Expand Down
6 changes: 3 additions & 3 deletions doc/whatsnew.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ Next release

- In accordance with the :ref:`policy-upstream-versions`:

- :mod:`message_ix_models` supports and is tested against :mod:`ixmp` and :mod:`message_ix_models` version 3.10.0 (:pull:`299`).
- Support for :mod:`ixmp` and :mod:`message_ix` versions 3.4, 3.5, and 3.6 is dropped (:pull:`288`, :pull:`289`).
The minimum supported version of both packages is 3.7.0.
- :mod:`message_ix_models` supports and is tested against :mod:`ixmp` and :mod:`message_ix_models` versions 3.10 (:pull:`299`) and 3.11 (:pull:`356`).
- Support for :mod:`ixmp` and :mod:`message_ix` versions 3.4, 3.5, 3.6, and 3.7 is dropped (:pull:`288`, :pull:`289`, :pull:`356`).
The minimum supported version of both packages is 3.8.0.

- Update :class:`.IEA_EWEB` to support:

Expand Down
2 changes: 1 addition & 1 deletion message_ix_models/model/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

import ixmp
import pandas as pd
from ixmp.util import maybe_check_out, maybe_commit
from message_ix import Scenario
from sdmx.model.v21 import Code

from message_ix_models.util import add_par_data, strip_par_data
from message_ix_models.util.ixmp import maybe_check_out, maybe_commit
from message_ix_models.util.scenarioinfo import ScenarioInfo, Spec

log = logging.getLogger(__name__)
Expand Down
2 changes: 0 additions & 2 deletions message_ix_models/model/snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from tqdm import tqdm

from message_ix_models import Spec
from message_ix_models.util import minimum_version
from message_ix_models.util.pooch import SOURCE, fetch

from .build import apply_spec
Expand Down Expand Up @@ -101,7 +100,6 @@ def read_excel(scenario: Scenario, path: Path) -> None:
scenario.add_par(name, data)


@minimum_version("message_ix 3.5")
def load(
scenario: Scenario, snapshot_id: int, extra_cache_path: Optional[str] = None
) -> None:
Expand Down
4 changes: 3 additions & 1 deletion message_ix_models/model/transport/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,9 @@ def add_structure(c: Computer) -> None:
)


@minimum_version("message_ix 3.8; genno 1.28")
@minimum_version(
"genno 1.28", "message_ix_models.model.transport.operator.uniform_in_dim"
)
def get_computer(
context: Context,
obj: Optional[Computer] = None,
Expand Down
2 changes: 1 addition & 1 deletion message_ix_models/model/transport/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
from typing import TYPE_CHECKING, Any, Literal, Optional, Union

from genno import Quantity
from genno.operator import as_quantity

from message_ix_models import Context, ScenarioInfo, Spec
from message_ix_models.project.navigate import T35_POLICY as NAVIGATE_SCENARIO
from message_ix_models.project.ssp import SSP_2024, ssp_field
from message_ix_models.project.transport_futures import SCENARIO as FUTURES_SCENARIO
from message_ix_models.util import package_data_path
from message_ix_models.util.config import ConfigHelper
from message_ix_models.util.genno import as_quantity
from message_ix_models.util.sdmx import AnnotationsMixIn

if TYPE_CHECKING:
Expand Down
6 changes: 3 additions & 3 deletions message_ix_models/model/transport/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import pandas as pd
from genno import Computer, Key, Quantity
from genno.core.key import single_key
from ixmp.report.common import RENAME_DIMS
from message_ix import make_df

from message_ix_models import ScenarioInfo
Expand All @@ -30,7 +31,6 @@
package_data_path,
same_node,
)
from message_ix_models.util.ixmp import rename_dims
from message_ix_models.util.sdmx import DATAFLOW, STORE, Dataflow

if TYPE_CHECKING:
Expand Down Expand Up @@ -88,7 +88,7 @@ def __init__(self, source, source_kw):
def __call__(self):
from genno.operator import load_file

return load_file(self.path, dims=rename_dims())
return load_file(self.path, dims=RENAME_DIMS)

def transform(self, c: "Computer", base_key: Key) -> Key:
import xarray as xr
Expand Down Expand Up @@ -168,7 +168,7 @@ def __init__(self, source, source_kw):
self.scenario = source_kw.pop("scenario", None)

# Dimensions for loaded data
self.dims = deepcopy(rename_dims())
self.dims = deepcopy(RENAME_DIMS)
self.dims["scenario"] = "scenario"

self.raise_on_extra_kw(source_kw)
Expand Down
3 changes: 1 addition & 2 deletions message_ix_models/model/transport/operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import pandas as pd
import xarray as xr
from genno import Computer, KeySeq, Operator, quote
from genno.operator import apply_units, rename_dims
from genno.operator import apply_units, as_quantity, rename_dims
from genno.testing import assert_qty_allclose, assert_units
from scipy import integrate
from sdmx.model.common import Code, Codelist
Expand All @@ -28,7 +28,6 @@
minimum_version,
show_versions,
)
from message_ix_models.util.genno import as_quantity

from .config import Config

Expand Down
2 changes: 1 addition & 1 deletion message_ix_models/model/transport/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def tax_emission(context: "Context", scenario: "Scenario", price: float) -> "Sce
return navigate_workflow.tax_emission(context, scenario, price)


@minimum_version("message_ix 3.10.1.dev0") # Changes that will be released in 3.11
@minimum_version("message_ix 3.11")
def generate(
context: "Context",
*,
Expand Down
3 changes: 1 addition & 2 deletions message_ix_models/model/water/data/demands.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import xarray as xr
from message_ix import make_df

from message_ix_models.util import broadcast, minimum_version, package_data_path
from message_ix_models.util import broadcast, package_data_path

if TYPE_CHECKING:
from message_ix_models import Context
Expand Down Expand Up @@ -160,7 +160,6 @@ def target_rate_trt(df: pd.DataFrame, basin: pd.DataFrame) -> pd.DataFrame:
return df


@minimum_version("message_ix 3.7")
def add_sectoral_demands(context: "Context") -> dict[str, pd.DataFrame]:
"""
Adds water sectoral demands
Expand Down
2 changes: 0 additions & 2 deletions message_ix_models/model/water/data/water_for_ppl.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from message_ix_models.util import (
broadcast,
make_matched_dfs,
minimum_version,
package_data_path,
same_node,
)
Expand Down Expand Up @@ -334,7 +333,6 @@ def _compose_capacity_factor(inp: pd.DataFrame, context: "Context") -> pd.DataFr


# water & electricity for cooling technologies
@minimum_version("message_ix 3.7")
def cool_tech(context: "Context") -> dict[str, pd.DataFrame]:
"""Process cooling technology data for a scenario instance.
The input values of parent technologies are read in from a scenario instance and
Expand Down
9 changes: 1 addition & 8 deletions message_ix_models/model/water/data/water_supply.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,9 @@
from message_ix_models import Context
from message_ix_models.model.water.data.demands import read_water_availability
from message_ix_models.model.water.utils import map_yv_ya_lt
from message_ix_models.util import (
broadcast,
minimum_version,
package_data_path,
same_node,
same_time,
)
from message_ix_models.util import broadcast, package_data_path, same_node, same_time


@minimum_version("message_ix 3.7")
def map_basin_region_wat(context: "Context") -> pd.DataFrame:
"""
Calculate share of water availability of basins per each parent region.
Expand Down
2 changes: 1 addition & 1 deletion message_ix_models/project/ssp/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def _expand(qty):
)


@minimum_version("genno 1.28")
@minimum_version("message_ix_models.model.transport.build.get_computer")
def get_computer(
row0: "pd.Series", method: METHOD, *, platform_name: Optional[str] = None
) -> "Computer":
Expand Down
19 changes: 2 additions & 17 deletions message_ix_models/report/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@
from contextlib import nullcontext
from copy import deepcopy
from functools import partial
from operator import itemgetter
from pathlib import Path
from typing import TYPE_CHECKING, Optional, Union
from warnings import warn

import genno.config
import yaml
from genno import Key, KeyExistsError
from genno import Key
from genno.compat.pyam import iamc as handle_iamc
from genno.core.key import single_key
from ixmp.util import discard_on_error
from message_ix import Reporter, Scenario

from message_ix_models import Context, ScenarioInfo
from message_ix_models.util import minimum_version
from message_ix_models.util._logging import mark_time, silence_log

from .config import Config
Expand Down Expand Up @@ -166,8 +165,6 @@ def report(context: Context, *args, **kwargs):
- :py:`context.report`, which is an instance of :class:`.report.Config`; see
there for available configuration settings.
"""
from message_ix_models.util.ixmp import discard_on_error

# Handle deprecated usage that appears in:
# - .model.cli.new_baseline()
# - .model.create.solve()
Expand Down Expand Up @@ -253,7 +250,6 @@ def _invoke_legacy_reporting(context):
return iamc_report_hackathon.report(mp=mp, scen=scen, context=context, **kwargs)


@minimum_version("message_ix 3.6")
def prepare_reporter(
context: Context,
scenario: Optional[Scenario] = None,
Expand Down Expand Up @@ -371,14 +367,3 @@ def defaults(rep: Reporter, context: Context) -> None:
# Add mappings for conversions to IAMC data structures
add_replacements("c", get_codes("commodity"))
add_replacements("t", get_codes("technology"))

# Ensure "y::model" and "y0" are present
# TODO remove this once message-ix-models depends on message_ix > 3.7.0 at minimum
for comp in (
("y::model", "model_periods", "y", "cat_year"),
("y0", itemgetter(0), "y::model"),
):
try:
rep.add(*comp, strict=True)
except KeyExistsError:
pass # message_ix > 3.7.0; these are already defined
17 changes: 6 additions & 11 deletions message_ix_models/report/sim.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@
import pandas as pd
from dask.core import quote
from genno import Key, KeyExistsError
from ixmp.report.common import RENAME_DIMS
from message_ix import Reporter
from pandas.api.types import is_scalar

from message_ix_models import ScenarioInfo
from message_ix_models.util import minimum_version
from message_ix_models.util._logging import mark_time, silence_log
from message_ix_models.util.ixmp import rename_dims

if TYPE_CHECKING:
from genno.types import AnyQuantity
Expand Down Expand Up @@ -99,10 +98,9 @@ def __hash__(self):

def dims_of(info: "Item") -> dict[str, str]:
"""Return a mapping from the full index names to short dimension IDs of `info`."""
return {d: rename_dims().get(d, d) for d in (info.dims or info.coords or [])}
return {d: RENAME_DIMS.get(d, d) for d in (info.dims or info.coords or [])}


@minimum_version("message_ix 3.7.0.post0")
@lru_cache(1)
def to_simulate():
"""Return items to be included in a simulated solution."""
Expand All @@ -126,16 +124,14 @@ def reporter_from_excel(path: "Path") -> "Reporter":
"""
import pandas as pd

from message_ix_models.util.ixmp import rename_dims

rep = Reporter()
info = rep.graph["scenario info"] = ScenarioInfo(model="m", scenario="s")
ef = rep.graph["_file"] = pd.ExcelFile(path)
mock = rep.graph["scenario"] = MockScenario(info, ef)

# Add tasks to retrieve sets from file
for set_name in mock.set_list():
key = rename_dims().get(set_name, set_name)
key = RENAME_DIMS.get(set_name, set_name)
rep.add(key, partial(mock.set, set_name))

# Add tasks to retrieve parameter data from file
Expand All @@ -146,7 +142,7 @@ def reporter_from_excel(path: "Path") -> "Reporter":

# Pre-populate some sets of `info`
for name in "commodity", "node", "year":
info.set[name] = rep.get(rename_dims()[name])
info.set[name] = rep.get(RENAME_DIMS[name])

return rep

Expand Down Expand Up @@ -189,7 +185,7 @@ def simulate_qty(
df = pd.DataFrame(**args)
else:
# Provided complete data frame
df = item_data.rename(columns=rename_dims())
df = item_data.rename(columns=RENAME_DIMS)

# Data must be entirely empty, or complete
assert not df.isna().any().any() or df.isna().all().all(), data
Expand Down Expand Up @@ -236,7 +232,6 @@ def data_from_file(path: Path, *, name: str, dims: Sequence[str]) -> "AnyQuantit
return genno.Quantity(tmp["value"], name=name)


@minimum_version("message_ix 3.6")
def add_simulated_solution(
rep: Reporter,
info: ScenarioInfo,
Expand Down Expand Up @@ -291,7 +286,7 @@ def add_simulated_solution(

if item_info.type == ItemType.SET and name not in rep:
# Add the set elements from `info`
rep.add(rename_dims().get(name, name), quote(info.set[name]))
rep.add(RENAME_DIMS.get(name, name), quote(info.set[name]))
elif item_info.type in (ItemType.PAR, ItemType.VAR):
# Retrieve an existing key for `name`
try:
Expand Down
2 changes: 0 additions & 2 deletions message_ix_models/tests/model/test_snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@

import pytest

from message_ix_models.model import snapshot
from message_ix_models.testing import GHA

log = logging.getLogger(__name__)


@snapshot.load.minimum_version
@pytest.mark.skipif(
condition=GHA and sys.platform in ("darwin", "win32"), reason="Slow."
)
Expand Down
4 changes: 2 additions & 2 deletions message_ix_models/tests/model/transport/test_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
make_mark,
simulated_solution,
)
from message_ix_models.report import prepare_reporter, sim
from message_ix_models.report import prepare_reporter
from message_ix_models.util._logging import silence_log

if TYPE_CHECKING:
Expand Down Expand Up @@ -200,7 +200,7 @@ def test_simulated(request, test_context, build, regions="R12", years="B"):
assert p.joinpath("DF_POPULATION_IN.xml").exists()


@sim.to_simulate.minimum_version
@build.get_computer.minimum_version
@MARK[10]
@make_mark["gh"](328)
def test_simulated_iamc(
Expand Down
Loading
Loading