Commit 3a3d1efe authored by Duggan, John's avatar Duggan, John
Browse files

Auto-populate dropdown options if an Enum type is used

parent ec3cf839
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
[tool.poetry]
name = "nova-trame"
version = "0.14.2"
version = "0.15.0"
description = "A Python Package for injecting curated themes and custom components into Trame applications"
authors = ["Duggan, John <dugganjw@ornl.gov>"]
readme = "README.md"
+6 −2
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
import logging
import os
import re
from enum import Enum
from typing import Any, Dict, Optional, Union

from trame.app import get_server
@@ -22,7 +23,7 @@ class InputField:

    @staticmethod
    def create_boilerplate_properties(
        v_model: Optional[Union[tuple[str, Any], str]], debounce: int, throttle: int
        v_model: Optional[Union[tuple[str, Any], str]], field_type: str, debounce: int, throttle: int
    ) -> dict:
        if debounce == -1:
            debounce = int(os.environ.get("NOVA_TRAME_DEFAULT_DEBOUNCE", 0))
@@ -69,6 +70,9 @@ class InputField:
                    "rules": (f"[(v) => trigger('validate_pydantic_field', ['{field}', v, index])]",),
                }

                if field_type == "select" and issubclass(field_info.annotation, Enum):
                    args |= {"items": str([option.value for option in field_info.annotation])}

            if debounce > 0 and throttle > 0:
                raise ValueError("debounce and throttle cannot be used together")

@@ -161,7 +165,7 @@ class InputField:
        """
        server = get_server(None, client_type="vue3")

        kwargs = {**cls.create_boilerplate_properties(v_model, debounce, throttle), **kwargs}
        kwargs = {**cls.create_boilerplate_properties(v_model, type, debounce, throttle), **kwargs}

        if "__events" not in kwargs or kwargs["__events"] is None:
            kwargs["__events"] = []
+37 −0
Original line number Diff line number Diff line
"""Unit tests for InputField."""

from enum import Enum
from time import sleep
from typing import cast

@@ -95,6 +96,42 @@ def test_pydantic_validation(driver: Firefox) -> None:
    assert error_message.startswith("Input should be a valid integer")


def test_items_attributes() -> None:
    class DropdownOptions(str, Enum):
        item_a = "item_a"
        item_b = "item_b"
        item_c = "item_c"

    class Dropdown(BaseModel):
        enum_field: DropdownOptions = Field(default=DropdownOptions.item_a)
        str_field: str = Field(default="test")

    dropdown = Dropdown()

    class MyTrameApp(ThemedApp):
        def __init__(self, server: Server = None) -> None:
            server = get_server(None, client_type="vue3")
            super().__init__(server=server)
            binding = TrameBinding(server.state).new_bind(dropdown)
            binding.connect("dropdown")
            self.create_ui()

        def create_ui(self) -> None:
            with super().create_ui() as layout:
                with layout.content:
                    autopopulated_items = cast(
                        vuetify.VSelect, InputField(v_model="dropdown.enum_field", type="select")
                    )
                    missing_select_type = cast(vuetify.VSelect, InputField(v_model="dropdown.enum_field"))
                    missing_enum_model = cast(vuetify.VSelect, InputField(v_model="dropdown.str_field", type="select"))

                    assert autopopulated_items.items == ("['item_a', 'item_b', 'item_c']",)
                    assert missing_select_type.items is None
                    assert missing_enum_model.items is None

    MyTrameApp()


def test_throttle_attributes() -> None:
    class MyTrameApp(ThemedApp):
        def __init__(self, server: Server = None) -> None: