-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
607c7c5
commit 6427777
Showing
11 changed files
with
435 additions
and
68 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Autogenerated by nbdev | ||
|
||
d = { 'settings': { 'branch': 'main', | ||
'doc_baseurl': '/ipywatch', | ||
'doc_host': 'https://itepifanio.github.io', | ||
'git_url': 'https://github.com/itepifanio/ipywatch', | ||
'lib_path': 'ipywatch'}, | ||
'syms': { 'ipywatch.history': { 'ipywatch.history.WidgetStateHistory': ('widget_history.html#widgetstatehistory', 'ipywatch/history.py'), | ||
'ipywatch.history.WidgetStateHistory.__delitem__': ( 'widget_history.html#widgetstatehistory.__delitem__', | ||
'ipywatch/history.py'), | ||
'ipywatch.history.WidgetStateHistory.__getitem__': ( 'widget_history.html#widgetstatehistory.__getitem__', | ||
'ipywatch/history.py'), | ||
'ipywatch.history.WidgetStateHistory.__init__': ( 'widget_history.html#widgetstatehistory.__init__', | ||
'ipywatch/history.py'), | ||
'ipywatch.history.WidgetStateHistory.__iter__': ( 'widget_history.html#widgetstatehistory.__iter__', | ||
'ipywatch/history.py'), | ||
'ipywatch.history.WidgetStateHistory.__len__': ( 'widget_history.html#widgetstatehistory.__len__', | ||
'ipywatch/history.py'), | ||
'ipywatch.history.WidgetStateHistory.__setitem__': ( 'widget_history.html#widgetstatehistory.__setitem__', | ||
'ipywatch/history.py'), | ||
'ipywatch.history.WidgetStateHistory.get_current_state': ( 'widget_history.html#widgetstatehistory.get_current_state', | ||
'ipywatch/history.py'), | ||
'ipywatch.history.WidgetStateHistory.get_state_history': ( 'widget_history.html#widgetstatehistory.get_state_history', | ||
'ipywatch/history.py'), | ||
'ipywatch.history.WidgetStateHistory.set_state': ( 'widget_history.html#widgetstatehistory.set_state', | ||
'ipywatch/history.py')}, | ||
'ipywatch.ipywatch': { 'ipywatch.ipywatch.Ipywatch': ('ipywatch.html#ipywatch', 'ipywatch/ipywatch.py'), | ||
'ipywatch.ipywatch.Ipywatch.__init__': ('ipywatch.html#ipywatch.__init__', 'ipywatch/ipywatch.py'), | ||
'ipywatch.ipywatch.Ipywatch._on_state_change': ( 'ipywatch.html#ipywatch._on_state_change', | ||
'ipywatch/ipywatch.py'), | ||
'ipywatch.ipywatch.WidgetStateHistoryListener': ( 'ipywatch.html#widgetstatehistorylistener', | ||
'ipywatch/ipywatch.py'), | ||
'ipywatch.ipywatch.WidgetStateHistoryListener.__init__': ( 'ipywatch.html#widgetstatehistorylistener.__init__', | ||
'ipywatch/ipywatch.py')}}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/02_widget_history.ipynb. | ||
|
||
# %% auto 0 | ||
__all__ = ['WidgetStateHistory'] | ||
|
||
# %% ../nbs/02_widget_history.ipynb 3 | ||
from collections import deque | ||
from typing import Any, Deque, Dict, Iterator | ||
|
||
# %% ../nbs/02_widget_history.ipynb 4 | ||
class WidgetStateHistory: | ||
def __init__(self, history_size: int = 5): | ||
self.history_size = history_size | ||
self._widget_states: Dict[str, Any] = {} | ||
|
||
def set_state(self, comm_id: str, state: Any): | ||
if comm_id not in self._widget_states: | ||
self._widget_states[comm_id] = deque(maxlen=self.history_size) | ||
|
||
self._widget_states[comm_id].append(state) | ||
|
||
def get_current_state(self, comm_id: str): | ||
if comm_id in self._widget_states and self._widget_states[comm_id]: | ||
return self._widget_states[comm_id][-1] | ||
|
||
raise KeyError(f"No state found for widget comm_id: {comm_id}") | ||
|
||
def get_state_history(self, comm_id: str) -> Any: | ||
if comm_id in self._widget_states: | ||
return self._widget_states[comm_id] | ||
|
||
raise KeyError(f"No history found for widget comm_id: {comm_id}") | ||
|
||
def __setitem__(self, comm_id: str, state: Any): | ||
self.set_state(comm_id, state) | ||
|
||
def __getitem__(self, comm_id: str): | ||
return self.get_current_state(comm_id) | ||
|
||
def __delitem__(self, comm_id: str): | ||
if comm_id in self._widget_states: | ||
del self._widget_states[comm_id] | ||
else: | ||
raise KeyError(f"Comm ID {comm_id} not found") | ||
|
||
def __iter__(self) -> Iterator[str]: | ||
return iter(self._widget_states) | ||
|
||
def __len__(self) -> int: | ||
return len(self._widget_states) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/03_ipywatch.ipynb. | ||
|
||
# %% auto 0 | ||
__all__ = ['WidgetStateHistoryListener', 'Ipywatch'] | ||
|
||
# %% ../nbs/03_ipywatch.ipynb 3 | ||
from typing import Any, Callable, List | ||
|
||
import ipywidgets | ||
from ipykernel.comm import Comm | ||
from ipywidgets import HBox, VBox, Label, Output, Button, Text, Tab, Layout | ||
|
||
from ipywatch.history import WidgetStateHistory | ||
|
||
# %% ../nbs/03_ipywatch.ipynb 4 | ||
class WidgetStateHistoryListener: | ||
def __init__( | ||
self, | ||
history_size: int = 5, | ||
on_state_change: Callable[[ipywidgets.Widget, Any], None]=None | ||
): | ||
self.history_size = history_size | ||
self.history = WidgetStateHistory(history_size) | ||
self.on_state_change = on_state_change | ||
|
||
_original_send = Comm.send | ||
|
||
def _patched_send(comm, data=None, metadata=None, buffers=None): | ||
comm_id = comm.comm_id | ||
|
||
widget = ipywidgets.Widget.widgets.get(comm_id) | ||
|
||
self.history.set_state(comm_id, data) | ||
|
||
if self.on_state_change: | ||
self.on_state_change(widget, data) | ||
|
||
_original_send(comm, data, metadata, buffers) | ||
|
||
Comm.send = _patched_send | ||
|
||
# %% ../nbs/03_ipywatch.ipynb 5 | ||
class Ipywatch(HBox): | ||
def __init__(self, width: str = '100%', height: str = '400px', history_size: int = 5, **kwargs): | ||
self.updating = False # Flag to prevent recursion | ||
|
||
self.listener = WidgetStateHistoryListener(history_size=history_size) | ||
|
||
self.messages = Output(layout=dict(width='100%', height='400px')) | ||
|
||
self.listener.on_state_change = self._on_state_change | ||
|
||
super().__init__( | ||
children=[self.messages], | ||
layout=Layout(width=width, height=height) | ||
) | ||
|
||
def _on_state_change(self, widget, state): | ||
if self.updating: | ||
return | ||
|
||
self.updating = True | ||
|
||
widget_type = type(widget).__name__ if widget else "Unknown" | ||
self.messages.append_stdout(f"Event emitted by {widget_type}: {state}\n") | ||
|
||
self.updating = False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "c6bc2197-18a4-4b3c-9124-9e8eb3eccbdb", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"#| default_exp history" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "06df2b84-4f6b-4933-bedb-971fea8d447e", | ||
"metadata": {}, | ||
"source": [ | ||
"# Widget history" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "fa1e8874-8cfa-4d6c-8af6-75e7f4b71141", | ||
"metadata": {}, | ||
"source": [ | ||
"Store a fixed number of stored states in-memory" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "c43c72ad-2594-4fa7-a905-b14db392c09e", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"#| exporti\n", | ||
"from collections import deque\n", | ||
"from typing import Any, Deque, Dict, Iterator" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "8ae746d4-240e-4ed7-9681-76b7a72af0bf", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"#| export\n", | ||
"class WidgetStateHistory:\n", | ||
" def __init__(self, history_size: int = 5):\n", | ||
" self.history_size = history_size\n", | ||
" self._widget_states: Dict[str, Any] = {}\n", | ||
"\n", | ||
" def set_state(self, comm_id: str, state: Any):\n", | ||
" if comm_id not in self._widget_states:\n", | ||
" self._widget_states[comm_id] = deque(maxlen=self.history_size)\n", | ||
"\n", | ||
" self._widget_states[comm_id].append(state)\n", | ||
"\n", | ||
" def get_current_state(self, comm_id: str):\n", | ||
" if comm_id in self._widget_states and self._widget_states[comm_id]:\n", | ||
" return self._widget_states[comm_id][-1]\n", | ||
"\n", | ||
" raise KeyError(f\"No state found for widget comm_id: {comm_id}\")\n", | ||
"\n", | ||
" def get_state_history(self, comm_id: str) -> Any:\n", | ||
" if comm_id in self._widget_states:\n", | ||
" return self._widget_states[comm_id]\n", | ||
"\n", | ||
" raise KeyError(f\"No history found for widget comm_id: {comm_id}\")\n", | ||
"\n", | ||
" def __setitem__(self, comm_id: str, state: Any):\n", | ||
" self.set_state(comm_id, state)\n", | ||
"\n", | ||
" def __getitem__(self, comm_id: str):\n", | ||
" return self.get_current_state(comm_id)\n", | ||
"\n", | ||
" def __delitem__(self, comm_id: str):\n", | ||
" if comm_id in self._widget_states:\n", | ||
" del self._widget_states[comm_id]\n", | ||
" else:\n", | ||
" raise KeyError(f\"Comm ID {comm_id} not found\")\n", | ||
"\n", | ||
" def __iter__(self) -> Iterator[str]:\n", | ||
" return iter(self._widget_states)\n", | ||
"\n", | ||
" def __len__(self) -> int:\n", | ||
" return len(self._widget_states)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "323932aa-7412-4c70-9a1f-a3b313ad5139", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"widget_states = WidgetStateHistory(history_size=5)\n", | ||
"\n", | ||
"widget_states[\"widget_1\"] = {\"value\": 10}\n", | ||
"widget_states[\"widget_1\"] = {\"value\": 20}\n", | ||
"assert len(widget_states) == 1\n", | ||
"assert widget_states['widget_1'] == {\"value\": 20}\n", | ||
"\n", | ||
"del widget_states[\"widget_1\"] \n", | ||
"assert len(widget_states) == 0" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "python3", | ||
"language": "python", | ||
"name": "python3" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 5 | ||
} |
Oops, something went wrong.