-
Notifications
You must be signed in to change notification settings - Fork 122
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
Support optional _parent_ and _root_ parameters in custom resolvers #599
Conversation
omegaconf/omegaconf.py
Outdated
pass_root = "_root_" in sig.parameters | ||
if pass_parent and use_cache: | ||
raise ValueError( | ||
"use_cache=True is incompatible with functions that receive the _node_" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why write _node_
and not _parent_
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To confuse the enemy, shhhh, the enemy is listening!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some minor doc tweaks (+ @Jasha10's comment)
I think I responded to all the comments. Take a second look (not always exactly as requested). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a minor doc formatting issue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great!
The last PR I just merged is breaking one of the tests. |
Custom resolvers can now receive optional _parent_ and _root_ parameters
e1aa116
to
9bf48e3
Compare
I worked around it by not returning a tuple, but this is something we did not anticipate. |
It might make sense to allow control over the generation of config nodes from dicts, list and tuples returned by custom resolvers. Side note, this exposed a bug: the code before my fix got into an infinite loop. Not sure what this is about, worth digging further. |
That's interesting one. It's caused by a cycle in the parent -> child dependency graph. Minimum repro: c = OmegaConf.create({"x": []})
c.x.append(c)
c.x I'm working on a PR to detect such cycles in typical situations, to at least get an explicit error instead of an infinite loop. Regarding an actual fix, not sure if it'd be possible without major changes (like allowing multiple parents), but a couple of ideas (which I haven't fully thought through):
|
Yeah, I dug a bit as well and I think it's a pretty unique circumstances. I didn't dug enough to see why this is happening, but my intuition matches what are describing. I have a handling for this situation here for some scenarios when adding a node that belongs to the same config. Supporting two parents would break interpolation. parent1:
parent2:
cfg1 = OmegaConf.create(parent1)
cfg2 = OmegaConf.create(parent2)
cfg3 = OmegaConf.create({"bar" : "${a.node.foo}"})
cfg1.a = cfg3 # cfg1 is now a parent
cfg2.a = cfg3 # cfg2 is now a parent too (?)
# At this point, what is the value of `cfg3.bar`? |
Good :) Because I gave up on my PR, it turns out there are too many intertwined functionalities that break when there is a cycle in the parents. The simple approach I started with is too limited, and other potential solutions I can think of would be trickier to implement, so I'm not going to address this now.
The specific line you pointed too isn't super relevant though (I think), but what's around it is: the important point is that currently the node is deepcopied in
I'm sure it would break a lot of things :) Not going to suggest that we should get into that. |
Not intentional. |
Yes. The path is _node_wrap() -> ListConfig.init() -> _set_value() -> _set_value_impl() -> append() I created an issue to keep track of it: #601 |
Custom resolvers can now receive optional parent and root parameters.
This is the doc example: