-
Notifications
You must be signed in to change notification settings - Fork 154
OmegaConf.to_container(..., throw_on_missing) keyword arg #730
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
Changes from 9 commits
c658e55
998802a
cb78bc7
3bbe835
ea7ad68
a283995
c655234
f5a6206
94b9a80
2ca0538
40278d8
1e7af80
28bcd62
834a0bc
52d5c89
c1893e3
f664ecd
ba97dcb
df47f0e
bbfbe02
0df8e1a
6f696f3
05221aa
e9fa803
05a3e51
4d3195f
0d87d3c
e11bb05
a059a8f
a4cc88c
6d570df
f98b1f0
e67739b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,13 +37,14 @@ | |
| type_str, | ||
| valid_value_annotation_type, | ||
| ) | ||
| from .base import Container, ContainerMetadata, DictKeyType, Node, SCMode | ||
| from .base import Container, ContainerMetadata, DictKeyType, Node | ||
| from .basecontainer import BaseContainer | ||
| from .errors import ( | ||
| ConfigAttributeError, | ||
| ConfigKeyError, | ||
| ConfigTypeError, | ||
| InterpolationResolutionError, | ||
| InterpolationToMissingValueError, | ||
| KeyValidationError, | ||
| MissingMandatoryValue, | ||
| OmegaConfBaseException, | ||
|
|
@@ -469,7 +470,7 @@ def _get_node( | |
| if throw_on_missing_key: | ||
| raise ConfigKeyError(f"Missing key {key}") | ||
| elif throw_on_missing_value and value._is_missing(): | ||
| raise MissingMandatoryValue("Missing mandatory value") | ||
| raise MissingMandatoryValue("Missing mandatory value: $KEY") | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can try this here:
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See my comment above. |
||
| return value | ||
|
|
||
| def pop(self, key: DictKeyType, default: Any = _DEFAULT_MARKER_) -> Any: | ||
|
|
@@ -711,6 +712,8 @@ def _to_object(self) -> Any: | |
| This requires `self` to be a structured config. | ||
| Nested subconfigs are converted to_container with resolve=True. | ||
| """ | ||
| from omegaconf import OmegaConf | ||
|
|
||
| object_type = self._metadata.object_type | ||
| assert is_structured_config(object_type) | ||
| object_type_field_names = set(get_structured_config_field_names(object_type)) | ||
|
|
@@ -720,14 +723,12 @@ def _to_object(self) -> Any: | |
| for k in self.keys(): | ||
| node = self._get_node(k) | ||
| assert isinstance(node, Node) | ||
| node = node._dereference_node() | ||
| try: | ||
| node = node._dereference_node() | ||
| except InterpolationToMissingValueError as e: | ||
| self._format_and_raise(key=k, value=None, cause=e) | ||
| if isinstance(node, Container): | ||
| v = BaseContainer._to_content( | ||
| node, | ||
| resolve=True, | ||
| enum_to_str=False, | ||
| structured_config_mode=SCMode.INSTANTIATE, | ||
| ) | ||
| v = OmegaConf.to_object(node) | ||
odelalleau marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| else: | ||
| v = node._value() | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,6 +36,7 @@ | |
| ConcretePlugin, | ||
| IllegalType, | ||
| Module, | ||
| NestedInterpolationToMissing, | ||
| Package, | ||
| Plugin, | ||
| Str2Int, | ||
|
|
@@ -1288,6 +1289,83 @@ def finalize(self, cfg: Any) -> None: | |
| ), | ||
| id="to_object:structured-missing-field", | ||
| ), | ||
| param( | ||
| Expected( | ||
| create=lambda: OmegaConf.structured(NestedInterpolationToMissing).subcfg, | ||
omry marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| op=lambda cfg: OmegaConf.to_object(cfg), | ||
| exception_type=InterpolationToMissingValueError, | ||
| msg=( | ||
| "MissingMandatoryValue while resolving interpolation: " | ||
| "Missing mandatory value: name" | ||
| ), | ||
| key="baz", | ||
| full_key="subcfg.baz", | ||
| child_node=lambda cfg: cfg._get_node("baz"), | ||
| ref_type=NestedInterpolationToMissing.BazParams, | ||
| ), | ||
| id="to_object:structured-throw_on_missing-interpolation", | ||
| ), | ||
| # to_container throw_on_missing | ||
| param( | ||
| Expected( | ||
| create=lambda: OmegaConf.create( | ||
| {"missing_val": "???", "subcfg": {"x": "${missing_val}"}} | ||
| ).subcfg, | ||
| op=lambda cfg: OmegaConf.to_container( | ||
| cfg, resolve=True, throw_on_missing=True | ||
| ), | ||
| exception_type=InterpolationToMissingValueError, | ||
| msg=( | ||
| "MissingMandatoryValue while resolving interpolation: " | ||
| "Missing mandatory value: missing_val" | ||
| ), | ||
| key="x", | ||
| full_key="subcfg.x", | ||
| child_node=lambda cfg: cfg._get_node("x"), | ||
| ), | ||
| id="to_container:throw_on_missing-interpolation", | ||
| ), | ||
| param( | ||
| Expected( | ||
| create=lambda: DictConfig("???"), | ||
| op=lambda cfg: OmegaConf.to_container(cfg, throw_on_missing=True), | ||
| exception_type=MissingMandatoryValue, | ||
| msg="Encountered a missing DictConfig with `throw_on_missing==True`", | ||
| ), | ||
| id="to_container:throw_on_missing-dict", | ||
| ), | ||
| param( | ||
| Expected( | ||
| create=lambda: ListConfig("???"), | ||
| op=lambda cfg: OmegaConf.to_container(cfg, throw_on_missing=True), | ||
| exception_type=MissingMandatoryValue, | ||
| msg="Encountered a missing ListConfig with `throw_on_missing==True`", | ||
| ), | ||
| id="to_container:throw_on_missing-list", | ||
| ), | ||
| param( | ||
| Expected( | ||
| create=lambda: DictConfig({"a": "???"}), | ||
| op=lambda cfg: OmegaConf.to_container(cfg, throw_on_missing=True), | ||
| exception_type=MissingMandatoryValue, | ||
| msg="Missing mandatory value: a", | ||
| key="a", | ||
| child_node=lambda cfg: cfg._get_node("a"), | ||
| ), | ||
| id="to_container:throw_on_missing-dict-value", | ||
| ), | ||
| param( | ||
| Expected( | ||
| create=lambda: ListConfig(["???"]), | ||
| op=lambda cfg: OmegaConf.to_container(cfg, throw_on_missing=True), | ||
| exception_type=MissingMandatoryValue, | ||
| msg="Missing mandatory value: 0", | ||
| key=0, | ||
| full_key="[0]", | ||
| child_node=lambda cfg: cfg._get_node(0), | ||
| ), | ||
| id="to_container:throw_on_missing-list-item", | ||
| ), | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is adding almost 200 lines to an already huge test file. |
||
| ] | ||
|
|
||
|
|
||
|
|
||
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.
Generally speaking, it's better to format exceptions at high level functions, otherwise you risk formatting them multiple times.
(e.g: in OmegaConf.to_container() or other high level functions calling _to_content()).
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.
Hmm... If I do formatting in
OmegaConf.to_container(), then I will not be able to set the$KEYproperly (since the for loop iterating through keys happens in this lower-level_to_contentfunction).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.
Is this related to this change?
raise MissingMandatoryValue("Missing mandatory value: $KEY")?Why not just use the key directly when raising the exception?
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.
Yes, I think it's related -- In the past, a
MissingMandatoryValuewould not have been raised.Something like this?
My point was: if we call
format_and_raiseinOmegaConf.to_containerinstead of here inBaseContainer._to_content, then theformat_and_raisefunction will not have the correctkeypassed in to it (since the high-level function does not know whatkeycaused the exception).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.
Yes.
Depending on exactly what is going on here, you may need to pass the key from the outside or use the key from the offending node (node._key()).
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.
I tried it in this commit on a separate branch (which is based off of this PR branch).
The tests pass, but we are losing some information in the error messages. For example, here is the error before the commit:
and here is the error after the commit:
There is no longer information about the
full_keythat caused the error.Is it really that bad to format multiple times?