We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
base_component.BaseComponent.__str__ method raising KeyError
I got a `KeyError` when calling this method: `base_component.BaseComponent.__str__`

Here is the code to reproduce:

```python
import os
from tfx.utils.dsl_utils import csv_input
from tfx.components.example_gen.csv_example_gen.component import CsvExampleGen

_taxi_root = os.path.join(os.environ['HOME'], 'taxi')
_data_root = os.path.join(_taxi_root, 'data/simple')
examples = csv_input(_data_root)
example_gen = CsvExampleGen(input_base=examples)
print(example_gen)
```

The error trace is:

```
/Users/alelevier/Documents/github/tfx/tfx/components/base/base_component.pyc in __str__(self)
     89         input_dict=self.input_dict,
     90         outputs=self.outputs,
---> 91         exec_properties=self.exec_properties)
     92 
     93   def __repr__(self):

KeyError: '\n  component_name'
```

I looked at the method, it needs use double `{{` and `}}` so change from:

```
  def __str__(self):
    return """
{
  component_name: {component_name},
  unique_name: {unique_name},
  driver: {driver},
  executor: {executor},
  input_dict: {input_dict},
  outputs: {outputs},
  exec_properties: {exec_properties}
}
    """.format(  # pylint: disable=missing-format-argument-key
        component_name=self.component_name,
        unique_name=self.unique_name,
        driver=self.driver,
        executor=self.executor,
        input_dict=self.input_dict,
        outputs=self.outputs,
        exec_properties=self.exec_properties)
```

To:

```
  def __str__(self):
    return """
{{
  component_name: {component_name},
  unique_name: {unique_name},
  driver: {driver},
  executor: {executor},
  input_dict: {input_dict},
  outputs: {outputs},
  exec_properties: {exec_properties}
}}
    """.format(  # pylint: disable=missing-format-argument-key
        component_name=self.component_name,
        unique_name=self.unique_name,
        driver=self.driver,
        executor=self.executor,
        input_dict=self.input_dict,
        outputs=self.outputs,
        exec_properties=self.exec_properties)
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `tfx/components/base/base_component.py`
Content:
```
1 # Copyright 2019 Google LLC. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """Base class for all TFX components."""
15 
16 from __future__ import absolute_import
17 from __future__ import division
18 from __future__ import print_function
19 
20 import abc
21 from six import with_metaclass
22 from typing import Any
23 from typing import Dict
24 from typing import Optional
25 from typing import Text
26 
27 from tfx.utils import channel
28 
29 
30 class ComponentOutputs(object):
31   """Helper class to wrap outputs from TFX components."""
32 
33   def __init__(self, d):
34     self.__dict__ = d
35 
36   def get_all(self):
37     return self.__dict__
38 
39 
40 class BaseComponent(with_metaclass(abc.ABCMeta, object)):
41   """Base TFX component.
42 
43   This is the parent class of any TFX component.
44 
45   Attributes:
46     component_name: Name of the component, should be unique per component class.
47     unique_name: Unique name for every component class instance.
48     driver: Driver class to handle pre-execution behaviors in a component.
49     executor: Executor class to do the real execution work.
50     input_dict: A [Text -> Channel] dict serving as the inputs to the component.
51     exec_properties: A [Text -> Any] dict serving as additional properties
52       needed for execution.
53     outputs: Optional Channel destinations of the component.
54   """
55 
56   def __init__(self,
57                component_name,
58                driver,
59                executor,
60                input_dict,
61                exec_properties,
62                unique_name = '',
63                outputs = ComponentOutputs({})):
64     self.component_name = component_name
65     self.driver = driver
66     self.executor = executor
67     self.input_dict = input_dict
68     self.exec_properties = exec_properties
69     self.unique_name = unique_name
70     self.outputs = outputs or self._create_outputs()
71     self._type_check(self.input_dict, self.exec_properties)
72 
73   def __str__(self):
74     return """
75 {
76   component_name: {component_name},
77   unique_name: {unique_name},
78   driver: {driver},
79   executor: {executor},
80   input_dict: {input_dict},
81   outputs: {outputs},
82   exec_properties: {exec_properties}
83 }
84     """.format(  # pylint: disable=missing-format-argument-key
85         component_name=self.component_name,
86         unique_name=self.unique_name,
87         driver=self.driver,
88         executor=self.executor,
89         input_dict=self.input_dict,
90         outputs=self.outputs,
91         exec_properties=self.exec_properties)
92 
93   def __repr__(self):
94     return self.__str__()
95 
96   @abc.abstractmethod
97   def _create_outputs(self):
98     """Creates outputs placeholder for components.
99 
100     Returns:
101       ComponentOutputs object containing the dict of [Text -> Channel]
102     """
103     raise NotImplementedError
104 
105   @abc.abstractmethod
106   def _type_check(self, input_dict,
107                   exec_properties):
108     """Does type checking for the inputs and exec_properties.
109 
110     Args:
111       input_dict: A Dict[Text, Channel] as the inputs of the Component.
112       exec_properties: A Dict[Text, Any] as the execution properties of the
113         component.
114     """
115     raise NotImplementedError
116
```
--- 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/tfx/components/base/base_component.py b/tfx/components/base/base_component.py
--- a/tfx/components/base/base_component.py
+++ b/tfx/components/base/base_component.py
@@ -72,7 +72,7 @@
 
   def __str__(self):
     return """
-{
+{{
   component_name: {component_name},
   unique_name: {unique_name},
   driver: {driver},
@@ -80,7 +80,7 @@
   input_dict: {input_dict},
   outputs: {outputs},
   exec_properties: {exec_properties}
-}
+}}
     """.format(  # pylint: disable=missing-format-argument-key
         component_name=self.component_name,
         unique_name=self.unique_name,

{"golden_diff": "diff --git a/tfx/components/base/base_component.py b/tfx/components/base/base_component.py\n--- a/tfx/components/base/base_component.py\n+++ b/tfx/components/base/base_component.py\n@@ -72,7 +72,7 @@\n \n   def __str__(self):\n     return \"\"\"\n-{\n+{{\n   component_name: {component_name},\n   unique_name: {unique_name},\n   driver: {driver},\n@@ -80,7 +80,7 @@\n   input_dict: {input_dict},\n   outputs: {outputs},\n   exec_properties: {exec_properties}\n-}\n+}}\n     \"\"\".format(  # pylint: disable=missing-format-argument-key\n         component_name=self.component_name,\n         unique_name=self.unique_name,\n", "issue": "base_component.BaseComponent.__str__ method raising KeyError\nI got a `KeyError` when calling this method: `base_component.BaseComponent.__str__`\r\n\r\nHere is the code to reproduce:\r\n\r\n```python\r\nimport os\r\nfrom tfx.utils.dsl_utils import csv_input\r\nfrom tfx.components.example_gen.csv_example_gen.component import CsvExampleGen\r\n\r\n_taxi_root = os.path.join(os.environ['HOME'], 'taxi')\r\n_data_root = os.path.join(_taxi_root, 'data/simple')\r\nexamples = csv_input(_data_root)\r\nexample_gen = CsvExampleGen(input_base=examples)\r\nprint(example_gen)\r\n```\r\n\r\nThe error trace is:\r\n\r\n```\r\n/Users/alelevier/Documents/github/tfx/tfx/components/base/base_component.pyc in __str__(self)\r\n     89         input_dict=self.input_dict,\r\n     90         outputs=self.outputs,\r\n---> 91         exec_properties=self.exec_properties)\r\n     92 \r\n     93   def __repr__(self):\r\n\r\nKeyError: '\\n  component_name'\r\n```\r\n\r\nI looked at the method, it needs use double `{{` and `}}` so change from:\r\n\r\n```\r\n  def __str__(self):\r\n    return \"\"\"\r\n{\r\n  component_name: {component_name},\r\n  unique_name: {unique_name},\r\n  driver: {driver},\r\n  executor: {executor},\r\n  input_dict: {input_dict},\r\n  outputs: {outputs},\r\n  exec_properties: {exec_properties}\r\n}\r\n    \"\"\".format(  # pylint: disable=missing-format-argument-key\r\n        component_name=self.component_name,\r\n        unique_name=self.unique_name,\r\n        driver=self.driver,\r\n        executor=self.executor,\r\n        input_dict=self.input_dict,\r\n        outputs=self.outputs,\r\n        exec_properties=self.exec_properties)\r\n```\r\n\r\nTo:\r\n\r\n```\r\n  def __str__(self):\r\n    return \"\"\"\r\n{{\r\n  component_name: {component_name},\r\n  unique_name: {unique_name},\r\n  driver: {driver},\r\n  executor: {executor},\r\n  input_dict: {input_dict},\r\n  outputs: {outputs},\r\n  exec_properties: {exec_properties}\r\n}}\r\n    \"\"\".format(  # pylint: disable=missing-format-argument-key\r\n        component_name=self.component_name,\r\n        unique_name=self.unique_name,\r\n        driver=self.driver,\r\n        executor=self.executor,\r\n        input_dict=self.input_dict,\r\n        outputs=self.outputs,\r\n        exec_properties=self.exec_properties)\r\n```\n", "before_files": [{"content": "# Copyright 2019 Google LLC. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Base class for all TFX components.\"\"\"\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport abc\nfrom six import with_metaclass\nfrom typing import Any\nfrom typing import Dict\nfrom typing import Optional\nfrom typing import Text\n\nfrom tfx.utils import channel\n\n\nclass ComponentOutputs(object):\n  \"\"\"Helper class to wrap outputs from TFX components.\"\"\"\n\n  def __init__(self, d):\n    self.__dict__ = d\n\n  def get_all(self):\n    return self.__dict__\n\n\nclass BaseComponent(with_metaclass(abc.ABCMeta, object)):\n  \"\"\"Base TFX component.\n\n  This is the parent class of any TFX component.\n\n  Attributes:\n    component_name: Name of the component, should be unique per component class.\n    unique_name: Unique name for every component class instance.\n    driver: Driver class to handle pre-execution behaviors in a component.\n    executor: Executor class to do the real execution work.\n    input_dict: A [Text -> Channel] dict serving as the inputs to the component.\n    exec_properties: A [Text -> Any] dict serving as additional properties\n      needed for execution.\n    outputs: Optional Channel destinations of the component.\n  \"\"\"\n\n  def __init__(self,\n               component_name,\n               driver,\n               executor,\n               input_dict,\n               exec_properties,\n               unique_name = '',\n               outputs = ComponentOutputs({})):\n    self.component_name = component_name\n    self.driver = driver\n    self.executor = executor\n    self.input_dict = input_dict\n    self.exec_properties = exec_properties\n    self.unique_name = unique_name\n    self.outputs = outputs or self._create_outputs()\n    self._type_check(self.input_dict, self.exec_properties)\n\n  def __str__(self):\n    return \"\"\"\n{\n  component_name: {component_name},\n  unique_name: {unique_name},\n  driver: {driver},\n  executor: {executor},\n  input_dict: {input_dict},\n  outputs: {outputs},\n  exec_properties: {exec_properties}\n}\n    \"\"\".format(  # pylint: disable=missing-format-argument-key\n        component_name=self.component_name,\n        unique_name=self.unique_name,\n        driver=self.driver,\n        executor=self.executor,\n        input_dict=self.input_dict,\n        outputs=self.outputs,\n        exec_properties=self.exec_properties)\n\n  def __repr__(self):\n    return self.__str__()\n\n  @abc.abstractmethod\n  def _create_outputs(self):\n    \"\"\"Creates outputs placeholder for components.\n\n    Returns:\n      ComponentOutputs object containing the dict of [Text -> Channel]\n    \"\"\"\n    raise NotImplementedError\n\n  @abc.abstractmethod\n  def _type_check(self, input_dict,\n                  exec_properties):\n    \"\"\"Does type checking for the inputs and exec_properties.\n\n    Args:\n      input_dict: A Dict[Text, Channel] as the inputs of the Component.\n      exec_properties: A Dict[Text, Any] as the execution properties of the\n        component.\n    \"\"\"\n    raise NotImplementedError\n", "path": "tfx/components/base/base_component.py"}], "after_files": [{"content": "# Copyright 2019 Google LLC. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Base class for all TFX components.\"\"\"\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport abc\nfrom six import with_metaclass\nfrom typing import Any\nfrom typing import Dict\nfrom typing import Optional\nfrom typing import Text\n\nfrom tfx.utils import channel\n\n\nclass ComponentOutputs(object):\n  \"\"\"Helper class to wrap outputs from TFX components.\"\"\"\n\n  def __init__(self, d):\n    self.__dict__ = d\n\n  def get_all(self):\n    return self.__dict__\n\n\nclass BaseComponent(with_metaclass(abc.ABCMeta, object)):\n  \"\"\"Base TFX component.\n\n  This is the parent class of any TFX component.\n\n  Attributes:\n    component_name: Name of the component, should be unique per component class.\n    unique_name: Unique name for every component class instance.\n    driver: Driver class to handle pre-execution behaviors in a component.\n    executor: Executor class to do the real execution work.\n    input_dict: A [Text -> Channel] dict serving as the inputs to the component.\n    exec_properties: A [Text -> Any] dict serving as additional properties\n      needed for execution.\n    outputs: Optional Channel destinations of the component.\n  \"\"\"\n\n  def __init__(self,\n               component_name,\n               driver,\n               executor,\n               input_dict,\n               exec_properties,\n               unique_name = '',\n               outputs = ComponentOutputs({})):\n    self.component_name = component_name\n    self.driver = driver\n    self.executor = executor\n    self.input_dict = input_dict\n    self.exec_properties = exec_properties\n    self.unique_name = unique_name\n    self.outputs = outputs or self._create_outputs()\n    self._type_check(self.input_dict, self.exec_properties)\n\n  def __str__(self):\n    return \"\"\"\n{{\n  component_name: {component_name},\n  unique_name: {unique_name},\n  driver: {driver},\n  executor: {executor},\n  input_dict: {input_dict},\n  outputs: {outputs},\n  exec_properties: {exec_properties}\n}}\n    \"\"\".format(  # pylint: disable=missing-format-argument-key\n        component_name=self.component_name,\n        unique_name=self.unique_name,\n        driver=self.driver,\n        executor=self.executor,\n        input_dict=self.input_dict,\n        outputs=self.outputs,\n        exec_properties=self.exec_properties)\n\n  def __repr__(self):\n    return self.__str__()\n\n  @abc.abstractmethod\n  def _create_outputs(self):\n    \"\"\"Creates outputs placeholder for components.\n\n    Returns:\n      ComponentOutputs object containing the dict of [Text -> Channel]\n    \"\"\"\n    raise NotImplementedError\n\n  @abc.abstractmethod\n  def _type_check(self, input_dict,\n                  exec_properties):\n    \"\"\"Does type checking for the inputs and exec_properties.\n\n    Args:\n      input_dict: A Dict[Text, Channel] as the inputs of the Component.\n      exec_properties: A Dict[Text, Any] as the execution properties of the\n        component.\n    \"\"\"\n    raise NotImplementedError\n", "path": "tfx/components/base/base_component.py"}]}