Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ dev = [
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.coverage.run]
omit = ["src/open_cups/session_state.py"] # TODO (#165): Remove this omission if we stick with the cookies-based session state implementation

[tool.hatch.build.targets.wheel]
packages = ["src/open_cups"]

Expand Down
4 changes: 2 additions & 2 deletions src/open_cups/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def show_room_selection_screen(lobby: LobbyState) -> None:

left, right = st.columns([2, 1])
with left:
st.title("Welcome to OpenCups")
st.title("Welcome to branched OpenCups")
st.write("Host or join a room to share feedback.")
with right:
st.image("assets/logo.png", width="content")
Expand Down Expand Up @@ -259,7 +259,7 @@ def handle_question_submit() -> None:
def run() -> None:
st_autorefresh(interval=AUTOREFRESH_INTERVAL_MS, key="data_refresh")

state_provider = StateProvider()
state_provider = StateProvider(USER_REMOVAL_TIMEOUT_SECONDS)
cleanup = state_provider.get_cleanup(USER_REMOVAL_TIMEOUT_SECONDS)
cleanup.cleanup_all()

Expand Down
18 changes: 14 additions & 4 deletions src/open_cups/session_state.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import uuid

import streamlit as st
from streamlit.components.v1 import html as components_html

COOKIE_NAME = "OPEN_CUPS_SESSION_ID"

class SessionState:
"""Per-user session state wrapper.
Expand All @@ -10,11 +12,19 @@ class SessionState:
for more details.
"""

def __init__(self) -> None:
def __init__(self, user_removal_timeout: int) -> None:
if "session_id" not in st.session_state:
existing = st.query_params.get("session_id")
st.session_state.session_id = existing or str(uuid.uuid4())
st.query_params["session_id"] = st.session_state.session_id
session_id = st.context.cookies.get(COOKIE_NAME)
if session_id is None:
session_id = str(uuid.uuid4())
components_html(
"<script>document.cookie = "
f'"{COOKIE_NAME}={session_id}; path=/; '
f'Max-Age={user_removal_timeout}; SameSite=Strict";'
"</script>",
height=0,
)
st.session_state.session_id = session_id

@property
def session_id(self) -> str:
Expand Down
8 changes: 4 additions & 4 deletions src/open_cups/state_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ def cleanup_all(self) -> None:


class Context:
def __init__(self) -> None:
def __init__(self, user_removal_timeout: int) -> None:
self.application_state: ApplicationState = self._get_application_state()
self.session_state = SessionState()
self.session_state = SessionState(user_removal_timeout=user_removal_timeout)

@staticmethod
@st.cache_resource
Expand All @@ -114,8 +114,8 @@ def _get_application_state() -> ApplicationState:


class StateProvider:
def __init__(self) -> None:
self.context = Context()
def __init__(self, user_removal_timeout: int) -> None:
self.context = Context(user_removal_timeout=user_removal_timeout)

def get_cleanup(self, timeout_seconds: int) -> CleanupState:
return CleanupState(self.context.application_state, timeout_seconds)
Expand Down
4 changes: 2 additions & 2 deletions tests/bdd/fixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ def capture_wrapper(
def capture_application_state(monkeypatch: pytest.MonkeyPatch) -> None:
original_init = Context.__init__

def wrapped_init(context: Context) -> None:
original_init(context)
def wrapped_init(context: Context, user_removal_timeout: int) -> None:
original_init(context, user_removal_timeout)
captured.application_state = context.application_state

monkeypatch.setattr(Context, "__init__", wrapped_init)
Loading