Repository: omry/omegaconf

Issue:
[bug] .pop isn't behaving as standard dict in struct mode
```py
from omegaconf import OmegaConf
c = OmegaConf.create({"a": 1})
OmegaConf.set_struct(c, True)
c.get("b", 1) # Works fine returns 1
c.pop("b", 1) # Throws ConfigAttributeError
```

Expected:

`.pop` should return value 1

Actual:
Throws ConfigAttributeError

Version: 2.0.0.rc24

Used to work in rc16

Discussion:

Patch:
diff --git a/omegaconf/dictconfig.py b/omegaconf/dictconfig.py
index 82a1636..fbac511 100644
--- a/omegaconf/dictconfig.py
+++ b/omegaconf/dictconfig.py
@@ -362,7 +362,7 @@ class DictConfig(BaseContainer, MutableMapping[str, Any]):
             if self._get_flag("readonly"):
                 raise ReadonlyConfigError("Cannot pop from read-only node")
 
-            node = self._get_node(key=key)
+            node = self._get_node(key=key, validate_access=False)
             if node is not None:
                 value = self._resolve_with_default(
                     key=key, value=node, default_value=default


Test patch:
diff --git a/tests/test_basic_ops_dict.py b/tests/test_basic_ops_dict.py
index 8145d7b..849d578 100644
--- a/tests/test_basic_ops_dict.py
+++ b/tests/test_basic_ops_dict.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 import re
 import tempfile
-from typing import Any, Dict, List, Union
+from typing import Any, Dict, List, Optional, Union
 
 import pytest
 
@@ -254,21 +254,56 @@ def test_iterate_dict_with_interpolation() -> None:
         i = i + 1
 
 
+@pytest.mark.parametrize(  # type: ignore
+    "struct",
+    [
+        pytest.param(None, id="struct_unspecified"),
+        pytest.param(False, id="struct_False"),
+        pytest.param(True, id="struct_True"),
+    ],
+)
 @pytest.mark.parametrize(  # type: ignore
     "cfg, key, default_, expected",
     [
-        ({"a": 1, "b": 2}, "a", None, 1),
-        ({"a": 1, "b": 2}, "not_found", "default", "default"),
+        pytest.param({"a": 1, "b": 2}, "a", "__NO_DEFAULT__", 1, id="no_default"),
+        pytest.param({"a": 1, "b": 2}, "not_found", None, None, id="none_default"),
+        pytest.param(
+            {"a": 1, "b": 2}, "not_found", "default", "default", id="with_default"
+        ),
         # Interpolations
-        ({"a": "${b}", "b": 2}, "a", None, 2),
+        pytest.param(
+            {"a": "${b}", "b": 2}, "a", "__NO_DEFAULT__", 2, id="interpolation"
+        ),
+        pytest.param(
+            {"a": "${b}"}, "a", "default", "default", id="interpolation_with_default"
+        ),
         # enum key
-        ({Enum1.FOO: "bar"}, Enum1.FOO, None, "bar"),
-        ({Enum1.FOO: "bar"}, Enum1.BAR, "default", "default"),
+        pytest.param(
+            {Enum1.FOO: "bar"},
+            Enum1.FOO,
+            "__NO_DEFAULT__",
+            "bar",
+            id="enum_key_no_default",
+        ),
+        pytest.param(
+            {Enum1.FOO: "bar"}, Enum1.BAR, None, None, id="enum_key_with_none_default",
+        ),
+        pytest.param(
+            {Enum1.FOO: "bar"},
+            Enum1.BAR,
+            "default",
+            "default",
+            id="enum_key_with_default",
+        ),
     ],
 )
-def test_dict_pop(cfg: Dict[Any, Any], key: Any, default_: Any, expected: Any) -> None:
+def test_dict_pop(
+    cfg: Dict[Any, Any], key: Any, default_: Any, expected: Any, struct: Optional[bool]
+) -> None:
     c = OmegaConf.create(cfg)
-    if default_ is not None:
+    OmegaConf.set_struct(c, struct)
+
+    if default_ != "__NO_DEFAULT__":
         val = c.pop(key, default_)
     else:
         val = c.pop(key)