Skip to content

Commit

Permalink
Add #500 to release notes
Browse files Browse the repository at this point in the history
  • Loading branch information
khaeru committed Nov 17, 2023
1 parent af97a7f commit bb3084a
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 35 deletions.
24 changes: 22 additions & 2 deletions RELEASE_NOTES.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
Next release
============

.. All changes
.. -----------
Migration notes
---------------
Update code that imports from the following modules:

- :py:`ixmp.reporting` → use :py:`ixmp.report`.
- :py:`ixmp.reporting.computations` → use :py:`ixmp.report.operator`.
- :py:`ixmp.utils` → use :py:`ixmp.util`.

Code that imports from the old locations will continue to work, but will raise :class:`DeprecationWarning`.

All changes
-----------

- Support for Python 3.7 is dropped (:pull:`492`).
- Rename :mod:`ixmp.report` and :mod:`ixmp.util` (:pull:`500`).
- New reporting operators :func:`.from_url`, :func:`.get_ts`, and :func:`.store_ts` (:pull:`500`).
- New CLI command :program:`ixmp platform copy` and :doc:`CLI documentation <cli>` (:pull:`500`).
- New argument :py:`indexed_by=...` to :meth:`.Scenario.items` (thus :meth:`.Scenario.par_list` and similar methods) to iterate over (or list) only items that are indexed by a particular set (:issue:`402`, :pull:`500`).
- New :func:`.util.discard_on_error` and matching argument to :meth:`.TimeSeries.transact` to avoid locking :class:`.TimeSeries` / :class:`.Scenario` on failed operations with :class:`.JDBCBackend` (:pull:`488`).
- Work around limitations of :class:`.JDBCBackend` (:pull:`500`):

- Unit :py:`""` cannot be added with the Oracle driver (:issue:`425`).
- Certain items (variables) could not be initialized when providing :py:`idx_sets=...`, even if those match the sets fixed by the underlying Java code.
With this fix, a matching list is silently accepted; a different list raises :class:`NotImplementedError`.
- Improved type hinting for static typing of code that uses :mod:`ixmp` (:issue:`465`, :pull:`500`).

.. _v3.7.0:

Expand Down
20 changes: 7 additions & 13 deletions doc/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,15 @@ Scenario
A Scenario is a :class:`.TimeSeries` that also contains model data, including model solution data.
See the :ref:`data model documentation <data-model-data>`.

The Scenario class provides methods to manipulate model data items:
The Scenario class provides methods to manipulate :ref:`model data items <data-item>`.
In addition to generic methods (:meth:`init_item`, :meth:`items`, :meth:`list_items`, :meth:`has_item`), there are methods for each of the four item types:

- Set: :meth:`init_set`, :meth:`add_set`, :meth:`set`, :meth:`remove_set`, :meth:`has_set`
- Parameter:

- ≥1-dimensional: :meth:`init_par`, :meth:`add_par`, :meth:`par`, :meth:`remove_par`, :meth:`par_list`, and :meth:`has_par`.
- 0-dimensional: :meth:`init_scalar`, :meth:`change_scalar`, and :meth:`scalar`.
These are thin wrappers around the corresponding ``*_par`` methods, which can also be used to manipulate 0-dimensional parameters.

- Variable: :meth:`init_var`, :meth:`var`, :meth:`var_list`, and :meth:`has_var`.
- Equation: :meth:`init_equ`, :meth:`equ`, :meth:`equ_list`, and :meth:`has_equ`.
Expand All @@ -116,33 +118,25 @@ Scenario
change_scalar
clone
equ
equ_list
has_equ
has_par
has_set
has_item
has_solution
has_var
idx_names
idx_sets
init_equ
init_par
init_item
init_scalar
init_set
init_var
items
list_items
load_scenario_data
par
par_list
read_excel
remove_par
remove_set
remove_solution
scalar
set
set_list
solve
to_excel
var
var_list

.. _configuration:

Expand Down
76 changes: 56 additions & 20 deletions ixmp/core/scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ def items(
filters: Optional[Dict[str, Sequence[str]]] = None,
*,
indexed_by: Optional[str] = None,
par_data: bool = True,
par_data: Optional[bool] = None,
) -> Iterable[str]:
"""Iterate over model data items.
Expand All @@ -348,13 +348,24 @@ def items(
parameters.
filters : dict, optional
Filters for values along dimensions; same as the `filters` argument to
:meth:`par`.
:meth:`par`. Only value for :attr:`.ItemType.PAR`.
indexed_by : str, optional
If given, only iterate over items where one of the item dimensions is
`indexed_by` the set of this name.
par_data : bool, optional
If :any:`True` (the default) and `type` is :data:`.ItemType.PAR`, also
iterate over data for each parameter.
Yields
------
str
if `type` is not :attr:`.ItemType.PAR`, or `par_data` is :any:`False`:
names of items.
tuple
Each tuple consists of (item name, item data).
if `type` is :attr:`.ItemType.PAR` and `par_data` is :any:`True`:
each tuple is (item name, item data).
"""
# Handle `filters` argument
if filters is None:
filters = dict()
elif type != ItemType.PAR:
Expand All @@ -363,8 +374,22 @@ def items(
+ repr(type.name).lower()
)

