Repository: streamlit/streamlit

Issue:
Components static files / encoding on windows
# Summary

(windows only)
When serving component static files, the encoding is not specified. It falls back to the system's default, which can fail to decode the file.

# Steps to reproduce

What are the steps we should take to reproduce the bug:

1. Set windows system encoding to Japanese
2. Install hiplot with `pip install hiplot`
3. Run the hiplot demo example (https://github.com/facebookresearch/hiplot/blob/master/examples/demo_streamlit.py)

## Expected behavior:

Bundle JS file served.

## Actual behavior:

Fails with an exception about encoding.
![image](https://user-images.githubusercontent.com/43445237/91541751-1b537880-e91d-11ea-818c-413a962c00e6.png)


## Is this a regression?

No

# Debug info

This is where the file read happens - encoding should be specified.
https://github.com/streamlit/streamlit/blob/2f7d3caf57629ebe856048321fbfbae88d3f7ad7/lib/streamlit/components/v1/components.py#L274

Original issue: https://github.com/facebookresearch/hiplot/issues/127


Discussion:
Thanks Dan - I'll take a look shortly
Bump. This causes issues for HiPlot users with streamlit on Windows - is it possible to look into it? It should be pretty straightforward to fix (https://github.com/facebookresearch/hiplot/issues/148)
Thank you :)

Resolving patch:
diff --git a/lib/streamlit/components/v1/components.py b/lib/streamlit/components/v1/components.py
--- a/lib/streamlit/components/v1/components.py
+++ b/lib/streamlit/components/v1/components.py
@@ -320,9 +320,9 @@ def get(self, path: str) -> None:
         LOGGER.debug("ComponentRequestHandler: GET: %s -> %s", path, abspath)
 
         try:
-            with open(abspath, "r") as file:
+            with open(abspath, "r", encoding="utf-8") as file:
                 contents = file.read()
-        except OSError as e:
+        except (OSError, UnicodeDecodeError) as e:
             self.write(f"{path} read error: {e}")
             self.set_status(404)
             return


Test patch:
diff --git a/lib/tests/streamlit/components_test.py b/lib/tests/streamlit/components_test.py
--- a/lib/tests/streamlit/components_test.py
+++ b/lib/tests/streamlit/components_test.py
@@ -429,6 +429,24 @@ def test_invalid_content_request(self):
             response.body,
         )
 
+    def test_invalid_encoding_request(self):
+        """Test request failure when invalid encoded file is provided."""
+
+        with mock.patch("streamlit.components.v1.components.os.path.isdir"):
+            declare_component("test", path=PATH)
+
+        with mock.patch("streamlit.components.v1.components.open") as m:
+            m.side_effect = UnicodeDecodeError(
+                "utf-8", b"", 9, 11, "unexpected end of data"
+            )
+            response = self._request_component("components_test.test")
+
+        self.assertEqual(404, response.code)
+        self.assertEqual(
+            b"components_test.test read error: 'utf-8' codec can't decode bytes in position 9-10: unexpected end of data",
+            response.body,
+        )
+
 
 class IFrameTest(testutil.DeltaGeneratorTestCase):
     def test_iframe(self):