or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

channel-communication.mdcore-framework.mdevents-interactivity.mdexception-handling.mdfile-management.mdhtml-system.mdindex.mdresponse-system.mdrouting-urls.mdstatic-files-assets.md

core-framework.mddocs/

0

# Core Application Framework

1

2

Essential classes and patterns for building Lona web applications. The core framework provides the fundamental components needed to create interactive web applications entirely in Python, including application setup, view handling, request processing, and routing.

3

4

## Capabilities

5

6

### Application Class

7

8

The main application class that serves as the entry point for Lona web applications, managing routes, middleware, templates, static files, and server configuration.

9

10

```python { .api }

11

class App:

12

def __init__(self, script_path: str):

13

"""

14

Initialize a Lona application.

15

16

Args:

17

script_path (str): Path to the main script file (__file__)

18

"""

19

20

def route(self, raw_pattern: str | int, name: str = '', interactive: bool = True,

21

http_pass_through: bool = False, frontend_view=None):

22

"""

23

Decorator for registering view routes.

24

25

Args:

26

raw_pattern (str | int): URL pattern to match or MATCH_ALL constant

27

name (str): Optional route name for reverse URL generation

28

interactive (bool): Whether the route supports interactivity

29

http_pass_through (bool): Pass HTTP requests directly to view

30

frontend_view: Optional frontend view function

31

32

Returns:

33

Decorator function

34

"""

35

36

def middleware(self):

37

"""

38

Decorator for registering middleware functions.

39

40

Returns:

41

Decorator function

42

"""

43

44

def frontend_view(self):

45

"""

46

Decorator for registering frontend views.

47

48

Returns:

49

Decorator function

50

"""

51

52

def error_403_view(self):

53

"""

54

Decorator for registering 403 error views.

55

56

Returns:

57

Decorator function

58

"""

59

60

def error_404_view(self):

61

"""

62

Decorator for registering 404 error views.

63

64

Returns:

65

Decorator function

66

"""

67

68

def error_500_view(self):

69

"""

70

Decorator for registering 500 error views.

71

72

Returns:

73

Decorator function

74

"""

75

76

def add_template(self, name: str, string: str = '', path: str = ''):

77

"""

78

Add a template to the application.

79

80

Args:

81

name (str): Template name

82

string (str): Template content as string

83

path (str): Path to template file

84

"""

85

86

def add_static_file(self, name: str, string: str = '', path: str = ''):

87

"""

88

Add a static file to the application.

89

90

Args:

91

name (str): Static file name

92

string (str): File content as string

93

path (str): Path to static file

94

"""

95

96

def add_route(self, route: 'Route'):

97

"""

98

Programmatically add a route to the application.

99

100

Args:

101

route (Route): Route object to add

102

"""

103

104

def run(self, host: str = 'localhost', port: int = 8080,

105

loop_class=None, **kwargs):

106

"""

107

Run the application development server.

108

109

Args:

110

host (str): Server host address

111

port (int): Server port number

112

loop_class: Optional event loop class

113

**kwargs: Additional server arguments

114

"""

115

116

def setup_server(self, host: str = 'localhost', port: int = 8080):

117

"""

118

Setup the server without running it.

119

120

Args:

121

host (str): Server host address

122

port (int): Server port number

123

124

Returns:

125

Server instance

126

"""

127

```

128

129

#### Usage Example

130

131

```python

132

from lona import App, View

133

from lona.html import HTML, H1

134

135

app = App(__file__)

136

137

@app.route('/')

138

class IndexView(View):

139

def handle_request(self, request):

140

return HTML(H1('Hello World'))

141

142

# Add middleware

143

@app.middleware()

144

def my_middleware(request):

145

request.custom_data = 'processed'

146

return request

147

148

# Add template

149

app.add_template('base', '''

150

<html>

151

<head><title>{{ title }}</title></head>

152

<body>{{ content }}</body>

153

</html>

154

''')

155

156

if __name__ == '__main__':

157

app.run(host='0.0.0.0', port=8080)

158

```

159

160

### View Class

161

162

Base class for creating views that handle HTTP requests and user interactions. Views can be stateless (for simple HTTP responses) or stateful (for interactive applications with real-time user interaction).

163

164

