import solara
import traitlets
import asyncio
from anyio import to_thread
import httpx
# reactive vars are per kernel, so we use
# traitlets, which solara can also observe
class Prices(traitlets.HasTraits):
btc = traitlets.Float()
prices = Prices(clicks=0)
async def add_clicks_from_task():
while 1:
try:
def update():
url = "https://api.binance.com/api/v1/ticker/price?symbol=BTCUSDT"
response = httpx.get(url)
prices.btc = float(response.json()["price"])
# on CPython, if we call it from the main event look thread
# this will fail. Note this will also work on pycafe
await to_thread.run_sync(update)
except Exception as e:
print(e)
await asyncio.sleep(1)
# run a task in the background
asyncio.create_task(add_clicks_from_task())
def use_trait_observe(has_trait_object, name):
"""Should be fixed in solara > 1.43.0, so you can use solara.use_trait_observe
"""
_, set_counter = solara.use_state(0)
def connect():
def update(change):
set_counter(lambda x: x+1)
has_trait_object.observe(update, name)
def cleanup():
has_trait_object.unobserve(update, name)
return cleanup
solara.use_effect(connect, [has_trait_object, name])
return getattr(has_trait_object, name)
@solara.component
def Page():
# make this component update when prices.btc changes
use_trait_observe(prices, "btc")
with solara.Card("BTC price", style={"max-width": "280px"}):
solara.Preformatted(f"$ {prices.btc:,}")