Skip to content
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

Facades as dataclasses #44

Merged
merged 45 commits into from Jan 18, 2023
Merged

Facades as dataclasses #44

merged 45 commits into from Jan 18, 2023

Conversation

jnnr
Copy link
Member

@jnnr jnnr commented Aug 4, 2022

This is a draft to show how facades can be implemented as dataclasses. The advantages are:

  • explicit definition of class attributes
  • type annotation
  • Clearer handling of required and default arguments

Special attention has been given to make sure that the behaviour of the classes regarding required and default arguments does not change. This has been checked manually, via the constraint tests and by re-running and comparing an energysystem in the model oemof-B3.

Note: ElectricalLine is imported from oemof.solph but does not inherit from the base class Facade. It has not been changed into a dataclass. It should move to the experimental package once that has been set up.

Problems encountered:

  • the facades original __init__ passes args and kwargs to the parent class (with super().__init__(*args, **kwargs), which makes it possible to set attributes of the base class that are not explicit in the facade (like invest_relation_output_capacity for storage). To keep this behaviour, I implemented a wrapper that adds that call to the __init__.
  • Declaring the facade as dataclass may override the __hash__ method that is defined in oemof.network.Node (the hash of the class is defined as the hash of the label). Applying the correct settings (unsafe_hash=False, frozen=False, eq=False, see 6fb68f5), the __hash__ method remains untouched.

@jnnr jnnr requested a review from henhuy August 4, 2022 08:03
@henhuy
Copy link
Collaborator

henhuy commented Oct 6, 2022

Hi @jnnr, like your approach to use pythons dataclass very much!
Only thing which bothers me, is your second decorator to use kwargs in dataclasses.
Could you explain where this is needed? Could not find a case where this is needed.
As I understand a new class Storage could implement missing attribute invest_relation_output_capacity itself, or not?

@jnnr
Copy link
Member Author

jnnr commented Oct 6, 2022

Thanks for your feedback, @henhuy!

As I understand a new class Storage could implement missing attribute invest_relation_output_capacity itself, or not?

Good point - in this way, all attributes would have to be defined explicitly in the facade, which is good.
Arguments like invest_relation_output_capacity, which are used optionally, would be None by default.
Will have to test if this has other implications. I will try this with Dispatchable and Storage. If it works, we can adapt all other facades.

Update: This has more implications:

  • "_facade_requires_" would not be passed to parent class Facade. This is ok because dataclasses can handle required/optional attributes
  • Setting self.type and adding subnodes happens in Facades' init, too. The decorator could still prepend the super() call to the dataclasses init, but without passing kwargs. Would that look ok to you, @henhuy?

@henhuy
Copy link
Collaborator

henhuy commented Oct 6, 2022

Also saw, that *args and **kwargs in Facade are also forwarded to Nodes __init__ function.
Thus, maybe some other kwargs may not be covered in case of fixed attr?
Argh - those kwargs are really annoying.
So maybe we stay with your approach.

@jnnr jnnr requested a review from gnn November 11, 2022 09:38
src/oemof/tabular/facades.py Outdated Show resolved Hide resolved
@jnnr jnnr self-assigned this Nov 23, 2022
@jnnr
Copy link
Member Author

jnnr commented Dec 19, 2022

Thanks for continuing this, @monika-o!
You can have a look at results of the constraint tests (in github actions or locally at your computer by running pytest tests/test_constraints.py to find out where your changes change the lp files (they represent the optimization problem). These tests compare the lp-files that are generated for each component to a predefined default. Goal is that they remain the same.

@jnnr jnnr mentioned this pull request Jan 4, 2023
15 tasks
src/oemof/tabular/facades.py Outdated Show resolved Hide resolved
src/oemof/tabular/facades.py Outdated Show resolved Hide resolved
@jnnr
Copy link
Member Author

jnnr commented Jan 6, 2023

TODOs:

Test

  • Test with oemof-B3 model instances: preprocessed Datapackages and results are identical.

@jnnr jnnr marked this pull request as ready for review January 9, 2023 08:40
Copy link
Member Author

@jnnr jnnr left a comment

Choose a reason for hiding this comment

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

I checked for all facade classes that have been adapted if their behavior has changed and found only few lines to correct.
In addition, the _facade_requires seem not to be used any more and could be dropped in the class Facade.

src/oemof/tabular/facades.py Show resolved Hide resolved
src/oemof/tabular/facades.py Show resolved Hide resolved
src/oemof/tabular/facades.py Outdated Show resolved Hide resolved
src/oemof/tabular/facades.py Outdated Show resolved Hide resolved
src/oemof/tabular/facades.py Outdated Show resolved Hide resolved
@jnnr jnnr requested review from MaGering and srhbrnds and removed request for gnn January 12, 2023 09:07
@jnnr
Copy link
Member Author

jnnr commented Jan 12, 2023

@henhuy, @MaGering. @srhbrnds : This feature is almost finished and should help working with tabular in the future. Please have a look or a review or just be informed. The main improvement is that by making the facades into dataclasses we can transparently show their attributes, datatypes and defaults.

@henhuy: I adapted the decorator kwargs_to_parent, if you have the time please have a look or let us take a look together.
@MaGering: This should not alter anything in your model. If you can, it might be good to have another check, i.e. to run your models with tabular on this branch.

@jnnr jnnr mentioned this pull request Jan 18, 2023
3 tasks
@jnnr jnnr merged commit 1e77679 into dev Jan 18, 2023
@jnnr jnnr deleted the features/dataclasses branch January 18, 2023 13:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants