auto enable /_upload endpoint only if Upload component is used (#2430)

This commit is contained in:
benedikt-bartscher 2024-01-23 21:20:06 +01:00 committed by GitHub
parent 84858854ae
commit 0b1b8ee639
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 43 additions and 12 deletions

View File

@ -43,6 +43,7 @@ from reflex.components.core.client_side_routing import (
Default404Page, Default404Page,
wait_for_client_redirect, wait_for_client_redirect,
) )
from reflex.components.core.upload import UploadFilesProvider
from reflex.config import get_config from reflex.config import get_config
from reflex.event import Event, EventHandler, EventSpec from reflex.event import Event, EventHandler, EventSpec
from reflex.middleware import HydrateMiddleware, Middleware from reflex.middleware import HydrateMiddleware, Middleware
@ -180,7 +181,6 @@ class App(Base):
# Set up the API. # Set up the API.
self.api = FastAPI() self.api = FastAPI()
self.add_cors() self.add_cors()
self.add_default_endpoints()
if self.state: if self.state:
# Set up the state manager. # Set up the state manager.
@ -242,7 +242,8 @@ class App(Base):
self.api.get(str(constants.Endpoint.PING))(ping) self.api.get(str(constants.Endpoint.PING))(ping)
# To upload files. # To upload files.
self.api.post(str(constants.Endpoint.UPLOAD))(upload(self)) if UploadFilesProvider.is_used:
self.api.post(str(constants.Endpoint.UPLOAD))(upload(self))
def add_cors(self): def add_cors(self):
"""Add CORS middleware to the app.""" """Add CORS middleware to the app."""
@ -800,6 +801,8 @@ class App(Base):
for future in concurrent.futures.as_completed(write_page_futures): for future in concurrent.futures.as_completed(write_page_futures):
future.result() future.result()
self.add_default_endpoints()
@contextlib.asynccontextmanager @contextlib.asynccontextmanager
async def modify_state(self, token: str) -> AsyncIterator[BaseState]: async def modify_state(self, token: str) -> AsyncIterator[BaseState]:
"""Modify the state out of band. """Modify the state out of band.

View File

@ -1,7 +1,7 @@
"""A file upload component.""" """A file upload component."""
from __future__ import annotations from __future__ import annotations
from typing import Any, Dict, List, Optional, Union from typing import Any, ClassVar, Dict, List, Optional, Union
from reflex import constants from reflex import constants
from reflex.components.chakra.forms.input import Input from reflex.components.chakra.forms.input import Input
@ -98,6 +98,23 @@ class UploadFilesProvider(Component):
library = f"/{Dirs.CONTEXTS_PATH}" library = f"/{Dirs.CONTEXTS_PATH}"
tag = "UploadFilesProvider" tag = "UploadFilesProvider"
is_used: ClassVar[bool] = False
@classmethod
def create(cls, *children, **props) -> Component:
"""Create an UploadFilesProvider component.
Args:
*children: The children of the component.
**props: The properties of the component.
Returns:
The UploadFilesProvider component.
"""
cls.is_used = True
return super().create(*children, **props)
class Upload(Component): class Upload(Component):
"""A file upload component.""" """A file upload component."""
@ -192,5 +209,5 @@ class Upload(Component):
@staticmethod @staticmethod
def _get_app_wrap_components() -> dict[tuple[int, str], Component]: def _get_app_wrap_components() -> dict[tuple[int, str], Component]:
return { return {
(5, "UploadFilesProvider"): UploadFilesProvider(), (5, "UploadFilesProvider"): UploadFilesProvider.create(),
} }

View File

@ -7,7 +7,7 @@ from typing import Any, Dict, Literal, Optional, Union, overload
from reflex.vars import Var, BaseVar, ComputedVar from reflex.vars import Var, BaseVar, ComputedVar
from reflex.event import EventChain, EventHandler, EventSpec from reflex.event import EventChain, EventHandler, EventSpec
from reflex.style import Style from reflex.style import Style
from typing import Any, Dict, List, Optional, Union from typing import Any, ClassVar, Dict, List, Optional, Union
from reflex import constants from reflex import constants
from reflex.components.chakra.forms.input import Input from reflex.components.chakra.forms.input import Input
from reflex.components.chakra.layout.box import Box from reflex.components.chakra.layout.box import Box
@ -29,6 +29,8 @@ def clear_selected_files(id_: str = DEFAULT_UPLOAD_ID) -> EventSpec: ...
def cancel_upload(upload_id: str) -> EventSpec: ... def cancel_upload(upload_id: str) -> EventSpec: ...
class UploadFilesProvider(Component): class UploadFilesProvider(Component):
is_used: ClassVar[bool] = False
@overload @overload
@classmethod @classmethod
def create( # type: ignore def create( # type: ignore
@ -87,7 +89,7 @@ class UploadFilesProvider(Component):
] = None, ] = None,
**props **props
) -> "UploadFilesProvider": ) -> "UploadFilesProvider":
"""Create the component. """Create an UploadFilesProvider component.
Args: Args:
*children: The children of the component. *children: The children of the component.
@ -97,13 +99,10 @@ class UploadFilesProvider(Component):
class_name: The class name for the component. class_name: The class name for the component.
autofocus: Whether the component should take the focus once the page is loaded autofocus: Whether the component should take the focus once the page is loaded
custom_attrs: custom attribute custom_attrs: custom attribute
**props: The props of the component. **props: The properties of the component.
Returns: Returns:
The component. The UploadFilesProvider component.
Raises:
TypeError: If an invalid child is passed.
""" """
... ...

View File

@ -245,7 +245,12 @@ def _extract_class_props_as_ast_nodes(
# Import from the target class to ensure type hints are resolvable. # Import from the target class to ensure type hints are resolvable.
exec(f"from {target_class.__module__} import *", type_hint_globals) exec(f"from {target_class.__module__} import *", type_hint_globals)
for name, value in target_class.__annotations__.items(): for name, value in target_class.__annotations__.items():
if name in spec.kwonlyargs or name in EXCLUDED_PROPS or name in all_props: if (
name in spec.kwonlyargs
or name in EXCLUDED_PROPS
or name in all_props
or (isinstance(value, str) and "ClassVar" in value)
):
continue continue
all_props.append(name) all_props.append(name)
@ -559,6 +564,13 @@ class StubGenerator(ast.NodeTransformer):
Returns: Returns:
The modified AnnAssign node (or None). The modified AnnAssign node (or None).
""" """
# skip ClassVars
if (
isinstance(node.annotation, ast.Subscript)
and isinstance(node.annotation.value, ast.Name)
and node.annotation.value.id == "ClassVar"
):
return node
if isinstance(node.target, ast.Name) and node.target.id.startswith("_"): if isinstance(node.target, ast.Name) and node.target.id.startswith("_"):
return None return None
if self.current_class in self.classes: if self.current_class in self.classes: