We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
"$" character in user's response to a CLI prompt is mistakenly interpreted as a variable to substitute
**Describe the bug**
"$" character in user's response to a CLI prompt is mistakenly interpreted as a variable to substitute

![image](https://user-images.githubusercontent.com/80363/94323126-72169700-ff49-11ea-85fc-5dfba04ceba1.png)


**To Reproduce**
Steps to reproduce the behavior:
1. Add a Datasource in the CLI
2. Choose a database, answer one of the prompts (e.g., password) with a string that contains the "$" character
3. See the error

**Expected behavior**
The "$" character should not be treated specially in user's answer to prompts

**Environment (please complete the following information):**
 - OS: N/A
 - GE Version: 0.12.1

**Additional context**
N/A


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `great_expectations/data_context/util.py`
Content:
```
1 import copy
2 import inspect
3 import logging
4 import os
5 import re
6 from collections import OrderedDict
7 
8 from great_expectations.data_context.types.base import (
9     DataContextConfig,
10     DataContextConfigSchema,
11 )
12 from great_expectations.exceptions import MissingConfigVariableError
13 from great_expectations.util import load_class, verify_dynamic_loading_support
14 
15 logger = logging.getLogger(__name__)
16 
17 
18 # TODO: Rename config to constructor_kwargs and config_defaults -> constructor_kwarg_default
19 # TODO: Improve error messages in this method. Since so much of our workflow is config-driven, this will be a *super* important part of DX.
20 def instantiate_class_from_config(config, runtime_environment, config_defaults=None):
21     """Build a GE class from configuration dictionaries."""
22 
23     if config_defaults is None:
24         config_defaults = {}
25 
26     config = copy.deepcopy(config)
27 
28     module_name = config.pop("module_name", None)
29     if module_name is None:
30         try:
31             module_name = config_defaults.pop("module_name")
32         except KeyError:
33             raise KeyError(
34                 "Neither config : {} nor config_defaults : {} contains a module_name key.".format(
35                     config, config_defaults,
36                 )
37             )
38     else:
39         # Pop the value without using it, to avoid sending an unwanted value to the config_class
40         config_defaults.pop("module_name", None)
41 
42     verify_dynamic_loading_support(module_name=module_name)
43 
44     class_name = config.pop("class_name", None)
45     if class_name is None:
46         logger.warning(
47             "Instantiating class from config without an explicit class_name is dangerous. Consider adding "
48             "an explicit class_name for %s" % config.get("name")
49         )
50         try:
51             class_name = config_defaults.pop("class_name")
52         except KeyError:
53             raise KeyError(
54                 "Neither config : {} nor config_defaults : {} contains a class_name key.".format(
55                     config, config_defaults,
56                 )
57             )
58     else:
59         # Pop the value without using it, to avoid sending an unwanted value to the config_class
60         config_defaults.pop("class_name", None)
61 
62     class_ = load_class(class_name=class_name, module_name=module_name)
63 
64     config_with_defaults = copy.deepcopy(config_defaults)
65     config_with_defaults.update(config)
66     if runtime_environment is not None:
67         # If there are additional kwargs available in the runtime_environment requested by a
68         # class to be instantiated, provide them
69         argspec = inspect.getfullargspec(class_.__init__)[0][1:]
70 
71         missing_args = set(argspec) - set(config_with_defaults.keys())
72         config_with_defaults.update(
73             {
74                 missing_arg: runtime_environment[missing_arg]
75                 for missing_arg in missing_args
76                 if missing_arg in runtime_environment
77             }
78         )
79         # Add the entire runtime_environment as well if it's requested
80         if "runtime_environment" in missing_args:
81             config_with_defaults.update({"runtime_environment": runtime_environment})
82 
83     try:
84         class_instance = class_(**config_with_defaults)
85     except TypeError as e:
86         raise TypeError(
87             "Couldn't instantiate class : {} with config : \n\t{}\n \n".format(
88                 class_name, format_dict_for_error_message(config_with_defaults)
89             )
90             + str(e)
91         )
92 
93     return class_instance
94 
95 
96 def format_dict_for_error_message(dict_):
97     # TODO : Tidy this up a bit. Indentation isn't fully consistent.
98 
99     return "\n\t".join("\t\t".join((str(key), str(dict_[key]))) for key in dict_)
100 
101 
102 def substitute_config_variable(template_str, config_variables_dict):
103     """
104     This method takes a string, and if it contains a pattern ${SOME_VARIABLE} or $SOME_VARIABLE,
105     returns a string where the pattern is replaced with the value of SOME_VARIABLE,
106     otherwise returns the string unchanged.
107 
108     If the environment variable SOME_VARIABLE is set, the method uses its value for substitution.
109     If it is not set, the value of SOME_VARIABLE is looked up in the config variables store (file).
110     If it is not found there, the input string is returned as is.
111 
112     :param template_str: a string that might or might not be of the form ${SOME_VARIABLE}
113             or $SOME_VARIABLE
114     :param config_variables_dict: a dictionary of config variables. It is loaded from the
115             config variables store (by default, "uncommitted/config_variables.yml file)
116     :return:
117     """
118     if template_str is None:
119         return template_str
120 
121     try:
122         match = re.search(r"\$\{(.*?)\}", template_str) or re.search(
123             r"\$([_a-z][_a-z0-9]*)", template_str
124         )
125     except TypeError:
126         # If the value is not a string (e.g., a boolean), we should return it as is
127         return template_str
128 
129     if match:
130         config_variable_value = config_variables_dict.get(match.group(1))
131         if config_variable_value is not None:
132             if match.start() == 0 and match.end() == len(template_str):
133                 return config_variable_value
134             else:
135                 return (
136                     template_str[: match.start()]
137                     + config_variable_value
138                     + template_str[match.end() :]
139                 )
140 
141         raise MissingConfigVariableError(
142             f"""\n\nUnable to find a match for config substitution variable: `{match.group(1)}`.
143 Please add this missing variable to your `uncommitted/config_variables.yml` file or your environment variables.
144 See https://great-expectations.readthedocs.io/en/latest/reference/data_context_reference.html#managing-environment-and-secrets""",
145             missing_config_variable=match.group(1),
146         )
147 
148     return template_str
149 
150 
151 def substitute_all_config_variables(data, replace_variables_dict):
152     """
153     Substitute all config variables of the form ${SOME_VARIABLE} in a dictionary-like
154     config object for their values.
155 
156     The method traverses the dictionary recursively.
157 
158     :param data:
159     :param replace_variables_dict:
160     :return: a dictionary with all the variables replaced with their values
161     """
162     if isinstance(data, DataContextConfig):
163         data = DataContextConfigSchema().dump(data)
164 
165     if isinstance(data, dict) or isinstance(data, OrderedDict):
166         return {
167             k: substitute_all_config_variables(v, replace_variables_dict)
168             for k, v in data.items()
169         }
170     elif isinstance(data, list):
171         return [
172             substitute_all_config_variables(v, replace_variables_dict) for v in data
173         ]
174     return substitute_config_variable(data, replace_variables_dict)
175 
176 
177 def file_relative_path(dunderfile, relative_path):
178     """
179     This function is useful when one needs to load a file that is
180     relative to the position of the current file. (Such as when
181     you encode a configuration file path in source file and want
182     in runnable in any current working directory)
183 
184     It is meant to be used like the following:
185     file_relative_path(__file__, 'path/relative/to/file')
186 
187     H/T https://github.com/dagster-io/dagster/blob/8a250e9619a49e8bff8e9aa7435df89c2d2ea039/python_modules/dagster/dagster/utils/__init__.py#L34
188     """
189     return os.path.join(os.path.dirname(dunderfile), relative_path)
190
```
--- 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/great_expectations/data_context/util.py b/great_expectations/data_context/util.py
--- a/great_expectations/data_context/util.py
+++ b/great_expectations/data_context/util.py
@@ -165,6 +165,8 @@
     if isinstance(data, dict) or isinstance(data, OrderedDict):
         return {
             k: substitute_all_config_variables(v, replace_variables_dict)
+            if k.lower() not in {"password"}
+            else v
             for k, v in data.items()
         }
     elif isinstance(data, list):

{"golden_diff": "diff --git a/great_expectations/data_context/util.py b/great_expectations/data_context/util.py\n--- a/great_expectations/data_context/util.py\n+++ b/great_expectations/data_context/util.py\n@@ -165,6 +165,8 @@\n     if isinstance(data, dict) or isinstance(data, OrderedDict):\n         return {\n             k: substitute_all_config_variables(v, replace_variables_dict)\n+            if k.lower() not in {\"password\"}\n+            else v\n             for k, v in data.items()\n         }\n     elif isinstance(data, list):\n", "issue": "\"$\" character in user's response to a CLI prompt is mistakenly interpreted as a variable to substitute\n**Describe the bug**\r\n\"$\" character in user's response to a CLI prompt is mistakenly interpreted as a variable to substitute\r\n\r\n![image](https://user-images.githubusercontent.com/80363/94323126-72169700-ff49-11ea-85fc-5dfba04ceba1.png)\r\n\r\n\r\n**To Reproduce**\r\nSteps to reproduce the behavior:\r\n1. Add a Datasource in the CLI\r\n2. Choose a database, answer one of the prompts (e.g., password) with a string that contains the \"$\" character\r\n3. See the error\r\n\r\n**Expected behavior**\r\nThe \"$\" character should not be treated specially in user's answer to prompts\r\n\r\n**Environment (please complete the following information):**\r\n - OS: N/A\r\n - GE Version: 0.12.1\r\n\r\n**Additional context**\r\nN/A\r\n\n", "before_files": [{"content": "import copy\nimport inspect\nimport logging\nimport os\nimport re\nfrom collections import OrderedDict\n\nfrom great_expectations.data_context.types.base import (\n    DataContextConfig,\n    DataContextConfigSchema,\n)\nfrom great_expectations.exceptions import MissingConfigVariableError\nfrom great_expectations.util import load_class, verify_dynamic_loading_support\n\nlogger = logging.getLogger(__name__)\n\n\n# TODO: Rename config to constructor_kwargs and config_defaults -> constructor_kwarg_default\n# TODO: Improve error messages in this method. Since so much of our workflow is config-driven, this will be a *super* important part of DX.\ndef instantiate_class_from_config(config, runtime_environment, config_defaults=None):\n    \"\"\"Build a GE class from configuration dictionaries.\"\"\"\n\n    if config_defaults is None:\n        config_defaults = {}\n\n    config = copy.deepcopy(config)\n\n    module_name = config.pop(\"module_name\", None)\n    if module_name is None:\n        try:\n            module_name = config_defaults.pop(\"module_name\")\n        except KeyError:\n            raise KeyError(\n                \"Neither config : {} nor config_defaults : {} contains a module_name key.\".format(\n                    config, config_defaults,\n                )\n            )\n    else:\n        # Pop the value without using it, to avoid sending an unwanted value to the config_class\n        config_defaults.pop(\"module_name\", None)\n\n    verify_dynamic_loading_support(module_name=module_name)\n\n    class_name = config.pop(\"class_name\", None)\n    if class_name is None:\n        logger.warning(\n            \"Instantiating class from config without an explicit class_name is dangerous. Consider adding \"\n            \"an explicit class_name for %s\" % config.get(\"name\")\n        )\n        try:\n            class_name = config_defaults.pop(\"class_name\")\n        except KeyError:\n            raise KeyError(\n                \"Neither config : {} nor config_defaults : {} contains a class_name key.\".format(\n                    config, config_defaults,\n                )\n            )\n    else:\n        # Pop the value without using it, to avoid sending an unwanted value to the config_class\n        config_defaults.pop(\"class_name\", None)\n\n    class_ = load_class(class_name=class_name, module_name=module_name)\n\n    config_with_defaults = copy.deepcopy(config_defaults)\n    config_with_defaults.update(config)\n    if runtime_environment is not None:\n        # If there are additional kwargs available in the runtime_environment requested by a\n        # class to be instantiated, provide them\n        argspec = inspect.getfullargspec(class_.__init__)[0][1:]\n\n        missing_args = set(argspec) - set(config_with_defaults.keys())\n        config_with_defaults.update(\n            {\n                missing_arg: runtime_environment[missing_arg]\n                for missing_arg in missing_args\n                if missing_arg in runtime_environment\n            }\n        )\n        # Add the entire runtime_environment as well if it's requested\n        if \"runtime_environment\" in missing_args:\n            config_with_defaults.update({\"runtime_environment\": runtime_environment})\n\n    try:\n        class_instance = class_(**config_with_defaults)\n    except TypeError as e:\n        raise TypeError(\n            \"Couldn't instantiate class : {} with config : \\n\\t{}\\n \\n\".format(\n                class_name, format_dict_for_error_message(config_with_defaults)\n            )\n            + str(e)\n        )\n\n    return class_instance\n\n\ndef format_dict_for_error_message(dict_):\n    # TODO : Tidy this up a bit. Indentation isn't fully consistent.\n\n    return \"\\n\\t\".join(\"\\t\\t\".join((str(key), str(dict_[key]))) for key in dict_)\n\n\ndef substitute_config_variable(template_str, config_variables_dict):\n    \"\"\"\n    This method takes a string, and if it contains a pattern ${SOME_VARIABLE} or $SOME_VARIABLE,\n    returns a string where the pattern is replaced with the value of SOME_VARIABLE,\n    otherwise returns the string unchanged.\n\n    If the environment variable SOME_VARIABLE is set, the method uses its value for substitution.\n    If it is not set, the value of SOME_VARIABLE is looked up in the config variables store (file).\n    If it is not found there, the input string is returned as is.\n\n    :param template_str: a string that might or might not be of the form ${SOME_VARIABLE}\n            or $SOME_VARIABLE\n    :param config_variables_dict: a dictionary of config variables. It is loaded from the\n            config variables store (by default, \"uncommitted/config_variables.yml file)\n    :return:\n    \"\"\"\n    if template_str is None:\n        return template_str\n\n    try:\n        match = re.search(r\"\\$\\{(.*?)\\}\", template_str) or re.search(\n            r\"\\$([_a-z][_a-z0-9]*)\", template_str\n        )\n    except TypeError:\n        # If the value is not a string (e.g., a boolean), we should return it as is\n        return template_str\n\n    if match:\n        config_variable_value = config_variables_dict.get(match.group(1))\n        if config_variable_value is not None:\n            if match.start() == 0 and match.end() == len(template_str):\n                return config_variable_value\n            else:\n                return (\n                    template_str[: match.start()]\n                    + config_variable_value\n                    + template_str[match.end() :]\n                )\n\n        raise MissingConfigVariableError(\n            f\"\"\"\\n\\nUnable to find a match for config substitution variable: `{match.group(1)}`.\nPlease add this missing variable to your `uncommitted/config_variables.yml` file or your environment variables.\nSee https://great-expectations.readthedocs.io/en/latest/reference/data_context_reference.html#managing-environment-and-secrets\"\"\",\n            missing_config_variable=match.group(1),\n        )\n\n    return template_str\n\n\ndef substitute_all_config_variables(data, replace_variables_dict):\n    \"\"\"\n    Substitute all config variables of the form ${SOME_VARIABLE} in a dictionary-like\n    config object for their values.\n\n    The method traverses the dictionary recursively.\n\n    :param data:\n    :param replace_variables_dict:\n    :return: a dictionary with all the variables replaced with their values\n    \"\"\"\n    if isinstance(data, DataContextConfig):\n        data = DataContextConfigSchema().dump(data)\n\n    if isinstance(data, dict) or isinstance(data, OrderedDict):\n        return {\n            k: substitute_all_config_variables(v, replace_variables_dict)\n            for k, v in data.items()\n        }\n    elif isinstance(data, list):\n        return [\n            substitute_all_config_variables(v, replace_variables_dict) for v in data\n        ]\n    return substitute_config_variable(data, replace_variables_dict)\n\n\ndef file_relative_path(dunderfile, relative_path):\n    \"\"\"\n    This function is useful when one needs to load a file that is\n    relative to the position of the current file. (Such as when\n    you encode a configuration file path in source file and want\n    in runnable in any current working directory)\n\n    It is meant to be used like the following:\n    file_relative_path(__file__, 'path/relative/to/file')\n\n    H/T https://github.com/dagster-io/dagster/blob/8a250e9619a49e8bff8e9aa7435df89c2d2ea039/python_modules/dagster/dagster/utils/__init__.py#L34\n    \"\"\"\n    return os.path.join(os.path.dirname(dunderfile), relative_path)\n", "path": "great_expectations/data_context/util.py"}], "after_files": [{"content": "import copy\nimport inspect\nimport logging\nimport os\nimport re\nfrom collections import OrderedDict\n\nfrom great_expectations.data_context.types.base import (\n    DataContextConfig,\n    DataContextConfigSchema,\n)\nfrom great_expectations.exceptions import MissingConfigVariableError\nfrom great_expectations.util import load_class, verify_dynamic_loading_support\n\nlogger = logging.getLogger(__name__)\n\n\n# TODO: Rename config to constructor_kwargs and config_defaults -> constructor_kwarg_default\n# TODO: Improve error messages in this method. Since so much of our workflow is config-driven, this will be a *super* important part of DX.\ndef instantiate_class_from_config(config, runtime_environment, config_defaults=None):\n    \"\"\"Build a GE class from configuration dictionaries.\"\"\"\n\n    if config_defaults is None:\n        config_defaults = {}\n\n    config = copy.deepcopy(config)\n\n    module_name = config.pop(\"module_name\", None)\n    if module_name is None:\n        try:\n            module_name = config_defaults.pop(\"module_name\")\n        except KeyError:\n            raise KeyError(\n                \"Neither config : {} nor config_defaults : {} contains a module_name key.\".format(\n                    config, config_defaults,\n                )\n            )\n    else:\n        # Pop the value without using it, to avoid sending an unwanted value to the config_class\n        config_defaults.pop(\"module_name\", None)\n\n    verify_dynamic_loading_support(module_name=module_name)\n\n    class_name = config.pop(\"class_name\", None)\n    if class_name is None:\n        logger.warning(\n            \"Instantiating class from config without an explicit class_name is dangerous. Consider adding \"\n            \"an explicit class_name for %s\" % config.get(\"name\")\n        )\n        try:\n            class_name = config_defaults.pop(\"class_name\")\n        except KeyError:\n            raise KeyError(\n                \"Neither config : {} nor config_defaults : {} contains a class_name key.\".format(\n                    config, config_defaults,\n                )\n            )\n    else:\n        # Pop the value without using it, to avoid sending an unwanted value to the config_class\n        config_defaults.pop(\"class_name\", None)\n\n    class_ = load_class(class_name=class_name, module_name=module_name)\n\n    config_with_defaults = copy.deepcopy(config_defaults)\n    config_with_defaults.update(config)\n    if runtime_environment is not None:\n        # If there are additional kwargs available in the runtime_environment requested by a\n        # class to be instantiated, provide them\n        argspec = inspect.getfullargspec(class_.__init__)[0][1:]\n\n        missing_args = set(argspec) - set(config_with_defaults.keys())\n        config_with_defaults.update(\n            {\n                missing_arg: runtime_environment[missing_arg]\n                for missing_arg in missing_args\n                if missing_arg in runtime_environment\n            }\n        )\n        # Add the entire runtime_environment as well if it's requested\n        if \"runtime_environment\" in missing_args:\n            config_with_defaults.update({\"runtime_environment\": runtime_environment})\n\n    try:\n        class_instance = class_(**config_with_defaults)\n    except TypeError as e:\n        raise TypeError(\n            \"Couldn't instantiate class : {} with config : \\n\\t{}\\n \\n\".format(\n                class_name, format_dict_for_error_message(config_with_defaults)\n            )\n            + str(e)\n        )\n\n    return class_instance\n\n\ndef format_dict_for_error_message(dict_):\n    # TODO : Tidy this up a bit. Indentation isn't fully consistent.\n\n    return \"\\n\\t\".join(\"\\t\\t\".join((str(key), str(dict_[key]))) for key in dict_)\n\n\ndef substitute_config_variable(template_str, config_variables_dict):\n    \"\"\"\n    This method takes a string, and if it contains a pattern ${SOME_VARIABLE} or $SOME_VARIABLE,\n    returns a string where the pattern is replaced with the value of SOME_VARIABLE,\n    otherwise returns the string unchanged.\n\n    If the environment variable SOME_VARIABLE is set, the method uses its value for substitution.\n    If it is not set, the value of SOME_VARIABLE is looked up in the config variables store (file).\n    If it is not found there, the input string is returned as is.\n\n    :param template_str: a string that might or might not be of the form ${SOME_VARIABLE}\n            or $SOME_VARIABLE\n    :param config_variables_dict: a dictionary of config variables. It is loaded from the\n            config variables store (by default, \"uncommitted/config_variables.yml file)\n    :return:\n    \"\"\"\n    if template_str is None:\n        return template_str\n\n    try:\n        match = re.search(r\"\\$\\{(.*?)\\}\", template_str) or re.search(\n            r\"\\$([_a-z][_a-z0-9]*)\", template_str\n        )\n    except TypeError:\n        # If the value is not a string (e.g., a boolean), we should return it as is\n        return template_str\n\n    if match:\n        config_variable_value = config_variables_dict.get(match.group(1))\n        if config_variable_value is not None:\n            if match.start() == 0 and match.end() == len(template_str):\n                return config_variable_value\n            else:\n                return (\n                    template_str[: match.start()]\n                    + config_variable_value\n                    + template_str[match.end() :]\n                )\n\n        raise MissingConfigVariableError(\n            f\"\"\"\\n\\nUnable to find a match for config substitution variable: `{match.group(1)}`.\nPlease add this missing variable to your `uncommitted/config_variables.yml` file or your environment variables.\nSee https://great-expectations.readthedocs.io/en/latest/reference/data_context_reference.html#managing-environment-and-secrets\"\"\",\n            missing_config_variable=match.group(1),\n        )\n\n    return template_str\n\n\ndef substitute_all_config_variables(data, replace_variables_dict):\n    \"\"\"\n    Substitute all config variables of the form ${SOME_VARIABLE} in a dictionary-like\n    config object for their values.\n\n    The method traverses the dictionary recursively.\n\n    :param data:\n    :param replace_variables_dict:\n    :return: a dictionary with all the variables replaced with their values\n    \"\"\"\n    if isinstance(data, DataContextConfig):\n        data = DataContextConfigSchema().dump(data)\n\n    if isinstance(data, dict) or isinstance(data, OrderedDict):\n        return {\n            k: substitute_all_config_variables(v, replace_variables_dict)\n            if k.lower() not in {\"password\"}\n            else v\n            for k, v in data.items()\n        }\n    elif isinstance(data, list):\n        return [\n            substitute_all_config_variables(v, replace_variables_dict) for v in data\n        ]\n    return substitute_config_variable(data, replace_variables_dict)\n\n\ndef file_relative_path(dunderfile, relative_path):\n    \"\"\"\n    This function is useful when one needs to load a file that is\n    relative to the position of the current file. (Such as when\n    you encode a configuration file path in source file and want\n    in runnable in any current working directory)\n\n    It is meant to be used like the following:\n    file_relative_path(__file__, 'path/relative/to/file')\n\n    H/T https://github.com/dagster-io/dagster/blob/8a250e9619a49e8bff8e9aa7435df89c2d2ea039/python_modules/dagster/dagster/utils/__init__.py#L34\n    \"\"\"\n    return os.path.join(os.path.dirname(dunderfile), relative_path)\n", "path": "great_expectations/data_context/util.py"}]}