diff --git a/omegaconf/_utils.py b/omegaconf/_utils.py index 9420d0136..8a538471b 100644 --- a/omegaconf/_utils.py +++ b/omegaconf/_utils.py @@ -63,6 +63,18 @@ _CMP_TYPES = {t: i for i, t in enumerate([float, int, bool, str, type(None)])} +class Marker: + def __init__(self, desc: str): + self.desc = desc + + def __repr__(self) -> str: + return self.desc + + +# To be used as default value when `None` is not an option. +_DEFAULT_MARKER_: Any = Marker("_DEFAULT_MARKER_") + + class OmegaConfDumper(yaml.Dumper): # type: ignore str_representer_added = False @@ -76,14 +88,6 @@ def str_representer(dumper: yaml.Dumper, data: str) -> yaml.ScalarNode: ) -class Marker: - def __init__(self, desc: str): - self.desc = desc - - def __repr__(self) -> str: - return self.desc - - def get_omega_conf_dumper() -> Type[OmegaConfDumper]: if not OmegaConfDumper.str_representer_added: OmegaConfDumper.add_representer(str, OmegaConfDumper.str_representer) diff --git a/omegaconf/base.py b/omegaconf/base.py index 71b2c3d87..df8b2e64d 100644 --- a/omegaconf/base.py +++ b/omegaconf/base.py @@ -9,7 +9,7 @@ from antlr4 import ParserRuleContext from ._utils import ( - Marker, + _DEFAULT_MARKER_, ValueKind, _get_value, _is_missing_value, @@ -33,8 +33,6 @@ DictKeyType = Union[str, int, Enum, float, bool] -_MARKER_: Any = Marker("_MARKER_") - @dataclass class Metadata: @@ -156,8 +154,8 @@ def _get_flag(self, flag: str) -> Optional[bool]: if cache is None: cache = self.__dict__["_flags_cache"] = {} - ret = cache.get(flag, _MARKER_) - if ret is _MARKER_: + ret = cache.get(flag, _DEFAULT_MARKER_) + if ret is _DEFAULT_MARKER_: ret = self._get_flag_no_cache(flag) cache[flag] = ret assert ret is None or isinstance(ret, bool) diff --git a/omegaconf/basecontainer.py b/omegaconf/basecontainer.py index 6c9429414..b3bad23de 100644 --- a/omegaconf/basecontainer.py +++ b/omegaconf/basecontainer.py @@ -9,7 +9,7 @@ import yaml from ._utils import ( - Marker, + _DEFAULT_MARKER_, _ensure_container, _get_value, _is_interpolation, @@ -38,8 +38,6 @@ if TYPE_CHECKING: from .dictconfig import DictConfig # pragma: no cover -DEFAULT_VALUE_MARKER: Any = Marker("DEFAULT_VALUE_MARKER") - class BaseContainer(Container, ABC): # static @@ -53,11 +51,11 @@ def _resolve_with_default( self, key: Union[DictKeyType, int], value: Node, - default_value: Any = DEFAULT_VALUE_MARKER, + default_value: Any = _DEFAULT_MARKER_, ) -> Any: """returns the value with the specified key, like obj.key and obj['key']""" if _is_missing_value(value): - if default_value is not DEFAULT_VALUE_MARKER: + if default_value is not _DEFAULT_MARKER_: return default_value raise MissingMandatoryValue("Missing mandatory value: $FULL_KEY") diff --git a/omegaconf/dictconfig.py b/omegaconf/dictconfig.py index a8532602c..e19025c22 100644 --- a/omegaconf/dictconfig.py +++ b/omegaconf/dictconfig.py @@ -16,6 +16,7 @@ ) from ._utils import ( + _DEFAULT_MARKER_, ValueKind, _get_value, _is_interpolation, @@ -35,7 +36,7 @@ valid_value_annotation_type, ) from .base import Container, ContainerMetadata, DictKeyType, Node -from .basecontainer import DEFAULT_VALUE_MARKER, BaseContainer +from .basecontainer import BaseContainer from .errors import ( ConfigAttributeError, ConfigKeyError, @@ -345,7 +346,7 @@ def __getattr__(self, key: str) -> Any: raise AttributeError() try: - return self._get_impl(key=key, default_value=DEFAULT_VALUE_MARKER) + return self._get_impl(key=key, default_value=_DEFAULT_MARKER_) except ConfigKeyError as e: self._format_and_raise( key=key, value=None, cause=e, type_override=ConfigAttributeError @@ -361,7 +362,7 @@ def __getitem__(self, key: DictKeyType) -> Any: """ try: - return self._get_impl(key=key, default_value=DEFAULT_VALUE_MARKER) + return self._get_impl(key=key, default_value=_DEFAULT_MARKER_) except AttributeError as e: self._format_and_raise( key=key, value=None, cause=e, type_override=ConfigKeyError @@ -414,7 +415,7 @@ def _get_impl(self, key: DictKeyType, default_value: Any) -> Any: try: node = self._get_node(key=key, throw_on_missing_key=True) except (ConfigAttributeError, ConfigKeyError): - if default_value is not DEFAULT_VALUE_MARKER: + if default_value is not _DEFAULT_MARKER_: return default_value else: raise @@ -449,7 +450,7 @@ def _get_node( raise MissingMandatoryValue("Missing mandatory value") return value - def pop(self, key: DictKeyType, default: Any = DEFAULT_VALUE_MARKER) -> Any: + def pop(self, key: DictKeyType, default: Any = _DEFAULT_MARKER_) -> Any: try: if self._get_flag("readonly"): raise ReadonlyConfigError("Cannot pop from read-only node") @@ -470,7 +471,7 @@ def pop(self, key: DictKeyType, default: Any = DEFAULT_VALUE_MARKER) -> Any: del self[key] return value else: - if default is not DEFAULT_VALUE_MARKER: + if default is not _DEFAULT_MARKER_: return default else: full = self._get_full_key(key=key) diff --git a/omegaconf/omegaconf.py b/omegaconf/omegaconf.py index 83c018333..9fc979579 100644 --- a/omegaconf/omegaconf.py +++ b/omegaconf/omegaconf.py @@ -28,7 +28,7 @@ from . import DictConfig, DictKeyType, ListConfig from ._utils import ( - Marker, + _DEFAULT_MARKER_, _ensure_container, _get_value, _is_none, @@ -73,12 +73,6 @@ MISSING: Any = "???" -# Marker used: -# - in OmegaConf.create() to differentiate between creating an empty {} DictConfig -# and creating a DictConfig with None content -# - in env() to detect between no default value vs a default value set to None -_EMPTY_MARKER_: Any = Marker("_EMPTY_MARKER_") - Resolver = Callable[..., Any] @@ -115,9 +109,9 @@ def legacy_env(key: str, default: Optional[str] = None) -> Any: else: raise ValidationError(f"Environment variable '{key}' not found") - def env(key: str, default: Optional[str] = _EMPTY_MARKER_) -> Optional[str]: + def env(key: str, default: Optional[str] = _DEFAULT_MARKER_) -> Optional[str]: if ( - default is not _EMPTY_MARKER_ + default is not _DEFAULT_MARKER_ and default is not None and not isinstance(default, str) ): @@ -129,7 +123,7 @@ def env(key: str, default: Optional[str] = _EMPTY_MARKER_) -> Optional[str]: try: return os.environ[key] except KeyError: - if default is not _EMPTY_MARKER_: + if default is not _DEFAULT_MARKER_: return default else: raise KeyError(f"Environment variable '{key}' not found") @@ -219,7 +213,7 @@ def create( @staticmethod def create( # noqa F811 - obj: Any = _EMPTY_MARKER_, + obj: Any = _DEFAULT_MARKER_, parent: Optional[BaseContainer] = None, flags: Optional[Dict[str, bool]] = None, ) -> Union[DictConfig, ListConfig]: @@ -231,7 +225,7 @@ def create( # noqa F811 @staticmethod def _create_impl( # noqa F811 - obj: Any = _EMPTY_MARKER_, + obj: Any = _DEFAULT_MARKER_, parent: Optional[BaseContainer] = None, flags: Optional[Dict[str, bool]] = None, ) -> Union[DictConfig, ListConfig]: @@ -240,7 +234,7 @@ def _create_impl( # noqa F811 from .dictconfig import DictConfig from .listconfig import ListConfig - if obj is _EMPTY_MARKER_: + if obj is _DEFAULT_MARKER_: obj = {} if isinstance(obj, str): obj = yaml.load(obj, Loader=get_yaml_loader()) @@ -770,7 +764,7 @@ def select( cfg: Container, key: str, *, - default: Any = _EMPTY_MARKER_, + default: Any = _DEFAULT_MARKER_, throw_on_resolution_failure: bool = True, throw_on_missing: bool = False, ) -> Any: @@ -782,13 +776,13 @@ def select( throw_on_resolution_failure=throw_on_resolution_failure, ) except ConfigKeyError: - if default is not _EMPTY_MARKER_: + if default is not _DEFAULT_MARKER_: return default else: raise if ( - default is not _EMPTY_MARKER_ + default is not _DEFAULT_MARKER_ and _root is not None and _last_key is not None and _last_key not in _root