```python { .api }

165

class View:

166

def handle_request(self, request: 'Request'):

167

"""

168

Main request handler method - override this in subclasses.

169

170

Args:

171

request (Request): The HTTP request object

172

173

Returns:

174

Response object, HTML content, or None for interactive views

175

"""

176

177

def show(self, html=None, template: str = None, title: str = None):

178

"""

179

Display HTML content to the user and enter interactive mode.

180

181

Args:

182

html: HTML content to display

183

template (str): Template name to render

184

title (str): Page title

185

"""

186

187

def set_title(self, title: str):

188

"""

189

Set the page title.

190

191

Args:

192

title (str): New page title

193

"""

194

195

def await_input_event(self, *nodes, html=None, timeout=None) -> 'InputEvent':

196

"""

197

Wait for any input event on specified nodes.

198

199

Args:

200

*nodes: HTML nodes to monitor for events

201

html: Optional HTML to show before waiting

202

timeout: Optional timeout in seconds

203

204

Returns:

205

InputEvent object containing event details

206

"""

207

208

def await_click(self, *nodes, html=None, timeout=None) -> 'InputEvent':

209

"""

210

Wait for click events on specified nodes.

211

212

Args:

213

*nodes: HTML nodes to monitor for clicks

214

html: Optional HTML to show before waiting

215

timeout: Optional timeout in seconds

216

217

Returns:

218

InputEvent object containing click details

219

"""

220

221

def await_change(self, *nodes, html=None, timeout=None) -> 'InputEvent':

222

"""

223

Wait for change events on specified nodes.

224

225

Args:

226

*nodes: HTML nodes to monitor for changes

227

html: Optional HTML to show before waiting

228

timeout: Optional timeout in seconds

229

230

Returns:

231

InputEvent object containing change details

232

"""

233

234

def await_focus(self, *nodes, html=None, timeout=None) -> 'InputEvent':

235

"""

236

Wait for focus events on specified nodes.

237

238

Args:

239

*nodes: HTML nodes to monitor for focus

240

html: Optional HTML to show before waiting

241

timeout: Optional timeout in seconds

242

243

Returns:

244

InputEvent object containing focus details

245

"""

246

247

def await_blur(self, *nodes, html=None, timeout=None) -> 'InputEvent':

248

"""

249

Wait for blur events on specified nodes.

250

251

Args:

252

*nodes: HTML nodes to monitor for blur

253

html: Optional HTML to show before waiting

254

timeout: Optional timeout in seconds

255

256

Returns:

257

InputEvent object containing blur details

258

"""

259

260

def send_str(self, string: str, broadcast: bool = False):

261

"""

262

Send a string message to the frontend.

263

264

Args:

265

string (str): Message to send

266

broadcast (bool): Whether to broadcast to all connected clients

267

"""

268

269

def fire_view_event(self, name: str, data=None):

270

"""

271

Fire a custom view event.

272

273

Args:

274

name (str): Event name

275

data: Event data payload

276

"""

277

278

def subscribe(self, topic: str, handler):

279

"""

280

Subscribe to a channel topic.

281

282

Args:

283

topic (str): Channel topic name

284

handler: Function to handle messages

285

"""

286

287

def unsubscribe(self, topic: str = None):

288

"""

289

Unsubscribe from channel topics.

290

291

Args:

292

topic (str): Specific topic to unsubscribe from, or None for all

293

"""

294

295

def sleep(self, delay: float):

296

"""

297

Async sleep for the specified delay.

298

299

Args:

300

delay (float): Sleep duration in seconds

301

"""

302

303

def is_daemon_view(self) -> bool:

304

"""

305

Check if this view runs as a daemon.

306

307

Returns:

308

bool: True if view is a daemon

309

"""

310

311

def is_interactive(self) -> bool:

312

"""

313

Check if this view supports interactivity.

314

315

Returns:

316

bool: True if view is interactive

317

"""

318

319

# Properties

320

request: 'Request' # Current request object

321

server: object # Server instance

322

logger: object # Logger instance

323

```

324

325

#### Usage Example

326

327

```python

328

from lona import App, View

329

from lona.html import HTML, H1, Button, P

330

from lona.responses import JsonResponse

331

332

app = App(__file__)

333

334

# Simple HTTP view

335

@app.route('/api/status')

336

class StatusView(View):

337

def handle_request(self, request):

338

return JsonResponse({'status': 'ok'})

339

340

# Interactive view

341

@app.route('/counter')

342

class CounterView(View):

343

def handle_request(self, request):

344

count = 0

345

button = Button('Increment')

346

counter_text = P(f'Count: {count}')

347

348

html = HTML(

349

H1('Interactive Counter'),

350

counter_text,

351

button

352

)

353

354

self.show(html)

355

356

while True:

357

self.await_click(button)

358

count += 1

359

counter_text.set_text(f'Count: {count}')

360

```

