or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ajax-networking.mdbrowser-integration.mdcli-tools.mdhtml-elements.mdindex.mdruntime-engine.mdstorage.mdtimers-animation.mdui-framework.mdwebsocket.md

websocket.mddocs/

0

# WebSocket Communication

1

2

Real-time bidirectional communication with WebSocket support for live data and interactive applications. Provides Python interface to browser WebSocket API for real-time web applications.

3

4

## Capabilities

5

6

### WebSocket Connection

7

8

Establish and manage WebSocket connections for real-time communication.

9

10

```python { .api }

11

class WebSocket:

12

"""

13

WebSocket connection handler.

14

"""

15

16

def __init__(self, url: str, protocols: list[str] = None):

17

"""

18

Create WebSocket connection.

19

20

Args:

21

url: WebSocket server URL (ws:// or wss://)

22

protocols: Optional list of sub-protocols

23

"""

24

25

def send(self, data: str | bytes) -> None:

26

"""

27

Send data through WebSocket.

28

29

Args:

30

data: Data to send (string or binary)

31

"""

32

33

def close(self, code: int = 1000, reason: str = "") -> None:

34

"""

35

Close WebSocket connection.

36

37

Args:

38

code: Close code (1000 = normal closure)

39

reason: Close reason string

40

"""

41

42

def bind(self, event: str, callback: Callable) -> None:

43

"""

44

Bind event handler.

45

46

Args:

47

event: Event type ('open', 'message', 'close', 'error')

48

callback: Event handler function

49

"""

50

51

# Properties

52

readyState: int # Connection state (0=connecting, 1=open, 2=closing, 3=closed)

53

url: str # Connection URL

54

protocol: str # Selected sub-protocol

55

bufferedAmount: int # Bytes queued for transmission

56

57

# Check WebSocket support

58

supported: bool # True if WebSocket is available in browser

59

```

60

61

**Basic Usage:**

62

```python

63

from browser.websocket import WebSocket, supported

64

65

if not supported:

66

print("WebSocket not supported in this browser")

67

else:

68

# Create WebSocket connection

69

ws = WebSocket("ws://localhost:8080/chat")

70

71

def on_open(event):

72

print("WebSocket connection established")

73

ws.send("Hello Server!")

74

75

def on_message(event):

76

message = event.data

77

print(f"Received: {message}")

78

79

def on_close(event):

80

print(f"Connection closed: {event.code} - {event.reason}")

81

82

def on_error(event):

83

print("WebSocket error occurred")

84

85

# Bind event handlers

86

ws.bind('open', on_open)

87

ws.bind('message', on_message)

88

ws.bind('close', on_close)

89

ws.bind('error', on_error)

90

```

91

92

### Chat Application

93

94

Real-time chat application using WebSocket communication.

95

96

```python { .api }

97

class ChatClient:

98

"""

99

Real-time chat client using WebSocket.

100

"""

101

102

def __init__(self, server_url: str, username: str):

103

"""

104

Initialize chat client.

105

106

Args:

107

server_url: WebSocket server URL

108

username: User's display name

109

"""

110

111

def connect(self) -> None:

112

"""Connect to chat server."""

113

114

def disconnect(self) -> None:

115

"""Disconnect from chat server."""

116

117

def send_message(self, message: str) -> None:

118

"""Send chat message."""

119

120

def join_room(self, room: str) -> None:

121

"""Join chat room."""

122

123

def leave_room(self, room: str) -> None:

124

"""Leave chat room."""

125

```

126

127

**Usage:**

128

```python

129

from browser.websocket import WebSocket

130

from browser import document, bind

131

from browser.html import DIV, INPUT, BUTTON, UL, LI

132

import json

133

134

class ChatApp:

135

def __init__(self):

136

self.ws = None

137

self.username = "User"

138

self.setup_ui()

139

self.connect()

140

141

def setup_ui(self):

142

"""Create chat interface."""

143

# Chat container

144

self.chat_container = DIV(style={

145

'width': '400px',

146

'height': '500px',

147

'border': '1px solid #ccc',

148

'display': 'flex',

149

'flex-direction': 'column'

150

})

151

152

# Messages area

153

self.messages_area = DIV(style={

154

'flex': '1',

155

'overflow-y': 'auto',

156

'padding': '10px',

157

'background': '#f9f9f9'

158

})

159

160

# Input area

161

input_area = DIV(style={

162

'display': 'flex',

163

'padding': '10px',

164

'border-top': '1px solid #ccc'

165

})

166

167

self.message_input = INPUT(

168

placeholder="Type a message...",

169

style={'flex': '1', 'margin-right': '10px'}

170

)

171

172

send_button = BUTTON("Send")

173

174

# Assemble UI

175

input_area <= self.message_input

176

input_area <= send_button

177

self.chat_container <= self.messages_area

178

self.chat_container <= input_area

179

document.body <= self.chat_container

180

181

# Event handlers

182

@bind(send_button, 'click')

183

def handle_send(event):

184

self.send_message()

185

186

@bind(self.message_input, 'keypress')

187

def handle_keypress(event):

188

if event.key == 'Enter':

189

self.send_message()

190

191

def connect(self):

192

"""Connect to WebSocket server."""

193

self.ws = WebSocket("ws://localhost:8080/chat")

194

195

def on_open(event):

196

self.add_system_message("Connected to chat server")

197

# Send join message

198

self.ws.send(json.dumps({

199

'type': 'join',

200

'username': self.username

201

}))

202

203

def on_message(event):

204

try:

205

data = json.loads(event.data)

206

self.handle_server_message(data)

207

except:

208

self.add_system_message(f"Received: {event.data}")

209

210

def on_close(event):

211

self.add_system_message("Disconnected from server")

212

213

def on_error(event):

214

self.add_system_message("Connection error")

215

216

self.ws.bind('open', on_open)

217

self.ws.bind('message', on_message)

218

self.ws.bind('close', on_close)

219

self.ws.bind('error', on_error)

220

221

def send_message(self):

222

"""Send chat message."""

223

message = self.message_input.value.strip()

224

if message and self.ws and self.ws.readyState == 1:

225

self.ws.send(json.dumps({

226

'type': 'message',

227

'username': self.username,

228

'text': message

229

}))

230

self.message_input.value = ""

231

232

def handle_server_message(self, data):

233

"""Handle messages from server."""

234

message_type = data.get('type')

235

236

if message_type == 'message':

237

self.add_chat_message(data['username'], data['text'])

238

elif message_type == 'join':

239

self.add_system_message(f"{data['username']} joined the chat")

240

elif message_type == 'leave':

241

self.add_system_message(f"{data['username']} left the chat")

242

elif message_type == 'error':

243

self.add_system_message(f"Error: {data['message']}")

244

245

def add_chat_message(self, username, text):

246

"""Add chat message to display."""

247

message_div = DIV(style={'margin': '5px 0'})

248

249

username_span = DIV(

250

f"{username}: ",

251

style={'font-weight': 'bold', 'display': 'inline'}

252

)

253

254

text_span = DIV(

255

text,

256

style={'display': 'inline'}

257

)

258

259

message_div <= username_span

260

message_div <= text_span

261

self.messages_area <= message_div

262

263

# Scroll to bottom

264

self.messages_area.scrollTop = self.messages_area.scrollHeight

265

266

def add_system_message(self, text):

267

"""Add system message to display."""

268

message_div = DIV(

269

text,

270

style={

271

'margin': '5px 0',

272

'font-style': 'italic',

273

'color': '#666'

274

}

275

)

276

277

self.messages_area <= message_div

278

self.messages_area.scrollTop = self.messages_area.scrollHeight

279

280

# Start chat application

281

chat_app = ChatApp()

282

```

283

284

### Live Data Updates

285

286

Real-time data streaming for live updates and monitoring.

287

288

```python { .api }

289

class LiveDataClient:

290

"""

291

Client for receiving live data updates.

292

"""

293

294

def __init__(self, data_url: str):

295

"""

296

Initialize live data client.

297

298

Args:

299

data_url: WebSocket URL for data stream

300

"""

301

302

def subscribe(self, channel: str, callback: Callable) -> None:

303

"""

304

Subscribe to data channel.

305

306

Args:

307

channel: Data channel name

308

callback: Function to call with data updates

309

"""

310

311

def unsubscribe(self, channel: str) -> None:

312

"""Unsubscribe from data channel."""

313

```

