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

Overriding configuration using an environment doesn't trigger type checks when merging into Structured config #488

Closed
4 tasks done
SimonStJG opened this issue Jan 22, 2021 · 6 comments · Fixed by #578
Closed
4 tasks done
Labels
bug Something isn't working

Comments

@SimonStJG
Copy link
Contributor

Describe the bug

If I create a structured configuration with an integer field and then merge in a configuration where that fields value is taken from an environment variable, the type checks usually associated with the structured field are not triggered.

To Reproduce

def test_strange_overriding_behaviour():
    @dataclass
    class Base:
        foo: int = omegaconf.MISSING

    override = textwrap.dedent("""
        foo: ${env:FOO_OVERRIDE}
    """)

    with MonkeyPatch.context() as mp:
        mp.setenv("FOO_OVERRIDE", "This is not an integer")
        base_conf = omegaconf.OmegaConf.structured(Base)
        override_conf = omegaconf.OmegaConf.create(override)

        # This does not raise ValidationError but merges successfully, and merged_conf.foo is set to the string
        # "This is not an integer"
        with pytest.raises(omegaconf.ValidationError):
            merged_conf = omegaconf.OmegaConf.merge(base_conf, override_conf)

Expected behavior

I expected a validation error to be raised on merge, as it would have been had I set:
override = "foo: "This is not an integer"

Additional context

  • OmegaConf version: 2.0.5
  • Python version: 3.8.5
  • Operating system : Ubuntu 16.04.7 LTS
  • Please provide a minimal repro
@SimonStJG SimonStJG added the bug Something isn't working label Jan 22, 2021
@SimonStJG
Copy link
Contributor Author

Also tested on 2.0.6

@omry
Copy link
Owner

omry commented Jan 22, 2021

Custom resolvers return value is not merged into the config. They can actually return anything (including incompatible objects).

This behavior is intentional.
It's worth considering validating the return value of custom resolvers defined in typed fields, but that's an enhancement and not a bug.

@omry
Copy link
Owner

omry commented Jan 22, 2021

from dataclasses import dataclass
from omegaconf import SI, OmegaConf

OmegaConf.register_resolver("foo", lambda: "not an int")


@dataclass
class Foo:
    bar: int = SI("${foo:}")


foo = OmegaConf.structured(Foo)
print(foo.bar) # not an int

@SimonStJG
Copy link
Contributor Author

Hi @omry, thanks for the explanation, that makes sense. Would you be interested in a little docs update pr, perhaps in the Interpolation subsection of the structured config section, to make this behaviour clear?

Also thanks for maintaining this, its been a lovely library to use.

@omry
Copy link
Owner

omry commented Jan 23, 2021

Yes, a PRs to improve the docs are always welcome!
Once we get into master, you can send a second PR cherry picking it into the 2.0_branch so that it appears in the docs for the current stable version.

Glad to hear you like OmegaConf. I also recommend that you check out Hydra, which builds on top of OmegaConf.

SimonStJG added a commit to SimonStJG/omegaconf that referenced this issue Jan 24, 2021
@omry omry closed this as completed in cf4b259 Jan 30, 2021
SimonStJG added a commit to SimonStJG/omegaconf that referenced this issue Jan 30, 2021
…y#488.

* Improve docs regarding interpolations in structured config.  Fixes omry#488.

