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

SC fields without a value are now convereted to omegaconf.MISSING #391

Merged
merged 1 commit into from
Sep 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/390.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Structured Configs fields without a value are now automatically treated as OmegaConf.MISSING
19 changes: 5 additions & 14 deletions omegaconf/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,18 +181,12 @@ def _resolve_forward(type_: Type[Any], module: str) -> Type[Any]:
return type_


def _raise_missing_error(obj: Any, name: str) -> None:
raise ValueError(
f"Missing default value for {get_type_of(obj).__name__}.{name}, to indicate "
"default must be populated later use OmegaConf.MISSING"
)


def get_attr_data(obj: Any, allow_objects: Optional[bool] = None) -> Dict[str, Any]:
from omegaconf.omegaconf import OmegaConf, _maybe_wrap

flags = {"allow_objects": allow_objects} if allow_objects is not None else {}
dummy_parent = OmegaConf.create(flags=flags)
from omegaconf import MISSING

d = {}
is_type = isinstance(obj, type)
Expand All @@ -209,8 +203,7 @@ def get_attr_data(obj: Any, allow_objects: Optional[bool] = None) -> Dict[str, A
if is_nested:
value = type_
else:
_raise_missing_error(obj, name)
assert False
value = MISSING
if _is_union(type_):
e = ConfigValueError(
f"Union types are not supported:\n{name}: {type_str(type_)}"
Expand All @@ -231,7 +224,7 @@ def get_attr_data(obj: Any, allow_objects: Optional[bool] = None) -> Dict[str, A
def get_dataclass_data(
obj: Any, allow_objects: Optional[bool] = None
) -> Dict[str, Any]:
from omegaconf.omegaconf import OmegaConf, _maybe_wrap
from omegaconf.omegaconf import MISSING, OmegaConf, _maybe_wrap

flags = {"allow_objects": allow_objects} if allow_objects is not None else {}
dummy_parent = OmegaConf.create({}, flags=flags)
Expand All @@ -245,15 +238,13 @@ def get_dataclass_data(
if hasattr(obj, name):
value = getattr(obj, name)
if value == dataclasses.MISSING:
_raise_missing_error(obj, name)
assert False
value = MISSING
else:
if field.default_factory == dataclasses.MISSING: # type: ignore
if is_nested:
value = type_
else:
_raise_missing_error(obj, name)
assert False
value = MISSING
else:
value = field.default_factory() # type: ignore

Expand Down
2 changes: 1 addition & 1 deletion omegaconf/version.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import sys # pragma: no cover

__version__ = "2.1.0dev5"
__version__ = "2.1.0dev6"

msg = """OmegaConf 2.0 and above is compatible with Python 3.6 and newer.
You have the following options:
Expand Down
2 changes: 1 addition & 1 deletion tests/structured_conf/data/attr_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ class NestedWithAny:


@attr.s(auto_attribs=True)
class NoDefaultErrors:
class NoDefaultValue:
no_default: Any


Expand Down
2 changes: 1 addition & 1 deletion tests/structured_conf/data/dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ class NestedWithAny:


@dataclass
class NoDefaultErrors:
class NoDefaultValue:
no_default: Any


Expand Down
10 changes: 2 additions & 8 deletions tests/structured_conf/test_structured_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,8 @@ def test_plugin_merge(self, class_type: str) -> None:

def test_native_missing(self, class_type: str) -> None:
module: Any = import_module(class_type)
with pytest.raises(
ValueError,
match=re.escape(
"Missing default value for WithNativeMISSING.num,"
" to indicate default must be populated later use OmegaConf.MISSING"
),
):
OmegaConf.create(module.WithNativeMISSING)
cfg = OmegaConf.create(module.WithNativeMISSING)
assert OmegaConf.is_missing(cfg, "num")

def test_allow_objects(self, class_type: str) -> None:
module: Any = import_module(class_type)
Expand Down
15 changes: 3 additions & 12 deletions tests/structured_conf/test_structured_config.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import re
from importlib import import_module
from typing import Any, Dict, Optional

Expand Down Expand Up @@ -147,18 +146,10 @@ def validate(cfg: DictConfig) -> None:

def test_value_without_a_default(self, class_type: str) -> None:
module: Any = import_module(class_type)
with pytest.raises(
ValueError,
match=re.escape(
"Missing default value for NoDefaultErrors.no_default,"
" to indicate default must be populated later use OmegaConf.MISSING"
),
):
OmegaConf.structured(module.NoDefaultErrors)
cfg = OmegaConf.structured(module.NoDefaultValue)
assert OmegaConf.is_missing(cfg, "no_default")

OmegaConf.structured(module.NoDefaultErrors(no_default=10)) == {
"no_default": 10
}
OmegaConf.structured(module.NoDefaultValue(no_default=10)) == {"no_default": 10}

def test_union_errors(self, class_type: str) -> None:
module: Any = import_module(class_type)
Expand Down