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

ListConfig append deepcopies input config nodes #738

Merged
merged 3 commits into from
Jun 3, 2021
Merged

Conversation

omry
Copy link
Owner

@omry omry commented Jun 2, 2021

Closes #601

Not worried about perf:
This is something we are already doing for DictConfig, and ListConfig is not used nearly as much.

@omry omry requested review from odelalleau and Jasha10 June 2, 2021 23:20
@Jasha10
Copy link
Collaborator

Jasha10 commented Jun 3, 2021

The BaseContainer._set_item_impl method uses a "no_deepcopy_set_nodes" flag to decide whether deepcopy shold be done.
I think that ListConfig.append should probably do the same...

@omry
Copy link
Owner Author

omry commented Jun 3, 2021

The BaseContainer._set_item_impl method uses a "no_deepcopy_set_nodes" flag to decide whether deepcopy shold be done.
I think that ListConfig.append should probably do the same...

This is an optimization, so not super critical because ListConfigs are not common.
I added it anyway. One thing I did not add was a logic that copies anyway if the assigned node is from the same config tree. I think this is handing some edge case but I would rather see it first before I enable the same logic in append.

@Jasha10
Copy link
Collaborator

Jasha10 commented Jun 3, 2021

One thing I did not add was a logic that copies anyway if the assigned node is from the same config tree. I think this is handing some edge case but I would rather see it first before I enable the same logic in append.

I commented out the edge-case logic to see what test would fail. The following case from test_merge.py would fail:

input1 = {"n": {"a": 10}, "i": "${n}"}
input2 = {"i": {"b": 20}}
expected = {"n": {"a": 10}, "i": {"a": 10, "b": 20}}
# the below succeeds
assert expected == OmegaConf.merge(input1, input2)
# the below fails: unsafe_merge returns {'n': {'a': 10, 'b': 20}, 'i': {'a': 10, 'b': 20}} 
assert expected == OmegaConf.unsafe_merge(input1, input2)

It seems that this edge case only happens when merging into an interpolation; the deepcopy prevents the merge from mutating other parts of the tree.
ListConfig.append does not mutate other parts of the tree, so I think we're safe.

@omry omry merged commit bc03bb3 into master Jun 3, 2021
@omry omry deleted the 601-list-copy branch June 3, 2021 17:47
Copy link
Collaborator

@odelalleau odelalleau left a comment

Choose a reason for hiding this comment

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

I guess I'm a few minutes late on the review, sorry. Feel free to ignore my minor comment below.

At high level I'm fine with it but I wonder if append() wouldn't be better implemented as "append None to the underlying content list, then call set_item() on the last index". There's more stuff happening in _set_item_impl() that I don't fully grasp, which may -- or may not -- matter as well for append().

@@ -0,0 +1 @@
ListConfig append now copies input config nodes
Copy link
Collaborator

Choose a reason for hiding this comment

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

Easier to read (at least to me):

Suggested change
ListConfig append now copies input config nodes
ListConfig.append now copies input config nodes

@omry
Copy link
Owner Author

omry commented Jun 3, 2021

I guess I'm a few minutes late on the review, sorry. Feel free to ignore my minor comment below.

At high level I'm fine with it but I wonder if append() wouldn't be better implemented as "append None to the underlying content list, then call set_item() on the last index". There's more stuff happening in _set_item_impl() that I don't fully grasp, which may -- or may not -- matter as well for append().

Good call.
It did cross my mind briefly but I didn't try.
Got it to work in #740.

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.

ListConfig.append() does not deep copy nodes
3 participants