prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Crazy error message shown when two widgets have the same key
  # Steps to reproduce
  
  1. Run this code
     ```
     import streamlit as st
  
     st.button("OK")
     st.button("OK")
     ```
  2. Observe!
  
  ## Expected behavior:
  
  You should get one button plus an error message explaining you can't have to `st.button` calls with the same key.
  
  ## Actual behavior:
  
  The error message complains about `st.-3952690150221448179` :scream_cat: 
  
  See screenshot:
  ![image](https://user-images.githubusercontent.com/690814/91766363-4f35d480-eb8f-11ea-8648-ce832caf4da3.png)
  
  ## Is this a regression?
  
  yes
  
  # Debug info
  
  - Streamlit version: 0.65.0
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `lib/streamlit/elements/utils.py`
  Content:
  ```
  1 import textwrap
  2 
  3 from streamlit import type_util
  4 from streamlit.report_thread import get_report_ctx
  5 from streamlit.errors import DuplicateWidgetID
  6 from typing import Optional, Any
  7 
  8 
  9 class NoValue(object):
  10     """Return this from DeltaGenerator.foo_widget() when you want the st.foo_widget()
  11     call to return None. This is needed because `DeltaGenerator._enqueue`
  12     replaces `None` with a `DeltaGenerator` (for use in non-widget elements).
  13     """
  14 
  15     pass
  16 
  17 
  18 def _clean_text(text):
  19     return textwrap.dedent(str(text)).strip()
  20 
  21 
  22 def _build_duplicate_widget_message(
  23     widget_func_name: str, user_key: Optional[str] = None
  24 ) -> str:
  25     if user_key is not None:
  26         message = textwrap.dedent(
  27             """
  28             There are multiple identical `st.{widget_type}` widgets with
  29             `key='{user_key}'`.
  30 
  31             To fix this, please make sure that the `key` argument is unique for
  32             each `st.{widget_type}` you create.
  33             """
  34         )
  35     else:
  36         message = textwrap.dedent(
  37             """
  38             There are multiple identical `st.{widget_type}` widgets with the
  39             same generated key.
  40 
  41             (When a widget is created, it's assigned an internal key based on
  42             its structure. Multiple widgets with an identical structure will
  43             result in the same internal key, which causes this error.)
  44 
  45             To fix this, please pass a unique `key` argument to
  46             `st.{widget_type}`.
  47             """
  48         )
  49 
  50     return message.strip("\n").format(widget_type=widget_func_name, user_key=user_key)
  51 
  52 
  53 def _set_widget_id(
  54     element_type: str,
  55     element_proto: Any,
  56     user_key: Optional[str] = None,
  57     widget_func_name: Optional[str] = None,
  58 ) -> None:
  59     """Set the widget id.
  60 
  61     Parameters
  62     ----------
  63     element_type : str
  64         The type of the element as stored in proto.
  65     element_proto : proto
  66         The proto of the specified type (e.g. Button/Multiselect/Slider proto)
  67     user_key : str or None
  68         Optional user-specified key to use for the widget ID.
  69         If this is None, we'll generate an ID by hashing the element.
  70     widget_func_name : str or None
  71         The widget's DeltaGenerator function name, if it's different from
  72         its element_type. Custom components are a special case: they all have
  73         the element_type "component_instance", but are instantiated with
  74         dynamically-named functions.
  75 
  76     """
  77 
  78     if widget_func_name is None:
  79         widget_func_name = element_type
  80 
  81     # Identify the widget with a hash of type + contents
  82     element_hash = hash((element_type, element_proto.SerializeToString()))
  83     if user_key is not None:
  84         widget_id = "%s-%s" % (user_key, element_hash)
  85     else:
  86         widget_id = "%s" % element_hash
  87 
  88     ctx = get_report_ctx()
  89     if ctx is not None:
  90         added = ctx.widget_ids_this_run.add(widget_id)
  91         if not added:
  92             raise DuplicateWidgetID(
  93                 _build_duplicate_widget_message(widget_id, user_key)
  94             )
  95     element_proto.id = widget_id
  96 
  97 
  98 def _get_widget_ui_value(
  99     element_type: str,
  100     element_proto: Any,
  101     user_key: Optional[str] = None,
  102     widget_func_name: Optional[str] = None,
  103 ) -> Any:
  104     """Get the widget ui_value from the report context.
  105     NOTE: This function should be called after the proto has been filled.
  106 
  107     Parameters
  108     ----------
  109     element_type : str
  110         The type of the element as stored in proto.
  111     element : proto
  112         The proto of the specified type (e.g. Button/Multiselect/Slider proto)
  113     user_key : str
  114         Optional user-specified string to use as the widget ID.
  115         If this is None, we'll generate an ID by hashing the element.
  116     widget_func_name : str or None
  117         The widget's DeltaGenerator function name, if it's different from
  118         its element_type. Custom components are a special case: they all have
  119         the element_type "component_instance", but are instantiated with
  120         dynamically-named functions.
  121 
  122     Returns
  123     -------
  124     ui_value : any
  125         The value of the widget set by the client or
  126         the default value passed. If the report context
  127         doesn't exist, None will be returned.
  128 
  129     """
  130     _set_widget_id(element_type, element_proto, user_key, widget_func_name)
  131     ctx = get_report_ctx()
  132     ui_value = ctx.widgets.get_widget_value(element_proto.id) if ctx else None
  133     return ui_value
  134 
  135 
  136 def last_index_for_melted_dataframes(data):
  137     if type_util.is_dataframe_compatible(data):
  138         data = type_util.convert_anything_to_df(data)
  139 
  140         if data.index.size > 0:
  141             return data.index[-1]
  142 
  143     return None
  144
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/lib/streamlit/elements/utils.py b/lib/streamlit/elements/utils.py
  --- a/lib/streamlit/elements/utils.py
  +++ b/lib/streamlit/elements/utils.py
  @@ -90,7 +90,7 @@
           added = ctx.widget_ids_this_run.add(widget_id)
           if not added:
               raise DuplicateWidgetID(
  -                _build_duplicate_widget_message(widget_id, user_key)
  +                _build_duplicate_widget_message(widget_func_name, user_key)
               )
       element_proto.id = widget_id
  
verification_info: {"golden_diff": "diff --git a/lib/streamlit/elements/utils.py b/lib/streamlit/elements/utils.py\n--- a/lib/streamlit/elements/utils.py\n+++ b/lib/streamlit/elements/utils.py\n@@ -90,7 +90,7 @@\n         added = ctx.widget_ids_this_run.add(widget_id)\n         if not added:\n             raise DuplicateWidgetID(\n-                _build_duplicate_widget_message(widget_id, user_key)\n+                _build_duplicate_widget_message(widget_func_name, user_key)\n             )\n     element_proto.id = widget_id\n", "issue": "Crazy error message shown when two widgets have the same key\n# Steps to reproduce\r\n\r\n1. Run this code\r\n   ```\r\n   import streamlit as st\r\n\r\n   st.button(\"OK\")\r\n   st.button(\"OK\")\r\n   ```\r\n2. Observe!\r\n\r\n## Expected behavior:\r\n\r\nYou should get one button plus an error message explaining you can't have to `st.button` calls with the same key.\r\n\r\n## Actual behavior:\r\n\r\nThe error message complains about `st.-3952690150221448179` :scream_cat: \r\n\r\nSee screenshot:\r\n![image](https://user-images.githubusercontent.com/690814/91766363-4f35d480-eb8f-11ea-8648-ce832caf4da3.png)\r\n\r\n## Is this a regression?\r\n\r\nyes\r\n\r\n# Debug info\r\n\r\n- Streamlit version: 0.65.0\r\n\n", "before_files": [{"content": "import textwrap\n\nfrom streamlit import type_util\nfrom streamlit.report_thread import get_report_ctx\nfrom streamlit.errors import DuplicateWidgetID\nfrom typing import Optional, Any\n\n\nclass NoValue(object):\n    \"\"\"Return this from DeltaGenerator.foo_widget() when you want the st.foo_widget()\n    call to return None. This is needed because `DeltaGenerator._enqueue`\n    replaces `None` with a `DeltaGenerator` (for use in non-widget elements).\n    \"\"\"\n\n    pass\n\n\ndef _clean_text(text):\n    return textwrap.dedent(str(text)).strip()\n\n\ndef _build_duplicate_widget_message(\n    widget_func_name: str, user_key: Optional[str] = None\n) -> str:\n    if user_key is not None:\n        message = textwrap.dedent(\n            \"\"\"\n            There are multiple identical `st.{widget_type}` widgets with\n            `key='{user_key}'`.\n\n            To fix this, please make sure that the `key` argument is unique for\n            each `st.{widget_type}` you create.\n            \"\"\"\n        )\n    else:\n        message = textwrap.dedent(\n            \"\"\"\n            There are multiple identical `st.{widget_type}` widgets with the\n            same generated key.\n\n            (When a widget is created, it's assigned an internal key based on\n            its structure. Multiple widgets with an identical structure will\n            result in the same internal key, which causes this error.)\n\n            To fix this, please pass a unique `key` argument to\n            `st.{widget_type}`.\n            \"\"\"\n        )\n\n    return message.strip(\"\\n\").format(widget_type=widget_func_name, user_key=user_key)\n\n\ndef _set_widget_id(\n    element_type: str,\n    element_proto: Any,\n    user_key: Optional[str] = None,\n    widget_func_name: Optional[str] = None,\n) -> None:\n    \"\"\"Set the widget id.\n\n    Parameters\n    ----------\n    element_type : str\n        The type of the element as stored in proto.\n    element_proto : proto\n        The proto of the specified type (e.g. Button/Multiselect/Slider proto)\n    user_key : str or None\n        Optional user-specified key to use for the widget ID.\n        If this is None, we'll generate an ID by hashing the element.\n    widget_func_name : str or None\n        The widget's DeltaGenerator function name, if it's different from\n        its element_type. Custom components are a special case: they all have\n        the element_type \"component_instance\", but are instantiated with\n        dynamically-named functions.\n\n    \"\"\"\n\n    if widget_func_name is None:\n        widget_func_name = element_type\n\n    # Identify the widget with a hash of type + contents\n    element_hash = hash((element_type, element_proto.SerializeToString()))\n    if user_key is not None:\n        widget_id = \"%s-%s\" % (user_key, element_hash)\n    else:\n        widget_id = \"%s\" % element_hash\n\n    ctx = get_report_ctx()\n    if ctx is not None:\n        added = ctx.widget_ids_this_run.add(widget_id)\n        if not added:\n            raise DuplicateWidgetID(\n                _build_duplicate_widget_message(widget_id, user_key)\n            )\n    element_proto.id = widget_id\n\n\ndef _get_widget_ui_value(\n    element_type: str,\n    element_proto: Any,\n    user_key: Optional[str] = None,\n    widget_func_name: Optional[str] = None,\n) -> Any:\n    \"\"\"Get the widget ui_value from the report context.\n    NOTE: This function should be called after the proto has been filled.\n\n    Parameters\n    ----------\n    element_type : str\n        The type of the element as stored in proto.\n    element : proto\n        The proto of the specified type (e.g. Button/Multiselect/Slider proto)\n    user_key : str\n        Optional user-specified string to use as the widget ID.\n        If this is None, we'll generate an ID by hashing the element.\n    widget_func_name : str or None\n        The widget's DeltaGenerator function name, if it's different from\n        its element_type. Custom components are a special case: they all have\n        the element_type \"component_instance\", but are instantiated with\n        dynamically-named functions.\n\n    Returns\n    -------\n    ui_value : any\n        The value of the widget set by the client or\n        the default value passed. If the report context\n        doesn't exist, None will be returned.\n\n    \"\"\"\n    _set_widget_id(element_type, element_proto, user_key, widget_func_name)\n    ctx = get_report_ctx()\n    ui_value = ctx.widgets.get_widget_value(element_proto.id) if ctx else None\n    return ui_value\n\n\ndef last_index_for_melted_dataframes(data):\n    if type_util.is_dataframe_compatible(data):\n        data = type_util.convert_anything_to_df(data)\n\n        if data.index.size > 0:\n            return data.index[-1]\n\n    return None\n", "path": "lib/streamlit/elements/utils.py"}], "after_files": [{"content": "import textwrap\n\nfrom streamlit import type_util\nfrom streamlit.report_thread import get_report_ctx\nfrom streamlit.errors import DuplicateWidgetID\nfrom typing import Optional, Any\n\n\nclass NoValue(object):\n    \"\"\"Return this from DeltaGenerator.foo_widget() when you want the st.foo_widget()\n    call to return None. This is needed because `DeltaGenerator._enqueue`\n    replaces `None` with a `DeltaGenerator` (for use in non-widget elements).\n    \"\"\"\n\n    pass\n\n\ndef _clean_text(text):\n    return textwrap.dedent(str(text)).strip()\n\n\ndef _build_duplicate_widget_message(\n    widget_func_name: str, user_key: Optional[str] = None\n) -> str:\n    if user_key is not None:\n        message = textwrap.dedent(\n            \"\"\"\n            There are multiple identical `st.{widget_type}` widgets with\n            `key='{user_key}'`.\n\n            To fix this, please make sure that the `key` argument is unique for\n            each `st.{widget_type}` you create.\n            \"\"\"\n        )\n    else:\n        message = textwrap.dedent(\n            \"\"\"\n            There are multiple identical `st.{widget_type}` widgets with the\n            same generated key.\n\n            (When a widget is created, it's assigned an internal key based on\n            its structure. Multiple widgets with an identical structure will\n            result in the same internal key, which causes this error.)\n\n            To fix this, please pass a unique `key` argument to\n            `st.{widget_type}`.\n            \"\"\"\n        )\n\n    return message.strip(\"\\n\").format(widget_type=widget_func_name, user_key=user_key)\n\n\ndef _set_widget_id(\n    element_type: str,\n    element_proto: Any,\n    user_key: Optional[str] = None,\n    widget_func_name: Optional[str] = None,\n) -> None:\n    \"\"\"Set the widget id.\n\n    Parameters\n    ----------\n    element_type : str\n        The type of the element as stored in proto.\n    element_proto : proto\n        The proto of the specified type (e.g. Button/Multiselect/Slider proto)\n    user_key : str or None\n        Optional user-specified key to use for the widget ID.\n        If this is None, we'll generate an ID by hashing the element.\n    widget_func_name : str or None\n        The widget's DeltaGenerator function name, if it's different from\n        its element_type. Custom components are a special case: they all have\n        the element_type \"component_instance\", but are instantiated with\n        dynamically-named functions.\n\n    \"\"\"\n\n    if widget_func_name is None:\n        widget_func_name = element_type\n\n    # Identify the widget with a hash of type + contents\n    element_hash = hash((element_type, element_proto.SerializeToString()))\n    if user_key is not None:\n        widget_id = \"%s-%s\" % (user_key, element_hash)\n    else:\n        widget_id = \"%s\" % element_hash\n\n    ctx = get_report_ctx()\n    if ctx is not None:\n        added = ctx.widget_ids_this_run.add(widget_id)\n        if not added:\n            raise DuplicateWidgetID(\n                _build_duplicate_widget_message(widget_func_name, user_key)\n            )\n    element_proto.id = widget_id\n\n\ndef _get_widget_ui_value(\n    element_type: str,\n    element_proto: Any,\n    user_key: Optional[str] = None,\n    widget_func_name: Optional[str] = None,\n) -> Any:\n    \"\"\"Get the widget ui_value from the report context.\n    NOTE: This function should be called after the proto has been filled.\n\n    Parameters\n    ----------\n    element_type : str\n        The type of the element as stored in proto.\n    element : proto\n        The proto of the specified type (e.g. Button/Multiselect/Slider proto)\n    user_key : str\n        Optional user-specified string to use as the widget ID.\n        If this is None, we'll generate an ID by hashing the element.\n    widget_func_name : str or None\n        The widget's DeltaGenerator function name, if it's different from\n        its element_type. Custom components are a special case: they all have\n        the element_type \"component_instance\", but are instantiated with\n        dynamically-named functions.\n\n    Returns\n    -------\n    ui_value : any\n        The value of the widget set by the client or\n        the default value passed. If the report context\n        doesn't exist, None will be returned.\n\n    \"\"\"\n    _set_widget_id(element_type, element_proto, user_key, widget_func_name)\n    ctx = get_report_ctx()\n    ui_value = ctx.widgets.get_widget_value(element_proto.id) if ctx else None\n    return ui_value\n\n\ndef last_index_for_melted_dataframes(data):\n    if type_util.is_dataframe_compatible(data):\n        data = type_util.convert_anything_to_df(data)\n\n        if data.index.size > 0:\n            return data.index[-1]\n\n    return None\n", "path": "lib/streamlit/elements/utils.py"}]}