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

OmegaConf.to_container(..., throw_on_missing) keyword arg #730

Merged
merged 33 commits into from
Jun 13, 2021

Conversation

Jasha10
Copy link
Collaborator

@Jasha10 Jasha10 commented May 21, 2021

This PR introduces a throw_on_missing keyword arg to the OmegaConf.to_container signature.

The OmegaConf.to_object method uses throw_on_missing==True when calling into OmegaConf.to_container.

This PR replaces #503, which is outdated.

TODO:

@Jasha10 Jasha10 requested review from omry and odelalleau May 21, 2021 09:40
@odelalleau
Copy link
Collaborator

Just a note that it's going to take me a little while to get through this one (due to other priorities).

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.

Looks mostly good to me -- the main point to discuss is whether or not we want to allow interpolations to missing values when throw_on_missing is True

try:
node = conf._get_node(key, throw_on_missing_value=throw_on_missing)
except MissingMandatoryValue as e:
conf._format_and_raise(key=key, value=None, cause=e)
Copy link
Owner

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()).

Copy link
Collaborator Author

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 $KEY properly (since the for loop iterating through keys happens in this lower-level _to_content function).

Copy link
Owner

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?

Copy link
Collaborator Author

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?

Yes, I think it's related -- In the past, a MissingMandatoryValue would not have been raised.

Why not just use the key directly when raising the exception?

Something like this?

raise MissingMandatoryValue(f"Missing mandatory value: {key}")

My point was: if we call format_and_raise in OmegaConf.to_container instead of here in BaseContainer._to_content, then the format_and_raise function will not have the correct key passed in to it (since the high-level function does not know what key caused the exception).

Copy link
Owner

Choose a reason for hiding this comment

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

Something like this?

raise MissingMandatoryValue(f"Missing mandatory value: {key}")

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()).

Copy link
Collaborator Author

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:

>>> OmegaConf.to_object(OmegaConf.create({"a": {"b": "???"}}))
Traceback (most recent call last):
...
omegaconf.errors.MissingMandatoryValue: Missing mandatory value: b
    full_key: a.b
    object_type=dict

and here is the error after the commit:

>>> OmegaConf.to_object(OmegaConf.create({"a": {"b": "???"}}))
Traceback (most recent call last):
...
omegaconf.errors.MissingMandatoryValue: Missing mandatory value: b
    full_key:
    object_type=dict

There is no longer information about the full_key that caused the error.

Generally speaking, it's better to format exceptions at high level functions, otherwise you risk formatting them multiple times.

Is it really that bad to format multiple times?

@omry
Copy link
Owner

omry commented Jun 5, 2021

  1. Update the PR to indicate that issue(s) it's closing.
  2. I think we should be able to get the docs and news fragment already.

@omry
Copy link
Owner

omry commented Jun 7, 2021

Unsubscribing for now, please request review when ready.

@Jasha10 Jasha10 requested review from omry and odelalleau June 7, 2021 22:43
@Jasha10 Jasha10 marked this pull request as ready for review June 7, 2021 22:43
try:
node = conf._get_node(key, throw_on_missing_value=throw_on_missing)
except MissingMandatoryValue as e:
conf._format_and_raise(key=key, value=None, cause=e)
Copy link
Owner

Choose a reason for hiding this comment

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

Something like this?

raise MissingMandatoryValue(f"Missing mandatory value: {key}")

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()).

@@ -469,7 +469,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")
Copy link
Owner

Choose a reason for hiding this comment

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

You can try this here:

            raise MissingMandatoryValue("Missing mandatory value: '{value._key()}'")

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

See my comment above.

child_node=lambda cfg: cfg._get_node(0),
),
id="to_container:throw_on_missing,list_item",
),
Copy link
Owner

Choose a reason for hiding this comment

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

This is adding almost 200 lines to an already huge test file.
We should refactor this file somehow at some point.

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.

One minor typo in the doc

@Jasha10 Jasha10 requested a review from omry June 9, 2021 20:33
@odelalleau odelalleau self-requested a review June 9, 2021 21:50
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.

Good on my side, thanks @Jasha10!

Copy link
Owner

@omry omry left a comment

Choose a reason for hiding this comment

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

lgtm, thanks.

@Jasha10 Jasha10 merged commit e3ea9a1 into omry:master Jun 13, 2021
@Jasha10 Jasha10 deleted the closes501 branch June 13, 2021 08:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants