Repository: facebookresearch/hydra

Issue:
completion bug when completion unresolved values
`python demos/6_sweep/experiment.py  hydra/launcher=fairtask hydra.launcher.params.queue=local hydra.launcher.params.queues.slurm.params.<TAB>`

->
KeyError: "str interpolation key 'hydra.job.num_jobs' not found"
completion bug when completion unresolved values
`python demos/6_sweep/experiment.py  hydra/launcher=fairtask hydra.launcher.params.queue=local hydra.launcher.params.queues.slurm.params.<TAB>`

->
KeyError: "str interpolation key 'hydra.job.num_jobs' not found"


Discussion:
Also, arbitrary runtime errors should be show up in completion:

`NotImplementedError: Unable to load hydra_plugins.fairtask.conf/query, are you missing an __init__.py?`
Also, arbitrary runtime errors should be show up in completion:

`NotImplementedError: Unable to load hydra_plugins.fairtask.conf/query, are you missing an __init__.py?`

Resolving patch:
diff --git a/hydra/plugins/completion_plugin.py b/hydra/plugins/completion_plugin.py
--- a/hydra/plugins/completion_plugin.py
+++ b/hydra/plugins/completion_plugin.py
@@ -4,7 +4,7 @@
 from abc import ABCMeta
 from abc import abstractmethod
 import six
-from omegaconf import DictConfig, ListConfig, Config
+from omegaconf import DictConfig, ListConfig, Config, MissingMandatoryValue
 
 from hydra.plugins import Plugin
 
@@ -82,7 +82,10 @@ def str_rep(in_key, in_value):
             matches = []
             if word.endswith(".") or word.endswith("="):
                 exact_key = word[0:-1]
-                conf_node = config.select(exact_key)
+                try:
+                    conf_node = config.select(exact_key)
+                except MissingMandatoryValue:
+                    conf_node = ""
                 if conf_node is not None:
                     if isinstance(conf_node, Config):
                         key_matches = CompletionPlugin._get_matches(conf_node, "")
@@ -107,7 +110,7 @@ def str_rep(in_key, in_value):
                     )
                 else:
                     if isinstance(config, DictConfig):
-                        for key, value in config.items():
+                        for key, value in config.items(resolve=False):
                             if key.startswith(word):
                                 matches.append(str_rep(key, value))
                     elif isinstance(config, ListConfig):


Test patch:
diff --git a/hydra/test_utils/configs/completion_test/config.yaml b/hydra/test_utils/configs/completion_test/config.yaml
--- a/hydra/test_utils/configs/completion_test/config.yaml
+++ b/hydra/test_utils/configs/completion_test/config.yaml
@@ -2,6 +2,7 @@
 dict:
   key1: val1
   key2: val2
+  key3: ???
 
 # an item with a prefix identical to that of the dict
 dict_prefix: yup
@@ -10,6 +11,7 @@ dict_prefix: yup
 list:
   - aa
   - bb
+  - ???
 
 # an item with a prefix identical to a list
 list_prefix: yup
\ No newline at end of file
diff --git a/tests/test_completion.py b/tests/test_completion.py
--- a/tests/test_completion.py
+++ b/tests/test_completion.py
@@ -41,11 +41,12 @@ def create_config_loader():
     [
         ("", 2, base_completion_list),
         ("dict", 2, ["dict.", "dict_prefix="]),
-        ("dict.", 3, ["dict.key1=", "dict.key2="]),
-        ("dict.key", 2, ["dict.key1=", "dict.key2="]),
+        ("dict.", 3, ["dict.key1=", "dict.key2=", "dict.key3="]),
+        ("dict.key", 2, ["dict.key1=", "dict.key2=", "dict.key3="]),
         ("dict.key1=", 2, ["dict.key1=val1"]),
+        ("dict.key3=", 2, ["dict.key3="]),
         ("list", 2, ["list.", "list_prefix="]),
-        ("list.", 2, ["list.0=", "list.1="]),
+        ("list.", 2, ["list.0=", "list.1=", "list.2="]),
         (
             "hydra/",
             3,
@@ -102,7 +103,7 @@ def test_shell_integration(
         line1 = "line={}".format(line_prefix + line)
         cmd = [
             "expect",
-            "-d",
+            # "-d",  # Uncomment for debug prints from expect
             "tests/expect/test_{}_completion.exp".format(shell),
             prog,
             line1,