314

315

**Usage:**

316

```python

317

from browser.websocket import WebSocket

318

from browser import document

319

from browser.html import DIV, TABLE, TR, TD, TH

320

import json

321

322

class StockTicker:

323

def __init__(self):

324

self.ws = None

325

self.stocks = {}

326

self.setup_ui()

327

self.connect()

328

329

def setup_ui(self):

330

"""Create stock ticker UI."""

331

self.container = DIV(style={

332

'width': '600px',

333

'margin': '20px auto'

334

})

335

336

title = DIV("Live Stock Prices", style={

337

'font-size': '24px',

338

'font-weight': 'bold',

339

'text-align': 'center',

340

'margin-bottom': '20px'

341

})

342

343

# Create table

344

self.table = TABLE(style={

345

'width': '100%',

346

'border-collapse': 'collapse'

347

})

348

349

# Table header

350

header = TR()

351

header <= TH("Symbol", style={'border': '1px solid #ccc', 'padding': '10px'})

352

header <= TH("Price", style={'border': '1px solid #ccc', 'padding': '10px'})

353

header <= TH("Change", style={'border': '1px solid #ccc', 'padding': '10px'})

354

header <= TH("Volume", style={'border': '1px solid #ccc', 'padding': '10px'})

355

356

self.table <= header

357

358

self.container <= title

359

self.container <= self.table

360

document.body <= self.container

361

362

def connect(self):

363

"""Connect to stock data WebSocket."""

364

self.ws = WebSocket("ws://localhost:8080/stocks")

365

366

def on_open(event):

367

print("Connected to stock data stream")

368

# Subscribe to stock updates

369

self.ws.send(json.dumps({

370

'action': 'subscribe',

371

'symbols': ['AAPL', 'GOOGL', 'MSFT', 'TSLA', 'AMZN']

372

}))

373

374

def on_message(event):

375

try:

376

data = json.loads(event.data)

377

if data['type'] == 'quote':

378

self.update_stock(data)

379

except Exception as e:

380

print(f"Error processing data: {e}")

381

382

def on_close(event):

383

print("Stock data stream closed")

384

385

self.ws.bind('open', on_open)

386

self.ws.bind('message', on_message)

387

self.ws.bind('close', on_close)

388

389

def update_stock(self, quote):

390

"""Update stock display with new quote."""

391

symbol = quote['symbol']

392

price = quote['price']

393

change = quote['change']

394

volume = quote['volume']

395

396

# Store quote

397

self.stocks[symbol] = quote

398

399

# Find or create table row

400

row_id = f"row_{symbol}"

401

row = document.get(row_id)

402

403

if not row:

404

# Create new row

405

row = TR(id=row_id)

406

407

symbol_cell = TD(symbol, style={'border': '1px solid #ccc', 'padding': '10px'})

408

price_cell = TD(f"${price:.2f}", style={'border': '1px solid #ccc', 'padding': '10px'})

409

410

# Color change cell based on positive/negative

411

change_color = 'green' if change >= 0 else 'red'

412

change_text = f"+{change:.2f}" if change >= 0 else f"{change:.2f}"

413

change_cell = TD(change_text, style={

414

'border': '1px solid #ccc',

415

'padding': '10px',

416

'color': change_color

417

})

418

419

volume_cell = TD(f"{volume:,}", style={'border': '1px solid #ccc', 'padding': '10px'})

420

421

row <= symbol_cell

422

row <= price_cell

423

row <= change_cell

424

row <= volume_cell

425

426

self.table <= row

427

else:

428

# Update existing row

429

cells = row.querySelectorAll('td')

430

cells[1].textContent = f"${price:.2f}"

431

432

change_color = 'green' if change >= 0 else 'red'

433

change_text = f"+{change:.2f}" if change >= 0 else f"{change:.2f}"

434

cells[2].textContent = change_text

435

cells[2].style.color = change_color

436

437

cells[3].textContent = f"{volume:,}"

438

439

# Start stock ticker

440

stock_ticker = StockTicker()

441

```

442

443