361

362

### Request Class

363

364

Represents an HTTP request with additional Lona-specific functionality for handling interactive applications, user sessions, and routing information.

365

366

```python { .api }

367

class Request:

368

# Request data

369

GET: dict # GET parameters

370

POST: dict # POST parameters

371

method: str # HTTP method (GET, POST, etc.)

372

url: str # Request URL

373

374

# User and session

375

user: object # User object (if authentication middleware used)

376

377

# Routing information

378

route: 'Route' # Matched route object

379

match_info: dict # URL pattern match information

380

381

# Lona-specific

382

interactive: bool # Whether request supports interactivity

383

connection: object # Connection object for interactive features

384

view: 'View' # Associated view instance (set during processing)

385

386

# Headers and metadata

387

headers: dict # Request headers

388

content_type: str # Content type header

389

content_length: int # Content length

390

391

# Session data (if session middleware enabled)

392

session: dict # Session data dictionary

393

```

394

395

#### Usage Example

396

397

```python

398

@app.route('/user/<int:user_id>')

399

class UserProfileView(View):

400

def handle_request(self, request):

401

# Access URL parameters

402

user_id = request.match_info['user_id']

403

404

# Access GET/POST data

405

search_query = request.GET.get('q', '')

406

407

# Check request method

408

if request.method == 'POST':

409

# Handle form submission

410

name = request.POST.get('name', '')

411

412

# Access user (if authenticated)

413

if request.user:

414

username = request.user.username

415

416

# Check if interactive

417

if request.interactive:

418

# Can use interactive features

419

self.show(HTML(H1(f'User {user_id}')))

420

else:

421

# Return static response

422

return HtmlResponse(f'<h1>User {user_id}</h1>')

423

```

424

425

### Route Class

426

427

Defines URL routing patterns and associates them with view classes or functions, supporting both interactive and non-interactive routes with optional HTTP pass-through.

428

429

```python { .api }

430

class Route:

431

def __init__(self, raw_pattern: str, view, name: str = '',

432

interactive: bool = True, http_pass_through: bool = False,

433

frontend_view=None):

434

"""

435

Create a new route definition.

436

437

Args:

438

raw_pattern (str): URL pattern (supports placeholders like <int:id>)

439

view: View class or function to handle requests

440

name (str): Optional route name for reverse URL generation

441

interactive (bool): Whether route supports interactive features

442

http_pass_through (bool): Pass HTTP requests directly to view

443

frontend_view: Optional frontend view function

444

"""

445

446

# Properties

447

raw_pattern: str # Original URL pattern string

448

view: object # View class or function

449

name: str # Route name for reverse lookups

450

interactive: bool # Interactive support flag

451

http_pass_through: bool # HTTP pass-through flag

452

frontend_view: object # Frontend view function

453

```

454

455

#### Usage Example

456

457

```python

458

from lona import App, Route, View

459

from lona.html import HTML, H1

460

461

app = App(__file__)

462

463

# Using decorator (recommended)

464

@app.route('/users/<int:user_id>', name='user_profile', interactive=True)

465

class UserView(View):

466

def handle_request(self, request):

467

user_id = request.match_info['user_id']

468

return HTML(H1(f'User {user_id}'))

469

470

# Programmatic route creation

471

class ApiView(View):

472

def handle_request(self, request):

473

return JsonResponse({'api': 'v1'})

474

475

api_route = Route('/api/v1', ApiView, name='api', interactive=False)

476

app.add_route(api_route)

477

478

# Route matching constant

479

from lona import MATCH_ALL

480

481

@app.route(MATCH_ALL, name='catch_all') # Matches any URL

482

class CatchAllView(View):

483

def handle_request(self, request):

484

return HTML(H1('Page not found'))

485

```

486

487

## Types

488

489

```python { .api }

490

from typing import Union, Optional, Dict, List, Callable, Any, Type

491

492

# Core framework types

493

ViewClass = Type['View']

494

ViewFunction = Callable[['Request'], Any]

495

ViewHandler = Union[ViewClass, ViewFunction]

496

MiddlewareHandler = Callable[['Request'], 'Request']

497

RoutePattern = Union[str, int] # int for MATCH_ALL constant

498

Settings = Union[object, Dict[str, Any]]

499

```