Repository: streamlit/streamlit

Issue:
Better welcome message when running `streamlit hello`
### Problem

When I first run `streamlit hello` I see the following text:

```
You can now view your Streamlit app in your browser. 
```

which is great for `streamlit run` but not `streamlit hello` (because I didn’t just create an app).

### Solution

It would be great to see something like:

```
Welcome to Streamlit. Check out our demo in your browser.

  <LIST OF URLS>

Ready to create your own Python apps super quickly? Just head over to:

  https://docs.streamlit.io

May you create awesome apps!
```



Discussion:

Resolving patch:
diff --git a/lib/streamlit/bootstrap.py b/lib/streamlit/bootstrap.py
--- a/lib/streamlit/bootstrap.py
+++ b/lib/streamlit/bootstrap.py
@@ -132,7 +132,7 @@ def _fix_sys_argv(script_path, args):
 
 
 def _on_server_start(server):
-    _print_url()
+    _print_url(server.is_running_hello)
 
     def maybe_open_browser():
         if config.get_option("server.headless"):
@@ -166,8 +166,12 @@ def _fix_pydeck_mapbox_api_warning():
     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."
+def _print_url(is_running_hello):
+    if is_running_hello:
+        title_message = "Welcome to Streamlit. Check out our demo in your browser."
+    else:
+        title_message = "You can now view your Streamlit app in your browser."
+
     named_urls = []
 
     if config.is_manually_set("browser.serverAddress"):
@@ -207,6 +211,12 @@ def _print_url():
 
     click.secho("")
 
+    if is_running_hello:
+        click.secho("  Ready to create your own Python apps super quickly? Just head over to:")
+        click.secho("  https://docs.streamlit.io")
+        click.secho("  May you create awesome apps!")
+        click.secho("")
+
 
 def run(script_path, command_line, args):
     """Run a script in a separate thread and start a server for the app.
diff --git a/lib/streamlit/server/Server.py b/lib/streamlit/server/Server.py
--- a/lib/streamlit/server/Server.py
+++ b/lib/streamlit/server/Server.py
@@ -352,6 +352,11 @@ def is_ready_for_browser_connection(self):
     def browser_is_connected(self):
         return self._state == State.ONE_OR_MORE_BROWSERS_CONNECTED
 
+    @property
+    def is_running_hello(self):
+        from streamlit.hello import hello
+        return self._script_path == hello.__file__
+
     @tornado.gen.coroutine
     def _loop_coroutine(self, on_started=None):
         try:


Test patch:
diff --git a/lib/tests/streamlit/bootstrap_test.py b/lib/tests/streamlit/bootstrap_test.py
--- a/lib/tests/streamlit/bootstrap_test.py
+++ b/lib/tests/streamlit/bootstrap_test.py
@@ -76,6 +76,23 @@ def tearDown(self):
         sys.stdout.close()  # sys.stdout is a StringIO at this point.
         sys.stdout = self.orig_stdout
 
+    def test_print_hello_message(self):
+        mock_is_manually_set = testutil.build_mock_config_is_manually_set(
+            {"browser.serverAddress": True}
+        )
+        mock_get_option = testutil.build_mock_config_get_option(
+            {"browser.serverAddress": "the-address"}
+        )
+
+        with patch.object(config, "get_option", new=mock_get_option), patch.object(
+                config, "is_manually_set", new=mock_is_manually_set
+        ):
+            bootstrap._print_url(True)
+
+        out = sys.stdout.getvalue()
+        self.assertTrue("Welcome to Streamlit. Check out our demo in your browser." in out)
+        self.assertTrue("URL: http://the-address" in out)
+
     def test_print_urls_configured(self):
         mock_is_manually_set = testutil.build_mock_config_is_manually_set(
             {"browser.serverAddress": True}
@@ -87,9 +104,10 @@ def test_print_urls_configured(self):
         with patch.object(config, "get_option", new=mock_get_option), patch.object(
             config, "is_manually_set", new=mock_is_manually_set
         ):
-            bootstrap._print_url()
+            bootstrap._print_url(False)
 
         out = sys.stdout.getvalue()
+        self.assertTrue("You can now view your Streamlit app in your browser." in out)
         self.assertTrue("URL: http://the-address" in out)
 
     @patch("streamlit.net_util.get_external_ip")
@@ -109,7 +127,7 @@ def test_print_urls_remote(self, mock_get_internal_ip, mock_get_external_ip):
         with patch.object(config, "get_option", new=mock_get_option), patch.object(
             config, "is_manually_set", new=mock_is_manually_set
         ):
-            bootstrap._print_url()
+            bootstrap._print_url(False)
 
         out = sys.stdout.getvalue()
         self.assertTrue("Network URL: http://internal-ip" in out)
@@ -134,7 +152,7 @@ def test_print_urls_remote_no_external(
         with patch.object(config, "get_option", new=mock_get_option), patch.object(
             config, "is_manually_set", new=mock_is_manually_set
         ):
-            bootstrap._print_url()
+            bootstrap._print_url(False)
 
         out = sys.stdout.getvalue()
         self.assertTrue("Network URL: http://internal-ip" in out)
@@ -159,7 +177,7 @@ def test_print_urls_remote_no_internal(
         with patch.object(config, "get_option", new=mock_get_option), patch.object(
             config, "is_manually_set", new=mock_is_manually_set
         ):
-            bootstrap._print_url()
+            bootstrap._print_url(False)
 
         out = sys.stdout.getvalue()
         self.assertTrue("Network URL: http://internal-ip" not in out)
@@ -179,7 +197,7 @@ def test_print_urls_local(self, mock_get_internal_ip):
         with patch.object(config, "get_option", new=mock_get_option), patch.object(
             config, "is_manually_set", new=mock_is_manually_set
         ):
-            bootstrap._print_url()
+            bootstrap._print_url(False)
 
         out = sys.stdout.getvalue()
         self.assertTrue("Local URL: http://localhost" in out)
@@ -199,7 +217,7 @@ def test_print_urls_port(self, mock_get_internal_ip):
         with patch.object(config, "get_option", new=mock_get_option), patch.object(
             config, "is_manually_set", new=mock_is_manually_set
         ):
-            bootstrap._print_url()
+            bootstrap._print_url(False)
 
         out = sys.stdout.getvalue()
         self.assertTrue("Local URL: http://localhost:9988" in out)
@@ -224,7 +242,7 @@ def test_print_urls_base(self, mock_get_internal_ip):
         with patch.object(config, "get_option", new=mock_get_option), patch.object(
             config, "is_manually_set", new=mock_is_manually_set
         ):
-            bootstrap._print_url()
+            bootstrap._print_url(False)
 
         out = sys.stdout.getvalue()
         self.assertTrue("Local URL: http://localhost:8501/foo" in out)
@@ -249,7 +267,7 @@ def test_print_urls_base_no_internal(self, mock_get_internal_ip):
         with patch.object(config, "get_option", new=mock_get_option), patch.object(
             config, "is_manually_set", new=mock_is_manually_set
         ):
-            bootstrap._print_url()
+            bootstrap._print_url(False)
 
         out = sys.stdout.getvalue()
         self.assertTrue("Local URL: http://localhost:8501/foo" in out)