prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
   experimental_get_query_params  won't work before rerun 
  ### Checklist
  
  - [X] I have searched the [existing issues](https://github.com/streamlit/streamlit/issues) for similar issues.
  - [X] I added a very descriptive title to this issue.
  - [X] I have provided sufficient information below to help reproduce this issue.
  
  ### Summary
  
  User can not get right query_params before rerun.
  
  ### Reproducible Code Example
  
  ```Python
  import streamlit as st
  
  st.experimental_set_query_params(param=3)
  st.write(st.experimental_get_query_params())
  ```
  
  
  ### Steps To Reproduce
  
  Run script, `{"param ": 3}` will not appear at first time until rerun script after querystring in browser already changed.
  
  ### Expected Behavior
  
  Show `{"param ": 3}`
  
  ### Current Behavior
  
  show empty dict
  
  ### Is this a regression?
  
  - [X] Yes, this used to work in a previous version.
  
  ### Debug info
  
  - Streamlit version: 1.20.0
  - Python version: 3.10.6
  - Operating System: Linux
  - Browser: Chrome
  - Virtual environment: None
  
  
  ### Additional Information
  
  In previous version `set_query_params` will set `ctx.query_string = parse.urlencode(query_params, doseq=True)` immediately.
  
  But in 1.20, this line is removed while `get_query_params` still get if from `ctx.query_string` .
  
  ### Are you willing to submit a PR?
  
  - [x] Yes, I am willing to submit a PR!
  
  --- 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/commands/query_params.py`
  Content:
  ```
  1 # Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022)
  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 
  15 import urllib.parse as parse
  16 from typing import Any, Dict, List
  17 
  18 from streamlit import util
  19 from streamlit.errors import StreamlitAPIException
  20 from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
  21 from streamlit.runtime.metrics_util import gather_metrics
  22 from streamlit.runtime.scriptrunner import get_script_run_ctx
  23 
  24 EMBED_QUERY_PARAM = "embed"
  25 EMBED_OPTIONS_QUERY_PARAM = "embed_options"
  26 EMBED_QUERY_PARAMS_KEYS = [EMBED_QUERY_PARAM, EMBED_OPTIONS_QUERY_PARAM]
  27 
  28 
  29 @gather_metrics("experimental_get_query_params")
  30 def get_query_params() -> Dict[str, List[str]]:
  31     """Return the query parameters that is currently showing in the browser's URL bar.
  32 
  33     Returns
  34     -------
  35     dict
  36       The current query parameters as a dict. "Query parameters" are the part of the URL that comes
  37       after the first "?".
  38 
  39     Example
  40     -------
  41     Let's say the user's web browser is at
  42     `http://localhost:8501/?show_map=True&selected=asia&selected=america`.
  43     Then, you can get the query parameters using the following:
  44 
  45     >>> import streamlit as st
  46     >>>
  47     >>> st.experimental_get_query_params()
  48     {"show_map": ["True"], "selected": ["asia", "america"]}
  49 
  50     Note that the values in the returned dict are *always* lists. This is
  51     because we internally use Python's urllib.parse.parse_qs(), which behaves
  52     this way. And this behavior makes sense when you consider that every item
  53     in a query string is potentially a 1-element array.
  54 
  55     """
  56     ctx = get_script_run_ctx()
  57     if ctx is None:
  58         return {}
  59     # Return new query params dict, but without embed, embed_options query params
  60     return util.exclude_key_query_params(
  61         parse.parse_qs(ctx.query_string), keys_to_exclude=EMBED_QUERY_PARAMS_KEYS
  62     )
  63 
  64 
  65 @gather_metrics("experimental_set_query_params")
  66 def set_query_params(**query_params: Any) -> None:
  67     """Set the query parameters that are shown in the browser's URL bar.
  68 
  69     .. warning::
  70         Query param `embed` cannot be set using this method.
  71 
  72     Parameters
  73     ----------
  74     **query_params : dict
  75         The query parameters to set, as key-value pairs.
  76 
  77     Example
  78     -------
  79 
  80     To point the user's web browser to something like
  81     "http://localhost:8501/?show_map=True&selected=asia&selected=america",
  82     you would do the following:
  83 
  84     >>> import streamlit as st
  85     >>>
  86     >>> st.experimental_set_query_params(
  87     ...     show_map=True,
  88     ...     selected=["asia", "america"],
  89     ... )
  90 
  91     """
  92     ctx = get_script_run_ctx()
  93     if ctx is None:
  94         return
  95 
  96     msg = ForwardMsg()
  97     msg.page_info_changed.query_string = _ensure_no_embed_params(
  98         query_params, ctx.query_string
  99     )
  100     ctx.enqueue(msg)
  101 
  102 
  103 def _ensure_no_embed_params(
  104     query_params: Dict[str, List[str]], query_string: str
  105 ) -> str:
  106     """Ensures there are no embed params set (raises StreamlitAPIException) if there is a try,
  107     also makes sure old param values in query_string are preserved. Returns query_string : str."""
  108     # Get query params dict without embed, embed_options params
  109     query_params_without_embed = util.exclude_key_query_params(
  110         query_params, keys_to_exclude=EMBED_QUERY_PARAMS_KEYS
  111     )
  112     if query_params != query_params_without_embed:
  113         raise StreamlitAPIException(
  114             "Query param embed and embed_options (case-insensitive) cannot be set using set_query_params method."
  115         )
  116 
  117     all_current_params = parse.parse_qs(query_string)
  118     current_embed_params = parse.urlencode(
  119         {
  120             EMBED_QUERY_PARAM: [
  121                 param
  122                 for param in util.extract_key_query_params(
  123                     all_current_params, param_key=EMBED_QUERY_PARAM
  124                 )
  125             ],
  126             EMBED_OPTIONS_QUERY_PARAM: [
  127                 param
  128                 for param in util.extract_key_query_params(
  129                     all_current_params, param_key=EMBED_OPTIONS_QUERY_PARAM
  130                 )
  131             ],
  132         },
  133         doseq=True,
  134     )
  135     query_string = parse.urlencode(query_params, doseq=True)
  136 
  137     if query_string:
  138         separator = "&" if current_embed_params else ""
  139         return separator.join([query_string, current_embed_params])
  140     return current_embed_params
  141
  ```
  --- 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/commands/query_params.py b/lib/streamlit/commands/query_params.py
  --- a/lib/streamlit/commands/query_params.py
  +++ b/lib/streamlit/commands/query_params.py
  @@ -97,6 +97,7 @@
       msg.page_info_changed.query_string = _ensure_no_embed_params(
           query_params, ctx.query_string
       )
  +    ctx.query_string = msg.page_info_changed.query_string
       ctx.enqueue(msg)
  
verification_info: {"golden_diff": "diff --git a/lib/streamlit/commands/query_params.py b/lib/streamlit/commands/query_params.py\n--- a/lib/streamlit/commands/query_params.py\n+++ b/lib/streamlit/commands/query_params.py\n@@ -97,6 +97,7 @@\n     msg.page_info_changed.query_string = _ensure_no_embed_params(\n         query_params, ctx.query_string\n     )\n+    ctx.query_string = msg.page_info_changed.query_string\n     ctx.enqueue(msg)\n", "issue": " experimental_get_query_params  won't work before rerun \n### Checklist\n\n- [X] I have searched the [existing issues](https://github.com/streamlit/streamlit/issues) for similar issues.\n- [X] I added a very descriptive title to this issue.\n- [X] I have provided sufficient information below to help reproduce this issue.\n\n### Summary\n\nUser can not get right query_params before rerun.\n\n### Reproducible Code Example\n\n```Python\nimport streamlit as st\r\n\r\nst.experimental_set_query_params(param=3)\r\nst.write(st.experimental_get_query_params())\n```\n\n\n### Steps To Reproduce\n\nRun script, `{\"param \": 3}` will not appear at first time until rerun script after querystring in browser already changed.\n\n### Expected Behavior\n\nShow `{\"param \": 3}`\n\n### Current Behavior\n\nshow empty dict\n\n### Is this a regression?\n\n- [X] Yes, this used to work in a previous version.\n\n### Debug info\n\n- Streamlit version: 1.20.0\r\n- Python version: 3.10.6\r\n- Operating System: Linux\r\n- Browser: Chrome\r\n- Virtual environment: None\r\n\n\n### Additional Information\n\nIn previous version `set_query_params` will set `ctx.query_string = parse.urlencode(query_params, doseq=True)` immediately.\r\n\r\nBut in 1.20, this line is removed while `get_query_params` still get if from `ctx.query_string` .\n\n### Are you willing to submit a PR?\n\n- [x] Yes, I am willing to submit a PR!\n", "before_files": [{"content": "# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022)\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\nimport urllib.parse as parse\nfrom typing import Any, Dict, List\n\nfrom streamlit import util\nfrom streamlit.errors import StreamlitAPIException\nfrom streamlit.proto.ForwardMsg_pb2 import ForwardMsg\nfrom streamlit.runtime.metrics_util import gather_metrics\nfrom streamlit.runtime.scriptrunner import get_script_run_ctx\n\nEMBED_QUERY_PARAM = \"embed\"\nEMBED_OPTIONS_QUERY_PARAM = \"embed_options\"\nEMBED_QUERY_PARAMS_KEYS = [EMBED_QUERY_PARAM, EMBED_OPTIONS_QUERY_PARAM]\n\n\n@gather_metrics(\"experimental_get_query_params\")\ndef get_query_params() -> Dict[str, List[str]]:\n    \"\"\"Return the query parameters that is currently showing in the browser's URL bar.\n\n    Returns\n    -------\n    dict\n      The current query parameters as a dict. \"Query parameters\" are the part of the URL that comes\n      after the first \"?\".\n\n    Example\n    -------\n    Let's say the user's web browser is at\n    `http://localhost:8501/?show_map=True&selected=asia&selected=america`.\n    Then, you can get the query parameters using the following:\n\n    >>> import streamlit as st\n    >>>\n    >>> st.experimental_get_query_params()\n    {\"show_map\": [\"True\"], \"selected\": [\"asia\", \"america\"]}\n\n    Note that the values in the returned dict are *always* lists. This is\n    because we internally use Python's urllib.parse.parse_qs(), which behaves\n    this way. And this behavior makes sense when you consider that every item\n    in a query string is potentially a 1-element array.\n\n    \"\"\"\n    ctx = get_script_run_ctx()\n    if ctx is None:\n        return {}\n    # Return new query params dict, but without embed, embed_options query params\n    return util.exclude_key_query_params(\n        parse.parse_qs(ctx.query_string), keys_to_exclude=EMBED_QUERY_PARAMS_KEYS\n    )\n\n\n@gather_metrics(\"experimental_set_query_params\")\ndef set_query_params(**query_params: Any) -> None:\n    \"\"\"Set the query parameters that are shown in the browser's URL bar.\n\n    .. warning::\n        Query param `embed` cannot be set using this method.\n\n    Parameters\n    ----------\n    **query_params : dict\n        The query parameters to set, as key-value pairs.\n\n    Example\n    -------\n\n    To point the user's web browser to something like\n    \"http://localhost:8501/?show_map=True&selected=asia&selected=america\",\n    you would do the following:\n\n    >>> import streamlit as st\n    >>>\n    >>> st.experimental_set_query_params(\n    ...     show_map=True,\n    ...     selected=[\"asia\", \"america\"],\n    ... )\n\n    \"\"\"\n    ctx = get_script_run_ctx()\n    if ctx is None:\n        return\n\n    msg = ForwardMsg()\n    msg.page_info_changed.query_string = _ensure_no_embed_params(\n        query_params, ctx.query_string\n    )\n    ctx.enqueue(msg)\n\n\ndef _ensure_no_embed_params(\n    query_params: Dict[str, List[str]], query_string: str\n) -> str:\n    \"\"\"Ensures there are no embed params set (raises StreamlitAPIException) if there is a try,\n    also makes sure old param values in query_string are preserved. Returns query_string : str.\"\"\"\n    # Get query params dict without embed, embed_options params\n    query_params_without_embed = util.exclude_key_query_params(\n        query_params, keys_to_exclude=EMBED_QUERY_PARAMS_KEYS\n    )\n    if query_params != query_params_without_embed:\n        raise StreamlitAPIException(\n            \"Query param embed and embed_options (case-insensitive) cannot be set using set_query_params method.\"\n        )\n\n    all_current_params = parse.parse_qs(query_string)\n    current_embed_params = parse.urlencode(\n        {\n            EMBED_QUERY_PARAM: [\n                param\n                for param in util.extract_key_query_params(\n                    all_current_params, param_key=EMBED_QUERY_PARAM\n                )\n            ],\n            EMBED_OPTIONS_QUERY_PARAM: [\n                param\n                for param in util.extract_key_query_params(\n                    all_current_params, param_key=EMBED_OPTIONS_QUERY_PARAM\n                )\n            ],\n        },\n        doseq=True,\n    )\n    query_string = parse.urlencode(query_params, doseq=True)\n\n    if query_string:\n        separator = \"&\" if current_embed_params else \"\"\n        return separator.join([query_string, current_embed_params])\n    return current_embed_params\n", "path": "lib/streamlit/commands/query_params.py"}], "after_files": [{"content": "# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022)\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\nimport urllib.parse as parse\nfrom typing import Any, Dict, List\n\nfrom streamlit import util\nfrom streamlit.errors import StreamlitAPIException\nfrom streamlit.proto.ForwardMsg_pb2 import ForwardMsg\nfrom streamlit.runtime.metrics_util import gather_metrics\nfrom streamlit.runtime.scriptrunner import get_script_run_ctx\n\nEMBED_QUERY_PARAM = \"embed\"\nEMBED_OPTIONS_QUERY_PARAM = \"embed_options\"\nEMBED_QUERY_PARAMS_KEYS = [EMBED_QUERY_PARAM, EMBED_OPTIONS_QUERY_PARAM]\n\n\n@gather_metrics(\"experimental_get_query_params\")\ndef get_query_params() -> Dict[str, List[str]]:\n    \"\"\"Return the query parameters that is currently showing in the browser's URL bar.\n\n    Returns\n    -------\n    dict\n      The current query parameters as a dict. \"Query parameters\" are the part of the URL that comes\n      after the first \"?\".\n\n    Example\n    -------\n    Let's say the user's web browser is at\n    `http://localhost:8501/?show_map=True&selected=asia&selected=america`.\n    Then, you can get the query parameters using the following:\n\n    >>> import streamlit as st\n    >>>\n    >>> st.experimental_get_query_params()\n    {\"show_map\": [\"True\"], \"selected\": [\"asia\", \"america\"]}\n\n    Note that the values in the returned dict are *always* lists. This is\n    because we internally use Python's urllib.parse.parse_qs(), which behaves\n    this way. And this behavior makes sense when you consider that every item\n    in a query string is potentially a 1-element array.\n\n    \"\"\"\n    ctx = get_script_run_ctx()\n    if ctx is None:\n        return {}\n    # Return new query params dict, but without embed, embed_options query params\n    return util.exclude_key_query_params(\n        parse.parse_qs(ctx.query_string), keys_to_exclude=EMBED_QUERY_PARAMS_KEYS\n    )\n\n\n@gather_metrics(\"experimental_set_query_params\")\ndef set_query_params(**query_params: Any) -> None:\n    \"\"\"Set the query parameters that are shown in the browser's URL bar.\n\n    .. warning::\n        Query param `embed` cannot be set using this method.\n\n    Parameters\n    ----------\n    **query_params : dict\n        The query parameters to set, as key-value pairs.\n\n    Example\n    -------\n\n    To point the user's web browser to something like\n    \"http://localhost:8501/?show_map=True&selected=asia&selected=america\",\n    you would do the following:\n\n    >>> import streamlit as st\n    >>>\n    >>> st.experimental_set_query_params(\n    ...     show_map=True,\n    ...     selected=[\"asia\", \"america\"],\n    ... )\n\n    \"\"\"\n    ctx = get_script_run_ctx()\n    if ctx is None:\n        return\n\n    msg = ForwardMsg()\n    msg.page_info_changed.query_string = _ensure_no_embed_params(\n        query_params, ctx.query_string\n    )\n    ctx.query_string = msg.page_info_changed.query_string\n    ctx.enqueue(msg)\n\n\ndef _ensure_no_embed_params(\n    query_params: Dict[str, List[str]], query_string: str\n) -> str:\n    \"\"\"Ensures there are no embed params set (raises StreamlitAPIException) if there is a try,\n    also makes sure old param values in query_string are preserved. Returns query_string : str.\"\"\"\n    # Get query params dict without embed, embed_options params\n    query_params_without_embed = util.exclude_key_query_params(\n        query_params, keys_to_exclude=EMBED_QUERY_PARAMS_KEYS\n    )\n    if query_params != query_params_without_embed:\n        raise StreamlitAPIException(\n            \"Query param embed and embed_options (case-insensitive) cannot be set using set_query_params method.\"\n        )\n\n    all_current_params = parse.parse_qs(query_string)\n    current_embed_params = parse.urlencode(\n        {\n            EMBED_QUERY_PARAM: [\n                param\n                for param in util.extract_key_query_params(\n                    all_current_params, param_key=EMBED_QUERY_PARAM\n                )\n            ],\n            EMBED_OPTIONS_QUERY_PARAM: [\n                param\n                for param in util.extract_key_query_params(\n                    all_current_params, param_key=EMBED_OPTIONS_QUERY_PARAM\n                )\n            ],\n        },\n        doseq=True,\n    )\n    query_string = parse.urlencode(query_params, doseq=True)\n\n    if query_string:\n        separator = \"&\" if current_embed_params else \"\"\n        return separator.join([query_string, current_embed_params])\n    return current_embed_params\n", "path": "lib/streamlit/commands/query_params.py"}]}