We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
PyDeck warning Mapbox API key not set
# Summary

Migrated a deck_gl chart to PyDeck API.  When page is run get a UserWarning that the Mapbox API key is not set.  Old deck_gl_chart() function does not display the warning. 

# Steps to reproduce

1:  Get a personal mapbox token,  Verify it is set using streamlit config show

[mapbox]

```
# Configure Streamlit to use a custom Mapbox token for elements like st.deck_gl_chart and st.map. If you don't do this you'll be using Streamlit's own token, which has limitations and is not guaranteed to always work. To get a token for yourself, create an account at https://mapbox.com. It's free! (for moderate usage levels)
# Default: "pk.eyJ1IjoidGhpYWdvdCIsImEiOiJjamh3bm85NnkwMng4M3dydnNveWwzeWNzIn0.vCBDzNsEF2uFSFk2AM0WZQ"
# The value below was set in C:\Users\...path...\.streamlit\config.toml
token = "pk.eyJ1Ijoia25......................."
```

2. Run a PyDeck chart, any demo should do
3. Inspect the output from streamlit run app.py in the shell

## Expected behavior:

map displays, no message in shell

## Actual behavior:

Map displays, shell displays a UserWarning

```
You can now view your Streamlit app in your browser.

  URL: http://localhost:8501

c:\apps\anaconda3\envs\ccadash\lib\site-packages\pydeck\bindings\deck.py:82: UserWarning: Mapbox API key is not set. This may impact available features of pydeck.
  UserWarning,
```

## Is this a regression?

That is, did this use to work the way you expected in the past?
yes

# Debug info

- Streamlit version:0.53.0
- Python version: 3.7.3
- Using Conda? PipEnv? PyEnv? Pex?   Conda
- OS version:   Windows 10
- Browser version:  Chrome  Version 79.0.3945.117 (Official Build) (64-bit)

# Additional information

If needed, add any other context about the problem here. For exmaple, did this bug come from https://discuss.streamlit.io or another site? Link the original source here!


--- 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/bootstrap.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 # Copyright 2018-2020 Streamlit Inc.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #    http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 import os
17 import signal
18 import sys
19 
20 import click
21 import tornado.ioloop
22 
23 from streamlit import config
24 from streamlit import net_util
25 from streamlit import url_util
26 from streamlit import env_util
27 from streamlit import util
28 from streamlit.Report import Report
29 from streamlit.logger import get_logger
30 from streamlit.server.Server import Server
31 
32 LOGGER = get_logger(__name__)
33 
34 # Wait for 1 second before opening a browser. This gives old tabs a chance to
35 # reconnect.
36 # This must be >= 2 * WebSocketConnection.ts#RECONNECT_WAIT_TIME_MS.
37 BROWSER_WAIT_TIMEOUT_SEC = 1
38 
39 
40 def _set_up_signal_handler():
41     LOGGER.debug("Setting up signal handler")
42 
43     def signal_handler(signal_number, stack_frame):
44         # The server will shut down its threads and stop the ioloop
45         Server.get_current().stop()
46 
47     signal.signal(signal.SIGTERM, signal_handler)
48     signal.signal(signal.SIGINT, signal_handler)
49     if sys.platform == "win32":
50         signal.signal(signal.SIGBREAK, signal_handler)
51     else:
52         signal.signal(signal.SIGQUIT, signal_handler)
53 
54 
55 def _fix_sys_path(script_path):
56     """Add the script's folder to the sys path.
57 
58     Python normally does this automatically, but since we exec the script
59     ourselves we need to do it instead.
60     """
61     sys.path.insert(0, os.path.dirname(script_path))
62 
63 
64 def _fix_matplotlib_crash():
65     """Set Matplotlib backend to avoid a crash.
66 
67     The default Matplotlib backend crashes Python on OSX when run on a thread
68     that's not the main thread, so here we set a safer backend as a fix.
69     Users can always disable this behavior by setting the config
70     runner.fixMatplotlib = false.
71 
72     This fix is OS-independent. We didn't see a good reason to make this
73     Mac-only. Consistency within Streamlit seemed more important.
74     """
75     if config.get_option("runner.fixMatplotlib"):
76         try:
77             # TODO: a better option may be to set
78             #  os.environ["MPLBACKEND"] = "Agg". We'd need to do this towards
79             #  the top of __init__.py, before importing anything that imports
80             #  pandas (which imports matplotlib). Alternately, we could set
81             #  this environment variable in a new entrypoint defined in
82             #  setup.py. Both of these introduce additional trickiness: they
83             #  need to run without consulting streamlit.config.get_option,
84             #  because this would import streamlit, and therefore matplotlib.
85             import matplotlib
86 
87             matplotlib.use("Agg")
88         except ImportError:
89             pass
90 
91 
92 def _fix_tornado_crash():
93     """Set default asyncio policy to be compatible with Tornado 6.
94 
95         Tornado 6 (at least) is not compatible with the default
96         asyncio implementation on Windows. So here we
97         pick the older SelectorEventLoopPolicy when the OS is Windows
98         if the known-incompatible default policy is in use.
99 
100         This has to happen as early as possible to make it a low priority and
101         overrideable
102 
103         See: https://github.com/tornadoweb/tornado/issues/2608
104 
105         FIXME: if/when tornado supports the defaults in asyncio,
106         remove and bump tornado requirement for py38
107     """
108     if env_util.IS_WINDOWS and sys.version_info >= (3, 8):
109         import asyncio
110 
111         try:
112             from asyncio import (
113                 WindowsProactorEventLoopPolicy,
114                 WindowsSelectorEventLoopPolicy,
115             )
116         except ImportError:
117             pass
118             # Not affected
119         else:
120             if type(asyncio.get_event_loop_policy()) is WindowsProactorEventLoopPolicy:
121                 # WindowsProactorEventLoopPolicy is not compatible with
122                 # Tornado 6 fallback to the pre-3.8 default of Selector
123                 asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy())
124 
125 
126 def _fix_sys_argv(script_path, args):
127     """sys.argv needs to exclude streamlit arguments and parameters
128     and be set to what a user's script may expect.
129     """
130     import sys
131 
132     sys.argv = [script_path] + list(args)
133 
134 
135 def _on_server_start(server):
136     _print_url()
137 
138     def maybe_open_browser():
139         if config.get_option("server.headless"):
140             # Don't open browser when in headless mode.
141             return
142 
143         if server.browser_is_connected:
144             # Don't auto-open browser if there's already a browser connected.
145             # This can happen if there's an old tab repeatedly trying to
146             # connect, and it happens to success before we launch the browser.
147             return
148 
149         if config.is_manually_set("browser.serverAddress"):
150             addr = config.get_option("browser.serverAddress")
151         else:
152             addr = "localhost"
153 
154         util.open_browser(Report.get_url(addr))
155 
156     # Schedule the browser to open using the IO Loop on the main thread, but
157     # only if no other browser connects within 1s.
158     ioloop = tornado.ioloop.IOLoop.current()
159     ioloop.call_later(BROWSER_WAIT_TIMEOUT_SEC, maybe_open_browser)
160 
161 
162 def _print_url():
163     title_message = "You can now view your Streamlit app in your browser."
164     named_urls = []
165 
166     if config.is_manually_set("browser.serverAddress"):
167         named_urls = [
168             ("URL", Report.get_url(config.get_option("browser.serverAddress")))
169         ]
170 
171     elif config.get_option("server.headless"):
172         named_urls = [
173             ("Network URL", Report.get_url(net_util.get_internal_ip())),
174             ("External URL", Report.get_url(net_util.get_external_ip())),
175         ]
176 
177     else:
178         named_urls = [
179             ("Local URL", Report.get_url("localhost")),
180             ("Network URL", Report.get_url(net_util.get_internal_ip())),
181         ]
182 
183     click.secho("")
184     click.secho("  %s" % title_message, fg="blue", bold=True)
185     click.secho("")
186 
187     for url_name, url in named_urls:
188         url_util.print_url(url_name, url)
189 
190     click.secho("")
191 
192 
193 def run(script_path, command_line, args):
194     """Run a script in a separate thread and start a server for the app.
195 
196     This starts a blocking ioloop.
197 
198     Parameters
199     ----------
200     script_path : str
201     command_line : str
202     args : [str]
203 
204     """
205     _fix_sys_path(script_path)
206     _fix_matplotlib_crash()
207     _fix_tornado_crash()
208     _fix_sys_argv(script_path, args)
209 
210     # Install a signal handler that will shut down the ioloop
211     # and close all our threads
212     _set_up_signal_handler()
213 
214     ioloop = tornado.ioloop.IOLoop.current()
215 
216     # Create and start the server.
217     server = Server(ioloop, script_path, command_line)
218     server.start(_on_server_start)
219 
220     # (Must com after start(), because this starts a new thread and start() may
221     # call sys.exit() which doesn't kill other threads.
222     server.add_preheated_report_session()
223 
224     # Start the ioloop. This function will not return until the
225     # server is shut down.
226     ioloop.start()
227
```
--- 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/lib/streamlit/bootstrap.py b/lib/streamlit/bootstrap.py
--- a/lib/streamlit/bootstrap.py
+++ b/lib/streamlit/bootstrap.py
@@ -159,6 +159,12 @@
     ioloop.call_later(BROWSER_WAIT_TIMEOUT_SEC, maybe_open_browser)
 
 
+def _fix_pydeck_mapbox_api_warning():
+    """Sets MAPBOX_API_KEY environment variable needed for PyDeck otherwise it will throw an exception"""
+
+    os.environ["MAPBOX_API_KEY"] = config.get_option("mapbox.token")
+
+
 def _print_url():
     title_message = "You can now view your Streamlit app in your browser."
     named_urls = []
@@ -206,6 +212,7 @@
     _fix_matplotlib_crash()
     _fix_tornado_crash()
     _fix_sys_argv(script_path, args)
+    _fix_pydeck_mapbox_api_warning()
 
     # Install a signal handler that will shut down the ioloop
     # and close all our threads

{"golden_diff": "diff --git a/lib/streamlit/bootstrap.py b/lib/streamlit/bootstrap.py\n--- a/lib/streamlit/bootstrap.py\n+++ b/lib/streamlit/bootstrap.py\n@@ -159,6 +159,12 @@\n     ioloop.call_later(BROWSER_WAIT_TIMEOUT_SEC, maybe_open_browser)\n \n \n+def _fix_pydeck_mapbox_api_warning():\n+    \"\"\"Sets MAPBOX_API_KEY environment variable needed for PyDeck otherwise it will throw an exception\"\"\"\n+\n+    os.environ[\"MAPBOX_API_KEY\"] = config.get_option(\"mapbox.token\")\n+\n+\n def _print_url():\n     title_message = \"You can now view your Streamlit app in your browser.\"\n     named_urls = []\n@@ -206,6 +212,7 @@\n     _fix_matplotlib_crash()\n     _fix_tornado_crash()\n     _fix_sys_argv(script_path, args)\n+    _fix_pydeck_mapbox_api_warning()\n \n     # Install a signal handler that will shut down the ioloop\n     # and close all our threads\n", "issue": "PyDeck warning Mapbox API key not set\n# Summary\r\n\r\nMigrated a deck_gl chart to PyDeck API.  When page is run get a UserWarning that the Mapbox API key is not set.  Old deck_gl_chart() function does not display the warning. \r\n\r\n# Steps to reproduce\r\n\r\n1:  Get a personal mapbox token,  Verify it is set using streamlit config show\r\n\r\n[mapbox]\r\n\r\n```\r\n# Configure Streamlit to use a custom Mapbox token for elements like st.deck_gl_chart and st.map. If you don't do this you'll be using Streamlit's own token, which has limitations and is not guaranteed to always work. To get a token for yourself, create an account at https://mapbox.com. It's free! (for moderate usage levels)\r\n# Default: \"pk.eyJ1IjoidGhpYWdvdCIsImEiOiJjamh3bm85NnkwMng4M3dydnNveWwzeWNzIn0.vCBDzNsEF2uFSFk2AM0WZQ\"\r\n# The value below was set in C:\\Users\\...path...\\.streamlit\\config.toml\r\ntoken = \"pk.eyJ1Ijoia25.......................\"\r\n```\r\n\r\n2. Run a PyDeck chart, any demo should do\r\n3. Inspect the output from streamlit run app.py in the shell\r\n\r\n## Expected behavior:\r\n\r\nmap displays, no message in shell\r\n\r\n## Actual behavior:\r\n\r\nMap displays, shell displays a UserWarning\r\n\r\n```\r\nYou can now view your Streamlit app in your browser.\r\n\r\n  URL: http://localhost:8501\r\n\r\nc:\\apps\\anaconda3\\envs\\ccadash\\lib\\site-packages\\pydeck\\bindings\\deck.py:82: UserWarning: Mapbox API key is not set. This may impact available features of pydeck.\r\n  UserWarning,\r\n```\r\n\r\n## Is this a regression?\r\n\r\nThat is, did this use to work the way you expected in the past?\r\nyes\r\n\r\n# Debug info\r\n\r\n- Streamlit version:0.53.0\r\n- Python version: 3.7.3\r\n- Using Conda? PipEnv? PyEnv? Pex?   Conda\r\n- OS version:   Windows 10\r\n- Browser version:  Chrome  Version 79.0.3945.117 (Official Build) (64-bit)\r\n\r\n# Additional information\r\n\r\nIf needed, add any other context about the problem here. For exmaple, did this bug come from https://discuss.streamlit.io or another site? Link the original source here!\r\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright 2018-2020 Streamlit Inc.\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 os\nimport signal\nimport sys\n\nimport click\nimport tornado.ioloop\n\nfrom streamlit import config\nfrom streamlit import net_util\nfrom streamlit import url_util\nfrom streamlit import env_util\nfrom streamlit import util\nfrom streamlit.Report import Report\nfrom streamlit.logger import get_logger\nfrom streamlit.server.Server import Server\n\nLOGGER = get_logger(__name__)\n\n# Wait for 1 second before opening a browser. This gives old tabs a chance to\n# reconnect.\n# This must be >= 2 * WebSocketConnection.ts#RECONNECT_WAIT_TIME_MS.\nBROWSER_WAIT_TIMEOUT_SEC = 1\n\n\ndef _set_up_signal_handler():\n    LOGGER.debug(\"Setting up signal handler\")\n\n    def signal_handler(signal_number, stack_frame):\n        # The server will shut down its threads and stop the ioloop\n        Server.get_current().stop()\n\n    signal.signal(signal.SIGTERM, signal_handler)\n    signal.signal(signal.SIGINT, signal_handler)\n    if sys.platform == \"win32\":\n        signal.signal(signal.SIGBREAK, signal_handler)\n    else:\n        signal.signal(signal.SIGQUIT, signal_handler)\n\n\ndef _fix_sys_path(script_path):\n    \"\"\"Add the script's folder to the sys path.\n\n    Python normally does this automatically, but since we exec the script\n    ourselves we need to do it instead.\n    \"\"\"\n    sys.path.insert(0, os.path.dirname(script_path))\n\n\ndef _fix_matplotlib_crash():\n    \"\"\"Set Matplotlib backend to avoid a crash.\n\n    The default Matplotlib backend crashes Python on OSX when run on a thread\n    that's not the main thread, so here we set a safer backend as a fix.\n    Users can always disable this behavior by setting the config\n    runner.fixMatplotlib = false.\n\n    This fix is OS-independent. We didn't see a good reason to make this\n    Mac-only. Consistency within Streamlit seemed more important.\n    \"\"\"\n    if config.get_option(\"runner.fixMatplotlib\"):\n        try:\n            # TODO: a better option may be to set\n            #  os.environ[\"MPLBACKEND\"] = \"Agg\". We'd need to do this towards\n            #  the top of __init__.py, before importing anything that imports\n            #  pandas (which imports matplotlib). Alternately, we could set\n            #  this environment variable in a new entrypoint defined in\n            #  setup.py. Both of these introduce additional trickiness: they\n            #  need to run without consulting streamlit.config.get_option,\n            #  because this would import streamlit, and therefore matplotlib.\n            import matplotlib\n\n            matplotlib.use(\"Agg\")\n        except ImportError:\n            pass\n\n\ndef _fix_tornado_crash():\n    \"\"\"Set default asyncio policy to be compatible with Tornado 6.\n\n        Tornado 6 (at least) is not compatible with the default\n        asyncio implementation on Windows. So here we\n        pick the older SelectorEventLoopPolicy when the OS is Windows\n        if the known-incompatible default policy is in use.\n\n        This has to happen as early as possible to make it a low priority and\n        overrideable\n\n        See: https://github.com/tornadoweb/tornado/issues/2608\n\n        FIXME: if/when tornado supports the defaults in asyncio,\n        remove and bump tornado requirement for py38\n    \"\"\"\n    if env_util.IS_WINDOWS and sys.version_info >= (3, 8):\n        import asyncio\n\n        try:\n            from asyncio import (\n                WindowsProactorEventLoopPolicy,\n                WindowsSelectorEventLoopPolicy,\n            )\n        except ImportError:\n            pass\n            # Not affected\n        else:\n            if type(asyncio.get_event_loop_policy()) is WindowsProactorEventLoopPolicy:\n                # WindowsProactorEventLoopPolicy is not compatible with\n                # Tornado 6 fallback to the pre-3.8 default of Selector\n                asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy())\n\n\ndef _fix_sys_argv(script_path, args):\n    \"\"\"sys.argv needs to exclude streamlit arguments and parameters\n    and be set to what a user's script may expect.\n    \"\"\"\n    import sys\n\n    sys.argv = [script_path] + list(args)\n\n\ndef _on_server_start(server):\n    _print_url()\n\n    def maybe_open_browser():\n        if config.get_option(\"server.headless\"):\n            # Don't open browser when in headless mode.\n            return\n\n        if server.browser_is_connected:\n            # Don't auto-open browser if there's already a browser connected.\n            # This can happen if there's an old tab repeatedly trying to\n            # connect, and it happens to success before we launch the browser.\n            return\n\n        if config.is_manually_set(\"browser.serverAddress\"):\n            addr = config.get_option(\"browser.serverAddress\")\n        else:\n            addr = \"localhost\"\n\n        util.open_browser(Report.get_url(addr))\n\n    # Schedule the browser to open using the IO Loop on the main thread, but\n    # only if no other browser connects within 1s.\n    ioloop = tornado.ioloop.IOLoop.current()\n    ioloop.call_later(BROWSER_WAIT_TIMEOUT_SEC, maybe_open_browser)\n\n\ndef _print_url():\n    title_message = \"You can now view your Streamlit app in your browser.\"\n    named_urls = []\n\n    if config.is_manually_set(\"browser.serverAddress\"):\n        named_urls = [\n            (\"URL\", Report.get_url(config.get_option(\"browser.serverAddress\")))\n        ]\n\n    elif config.get_option(\"server.headless\"):\n        named_urls = [\n            (\"Network URL\", Report.get_url(net_util.get_internal_ip())),\n            (\"External URL\", Report.get_url(net_util.get_external_ip())),\n        ]\n\n    else:\n        named_urls = [\n            (\"Local URL\", Report.get_url(\"localhost\")),\n            (\"Network URL\", Report.get_url(net_util.get_internal_ip())),\n        ]\n\n    click.secho(\"\")\n    click.secho(\"  %s\" % title_message, fg=\"blue\", bold=True)\n    click.secho(\"\")\n\n    for url_name, url in named_urls:\n        url_util.print_url(url_name, url)\n\n    click.secho(\"\")\n\n\ndef run(script_path, command_line, args):\n    \"\"\"Run a script in a separate thread and start a server for the app.\n\n    This starts a blocking ioloop.\n\n    Parameters\n    ----------\n    script_path : str\n    command_line : str\n    args : [str]\n\n    \"\"\"\n    _fix_sys_path(script_path)\n    _fix_matplotlib_crash()\n    _fix_tornado_crash()\n    _fix_sys_argv(script_path, args)\n\n    # Install a signal handler that will shut down the ioloop\n    # and close all our threads\n    _set_up_signal_handler()\n\n    ioloop = tornado.ioloop.IOLoop.current()\n\n    # Create and start the server.\n    server = Server(ioloop, script_path, command_line)\n    server.start(_on_server_start)\n\n    # (Must com after start(), because this starts a new thread and start() may\n    # call sys.exit() which doesn't kill other threads.\n    server.add_preheated_report_session()\n\n    # Start the ioloop. This function will not return until the\n    # server is shut down.\n    ioloop.start()\n", "path": "lib/streamlit/bootstrap.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright 2018-2020 Streamlit Inc.\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 os\nimport signal\nimport sys\n\nimport click\nimport tornado.ioloop\n\nfrom streamlit import config\nfrom streamlit import net_util\nfrom streamlit import url_util\nfrom streamlit import env_util\nfrom streamlit import util\nfrom streamlit.Report import Report\nfrom streamlit.logger import get_logger\nfrom streamlit.server.Server import Server\n\nLOGGER = get_logger(__name__)\n\n# Wait for 1 second before opening a browser. This gives old tabs a chance to\n# reconnect.\n# This must be >= 2 * WebSocketConnection.ts#RECONNECT_WAIT_TIME_MS.\nBROWSER_WAIT_TIMEOUT_SEC = 1\n\n\ndef _set_up_signal_handler():\n    LOGGER.debug(\"Setting up signal handler\")\n\n    def signal_handler(signal_number, stack_frame):\n        # The server will shut down its threads and stop the ioloop\n        Server.get_current().stop()\n\n    signal.signal(signal.SIGTERM, signal_handler)\n    signal.signal(signal.SIGINT, signal_handler)\n    if sys.platform == \"win32\":\n        signal.signal(signal.SIGBREAK, signal_handler)\n    else:\n        signal.signal(signal.SIGQUIT, signal_handler)\n\n\ndef _fix_sys_path(script_path):\n    \"\"\"Add the script's folder to the sys path.\n\n    Python normally does this automatically, but since we exec the script\n    ourselves we need to do it instead.\n    \"\"\"\n    sys.path.insert(0, os.path.dirname(script_path))\n\n\ndef _fix_matplotlib_crash():\n    \"\"\"Set Matplotlib backend to avoid a crash.\n\n    The default Matplotlib backend crashes Python on OSX when run on a thread\n    that's not the main thread, so here we set a safer backend as a fix.\n    Users can always disable this behavior by setting the config\n    runner.fixMatplotlib = false.\n\n    This fix is OS-independent. We didn't see a good reason to make this\n    Mac-only. Consistency within Streamlit seemed more important.\n    \"\"\"\n    if config.get_option(\"runner.fixMatplotlib\"):\n        try:\n            # TODO: a better option may be to set\n            #  os.environ[\"MPLBACKEND\"] = \"Agg\". We'd need to do this towards\n            #  the top of __init__.py, before importing anything that imports\n            #  pandas (which imports matplotlib). Alternately, we could set\n            #  this environment variable in a new entrypoint defined in\n            #  setup.py. Both of these introduce additional trickiness: they\n            #  need to run without consulting streamlit.config.get_option,\n            #  because this would import streamlit, and therefore matplotlib.\n            import matplotlib\n\n            matplotlib.use(\"Agg\")\n        except ImportError:\n            pass\n\n\ndef _fix_tornado_crash():\n    \"\"\"Set default asyncio policy to be compatible with Tornado 6.\n\n        Tornado 6 (at least) is not compatible with the default\n        asyncio implementation on Windows. So here we\n        pick the older SelectorEventLoopPolicy when the OS is Windows\n        if the known-incompatible default policy is in use.\n\n        This has to happen as early as possible to make it a low priority and\n        overrideable\n\n        See: https://github.com/tornadoweb/tornado/issues/2608\n\n        FIXME: if/when tornado supports the defaults in asyncio,\n        remove and bump tornado requirement for py38\n    \"\"\"\n    if env_util.IS_WINDOWS and sys.version_info >= (3, 8):\n        import asyncio\n\n        try:\n            from asyncio import (\n                WindowsProactorEventLoopPolicy,\n                WindowsSelectorEventLoopPolicy,\n            )\n        except ImportError:\n            pass\n            # Not affected\n        else:\n            if type(asyncio.get_event_loop_policy()) is WindowsProactorEventLoopPolicy:\n                # WindowsProactorEventLoopPolicy is not compatible with\n                # Tornado 6 fallback to the pre-3.8 default of Selector\n                asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy())\n\n\ndef _fix_sys_argv(script_path, args):\n    \"\"\"sys.argv needs to exclude streamlit arguments and parameters\n    and be set to what a user's script may expect.\n    \"\"\"\n    import sys\n\n    sys.argv = [script_path] + list(args)\n\n\ndef _on_server_start(server):\n    _print_url()\n\n    def maybe_open_browser():\n        if config.get_option(\"server.headless\"):\n            # Don't open browser when in headless mode.\n            return\n\n        if server.browser_is_connected:\n            # Don't auto-open browser if there's already a browser connected.\n            # This can happen if there's an old tab repeatedly trying to\n            # connect, and it happens to success before we launch the browser.\n            return\n\n        if config.is_manually_set(\"browser.serverAddress\"):\n            addr = config.get_option(\"browser.serverAddress\")\n        else:\n            addr = \"localhost\"\n\n        util.open_browser(Report.get_url(addr))\n\n    # Schedule the browser to open using the IO Loop on the main thread, but\n    # only if no other browser connects within 1s.\n    ioloop = tornado.ioloop.IOLoop.current()\n    ioloop.call_later(BROWSER_WAIT_TIMEOUT_SEC, maybe_open_browser)\n\n\ndef _fix_pydeck_mapbox_api_warning():\n    \"\"\"Sets MAPBOX_API_KEY environment variable needed for PyDeck otherwise it will throw an exception\"\"\"\n\n    os.environ[\"MAPBOX_API_KEY\"] = config.get_option(\"mapbox.token\")\n\n\ndef _print_url():\n    title_message = \"You can now view your Streamlit app in your browser.\"\n    named_urls = []\n\n    if config.is_manually_set(\"browser.serverAddress\"):\n        named_urls = [\n            (\"URL\", Report.get_url(config.get_option(\"browser.serverAddress\")))\n        ]\n\n    elif config.get_option(\"server.headless\"):\n        named_urls = [\n            (\"Network URL\", Report.get_url(net_util.get_internal_ip())),\n            (\"External URL\", Report.get_url(net_util.get_external_ip())),\n        ]\n\n    else:\n        named_urls = [\n            (\"Local URL\", Report.get_url(\"localhost\")),\n            (\"Network URL\", Report.get_url(net_util.get_internal_ip())),\n        ]\n\n    click.secho(\"\")\n    click.secho(\"  %s\" % title_message, fg=\"blue\", bold=True)\n    click.secho(\"\")\n\n    for url_name, url in named_urls:\n        url_util.print_url(url_name, url)\n\n    click.secho(\"\")\n\n\ndef run(script_path, command_line, args):\n    \"\"\"Run a script in a separate thread and start a server for the app.\n\n    This starts a blocking ioloop.\n\n    Parameters\n    ----------\n    script_path : str\n    command_line : str\n    args : [str]\n\n    \"\"\"\n    _fix_sys_path(script_path)\n    _fix_matplotlib_crash()\n    _fix_tornado_crash()\n    _fix_sys_argv(script_path, args)\n    _fix_pydeck_mapbox_api_warning()\n\n    # Install a signal handler that will shut down the ioloop\n    # and close all our threads\n    _set_up_signal_handler()\n\n    ioloop = tornado.ioloop.IOLoop.current()\n\n    # Create and start the server.\n    server = Server(ioloop, script_path, command_line)\n    server.start(_on_server_start)\n\n    # (Must com after start(), because this starts a new thread and start() may\n    # call sys.exit() which doesn't kill other threads.\n    server.add_preheated_report_session()\n\n    # Start the ioloop. This function will not return until the\n    # server is shut down.\n    ioloop.start()\n", "path": "lib/streamlit/bootstrap.py"}]}