### Connection Management

444

445

Advanced WebSocket connection handling with reconnection and heartbeat.

446

447

```python { .api }

448

class ReliableWebSocket:

449

"""

450

WebSocket with automatic reconnection and heartbeat.

451

"""

452

453

def __init__(self, url: str, options: dict = None):

454

"""

455

Initialize reliable WebSocket.

456

457

Args:

458

url: WebSocket server URL

459

options: Connection options (reconnect_interval, max_retries, etc.)

460

"""

461

462

def set_heartbeat(self, interval: int, message: str = "ping") -> None:

463

"""

464

Enable heartbeat to keep connection alive.

465

466

Args:

467

interval: Heartbeat interval in milliseconds

468

message: Heartbeat message to send

469

"""

470

471

def enable_auto_reconnect(self, max_retries: int = -1,

472

backoff: bool = True) -> None:

473

"""

474

Enable automatic reconnection on disconnect.

475

476

Args:

477

max_retries: Maximum reconnection attempts (-1 for unlimited)

478

backoff: Use exponential backoff for retry delays

479

"""

480

```

481

482

**Usage:**

483

```python

484

from browser.websocket import WebSocket

485

from browser.timer import set_interval, clear_interval

486

487

class ReliableConnection:

488

def __init__(self, url):

489

self.url = url

490

self.ws = None

491

self.reconnect_attempts = 0

492

self.max_reconnect_attempts = 5

493

self.reconnect_interval = 1000 # Start with 1 second

494

self.heartbeat_interval = None

495

self.connect()

496

497

def connect(self):

498

"""Establish WebSocket connection."""

499

print(f"Connecting to {self.url}...")

500

self.ws = WebSocket(self.url)

501

502

def on_open(event):

503

print("Connected successfully")

504

self.reconnect_attempts = 0

505

self.reconnect_interval = 1000 # Reset interval

506

self.start_heartbeat()

507

508

def on_message(event):

509

if event.data == "pong":

510

print("Heartbeat response received")

511

else:

512

# Handle actual messages

513

print(f"Received: {event.data}")

514

515

def on_close(event):

516

print("Connection closed")

517

self.stop_heartbeat()

518

if event.code != 1000: # Not normal closure

519

self.attempt_reconnect()

520

521

def on_error(event):

522

print("Connection error")

523

524

self.ws.bind('open', on_open)

525

self.ws.bind('message', on_message)

526

self.ws.bind('close', on_close)

527

self.ws.bind('error', on_error)

528

529

def start_heartbeat(self):

530

"""Start sending heartbeat messages."""

531

def send_ping():

532

if self.ws and self.ws.readyState == 1:

533

self.ws.send("ping")

534

535

self.heartbeat_interval = set_interval(send_ping, 30000) # 30 seconds

536

537

def stop_heartbeat(self):

538

"""Stop heartbeat."""

539

if self.heartbeat_interval:

540

clear_interval(self.heartbeat_interval)

541

self.heartbeat_interval = None

542

543

def attempt_reconnect(self):

544

"""Attempt to reconnect with exponential backoff."""

545

if self.reconnect_attempts >= self.max_reconnect_attempts:

546

print("Max reconnection attempts reached")

547

return

548

549

self.reconnect_attempts += 1

550

delay = self.reconnect_interval * (2 ** (self.reconnect_attempts - 1))

551

552

print(f"Reconnecting in {delay}ms (attempt {self.reconnect_attempts})")

553

554

def do_reconnect():

555

self.connect()

556

557

set_timeout(do_reconnect, delay)

558

559

def send(self, data):

560

"""Send data if connected."""

561

if self.ws and self.ws.readyState == 1:

562

self.ws.send(data)

563

else:

564

print("Cannot send - not connected")

565

566

def close(self):

567

"""Close connection."""

568

self.stop_heartbeat()

569

if self.ws:

570

self.ws.close(1000, "Client closing")

571

572

# Usage

573

reliable_ws = ReliableConnection("ws://localhost:8080/api")

574

```

575

576

This WebSocket system provides comprehensive real-time communication capabilities for Brython applications, enabling live chat, data streaming, notifications, and other interactive features that require bidirectional communication between client and server.