* Reword description of type validation in structured config
omry pushed a commit that referenced this issue Jan 30, 2021
… (#500)

* Improve docs regarding interpolations in structured config.  Fixes #488.

* Reword description of type validation in structured config
odelalleau added a commit to odelalleau/omegaconf that referenced this issue Feb 5, 2021
odelalleau added a commit to odelalleau/omegaconf that referenced this issue Feb 5, 2021
odelalleau pushed a commit to odelalleau/omegaconf that referenced this issue Feb 5, 2021
…y#488 (omry#493)

* Improve docs regarding interpolations in structured config.  Fixes omry#488.

* Reword description of type validation in structured config
@odelalleau
Copy link
Collaborator

odelalleau commented Feb 6, 2021

Reopening as this will be fixed by #445 an upcoming PR following up on #445 in OmegaConf 2.1.

The new behavior will automatically try to convert the output of a resolver (or any interpolation) into the desired type.

@odelalleau odelalleau reopened this Feb 6, 2021
odelalleau added a commit to odelalleau/omegaconf that referenced this issue Feb 10, 2021
odelalleau added a commit to odelalleau/omegaconf that referenced this issue Feb 10, 2021
odelalleau added a commit to odelalleau/omegaconf that referenced this issue Feb 11, 2021
odelalleau added a commit to odelalleau/omegaconf that referenced this issue Mar 3, 2021
This commit fixes several issues:

* For nested resolvers (ex: `${f:${g:x}}`), intermediate resolver
  outputs (of `g` in this example) were wrapped in a ValueNode just to
  be unwrapped immediately, which was wasteful. This commit pushes the
  node wrapping to the very last step of the interpolation resolution.

* There was no type checking to make sure that the result of an
  interpolation had a type consistent with the node's type (when
  specified). Now a check is made and the interpolation result may be
  converted into the desired type (see omry#488).

* If a resolver interpolation returns a dict / list, it is now wrapped
  into a DictConfig / ListConfig, instead of a ValueNode. This makes it
  possible to generate configs from resolvers (see omry#540)

Fixes omry#488
Fixes omry#540
odelalleau added a commit to odelalleau/omegaconf that referenced this issue Mar 3, 2021
This commit fixes several issues:

* For nested resolvers (ex: `${f:${g:x}}`), intermediate resolver
  outputs (of `g` in this example) were wrapped in a ValueNode just to
  be unwrapped immediately, which was wasteful. This commit pushes the
  node wrapping to the very last step of the interpolation resolution.

* There was no type checking to make sure that the result of an
  interpolation had a type consistent with the node's type (when
  specified). Now a check is made and the interpolation result may be
  converted into the desired type (see omry#488).

* If a resolver interpolation returns a dict / list, it is now wrapped
  into a DictConfig / ListConfig, instead of a ValueNode. This makes it
  possible to generate configs from resolvers (see omry#540)

Fixes omry#488
Fixes omry#540
odelalleau added a commit to odelalleau/omegaconf that referenced this issue Mar 10, 2021
This commit fixes several issues:

* For nested resolvers (ex: `${f:${g:x}}`), intermediate resolver
  outputs (of `g` in this example) were wrapped in a ValueNode just to
  be unwrapped immediately, which was wasteful. This commit pushes the
  node wrapping to the very last step of the interpolation resolution.

* There was no type checking to make sure that the result of an
  interpolation had a type consistent with the node's type (when
  specified). Now a check is made and the interpolation result may be
  converted into the desired type (see omry#488).

* If a resolver interpolation returns a dict / list, it is now wrapped
  into a DictConfig / ListConfig, instead of a ValueNode. This makes it
  possible to generate configs from resolvers (see omry#540)

Fixes omry#488
Fixes omry#540
@omry omry closed this as completed in #578 Mar 13, 2021
omry pushed a commit that referenced this issue Mar 13, 2021
Validate and convert interpolation results to their intended type

This PR fixes several issues:

* For nested resolvers (ex: `${f:${g:x}}`), intermediate resolver
  outputs (of `g` in this example) were wrapped in a ValueNode just to
  be unwrapped immediately, which was wasteful. This commit pushes the
  node wrapping to the very last step of the interpolation resolution.

* There was no type checking to make sure that the result of an
  interpolation had a type consistent with the node's type (when
  specified). Now a check is made and the interpolation result may be
  converted into the desired type (see #488).

* If a resolver interpolation returns a dict / list, it is now wrapped
  into a DictConfig / ListConfig, instead of a ValueNode. This makes it
  possible to generate configs from resolvers (see #540). These configs
  are read-only since they are being re-generated on each access.


Fixes #488
Fixes #540
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants