Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion examples/sample/sample_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,28 @@

st.title("Sample Panel")

col1, col2 = st.columns([0.4, 0.6])
col1, col2, col3 = st.columns([0.4, 0.3, 0.3])

with col1:
st.markdown("**Type**")
st.write("String")
st.write("Integer")
st.write("Float")
st.write("Boolean")
st.write("List")

with col2:
st.markdown("**Set Values**")
st.write(panel.get_value("sample_string"))
st.write(panel.get_value("sample_int"))
st.write(panel.get_value("sample_float"))
st.write(panel.get_value("sample_bool"))
st.write(panel.get_value("float_values"))

with col3:
st.markdown("**Default Values**")
st.write(panel.get_value("missing_string", "0"))
st.write(panel.get_value("missing_int", 0))
st.write(panel.get_value("missing_float", 0.0))
st.write(panel.get_value("missing_bool", False))
st.write(panel.get_value("missing_list", [0.0]))
15 changes: 11 additions & 4 deletions src/nipanel/_panel_value_accessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,23 @@ def panel_id(self) -> str:
"""Read-only accessor for the panel ID."""
return self._panel_id

def get_value(self, value_id: str) -> object:
"""Get the value for a control on the panel.
def get_value(self, value_id: str, default_value: object = None) -> object:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want the default value to affect type inference?

_T = TypeVar("_T")

@overload
def get_value(self, value_id: str) -> object: ...

@overload
def get_value(self, value_id: str, default_value: _T | None = None) -> _T: ...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"""Get the value for a control on the panel with an optional default value.

Args:
value_id: The id of the value
default_value: The default value to return if the value is not set

Returns:
The value
The value, or the default value if not set
"""
return self._panel_client.get_value(self._panel_id, value_id)
try:
return self._panel_client.get_value(self._panel_id, value_id)
except grpc.RpcError as e:
if e.code() == grpc.StatusCode.NOT_FOUND and default_value is not None:
return default_value
else:
raise e

def set_value(self, value_id: str, value: object) -> None:
"""Set the value for a control on the panel.
Expand Down
26 changes: 25 additions & 1 deletion tests/unit/test_streamlit_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def test___panel___set_value___sets_value(
}


def test___panel___get_unset_value___raises_exception(
def test___panel___get_unset_value_with_no_default___raises_exception(
fake_panel_channel: grpc.Channel,
) -> None:
"""Test that get_value() raises an exception for an unset value."""
Expand All @@ -146,6 +146,30 @@ def test___panel___set_value___gets_value(
assert panel.get_value(value_id) == string_value


def test___set_value___get_value_ignores_default(
fake_panel_channel: grpc.Channel,
) -> None:
panel = StreamlitPanel("my_panel", "path/to/script", grpc_channel=fake_panel_channel)

value_id = "test_id"
string_value = "test_value"
panel.set_value(value_id, string_value)

assert panel.get_value(value_id, "default") == string_value


def test___get_value_returns_default_when_value_not_set(
fake_panel_channel: grpc.Channel,
) -> None:
panel = StreamlitPanel("my_panel", "path/to/script", grpc_channel=fake_panel_channel)

assert panel.get_value("missing_string", "default") == "default"
assert panel.get_value("missing_int", 123) == 123
assert panel.get_value("missing_float", 1.23) == 1.23
assert panel.get_value("missing_bool", True) is True
assert panel.get_value("missing_list", [1, 2, 3]) == [1, 2, 3]


@pytest.mark.parametrize(
"value_payload",
[
Expand Down
2 changes: 2 additions & 0 deletions tests/utils/_fake_python_panel_servicer.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ def EnumeratePanels( # noqa: N802

def GetValue(self, request: GetValueRequest, context: Any) -> GetValueResponse: # noqa: N802
"""Trivial implementation for testing."""
if request.value_id not in self._panel_value_ids.get(request.panel_id, {}):
context.abort(grpc.StatusCode.NOT_FOUND, "Value ID not found in panel")
value = self._panel_value_ids[request.panel_id][request.value_id]
return GetValueResponse(value=value)

Expand Down