We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
dir interpolation from hydra into job config is not working
I can set the `second_dir`  from `base_dir`, but `output_subdir` can not in this case.
```
experiment:
  base_dir: ???
  second_dir: ${experiment.base_dir}
hydra:
  output_subdir: ${experiment.base_dir}/.hydra
```
`KeyError: "str interpolation key 'experiment.base_dir' not found"`

Is there any way I can change the hydra config based on current .yaml or some alternately way?  
 Thanks!

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `hydra/plugins/common/utils.py`
Content:
```
1 # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
2 
3 import copy
4 import logging
5 import os
6 import re
7 import sys
8 from hydra._internal.pathlib import Path
9 from time import strftime, localtime
10 
11 import six
12 from omegaconf import OmegaConf, DictConfig, ListConfig
13 
14 # pylint: disable=C0103
15 log = logging.getLogger(__name__)
16 
17 
18 def configure_log(log_config, verbose_config):
19     assert isinstance(verbose_config, (bool, str, ListConfig))
20     if log_config is not None:
21         conf = log_config.to_container(resolve=True)
22         logging.config.dictConfig(conf)
23     else:
24         # default logging to stdout
25         root = logging.getLogger()
26         root.setLevel(logging.INFO)
27         handler = logging.StreamHandler(sys.stdout)
28         formatter = logging.Formatter(
29             "[%(asctime)s][%(name)s][%(levelname)s] - %(message)s"
30         )
31         handler.setFormatter(formatter)
32         root.addHandler(handler)
33     if isinstance(verbose_config, bool):
34         if verbose_config:
35             logging.getLogger().setLevel(logging.DEBUG)
36     else:
37         if isinstance(verbose_config, str):
38             verbose_config = OmegaConf.create([verbose_config])
39         for logger in verbose_config:
40             logging.getLogger(logger).setLevel(logging.DEBUG)
41 
42 
43 def _save_config(cfg, filename, output_dir):
44     Path(str(output_dir)).mkdir(parents=True, exist_ok=True)
45     with open(str(output_dir / filename), "w") as file:
46         file.write(cfg.pretty())
47 
48 
49 def get_overrides_dirname(lst, exclude_keys=[]):
50     lst = [x for x in lst if x not in exclude_keys]
51     lst.sort()
52     return re.sub(pattern="[=]", repl="=", string=",".join(lst))
53 
54 
55 def filter_overrides(overrides):
56     """
57     :param overrides: overrides list
58     :return: returning a new overrides list with all the keys starting with hydra. fitlered.
59     """
60     return [x for x in overrides if not x.startswith("hydra.")]
61 
62 
63 def run_job(config, task_function, job_dir_key, job_subdir_key):
64     old_cwd = os.getcwd()
65     working_dir = str(config.select(job_dir_key))
66     if job_subdir_key is not None:
67         # evaluate job_subdir_key lazily.
68         # this is running on the client side in sweep and contains things such as job:id which
69         # are only available there.
70         subdir = str(config.select(job_subdir_key))
71         working_dir = os.path.join(working_dir, subdir)
72     try:
73         ret = JobReturn()
74         ret.working_dir = working_dir
75         task_cfg = copy.deepcopy(config)
76         # TODO: update this after https://github.com/omry/omegaconf/issues/42 is resolved
77         hydra_cfg = OmegaConf.create({"hydra": task_cfg["hydra"]})
78         del task_cfg["hydra"]
79         ret.cfg = task_cfg
80         ret.hydra_cfg = copy.deepcopy(HydraConfig())
81         ret.overrides = config.hydra.overrides.task.to_container()
82         # handle output directories here
83         Path(str(working_dir)).mkdir(parents=True, exist_ok=True)
84         os.chdir(working_dir)
85         hydra_output = Path(hydra_cfg.hydra.output_subdir)
86 
87         configure_log(hydra_cfg.hydra.job_logging, hydra_cfg.hydra.verbose)
88         _save_config(task_cfg, "config.yaml", hydra_output)
89         _save_config(hydra_cfg, "hydra.yaml", hydra_output)
90         _save_config(config.hydra.overrides.task, "overrides.yaml", hydra_output)
91         ret.return_value = task_function(task_cfg)
92         ret.task_name = JobRuntime().get("name")
93         return ret
94     finally:
95         os.chdir(old_cwd)
96 
97 
98 def get_valid_filename(s):
99     s = str(s).strip().replace(" ", "_")
100     return re.sub(r"(?u)[^-\w.]", "", s)
101 
102 
103 def setup_globals():
104     try:
105         OmegaConf.register_resolver(
106             "now", lambda pattern: strftime(pattern, localtime())
107         )
108 
109         def job_error(x):
110             raise Exception(
111                 "job:{} is no longer available. use hydra.job.{}".format(x, x)
112             )
113 
114         OmegaConf.register_resolver("job", job_error)
115 
116     except AssertionError:
117         # calling it again in no_workers mode will throw. safe to ignore.
118         pass
119 
120 
121 class JobReturn:
122     def __init__(self):
123         self.overrides = None
124         self.return_value = None
125         self.cfg = None
126         self.hydra_cfg = None
127         self.working_dir = None
128         self.task_name = None
129 
130 
131 class Singleton(type):
132     _instances = {}
133 
134     def __call__(cls, *args, **kwargs):
135         if cls not in cls._instances:
136             cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
137         return cls._instances[cls]
138 
139     @staticmethod
140     def get_state():
141         return Singleton._instances
142 
143     @staticmethod
144     def set_state(instances):
145         Singleton._instances = instances
146 
147 
148 @six.add_metaclass(Singleton)
149 class JobRuntime:
150     def __init__(self):
151         self.conf = OmegaConf.create()
152         self.set("name", "UNKNOWN_NAME")
153 
154     def get(self, key):
155         ret = self.conf.select(key)
156         if ret is None:
157             raise KeyError("Key not found in {}: {}".format(type(self).__name__, key))
158         return ret
159 
160     def set(self, key, value):
161         log.debug("Setting {}:{}={}".format(type(self).__name__, key, value))
162         self.conf[key] = value
163 
164 
165 @six.add_metaclass(Singleton)
166 class HydraConfig(DictConfig):
167     def __init__(self):
168         super(HydraConfig, self).__init__(content={})
169         self.hydra = None
170 
171     def set_config(self, cfg):
172         try:
173             OmegaConf.set_readonly(self, False)
174             self.hydra = copy.deepcopy(cfg.hydra)
175         finally:
176             OmegaConf.set_readonly(self, True)
177
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/hydra/plugins/common/utils.py b/hydra/plugins/common/utils.py
--- a/hydra/plugins/common/utils.py
+++ b/hydra/plugins/common/utils.py
@@ -73,8 +73,6 @@
         ret = JobReturn()
         ret.working_dir = working_dir
         task_cfg = copy.deepcopy(config)
-        # TODO: update this after https://github.com/omry/omegaconf/issues/42 is resolved
-        hydra_cfg = OmegaConf.create({"hydra": task_cfg["hydra"]})
         del task_cfg["hydra"]
         ret.cfg = task_cfg
         ret.hydra_cfg = copy.deepcopy(HydraConfig())
@@ -82,9 +80,13 @@
         # handle output directories here
         Path(str(working_dir)).mkdir(parents=True, exist_ok=True)
         os.chdir(working_dir)
-        hydra_output = Path(hydra_cfg.hydra.output_subdir)
+        hydra_output = Path(config.hydra.output_subdir)
+
+        configure_log(config.hydra.job_logging, config.hydra.verbose)
+
+        # TODO: update this after https://github.com/omry/omegaconf/issues/42 is resolved
+        hydra_cfg = OmegaConf.create({"hydra": config["hydra"]})
 
-        configure_log(hydra_cfg.hydra.job_logging, hydra_cfg.hydra.verbose)
         _save_config(task_cfg, "config.yaml", hydra_output)
         _save_config(hydra_cfg, "hydra.yaml", hydra_output)
         _save_config(config.hydra.overrides.task, "overrides.yaml", hydra_output)

{"golden_diff": "diff --git a/hydra/plugins/common/utils.py b/hydra/plugins/common/utils.py\n--- a/hydra/plugins/common/utils.py\n+++ b/hydra/plugins/common/utils.py\n@@ -73,8 +73,6 @@\n         ret = JobReturn()\n         ret.working_dir = working_dir\n         task_cfg = copy.deepcopy(config)\n-        # TODO: update this after https://github.com/omry/omegaconf/issues/42 is resolved\n-        hydra_cfg = OmegaConf.create({\"hydra\": task_cfg[\"hydra\"]})\n         del task_cfg[\"hydra\"]\n         ret.cfg = task_cfg\n         ret.hydra_cfg = copy.deepcopy(HydraConfig())\n@@ -82,9 +80,13 @@\n         # handle output directories here\n         Path(str(working_dir)).mkdir(parents=True, exist_ok=True)\n         os.chdir(working_dir)\n-        hydra_output = Path(hydra_cfg.hydra.output_subdir)\n+        hydra_output = Path(config.hydra.output_subdir)\n+\n+        configure_log(config.hydra.job_logging, config.hydra.verbose)\n+\n+        # TODO: update this after https://github.com/omry/omegaconf/issues/42 is resolved\n+        hydra_cfg = OmegaConf.create({\"hydra\": config[\"hydra\"]})\n \n-        configure_log(hydra_cfg.hydra.job_logging, hydra_cfg.hydra.verbose)\n         _save_config(task_cfg, \"config.yaml\", hydra_output)\n         _save_config(hydra_cfg, \"hydra.yaml\", hydra_output)\n         _save_config(config.hydra.overrides.task, \"overrides.yaml\", hydra_output)\n", "issue": "dir interpolation from hydra into job config is not working\nI can set the `second_dir`  from `base_dir`, but `output_subdir` can not in this case.\r\n```\r\nexperiment:\r\n  base_dir: ???\r\n  second_dir: ${experiment.base_dir}\r\nhydra:\r\n  output_subdir: ${experiment.base_dir}/.hydra\r\n```\r\n`KeyError: \"str interpolation key 'experiment.base_dir' not found\"`\r\n\r\nIs there any way I can change the hydra config based on current .yaml or some alternately way?  \r\n Thanks!\n", "before_files": [{"content": "# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n\nimport copy\nimport logging\nimport os\nimport re\nimport sys\nfrom hydra._internal.pathlib import Path\nfrom time import strftime, localtime\n\nimport six\nfrom omegaconf import OmegaConf, DictConfig, ListConfig\n\n# pylint: disable=C0103\nlog = logging.getLogger(__name__)\n\n\ndef configure_log(log_config, verbose_config):\n    assert isinstance(verbose_config, (bool, str, ListConfig))\n    if log_config is not None:\n        conf = log_config.to_container(resolve=True)\n        logging.config.dictConfig(conf)\n    else:\n        # default logging to stdout\n        root = logging.getLogger()\n        root.setLevel(logging.INFO)\n        handler = logging.StreamHandler(sys.stdout)\n        formatter = logging.Formatter(\n            \"[%(asctime)s][%(name)s][%(levelname)s] - %(message)s\"\n        )\n        handler.setFormatter(formatter)\n        root.addHandler(handler)\n    if isinstance(verbose_config, bool):\n        if verbose_config:\n            logging.getLogger().setLevel(logging.DEBUG)\n    else:\n        if isinstance(verbose_config, str):\n            verbose_config = OmegaConf.create([verbose_config])\n        for logger in verbose_config:\n            logging.getLogger(logger).setLevel(logging.DEBUG)\n\n\ndef _save_config(cfg, filename, output_dir):\n    Path(str(output_dir)).mkdir(parents=True, exist_ok=True)\n    with open(str(output_dir / filename), \"w\") as file:\n        file.write(cfg.pretty())\n\n\ndef get_overrides_dirname(lst, exclude_keys=[]):\n    lst = [x for x in lst if x not in exclude_keys]\n    lst.sort()\n    return re.sub(pattern=\"[=]\", repl=\"=\", string=\",\".join(lst))\n\n\ndef filter_overrides(overrides):\n    \"\"\"\n    :param overrides: overrides list\n    :return: returning a new overrides list with all the keys starting with hydra. fitlered.\n    \"\"\"\n    return [x for x in overrides if not x.startswith(\"hydra.\")]\n\n\ndef run_job(config, task_function, job_dir_key, job_subdir_key):\n    old_cwd = os.getcwd()\n    working_dir = str(config.select(job_dir_key))\n    if job_subdir_key is not None:\n        # evaluate job_subdir_key lazily.\n        # this is running on the client side in sweep and contains things such as job:id which\n        # are only available there.\n        subdir = str(config.select(job_subdir_key))\n        working_dir = os.path.join(working_dir, subdir)\n    try:\n        ret = JobReturn()\n        ret.working_dir = working_dir\n        task_cfg = copy.deepcopy(config)\n        # TODO: update this after https://github.com/omry/omegaconf/issues/42 is resolved\n        hydra_cfg = OmegaConf.create({\"hydra\": task_cfg[\"hydra\"]})\n        del task_cfg[\"hydra\"]\n        ret.cfg = task_cfg\n        ret.hydra_cfg = copy.deepcopy(HydraConfig())\n        ret.overrides = config.hydra.overrides.task.to_container()\n        # handle output directories here\n        Path(str(working_dir)).mkdir(parents=True, exist_ok=True)\n        os.chdir(working_dir)\n        hydra_output = Path(hydra_cfg.hydra.output_subdir)\n\n        configure_log(hydra_cfg.hydra.job_logging, hydra_cfg.hydra.verbose)\n        _save_config(task_cfg, \"config.yaml\", hydra_output)\n        _save_config(hydra_cfg, \"hydra.yaml\", hydra_output)\n        _save_config(config.hydra.overrides.task, \"overrides.yaml\", hydra_output)\n        ret.return_value = task_function(task_cfg)\n        ret.task_name = JobRuntime().get(\"name\")\n        return ret\n    finally:\n        os.chdir(old_cwd)\n\n\ndef get_valid_filename(s):\n    s = str(s).strip().replace(\" \", \"_\")\n    return re.sub(r\"(?u)[^-\\w.]\", \"\", s)\n\n\ndef setup_globals():\n    try:\n        OmegaConf.register_resolver(\n            \"now\", lambda pattern: strftime(pattern, localtime())\n        )\n\n        def job_error(x):\n            raise Exception(\n                \"job:{} is no longer available. use hydra.job.{}\".format(x, x)\n            )\n\n        OmegaConf.register_resolver(\"job\", job_error)\n\n    except AssertionError:\n        # calling it again in no_workers mode will throw. safe to ignore.\n        pass\n\n\nclass JobReturn:\n    def __init__(self):\n        self.overrides = None\n        self.return_value = None\n        self.cfg = None\n        self.hydra_cfg = None\n        self.working_dir = None\n        self.task_name = None\n\n\nclass Singleton(type):\n    _instances = {}\n\n    def __call__(cls, *args, **kwargs):\n        if cls not in cls._instances:\n            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)\n        return cls._instances[cls]\n\n    @staticmethod\n    def get_state():\n        return Singleton._instances\n\n    @staticmethod\n    def set_state(instances):\n        Singleton._instances = instances\n\n\n@six.add_metaclass(Singleton)\nclass JobRuntime:\n    def __init__(self):\n        self.conf = OmegaConf.create()\n        self.set(\"name\", \"UNKNOWN_NAME\")\n\n    def get(self, key):\n        ret = self.conf.select(key)\n        if ret is None:\n            raise KeyError(\"Key not found in {}: {}\".format(type(self).__name__, key))\n        return ret\n\n    def set(self, key, value):\n        log.debug(\"Setting {}:{}={}\".format(type(self).__name__, key, value))\n        self.conf[key] = value\n\n\n@six.add_metaclass(Singleton)\nclass HydraConfig(DictConfig):\n    def __init__(self):\n        super(HydraConfig, self).__init__(content={})\n        self.hydra = None\n\n    def set_config(self, cfg):\n        try:\n            OmegaConf.set_readonly(self, False)\n            self.hydra = copy.deepcopy(cfg.hydra)\n        finally:\n            OmegaConf.set_readonly(self, True)\n", "path": "hydra/plugins/common/utils.py"}], "after_files": [{"content": "# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n\nimport copy\nimport logging\nimport os\nimport re\nimport sys\nfrom hydra._internal.pathlib import Path\nfrom time import strftime, localtime\n\nimport six\nfrom omegaconf import OmegaConf, DictConfig, ListConfig\n\n# pylint: disable=C0103\nlog = logging.getLogger(__name__)\n\n\ndef configure_log(log_config, verbose_config):\n    assert isinstance(verbose_config, (bool, str, ListConfig))\n    if log_config is not None:\n        conf = log_config.to_container(resolve=True)\n        logging.config.dictConfig(conf)\n    else:\n        # default logging to stdout\n        root = logging.getLogger()\n        root.setLevel(logging.INFO)\n        handler = logging.StreamHandler(sys.stdout)\n        formatter = logging.Formatter(\n            \"[%(asctime)s][%(name)s][%(levelname)s] - %(message)s\"\n        )\n        handler.setFormatter(formatter)\n        root.addHandler(handler)\n    if isinstance(verbose_config, bool):\n        if verbose_config:\n            logging.getLogger().setLevel(logging.DEBUG)\n    else:\n        if isinstance(verbose_config, str):\n            verbose_config = OmegaConf.create([verbose_config])\n        for logger in verbose_config:\n            logging.getLogger(logger).setLevel(logging.DEBUG)\n\n\ndef _save_config(cfg, filename, output_dir):\n    Path(str(output_dir)).mkdir(parents=True, exist_ok=True)\n    with open(str(output_dir / filename), \"w\") as file:\n        file.write(cfg.pretty())\n\n\ndef get_overrides_dirname(lst, exclude_keys=[]):\n    lst = [x for x in lst if x not in exclude_keys]\n    lst.sort()\n    return re.sub(pattern=\"[=]\", repl=\"=\", string=\",\".join(lst))\n\n\ndef filter_overrides(overrides):\n    \"\"\"\n    :param overrides: overrides list\n    :return: returning a new overrides list with all the keys starting with hydra. fitlered.\n    \"\"\"\n    return [x for x in overrides if not x.startswith(\"hydra.\")]\n\n\ndef run_job(config, task_function, job_dir_key, job_subdir_key):\n    old_cwd = os.getcwd()\n    working_dir = str(config.select(job_dir_key))\n    if job_subdir_key is not None:\n        # evaluate job_subdir_key lazily.\n        # this is running on the client side in sweep and contains things such as job:id which\n        # are only available there.\n        subdir = str(config.select(job_subdir_key))\n        working_dir = os.path.join(working_dir, subdir)\n    try:\n        ret = JobReturn()\n        ret.working_dir = working_dir\n        task_cfg = copy.deepcopy(config)\n        del task_cfg[\"hydra\"]\n        ret.cfg = task_cfg\n        ret.hydra_cfg = copy.deepcopy(HydraConfig())\n        ret.overrides = config.hydra.overrides.task.to_container()\n        # handle output directories here\n        Path(str(working_dir)).mkdir(parents=True, exist_ok=True)\n        os.chdir(working_dir)\n        hydra_output = Path(config.hydra.output_subdir)\n\n        configure_log(config.hydra.job_logging, config.hydra.verbose)\n\n        # TODO: update this after https://github.com/omry/omegaconf/issues/42 is resolved\n        hydra_cfg = OmegaConf.create({\"hydra\": config[\"hydra\"]})\n\n        _save_config(task_cfg, \"config.yaml\", hydra_output)\n        _save_config(hydra_cfg, \"hydra.yaml\", hydra_output)\n        _save_config(config.hydra.overrides.task, \"overrides.yaml\", hydra_output)\n        ret.return_value = task_function(task_cfg)\n        ret.task_name = JobRuntime().get(\"name\")\n        return ret\n    finally:\n        os.chdir(old_cwd)\n\n\ndef get_valid_filename(s):\n    s = str(s).strip().replace(\" \", \"_\")\n    return re.sub(r\"(?u)[^-\\w.]\", \"\", s)\n\n\ndef setup_globals():\n    try:\n        OmegaConf.register_resolver(\n            \"now\", lambda pattern: strftime(pattern, localtime())\n        )\n\n        def job_error(x):\n            raise Exception(\n                \"job:{} is no longer available. use hydra.job.{}\".format(x, x)\n            )\n\n        OmegaConf.register_resolver(\"job\", job_error)\n\n    except AssertionError:\n        # calling it again in no_workers mode will throw. safe to ignore.\n        pass\n\n\nclass JobReturn:\n    def __init__(self):\n        self.overrides = None\n        self.return_value = None\n        self.cfg = None\n        self.hydra_cfg = None\n        self.working_dir = None\n        self.task_name = None\n\n\nclass Singleton(type):\n    _instances = {}\n\n    def __call__(cls, *args, **kwargs):\n        if cls not in cls._instances:\n            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)\n        return cls._instances[cls]\n\n    @staticmethod\n    def get_state():\n        return Singleton._instances\n\n    @staticmethod\n    def set_state(instances):\n        Singleton._instances = instances\n\n\n@six.add_metaclass(Singleton)\nclass JobRuntime:\n    def __init__(self):\n        self.conf = OmegaConf.create()\n        self.set(\"name\", \"UNKNOWN_NAME\")\n\n    def get(self, key):\n        ret = self.conf.select(key)\n        if ret is None:\n            raise KeyError(\"Key not found in {}: {}\".format(type(self).__name__, key))\n        return ret\n\n    def set(self, key, value):\n        log.debug(\"Setting {}:{}={}\".format(type(self).__name__, key, value))\n        self.conf[key] = value\n\n\n@six.add_metaclass(Singleton)\nclass HydraConfig(DictConfig):\n    def __init__(self):\n        super(HydraConfig, self).__init__(content={})\n        self.hydra = None\n\n    def set_config(self, cfg):\n        try:\n            OmegaConf.set_readonly(self, False)\n            self.hydra = copy.deepcopy(cfg.hydra)\n        finally:\n            OmegaConf.set_readonly(self, True)\n", "path": "hydra/plugins/common/utils.py"}]}