-
Notifications
You must be signed in to change notification settings - Fork 94
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
Feature attrdict and model definition declutter #719
Conversation
… YAML / inheritance functions
@brynpickering tests run well on my side, with no visible impact on performance. |
Some additional context @brynpickering: |
Documentation has been updated. The YAML section now also explains templating (since it's now a generic feature). |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #719 +/- ##
==========================================
+ Coverage 95.98% 96.09% +0.10%
==========================================
Files 29 29
Lines 4060 4067 +7
Branches 580 584 +4
==========================================
+ Hits 3897 3908 +11
+ Misses 72 68 -4
Partials 91 91
|
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.
Nice. I'm on board with this. We're slowly but surely extracting content from AttrDict and will eventually be able to remove it entirely! We'll need to work out why this change has impacted the national-scale example model, though. Something about the order of dict unions is likely messing up the national-scale model.
@@ -125,9 +206,160 @@ scenarios: | |||
* The imported files may include further files, so arbitrary degrees of nested configurations are possible. | |||
* The `import` statement can either give an absolute path or a path relative to the importing file. | |||
|
|||
## Overriding one file with another | |||
### Reusing definitions through templates |
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.
should we make it clear that templates can only be used in nodes, techs, and data_tables (at present)?
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.
not needed, they can be used anywhere now
The code in nodes, techs and data_tables that handled this was removed in this PR.
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.
ok, interesting. so you could technically have:
templates:
my_template:
tech1: ...
tech2: ...
techs:
template: my_template
?
I suppose it's fine that it can cover that edge case, even if it wouldn't be realistically used. I see now why you were concerned about the order of overrides/templates. I.e., this can't work:
templates:
my_template:
techs:
tech1: ...
tech2: ...
overrides:
override1:
template: my_template
Because the overrides are resolved before templates are?
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.
Correct. Your first example would work well.
I saw templates as purely 'extended' yaml. As in, they would work with any YAML file, and the templates code would live inside io.py
.
You are also correct in that using templates within the override would introduce issues. My code currently does not cover for it. This is the kind of edge-case that is avoided by just solving it before overrides.
So, two choices:
- Do we keep the current behaviour, and add code for the edge-case you described?
- Do we move templates to the
io.py
function (meaning thatread_rich_yaml
always solves them)?
I prefer the second even if we lose some templating power because it is more robust overall, code-wise.
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.
In terms of power of the functionality for the user, the first is the best option (since you can update just a template in an override and have it propagate throughout the rest of the model). Let's leave it like that and if we get lots of complaints of weird behaviour, we can revisit. It does require us to protect "template" as a key and not allow it as a subkey of override or scenario.
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.
Correct. I will add a function that tests for that then.
It is important because after this goes in, schemas (pydantic
) and so on must check the data structure of the dictionary returned by model_definition
, so this edge case will be missed.
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.
After going through this edge-case, it seems like a non-issue. The templates algorithm will just see the 'new' templates
or template
requested if you change it on the data, and solve accordingly.
This is more a question of what would feel 'natural' to users: updating what templates
'do' within the overrides, or just seeing them as 'copy-paste' within the overrides. Either case should be basically the same in terms of the amount of bugs.
Updating the templates within the overrides seems too convoluted for me, so I would not use it, but I think it's fine to keep the code as-is.
docs/migrating.md
Outdated
@@ -181,10 +181,9 @@ This split means you can change configuration options on-the-fly if you are work | |||
`locations` (abbreviated to `locs` in the Calliope data dimensions) has been renamed to `nodes` (no abbreviation). | |||
This allows us to not require an abbreviation and is a disambiguation from the [pandas.DataFrame.loc][] and [xarray.DataArray.loc][] methods. | |||
|
|||
### `parent` → `base_tech` + `template` | |||
### `parent` → `base_tech` |
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.
The original is correct. in v0.6 you could have an inheritance chain with parent
. You could define a parent from tech_groups
, which in turn could define a base_tech as its parent.
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.
The problem here is that this PR removes all the 'inheritance' stuff. The original text would be confusing...
Would this make sense?
### `parent` → `base_tech`
Technology inheritance has been unlinked from its abstract "base" technology. Technologies must now inherit from `base_tech` which fixed to be one of [`demand`, `supply`, `conversion`, `transmission`, `storage`].
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.
OK, but for migrating from having an inheritance chain (previously defined by parent
alone) is having base_tech
+ template
. Maybe there needs to be a separate section for tech_groups
-> templates
. Basically, if a user has tech_groups
, this page should provide them with a clear pointer for how to migrate. Currently there isn't one. That templates
can do even more than tech_groups
is besides the point.
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.
Sounds reasonable. I will include that once other aspects of this PR are clarified.
Ready for review again @brynpickering! I've included all your suggestions, except a couple that I believe are not necessary (see the unresolved comments). The random error in the national example model has been fixed. I must be honest in saying that I still see it as a bug, but it is not within the scope of this PR since it predates it. |
Thanks @irm-codebase - I've responded. Where has the loss in coverage come from? |
No prob. Looking at the codeconv report, it seems like it comes from the thinning of I can add tests, but they would not be for the functionality impacted by this PR. |
Makes sense. Nah, I won't force that on you! |
An exception seems to be in |
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.
Sorry, forgot to comment on this!
@brynpickering final update is in! I did this because the example serves both cases, and adding more text just increases our maintenance burden. |
Prepares our IO structure for
pydantic
by moving as much YAML read features as possible out ofAttrDict
.Summary of changes in this pull request
AttrDict
templates:
improvementscalliope.Model
template:
can be used anywhere within a YAML file, not justnodes
,techs
ordata_tables
inheritance
helper function. It was made redundant by the template solving.scenario
,override_dict
andtemplates
intopreprocess/model_definition.py
to ensure a single point of entry for defining their order of priority.Reviewer checklist