Isolate Recipe defaults to prevent modification via instances #509
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.
Describe the problem
If a recipe defines default values for list-based or dict-based fields (such as
JSONField
orArrayField
), the objects built from this recipe directly refer to these recipe defaults instead of holding their own copy of the data.Therefore, any modifications on these fields affect the recipe "parent" attribute and all depending instances. In my opinion/experience, this behavior is unexpected and error prone.
Note: For other data types, the isolation between recipe and instances is already guaranteed, which is also an argument to apply the same behavior in all cases.
Describe the proposed change
With this change, every baked instance holds an isolated copy of the recipe default attributes of any Container class (e.g.,
dict
orlist
). This prevents from affecting the parent recipe, and other (existing or future) instances, when such fields are modified on an instance.Note: The intent of this PR is trying to be "as clear as possible", without claiming to have properly solved the problem itself. The resolving implementation proposed is my "best bet", but it might be quite naive, and could likely miss important elements. Please feel free to pick what you like and create a new PR that would supersede it (especially if you feel you can fix it quickly without much coordination/communication overhead here 😉).
Workaround
With the current situation, it is possible to use a Callable as workaround to provide an immutable default value for list-based or dict-based attributes:
This solution is but not convenient as it requires awareness of the recipe behavior (and additional code).
PR Checklist