-
Notifications
You must be signed in to change notification settings - Fork 5
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
Only trigger has_model_changed
when changes are actually made
#17
Comments
@dannosaur I can see how A bit tangential: Could https://github.com/team23/pydantic-apply Then, it could look like this. incoming_data: dict # some data coming from someplace else
obj = MyModel(**values_from_cache)
obj.model_apply(incoming_data) |
See, this is why I love the open source community. Another pydantic module that's incredibly useful that I didn't know about! It doesn't solve the use case though beyond making the code a lot nicer to look at, effectively the 2-3 lines in your sample, but if the values in |
This is actually the intended behaviour. Reason for this is that we see all assignments as a change, no matter if the value did actually change. This is by design, as detecting the value as really being different may not be that simple. Let me elaborate on this:
As of this we decided to always assume that when you write I know this might not be the intended behaviour for some cases, but at least each and every one of those cases can easily be found and managed (like with your code above). On the contrary if we did test the value for equality this might introduce side effects that may be hard to find and debug and lead to more headaches. Having all that said it is actually very easy to extend the class MyOwnChangeDetectionMixin(ChangeDetectionMixin):
@no_type_check
def __setattr__(self, name, value) -> None: # noqa: ANN001
# Note: You may need to also handle private attributes here
if value == self.__dict__[name]:
# Just return and do nothing if the value has not changed. Note this will
# also ensure we never mess things up with values defining their own `__eq__`
# implementation - while this also means those may not be set if the
# implementation is somewhat strange (like only checking the `id` field).
return
super().__setattr__(name, value) This also has some quirks but may be just enough for most cases and will certainly be enough for all those cases you just have strings, integers and stuff. One additional note about |
Having that all said: I'm open to having this behaviour changed if we come up with a good solution. The current implementation is a little bit naive at the moment, but still is in my opinion the best reasonable compromise when thinking about all those "special" values we could have here. |
Some options we have:
I'm currently in favour of adding an equality check for simple types and document the behaviour. |
I have created #19 to implement this idea. @dannosaur Want to test this? |
@dannosaur Does this work for you? Do you have any feedback? |
@ddanier I haven't been ignoring you! Since I wrote this ticket things took a turn and I've ended up focusing on other things for a few days. As it happens the exact use case I had for this no longer applies, BUT I have another project (or 2) where this could be very useful so I intend to check our your proposed changes shortly (though it's a holiday in the US this weekend, so might be Monday now). I'll post back soon :) |
@dannosaur No issue at all and for sure I don't want to apply any pressure on you testing this. I just thought this would make a nice addition to 0.6.0 and thus wanted to ensure it will really solve your use case. Feedback will be very much appreciated :) |
Solve #17: Check value equality for scalar field values
Released with 0.6.0 |
It seems the
has_model_changed
is triggered in the__setattr__
and doesn't consider what the value was beforehand. Take this;Ideally this flag would only flip if the value being set is not an exact match to what's already against that field in the model. This could facilitate code blocks that blindly set values against the model instead of having to check itself first;
I might have a crack at this at some point. Just wanted to throw this out there.
The text was updated successfully, but these errors were encountered: