diff --git a/pynecone/utils/format.py b/pynecone/utils/format.py index ad0a31aa9..b42dd8551 100644 --- a/pynecone/utils/format.py +++ b/pynecone/utils/format.py @@ -299,7 +299,8 @@ def format_upload_event(event_spec: EventSpec) -> str: from pynecone.compiler import templates state, name = get_event_handler_parts(event_spec.handler) - return f'uploadFiles({state}, {templates.RESULT}, {templates.SET_RESULT}, {state}.files, "{name}", UPLOAD)' + parent_state = state.split(".")[0] + return f'uploadFiles({parent_state}, {templates.RESULT}, {templates.SET_RESULT}, {parent_state}.files, "{state}.{name}", UPLOAD)' def format_query_params(router_data: Dict[str, Any]) -> Dict[str, str]: diff --git a/tests/conftest.py b/tests/conftest.py index 58a688031..1eadf0a3d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,7 +4,8 @@ from typing import Generator import pytest -from pynecone.state import State +import pynecone as pc +from pynecone.event import EventSpec @pytest.fixture(scope="function") @@ -25,7 +26,7 @@ def list_mutation_state(): A state with list mutation features. """ - class TestState(State): + class TestState(pc.State): """The test state.""" # plain list @@ -88,7 +89,7 @@ def dict_mutation_state(): A state with dict mutation features. """ - class TestState(State): + class TestState(pc.State): """The test state.""" # plain dict @@ -134,3 +135,65 @@ def dict_mutation_state(): self.friend_in_nested_dict["friend"]["age"] = 30 return TestState() + + +class UploadState(pc.State): + """The base state for uploading a file.""" + + img: str + + async def handle_upload(self, file: pc.UploadFile): + """Handle the upload of a file. + + Args: + file: The uploaded file. + """ + upload_data = await file.read() + outfile = f".web/public/{file.filename}" + + # Save the file. + with open(outfile, "wb") as file_object: + file_object.write(upload_data) + + # Update the img var. + self.img = file.filename + + +class BaseState(pc.State): + """The test base state.""" + + pass + + +class SubUploadState(BaseState): + """The test substate.""" + + img: str + + async def handle_upload(self, file: pc.UploadFile): + """Handle the upload of a file. + + Args: + file: The uploaded file. + """ + pass + + +@pytest.fixture +def upload_event_spec(): + """Create an event Spec for a base state. + + Returns: + Event Spec. + """ + return EventSpec(handler=UploadState.handle_upload, upload=True) # type: ignore + + +@pytest.fixture +def upload_sub_state_event_spec(): + """Create an event Spec for a substate. + + Returns: + Event Spec. + """ + return EventSpec(handler=SubUploadState.handle_upload, upload=True) # type: ignore diff --git a/tests/test_utils.py b/tests/test_utils.py index 655a72505..b3450fa42 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -285,3 +285,30 @@ def test_is_backend_variable(input, output): ) def test_issubclass(cls: type, cls_check: type, expected: bool): assert types._issubclass(cls, cls_check) == expected + + +def test_format_upload_event(upload_event_spec): + """Test formatting an upload event spec. + + Args: + upload_event_spec: The event spec fixture. + """ + assert ( + format.format_upload_event(upload_event_spec) + == "uploadFiles(upload_state, result, setResult, " + 'upload_state.files, "upload_state.handle_upload", ' + "UPLOAD)" + ) + + +def test_format_sub_state_event(upload_sub_state_event_spec): + """Test formatting an upload event spec of substate. + + Args: + upload_sub_state_event_spec: The event spec fixture. + """ + assert ( + format.format_upload_event(upload_sub_state_event_spec) + == "uploadFiles(base_state, result, setResult, base_state.files, " + '"base_state.sub_upload_state.handle_upload", UPLOAD)' + )