prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  On the newest docs, "Deploy a Streamlit app" page is empty
  **Link to doc page in question (if any):**
  
  https://docs.streamlit.io/en/stable/deploy_streamlit_app.html
  
  **What you think the docs should say:**
  
  For now, show placeholder content (link to heroku deploy instructions?)
  In the future, describe what to do for S4A.
  
  
  --- 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/file_uploader.py`
  Content:
  ```
  1 from streamlit import config
  2 
  3 from streamlit.proto.FileUploader_pb2 import FileUploader as FileUploaderProto
  4 from streamlit.report_thread import get_report_ctx
  5 from streamlit.file_util import get_encoded_file_data
  6 from streamlit.errors import StreamlitDeprecationWarning
  7 from .utils import NoValue, _set_widget_id
  8 
  9 
  10 class FileUploaderMixin:
  11     def file_uploader(
  12         dg, label, type=None, accept_multiple_files=False, key=None, **kwargs
  13     ):
  14         """Display a file uploader widget.
  15         By default, uploaded files are limited to 200MB. You can configure
  16         this using the `server.maxUploadSize` config option.
  17 
  18         Parameters
  19         ----------
  20         label : str or None
  21             A short label explaining to the user what this file uploader is for.
  22 
  23         type : str or list of str or None
  24             Array of allowed extensions. ['png', 'jpg']
  25             The default is None, which means all extensions are allowed.
  26 
  27         accept_multiple_files : bool
  28             If True, allows the user to upload multiple files at the same time,
  29             in which case the return value will be a list of files.
  30             Default: False
  31 
  32         key : str
  33             An optional string to use as the unique key for the widget.
  34             If this is omitted, a key will be generated for the widget
  35             based on its content. Multiple widgets of the same type may
  36             not share the same key.
  37 
  38         Returns
  39         -------
  40         None or UploadedFile or list of UploadedFile
  41             - If allow_multiple_files is False, returns either None or
  42               an UploadedFile object.
  43             - If allow_multiple_files is True, returns a list with the
  44               uploaded files as UploadedFile objects. If no files were
  45               uploaded, returns an empty list.
  46             The UploadedFile class is a subclass of BytesIO, and therefore
  47             it is "file-like". This means you can pass them anywhere where
  48             a file is expected.
  49 
  50         Examples
  51         --------
  52         Insert a file uploader that accepts a single file at a time:
  53 
  54         >>> uploaded_file = st.file_uploader("Choose a file")
  55         >>> if uploaded_file is not None:
  56         ...     # To read file as bytes:
  57         ...     bytes_data = uploaded_file.read()
  58         ...     st.write(bytes_data)
  59         >>>
  60         ...     # To convert to a string based IO:
  61         ...     stringio = StringIO(uploaded_file.decode("utf-8"))
  62         ...     st.write(stringio)
  63         >>>
  64         ...     # To read file as string:
  65         ...     string_data = stringio.read()
  66         ...     st.write(string_data)
  67         >>>
  68         ...     # Can be used wherever a "file-like" object is accepted:
  69         ...     dataframe = pd.read_csv(uploaded_file)
  70         ...     st.write(dataframe)
  71 
  72         Insert a file uploader that accepts multiple files at a time:
  73 
  74         >>> uploaded_files = st.file_uploader("Choose a CSV file", accept_multiple_files=True)
  75         >>> for uploaded_file in uploaded_files:
  76         ...     bytes_data = uploaded_file.read()
  77         ...     st.write("filename:", uploaded_file.name)
  78         ...     st.write(bytes_data)
  79         """
  80 
  81         if type:
  82             if isinstance(type, str):
  83                 type = [type]
  84 
  85             # May need a regex or a library to validate file types are valid
  86             # extensions.
  87             type = [
  88                 file_type if file_type[0] == "." else f".{file_type}"
  89                 for file_type in type
  90             ]
  91 
  92         has_encoding = "encoding" in kwargs
  93         show_deprecation_warning = config.get_option(
  94             "deprecation.showfileUploaderEncoding"
  95         )
  96 
  97         if show_deprecation_warning and has_encoding:
  98             dg.exception(FileUploaderEncodingWarning())  # type: ignore
  99 
  100         file_uploader_proto = FileUploaderProto()
  101         file_uploader_proto.label = label
  102         file_uploader_proto.type[:] = type if type is not None else []
  103         file_uploader_proto.max_upload_size_mb = config.get_option(
  104             "server.maxUploadSize"
  105         )
  106         file_uploader_proto.multiple_files = accept_multiple_files
  107         _set_widget_id("file_uploader", file_uploader_proto, user_key=key)
  108 
  109         files = None
  110         ctx = get_report_ctx()
  111         if ctx is not None:
  112             files = ctx.uploaded_file_mgr.get_files(
  113                 session_id=ctx.session_id, widget_id=file_uploader_proto.id
  114             )
  115 
  116         if files is None or len(files) == 0:
  117             return_value = [] if accept_multiple_files else NoValue
  118         else:
  119             return_value = files if accept_multiple_files else files[0]
  120 
  121         return dg._enqueue("file_uploader", file_uploader_proto, return_value)  # type: ignore
  122 
  123 
  124 class FileUploaderEncodingWarning(StreamlitDeprecationWarning):
  125     def __init__(self):
  126         msg = self._get_message()
  127         config_option = "deprecation.showfileUploaderEncoding"
  128         super(FileUploaderEncodingWarning, self).__init__(
  129             msg=msg, config_option=config_option
  130         )
  131 
  132     def _get_message(self):
  133         return """
  134 The behavior of `st.file_uploader` no longer autodetects the file's encoding.
  135 This means that _all files_ will be returned as binary buffers. If you need to
  136 work with a string buffer, you can convert to a StringIO by decoding the binary
  137 buffer as shown below:
  138 
  139 ```
  140 file_buffer = st.file_uploader(...)
  141 string_io = file_buffer.decode()
  142 ```
  143             """
  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/file_uploader.py b/lib/streamlit/elements/file_uploader.py
  --- a/lib/streamlit/elements/file_uploader.py
  +++ b/lib/streamlit/elements/file_uploader.py
  @@ -43,6 +43,7 @@
               - If allow_multiple_files is True, returns a list with the
                 uploaded files as UploadedFile objects. If no files were
                 uploaded, returns an empty list.
  +
               The UploadedFile class is a subclass of BytesIO, and therefore
               it is "file-like". This means you can pass them anywhere where
               a file is expected.
  
verification_info: {"golden_diff": "diff --git a/lib/streamlit/elements/file_uploader.py b/lib/streamlit/elements/file_uploader.py\n--- a/lib/streamlit/elements/file_uploader.py\n+++ b/lib/streamlit/elements/file_uploader.py\n@@ -43,6 +43,7 @@\n             - If allow_multiple_files is True, returns a list with the\n               uploaded files as UploadedFile objects. If no files were\n               uploaded, returns an empty list.\n+\n             The UploadedFile class is a subclass of BytesIO, and therefore\n             it is \"file-like\". This means you can pass them anywhere where\n             a file is expected.\n", "issue": "On the newest docs, \"Deploy a Streamlit app\" page is empty\n**Link to doc page in question (if any):**\r\n\r\nhttps://docs.streamlit.io/en/stable/deploy_streamlit_app.html\r\n\r\n**What you think the docs should say:**\r\n\r\nFor now, show placeholder content (link to heroku deploy instructions?)\r\nIn the future, describe what to do for S4A.\r\n\n", "before_files": [{"content": "from streamlit import config\n\nfrom streamlit.proto.FileUploader_pb2 import FileUploader as FileUploaderProto\nfrom streamlit.report_thread import get_report_ctx\nfrom streamlit.file_util import get_encoded_file_data\nfrom streamlit.errors import StreamlitDeprecationWarning\nfrom .utils import NoValue, _set_widget_id\n\n\nclass FileUploaderMixin:\n    def file_uploader(\n        dg, label, type=None, accept_multiple_files=False, key=None, **kwargs\n    ):\n        \"\"\"Display a file uploader widget.\n        By default, uploaded files are limited to 200MB. You can configure\n        this using the `server.maxUploadSize` config option.\n\n        Parameters\n        ----------\n        label : str or None\n            A short label explaining to the user what this file uploader is for.\n\n        type : str or list of str or None\n            Array of allowed extensions. ['png', 'jpg']\n            The default is None, which means all extensions are allowed.\n\n        accept_multiple_files : bool\n            If True, allows the user to upload multiple files at the same time,\n            in which case the return value will be a list of files.\n            Default: False\n\n        key : str\n            An optional string to use as the unique key for the widget.\n            If this is omitted, a key will be generated for the widget\n            based on its content. Multiple widgets of the same type may\n            not share the same key.\n\n        Returns\n        -------\n        None or UploadedFile or list of UploadedFile\n            - If allow_multiple_files is False, returns either None or\n              an UploadedFile object.\n            - If allow_multiple_files is True, returns a list with the\n              uploaded files as UploadedFile objects. If no files were\n              uploaded, returns an empty list.\n            The UploadedFile class is a subclass of BytesIO, and therefore\n            it is \"file-like\". This means you can pass them anywhere where\n            a file is expected.\n\n        Examples\n        --------\n        Insert a file uploader that accepts a single file at a time:\n\n        >>> uploaded_file = st.file_uploader(\"Choose a file\")\n        >>> if uploaded_file is not None:\n        ...     # To read file as bytes:\n        ...     bytes_data = uploaded_file.read()\n        ...     st.write(bytes_data)\n        >>>\n        ...     # To convert to a string based IO:\n        ...     stringio = StringIO(uploaded_file.decode(\"utf-8\"))\n        ...     st.write(stringio)\n        >>>\n        ...     # To read file as string:\n        ...     string_data = stringio.read()\n        ...     st.write(string_data)\n        >>>\n        ...     # Can be used wherever a \"file-like\" object is accepted:\n        ...     dataframe = pd.read_csv(uploaded_file)\n        ...     st.write(dataframe)\n\n        Insert a file uploader that accepts multiple files at a time:\n\n        >>> uploaded_files = st.file_uploader(\"Choose a CSV file\", accept_multiple_files=True)\n        >>> for uploaded_file in uploaded_files:\n        ...     bytes_data = uploaded_file.read()\n        ...     st.write(\"filename:\", uploaded_file.name)\n        ...     st.write(bytes_data)\n        \"\"\"\n\n        if type:\n            if isinstance(type, str):\n                type = [type]\n\n            # May need a regex or a library to validate file types are valid\n            # extensions.\n            type = [\n                file_type if file_type[0] == \".\" else f\".{file_type}\"\n                for file_type in type\n            ]\n\n        has_encoding = \"encoding\" in kwargs\n        show_deprecation_warning = config.get_option(\n            \"deprecation.showfileUploaderEncoding\"\n        )\n\n        if show_deprecation_warning and has_encoding:\n            dg.exception(FileUploaderEncodingWarning())  # type: ignore\n\n        file_uploader_proto = FileUploaderProto()\n        file_uploader_proto.label = label\n        file_uploader_proto.type[:] = type if type is not None else []\n        file_uploader_proto.max_upload_size_mb = config.get_option(\n            \"server.maxUploadSize\"\n        )\n        file_uploader_proto.multiple_files = accept_multiple_files\n        _set_widget_id(\"file_uploader\", file_uploader_proto, user_key=key)\n\n        files = None\n        ctx = get_report_ctx()\n        if ctx is not None:\n            files = ctx.uploaded_file_mgr.get_files(\n                session_id=ctx.session_id, widget_id=file_uploader_proto.id\n            )\n\n        if files is None or len(files) == 0:\n            return_value = [] if accept_multiple_files else NoValue\n        else:\n            return_value = files if accept_multiple_files else files[0]\n\n        return dg._enqueue(\"file_uploader\", file_uploader_proto, return_value)  # type: ignore\n\n\nclass FileUploaderEncodingWarning(StreamlitDeprecationWarning):\n    def __init__(self):\n        msg = self._get_message()\n        config_option = \"deprecation.showfileUploaderEncoding\"\n        super(FileUploaderEncodingWarning, self).__init__(\n            msg=msg, config_option=config_option\n        )\n\n    def _get_message(self):\n        return \"\"\"\nThe behavior of `st.file_uploader` no longer autodetects the file's encoding.\nThis means that _all files_ will be returned as binary buffers. If you need to\nwork with a string buffer, you can convert to a StringIO by decoding the binary\nbuffer as shown below:\n\n```\nfile_buffer = st.file_uploader(...)\nstring_io = file_buffer.decode()\n```\n            \"\"\"\n", "path": "lib/streamlit/elements/file_uploader.py"}], "after_files": [{"content": "from streamlit import config\n\nfrom streamlit.proto.FileUploader_pb2 import FileUploader as FileUploaderProto\nfrom streamlit.report_thread import get_report_ctx\nfrom streamlit.file_util import get_encoded_file_data\nfrom streamlit.errors import StreamlitDeprecationWarning\nfrom .utils import NoValue, _set_widget_id\n\n\nclass FileUploaderMixin:\n    def file_uploader(\n        dg, label, type=None, accept_multiple_files=False, key=None, **kwargs\n    ):\n        \"\"\"Display a file uploader widget.\n        By default, uploaded files are limited to 200MB. You can configure\n        this using the `server.maxUploadSize` config option.\n\n        Parameters\n        ----------\n        label : str or None\n            A short label explaining to the user what this file uploader is for.\n\n        type : str or list of str or None\n            Array of allowed extensions. ['png', 'jpg']\n            The default is None, which means all extensions are allowed.\n\n        accept_multiple_files : bool\n            If True, allows the user to upload multiple files at the same time,\n            in which case the return value will be a list of files.\n            Default: False\n\n        key : str\n            An optional string to use as the unique key for the widget.\n            If this is omitted, a key will be generated for the widget\n            based on its content. Multiple widgets of the same type may\n            not share the same key.\n\n        Returns\n        -------\n        None or UploadedFile or list of UploadedFile\n            - If allow_multiple_files is False, returns either None or\n              an UploadedFile object.\n            - If allow_multiple_files is True, returns a list with the\n              uploaded files as UploadedFile objects. If no files were\n              uploaded, returns an empty list.\n\n            The UploadedFile class is a subclass of BytesIO, and therefore\n            it is \"file-like\". This means you can pass them anywhere where\n            a file is expected.\n\n        Examples\n        --------\n        Insert a file uploader that accepts a single file at a time:\n\n        >>> uploaded_file = st.file_uploader(\"Choose a file\")\n        >>> if uploaded_file is not None:\n        ...     # To read file as bytes:\n        ...     bytes_data = uploaded_file.read()\n        ...     st.write(bytes_data)\n        >>>\n        ...     # To convert to a string based IO:\n        ...     stringio = StringIO(uploaded_file.decode(\"utf-8\"))\n        ...     st.write(stringio)\n        >>>\n        ...     # To read file as string:\n        ...     string_data = stringio.read()\n        ...     st.write(string_data)\n        >>>\n        ...     # Can be used wherever a \"file-like\" object is accepted:\n        ...     dataframe = pd.read_csv(uploaded_file)\n        ...     st.write(dataframe)\n\n        Insert a file uploader that accepts multiple files at a time:\n\n        >>> uploaded_files = st.file_uploader(\"Choose a CSV file\", accept_multiple_files=True)\n        >>> for uploaded_file in uploaded_files:\n        ...     bytes_data = uploaded_file.read()\n        ...     st.write(\"filename:\", uploaded_file.name)\n        ...     st.write(bytes_data)\n        \"\"\"\n\n        if type:\n            if isinstance(type, str):\n                type = [type]\n\n            # May need a regex or a library to validate file types are valid\n            # extensions.\n            type = [\n                file_type if file_type[0] == \".\" else f\".{file_type}\"\n                for file_type in type\n            ]\n\n        has_encoding = \"encoding\" in kwargs\n        show_deprecation_warning = config.get_option(\n            \"deprecation.showfileUploaderEncoding\"\n        )\n\n        if show_deprecation_warning and has_encoding:\n            dg.exception(FileUploaderEncodingWarning())  # type: ignore\n\n        file_uploader_proto = FileUploaderProto()\n        file_uploader_proto.label = label\n        file_uploader_proto.type[:] = type if type is not None else []\n        file_uploader_proto.max_upload_size_mb = config.get_option(\n            \"server.maxUploadSize\"\n        )\n        file_uploader_proto.multiple_files = accept_multiple_files\n        _set_widget_id(\"file_uploader\", file_uploader_proto, user_key=key)\n\n        files = None\n        ctx = get_report_ctx()\n        if ctx is not None:\n            files = ctx.uploaded_file_mgr.get_files(\n                session_id=ctx.session_id, widget_id=file_uploader_proto.id\n            )\n\n        if files is None or len(files) == 0:\n            return_value = [] if accept_multiple_files else NoValue\n        else:\n            return_value = files if accept_multiple_files else files[0]\n\n        return dg._enqueue(\"file_uploader\", file_uploader_proto, return_value)  # type: ignore\n\n\nclass FileUploaderEncodingWarning(StreamlitDeprecationWarning):\n    def __init__(self):\n        msg = self._get_message()\n        config_option = \"deprecation.showfileUploaderEncoding\"\n        super(FileUploaderEncodingWarning, self).__init__(\n            msg=msg, config_option=config_option\n        )\n\n    def _get_message(self):\n        return \"\"\"\nThe behavior of `st.file_uploader` no longer autodetects the file's encoding.\nThis means that _all files_ will be returned as binary buffers. If you need to\nwork with a string buffer, you can convert to a StringIO by decoding the binary\nbuffer as shown below:\n\n```\nfile_buffer = st.file_uploader(...)\nstring_io = file_buffer.decode()\n```\n            \"\"\"\n", "path": "lib/streamlit/elements/file_uploader.py"}]}