# Handle `par_data` argument
if type == ItemType.PAR and par_data is None:
warn(
"using default par_data=True. In a future version of ixmp, "
"par_data=False will be default.",
FutureWarning,
2,
)
par_data = True
elif par_data is None:
par_data = False

# Sorted list of items from the back end
names = sorted(self._backend("list_items", str(type.name).lower()))

# Iterate over items
for name in names:
idx_names = set(self.idx_names(name))
idx_sets = set(self.idx_sets(name))
Expand All @@ -383,24 +408,35 @@ def items(
_filters = {k: v for k, v in filters.items() if k in idx_names}
yield (name, self.par(name, filters=_filters)) # type: ignore [misc]
else:
# Only the name of the item
yield name

def has_item(self, name: str, item_type=ItemType.MODEL) -> bool:
"""Check whether the Scenario has an item `name` of `item_type`.
In general, user code **should** call one of :meth:`.has_equ`, :meth:`.has_par`,
:meth:`.has_set`, or :meth:`.has_var` instead of calling this method directly.
Returns
-------
True
if the Scenario contains an item of `item_type` with name `name`.
False
otherwise
See also
--------
items
"""
return name in self.items(item_type, par_data=False)

#: Check whether the scenario has a equation `name`.
#: Check whether the scenario has a equation `name`. See :meth:`has_item`.
has_equ = partialmethod(has_item, item_type=ItemType.EQU)
#: Check whether the scenario has a parameter `name`.
#: Check whether the scenario has a parameter `name`. See :meth:`has_item`.
has_par = partialmethod(has_item, item_type=ItemType.PAR)
#: Check whether the scenario has a set `name`.
#: Check whether the scenario has a set `name`. See :meth:`has_item`.
has_set = partialmethod(has_item, item_type=ItemType.SET)
#: Check whether the scenario has a variable `name`.
#: Check whether the scenario has a variable `name`. See :meth:`has_item`.
has_var = partialmethod(has_item, item_type=ItemType.VAR)

def init_item(
Expand Down Expand Up @@ -450,17 +486,17 @@ def init_item(
"init_item", str(item_type.name).lower(), name, idx_sets, idx_names
)

#: Initialize a new equation.
#: Initialize a new equation. See :meth:`init_item`.
init_equ = partialmethod(init_item, ItemType.EQU)
#: Initialize a new parameter.
#: Initialize a new parameter. See :meth:`init_item`.
init_par = partialmethod(init_item, ItemType.PAR)
#: Initialize a new set.
#: Initialize a new set. See :meth:`init_item`.
init_set = partialmethod(init_item, ItemType.SET)
#: Initialize a new variable.
#: Initialize a new variable. See :meth:`init_item`.
init_var = partialmethod(init_item, ItemType.VAR)

def list_items(
self, item_type=ItemType.MODEL, indexed_by: Optional[str] = None
self, item_type: ItemType, indexed_by: Optional[str] = None
) -> List[str]:
"""List all defined items of type `item_type`.
Expand All @@ -470,14 +506,14 @@ def list_items(
"""
return list(self.items(item_type, indexed_by=indexed_by, par_data=False))

#: List all defined equations.
equ_list = partialmethod(list_items, item_type=ItemType.EQU)
#: List all defined parameters.
par_list = partialmethod(list_items, item_type=ItemType.PAR)
#: List all defined sets.
set_list = partialmethod(list_items, item_type=ItemType.SET)
#: List all defined variables.
var_list = partialmethod(list_items, item_type=ItemType.VAR)
#: List all defined equations. See :meth:`list_items`.
equ_list = partialmethod(list_items, ItemType.EQU)
#: List all defined parameters. See :meth:`list_items`.
par_list = partialmethod(list_items, ItemType.PAR)
#: List all defined sets. See :meth:`list_items`.
set_list = partialmethod(list_items, ItemType.SET)
#: List all defined variables. See :meth:`list_items`.
var_list = partialmethod(list_items, ItemType.VAR)

def add_par(
self,
Expand Down

0 comments on commit bb3084a

Please sign in to comment.