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
2 changes: 1 addition & 1 deletion doc/source/openapi-v1.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions ixmp4/core/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,20 @@ def meta(self) -> "RunMetaFacade":
def meta(self, meta: dict[str, PrimitiveTypes | np.generic | None]) -> None:
self._meta._set(meta)

@property
def is_default(self) -> bool:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def is_default(self) -> bool:
@property
def is_default(self) -> bool:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, we can do that :)
Would we want this to be a read-only property or should this get a setter and deleter (that would then presumably call Run.set_as_default() and Run.unset_as_default())?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've not written setter and deleter for now since they are not required for the message_ix tutorials. If we want them at a later point, I propose a follow-up issue/PR.

We would likely want something of this sort:

@is_default.setter
def is_default(self, value: bool) -> None:
    if value:
        self.set_as_default()
    else:
        self.unset_as_default()

If it bothers us that mypy deems one test case as unreachable, we might want to set up an attribute _is_default and use is_default.setter to set that directly. Though even if is_default.getter simply returns the state of _is_default, mypy might not recognize this properly because it's hidden behind this extra layer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I agree lets leave that for another time...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe @danielhuppmann can clarify whether we actually want that :)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think doing is_default as a property is a good idea, but I would stick with the more "functional" set_as_default() to change the status, to avoid confusion or making changes by accident.

return self._model.is_default

def set_as_default(self) -> None:
"""Sets this run as the default version for its `model` + `scenario`
combination."""
self.backend.runs.set_as_default_version(self._model.id)
self._model = self.backend.runs.get_by_id(self._model.id)

def unset_as_default(self) -> None:
"""Unsets this run as the default version."""
self.backend.runs.unset_as_default_version(self._model.id)
self._model = self.backend.runs.get_by_id(self._model.id)

def require_lock(self) -> None:
if not self.owns_lock:
Expand Down
11 changes: 11 additions & 0 deletions tests/core/test_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,3 +319,14 @@ def test_run_clone(self, platform: ixmp4.Platform) -> None:
run = platform.runs.create("Model", "Scenario")
clone_without_iamc = run.clone()
assert clone_without_iamc.iamc.tabulate().empty

def test_run_is_default(self, platform: ixmp4.Platform) -> None:
run = platform.runs.create("Model", "Scenario")
assert run.is_default is False

run.set_as_default()
assert run.is_default

# Mypy doesn't know that set_as_default() reloads the underlying run._model
run.unset_as_default() # type: ignore[unreachable]
assert not run.is_default