-
Notifications
You must be signed in to change notification settings - Fork 893
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
Revisit: Make KedroContext a dataclass and add config_loader
as a property
#1459
Comments
Turns out using the
|
This was merged already, but as we approaching 0.19, I want to revise if it's a good idea to freeze We should also consider how easy for plugin developer to use |
python/cpython#93133 (comment) Potentially helpful with the issues that using mock with dataclass or attr. |
I cross-reference #3214 here which is likely a duplicate of this, sorry!
|
Thanks for x-ref the issues. The issue has been 1.5 years old and my thinking has changed a little bit as well. I agree with you mostly because:
Basically, I think we can take a middle-ground which is Mutable class + immutable attributes. The key is to use import attr
from attrs.setters import frozen
@attr.s
class Foo:
# A partial frozen class
bar: int = attr.field(default=0, on_setattr=frozen)
f = Foo()
f.abc = 3 # It's ok to mutate the class
f.bar = 3 # It's not ok to mutate existing attribtue |
Is this possible with plain dataclass? (To avoid the extra dependency if possible) |
Choosing between
|
Package | Override existing attribute | Add extra attribute |
---|---|---|
dataclass |
✅ | ✅ |
attrs |
✅ | ❌ |
This implies that if we switch to dataclass
instead of attrs, we can keep the exact current behaviour, but the price is to have a boilerplate code as described in the first paragraph.
frozen dataclass
can be overriden and added
from dataclasses import dataclass
@dataclass(frozen=True)
class PointDataClass:
x: int
y: int
point_data_class = PointDataClass(x=1, y=1)
point_data_class.z = 2 # # FrozenInstanceError: cannot assign to field 'z'
object.__setattr__(point_data_class, "y", 4) # works: you can override an existing field
print(point_data_class.y)
point_data_class.__setattr__("z", 2) # self.__setattr__ does not work: FrozenInstanceError: cannot assign to field 'z'
object.__setattr__(point_data_class, "z", 2) # object.__setattr__ works! You can add an attribute
print(point_data_class.z) # 2
frozen attrs
attributes can be overriden and but not added
from attrs import frozen
@frozen
class PointAttrs:
x: int
y: int
point_attrs = PointAttrs(x=1, y=1)
point_attrs.z = 2
point_attrs.__setattr__("z", 2) # self.__setattr__ does not work: FrozenInstanceError
object.__setattr__(point_attrs, "y", 4) # object.__setattr__ works : you can override an existing field
print(point_attrs.y) # 4
object.__setattr__(point_attrs, "z", 2) # # object.__setattr__ does NOT work! You CANNOT add an attribute: AttributeError: 'PointAttrs' object has no attribute 'z'
@astrojuanlu So I think the key here is:
The example above shows that we can make it works for partial immutability. In my mind Whether or not we should use |
config_loader
as a propertyconfig_loader
as a property
Completed in #3300 |
Description
As
KedroSession
now control the lifecycle of Kedro's run,KedroContext
act like a container and it stores important attributes. Since we now dropped Python 3.6 support, we can make use of Python'sdataclass
to further tidy upKedroContext
's constructor code.todo:
KedroContext
a dataclass(MakeKedroContext
a frozen dataclass #1465)config_loader
as @Property instead of relying the privatecontext._get_config_loader()
Addconfig_loader
asKedroContext
property #1505The text was updated successfully, but these errors were encountered: