コード例 #1
0
 def get_app(self):
     self.registry = ComponentRegistry()
     return tornado.web.Application([(
         "/component/(.*)",
         ComponentRequestHandler,
         dict(registry=self.registry.instance()),
     )])
コード例 #2
0
class ComponentRequestHandlerTest(tornado.testing.AsyncHTTPTestCase):
    """Test /component endpoint."""

    def tearDown(self) -> None:
        ComponentRegistry._instance = None

    def get_app(self):
        self.registry = ComponentRegistry()
        return tornado.web.Application(
            [
                (
                    "/component/(.*)",
                    ComponentRequestHandler,
                    dict(registry=self.registry.instance()),
                )
            ]
        )

    def _request_component(self, path):
        return self.fetch("/component/%s" % path, method="GET")

    def test_success_request(self):
        """Test request success when valid parameters are provided."""

        with mock.patch("streamlit.components.v1.components.os.path.isdir"):
            # We don't need the return value in this case.
            declare_component("test", path=PATH)

        with mock.patch(
            "streamlit.components.v1.components.open",
            mock.mock_open(read_data="Test Content"),
        ):
            response = self._request_component("components_test.test")

        self.assertEqual(200, response.code)
        self.assertEqual(b"Test Content", response.body)

    def test_invalid_component_request(self):
        """Test request failure when invalid component name is provided."""

        response = self._request_component("invalid_component")
        self.assertEqual(404, response.code)
        self.assertEqual(b"invalid_component not found", response.body)

    def test_invalid_content_request(self):
        """Test request failure when invalid content (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 = OSError("Invalid content")
            response = self._request_component("components_test.test")

        self.assertEqual(404, response.code)
        self.assertEqual(
            b"components_test.test read error: Invalid content", response.body,
        )
コード例 #3
0
    def test_only_url(self):
        """Succeed when a URL is provided."""
        component = components.declare_component("test", url=URL)
        self.assertEqual(URL, component.url)
        self.assertIsNone(component.path)

        self.assertEqual(
            ComponentRegistry.instance().get_component_path("components_test"),
            component.abspath,
        )
コード例 #4
0
    def test_register_invalid_path(self):
        """We raise an exception if a component is registered with a
        non-existent path.
        """
        test_path = "/a/test/component/directory"

        registry = ComponentRegistry.instance()
        with self.assertRaises(StreamlitAPIException) as ctx:
            registry.register_component(CustomComponent("test_component", test_path))
            self.assertIn("No such component directory", ctx.exception)
コード例 #5
0
    def test_register_component_no_path(self):
        """It's not an error to register a component without a path."""
        registry = ComponentRegistry.instance()

        # Return None when the component hasn't been registered
        self.assertIsNone(registry.get_component_path("test_component"))

        # And also return None when the component doesn't have a path
        registry.register_component(
            CustomComponent("test_component", url="http://not.a.url"))
        self.assertIsNone(registry.get_component_path("test_component"))
コード例 #6
0
    def test_register_component_with_path(self):
        """Registering a component should associate it with its path."""
        test_path = "/a/test/component/directory"

        def isdir(path):
            return path == test_path

        registry = ComponentRegistry.instance()
        with mock.patch("streamlit.components.v1.components.os.path.isdir",
                        side_effect=isdir):
            registry.register_component(
                CustomComponent("test_component", path=test_path))

        self.assertEqual(test_path,
                         registry.get_component_path("test_component"))
コード例 #7
0
    def test_only_path(self):
        """Succeed when a path is provided."""
        def isdir(path):
            return path == PATH or path == os.path.abspath(PATH)

        with mock.patch("streamlit.components.v1.components.os.path.isdir",
                        side_effect=isdir):
            component = components.declare_component("test", path=PATH)

        self.assertEqual(PATH, component.path)
        self.assertIsNone(component.url)

        self.assertEqual(
            ComponentRegistry.instance().get_component_path(component.name),
            component.abspath,
        )
コード例 #8
0
    def test_register_duplicate_path(self):
        """It's not an error to re-register a component.
        (This can happen during development).
        """
        test_path_1 = "/a/test/component/directory"
        test_path_2 = "/another/test/component/directory"

        def isdir(path):
            return path in (test_path_1, test_path_2)

        registry = ComponentRegistry.instance()
        with mock.patch(
            "streamlit.components.v1.components.os.path.isdir", side_effect=isdir
        ):
            registry.register_component(CustomComponent("test_component", test_path_1))
            registry.register_component(CustomComponent("test_component", test_path_1))
            self.assertEqual(test_path_1, registry.get_component_path("test_component"))

            registry.register_component(CustomComponent("test_component", test_path_2))
            self.assertEqual(test_path_2, registry.get_component_path("test_component"))
コード例 #9
0
    def _create_app(self) -> tornado.web.Application:
        """Create our tornado web app."""
        base = config.get_option("server.baseUrlPath")

        routes = [
            (
                make_url_path_regex(base, "stream"),
                _BrowserWebSocketHandler,
                dict(server=self),
            ),
            (
                make_url_path_regex(base, "healthz"),
                HealthHandler,
                dict(callback=lambda: self.is_ready_for_browser_connection),
            ),
            (make_url_path_regex(base, "debugz"), DebugHandler, dict(server=self)),
            (make_url_path_regex(base, "metrics"), MetricsHandler),
            (
                make_url_path_regex(base, "message"),
                MessageCacheHandler,
                dict(cache=self._message_cache),
            ),
            (
                make_url_path_regex(
                    base,
                    UPLOAD_FILE_ROUTE,
                ),
                UploadFileRequestHandler,
                dict(
                    file_mgr=self._uploaded_file_mgr,
                    get_session_info=self._get_session_info,
                ),
            ),
            (
                make_url_path_regex(base, "assets/(.*)"),
                AssetsFileHandler,
                {"path": "%s/" % file_util.get_assets_dir()},
            ),
            (make_url_path_regex(base, "media/(.*)"), MediaFileHandler, {"path": ""}),
            (
                make_url_path_regex(base, "component/(.*)"),
                ComponentRequestHandler,
                dict(registry=ComponentRegistry.instance()),
            ),
        ]

        if config.get_option("server.scriptHealthCheckEnabled"):
            routes.extend(
                [
                    (
                        make_url_path_regex(base, "script-health-check"),
                        HealthHandler,
                        dict(callback=lambda: self.does_script_run_without_error()),
                    )
                ]
            )

        if config.get_option("global.developmentMode"):
            LOGGER.debug("Serving static content from the Node dev server")
        else:
            static_path = file_util.get_static_dir()
            LOGGER.debug("Serving static content from %s", static_path)

            routes.extend(
                [
                    (
                        make_url_path_regex(base, "(.*)"),
                        StaticFileHandler,
                        {"path": "%s/" % static_path, "default_filename": "index.html"},
                    ),
                    (make_url_path_regex(base, trailing_slash=False), AddSlashHandler),
                ]
            )

        return tornado.web.Application(
            routes,  # type: ignore[arg-type]
            cookie_secret=config.get_option("server.cookieSecret"),
            xsrf_cookies=config.get_option("server.enableXsrfProtection"),
            **TORNADO_SETTINGS,  # type: ignore[arg-type]
        )
コード例 #10
0
class ComponentRequestHandlerTest(tornado.testing.AsyncHTTPTestCase):
    """Test /component endpoint."""
    def tearDown(self) -> None:
        ComponentRegistry._instance = None

    def get_app(self):
        self.registry = ComponentRegistry()
        return tornado.web.Application([(
            "/component/(.*)",
            ComponentRequestHandler,
            dict(registry=self.registry.instance()),
        )])

    def _request_component(self, path):
        return self.fetch("/component/%s" % path, method="GET")

    def test_success_request(self):
        """Test request success when valid parameters are provided."""

        with mock.patch("streamlit.components.v1.components.os.path.isdir"):
            # We don't need the return value in this case.
            declare_component("test", path=PATH)

        with mock.patch(
                "streamlit.components.v1.components.open",
                mock.mock_open(read_data="Test Content"),
        ):
            response = self._request_component("components_test.test")

        self.assertEqual(200, response.code)
        self.assertEqual(b"Test Content", response.body)

    def test_invalid_component_request(self):
        """Test request failure when invalid component name is provided."""

        response = self._request_component("invalid_component")
        self.assertEqual(404, response.code)
        self.assertEqual(b"not found", response.body)

    def test_invalid_content_request(self):
        """Test request failure when invalid content (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 = OSError("Invalid content")
            response = self._request_component("components_test.test")

        self.assertEqual(404, response.code)
        self.assertEqual(
            b"read error",
            response.body,
        )

    def test_support_binary_files_request(self):
        """Test support for binary files reads."""
        def _open_read(m, payload):
            is_binary = False
            args, kwargs = m.call_args
            if len(args) > 1:
                if "b" in args[1]:
                    is_binary = True
            encoding = "utf-8"
            if "encoding" in kwargs:
                encoding = kwargs["encoding"]

            if is_binary:
                from io import BytesIO

                return BytesIO(payload)
            else:
                from io import TextIOWrapper

                return TextIOWrapper(str(payload, encoding=encoding))

        with mock.patch("streamlit.components.v1.components.os.path.isdir"):
            declare_component("test", path=PATH)

        payload = b"\x00\x01\x00\x00\x00\x0D\x00\x80"  # binary non utf-8 payload

        with mock.patch("streamlit.components.v1.components.open") as m:
            m.return_value.__enter__ = lambda _: _open_read(m, payload)
            response = self._request_component("components_test.test")

        self.assertEqual(200, response.code)
        self.assertEqual(
            payload,
            response.body,
        )
コード例 #11
0
    def _create_app(self):
        """Create our tornado web app.

        Returns
        -------
        tornado.web.Application

        """
        base = config.get_option("server.baseUrlPath")
        routes = [
            (
                make_url_path_regex(base, "stream"),
                _BrowserWebSocketHandler,
                dict(server=self),
            ),
            (
                make_url_path_regex(base, "healthz"),
                HealthHandler,
                dict(callback=lambda: self.is_ready_for_browser_connection),
            ),
            (make_url_path_regex(base,
                                 "debugz"), DebugHandler, dict(server=self)),
            (make_url_path_regex(base, "metrics"), MetricsHandler),
            (
                make_url_path_regex(base, "message"),
                MessageCacheHandler,
                dict(cache=self._message_cache),
            ),
            (
                # Tornado doesn't allow body in DELETE requests.
                # Passing lookup values in URL
                make_url_path_regex(
                    base,
                    "/upload_file/(?P<session_id>.*)/(?P<widget_id>.*)/(?P<file_id>[0-9]*)?",
                ),
                UploadFileRequestHandler,
                dict(file_mgr=self._uploaded_file_mgr),
            ),
            (
                make_url_path_regex(base, "upload_file"),
                UploadFileRequestHandler,
                dict(file_mgr=self._uploaded_file_mgr),
            ),
            (
                make_url_path_regex(base, "assets/(.*)"),
                AssetsFileHandler,
                {
                    "path": "%s/" % file_util.get_assets_dir()
                },
            ),
            (make_url_path_regex(base, "media/(.*)"), MediaFileHandler, {
                "path": ""
            }),
            (
                make_url_path_regex(base, "component/(.*)"),
                ComponentRequestHandler,
                dict(registry=ComponentRegistry.instance()),
            ),
        ]

        if config.get_option("global.developmentMode"):
            LOGGER.debug("Serving static content from the Node dev server")
        else:
            static_path = file_util.get_static_dir()
            LOGGER.debug("Serving static content from %s", static_path)

            routes.extend([
                (
                    make_url_path_regex(base, "(.*)"),
                    StaticFileHandler,
                    {
                        "path": "%s/" % static_path,
                        "default_filename": "index.html"
                    },
                ),
                (make_url_path_regex(base,
                                     trailing_slash=False), AddSlashHandler),
            ])

        return tornado.web.Application(
            routes,  # type: ignore[arg-type]
            cookie_secret=config.get_option("server.cookieSecret"),
            xsrf_cookies=config.get_option("server.enableXsrfProtection"),
            **TORNADO_SETTINGS,  # type: ignore[arg-type]
        )