-
Notifications
You must be signed in to change notification settings - Fork 4
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
Improve yaml models: ConfigTasks #122
Merged
Merged
Changes from 8 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
56d911a
[wip] PoC solution for #84
DropD 5fcd72c
fix #84
DropD a690f43
cleanup
DropD 38a8cb9
add missing config tasks doctests
DropD daf8430
Merge branch 'main' into improve-models-tasks
DropD 696ca6d
rename `NamelistInfo` -> `NamelistSpec`
DropD 534efc3
add comment about type checker specific isinstance check
DropD f773837
rename `_yaml_data_models` -> `yaml_data_models`
DropD 4604dde
cleanup some imports
DropD 46db910
fix typo in 'yaml_data_models.py'
DropD cc62bc7
Merge branch 'main' into improve-models-tasks
DropD File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,15 +3,19 @@ | |
import re | ||
from dataclasses import dataclass, field | ||
from pathlib import Path | ||
from typing import TYPE_CHECKING, Any, Self | ||
|
||
import f90nml | ||
|
||
from sirocco.core.graph_items import Task | ||
from sirocco.parsing._yaml_data_models import ConfigIconTaskSpecs | ||
from sirocco.parsing import yaml_data_models as models | ||
|
||
if TYPE_CHECKING: | ||
from sirocco.parsing.yaml_data_models import ConfigTask | ||
|
||
|
||
@dataclass(kw_only=True) | ||
class IconTask(ConfigIconTaskSpecs, Task): | ||
class IconTask(models.ConfigIconTaskSpecs, Task): | ||
core_namelists: dict[str, f90nml.Namelist] = field(default_factory=dict) | ||
|
||
def init_core_namelists(self): | ||
|
@@ -93,3 +97,20 @@ def section_index(section_name) -> tuple[str, int | None]: | |
if m := multi_section_pattern.match(section_name): | ||
return m.group(1), int(m.group(2)) - 1 | ||
return section_name, None | ||
|
||
@classmethod | ||
def build_from_config(cls: type[Self], config: ConfigTask, **kwargs: Any) -> Self: | ||
config_kwargs = dict(config) | ||
del config_kwargs["parameters"] | ||
# The following check is here for type checkers. | ||
# We don't want to narrow the type in the signature, as that would break liskov substitution. | ||
# We guarantee elsewhere this is called with the correct type at runtime | ||
if not isinstance(config, models.ConfigIconTask): | ||
raise TypeError | ||
Comment on lines
+109
to
+110
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This check is here to satisfy mypy, because we can not put this as a type hint in the signature (would break Liskof substitution principle -> mypy complains). Not necessary for |
||
config_kwargs["namelists"] = { | ||
nml.path.name: models.NamelistSpec(**nml.model_dump()) for nml in config.namelists | ||
} | ||
return cls( | ||
**kwargs, | ||
**config_kwargs, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
from ._yaml_data_models import ( | ||
from .yaml_data_models import ( | ||
ConfigWorkflow, | ||
) | ||
|
||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, just for my understanding: We're supporting Python >= 3.10, but
Self
type was introduced in 3.11. Is that an issue, or can we use newer Python features in type hinting? According to ChatGPT:"""
You're correct—Self was introduced in Python 3.11, not 3.12. Since your package claims to support Python 3.10+, using Self directly would be a problem for users on 3.10.
Can you use newer Python concepts in type annotations?
Yes! Starting with PEP 563 (Python 3.7) and PEP 649 (Python 3.10), Python supports postponed evaluation of annotations, meaning type hints are stored as strings instead of being evaluated immediately. This allows you to use newer type hints while keeping compatibility with older versions, as long as they aren't used at runtime.
Solution:
If you add this import at the top of your module:
from __future__ import annotations
Then the Self annotation will be treated as a string ("Self") and won't cause syntax errors in Python 3.10. However, tools like mypy will still understand it.
"""
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GPT is correct in that it was introduced later and in that in our case it works (at runtime) because it is treated as a string. Here's how that applies to Sirocco:
For now, we have set the hatch project to run type analysis on 3.12 and we use the future annotations. Therefore it is type checked as if it was supporting 3.12+ (ok at analysis time), while the interpreter treats all the type hints as just strings (ok at run time).
If we were to lower that to 3.10, we would have to import
Self
fromtyping_extensions
(making that a dependency), if we choose to keep using it. It would also affect other things (not touched in this PR) likeclass Store[T]
, which would have to turn intoclass Store(typing.Generic[T])
. The backports intyping_extensions
can catch some of this but not syntax changes likeclass Store[T]
(which I am honestly suprised that it works at runtime). I am also wondering whyfrom typing import Self
does not cause an import error in 3.10, but it seems not to.