or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

buffer-management.mdcommand-line.mdconfiguration.mderror-handling.mdhttp-processing.mdindex.mdproxy-headers.mdserver-management.mdtask-management.md

buffer-management.mddocs/

0

# Buffer Management

1

2

Efficient memory and file-based buffer system for handling request and response data with automatic overflow management and streaming capabilities.

3

4

## Capabilities

5

6

### Buffer Base Class

7

8

Foundation class for all buffer implementations providing common interface and operations.

9

10

```python { .api }

11

class FileBasedBuffer:

12

"""

13

Base class for file-like buffer implementations.

14

15

Provides common buffering operations with support for reading,

16

writing, seeking, and efficient data management across different

17

storage backends (memory, temporary files).

18

"""

19

20

remain: int = 0 # Number of bytes remaining to be read

21

22

def __init__(self, file, from_buffer=None):

23

"""

24

Initialize buffer with file-like object.

25

26

Parameters:

27

- file: File-like object for data storage

28

- from_buffer: Optional existing buffer to copy data from

29

"""

30

31

def __len__(self):

32

"""

33

Get number of bytes remaining in buffer.

34

35

Returns:

36

int: Number of unread bytes

37

"""

38

39

def __bool__(self):

40

"""

41

Check if buffer exists (always True for FileBasedBuffer).

42

43

Returns:

44

bool: Always True

45

"""

46

47

def append(self, s):

48

"""

49

Append data to buffer.

50

51

Parameters:

52

- s (bytes): Data to append to buffer

53

54

Notes:

55

- Maintains current read position

56

- Updates remaining byte count

57

"""

58

59

def get(self, numbytes=-1, skip=False):

60

"""

61

Read data from buffer.

62

63

Parameters:

64

- numbytes (int): Number of bytes to read (-1 for all)

65

- skip (bool): Whether to advance read position

66

67

Returns:

68

bytes: Read data

69

70

Notes:

71

- If skip=False, read position unchanged

72

- If skip=True, data is consumed from buffer

73

"""

74

75

def skip(self, numbytes, allow_prune=0):

76

"""

77

Skip bytes in buffer without reading.

78

79

Parameters:

80

- numbytes (int): Number of bytes to skip

81

- allow_prune (int): Unused parameter for compatibility

82

83

Raises:

84

ValueError: If trying to skip more bytes than available

85

"""

86

87

def newfile(self):

88

"""

89

Create new file-like object for buffer.

90

91

Returns:

92

File-like object

93

94

Notes:

95

- Must be implemented by subclasses

96

- Used during buffer pruning operations

97

"""

98

99

def prune(self):

100

"""

101

Remove consumed data to free memory/disk space.

102

103

Creates new file with only unread data, discarding

104

data that has already been consumed.

105

"""

106

107

def getfile(self):

108

"""

109

Get underlying file-like object.

110

111

Returns:

112

File-like object used for storage

113

"""

114

115

def close(self):

116

"""

117

Close buffer and release resources.

118

119

Closes underlying file if it has a close method

120

and resets remaining byte count to zero.

121

"""

122

```

123

124

### Memory-Based Buffer

125

126

In-memory buffer implementation using BytesIO for small to medium sized data.

127

128

```python { .api }

129

class BytesIOBasedBuffer(FileBasedBuffer):

130

"""

131

Memory-based buffer using BytesIO for storage.

132

133

Efficient for small to medium sized data that fits

134

comfortably in memory. Faster than file-based alternatives

135

but limited by available RAM.

136

"""

137

138

def __init__(self, from_buffer=None):

139

"""

140

Initialize memory-based buffer.

141

142

Parameters:

143

- from_buffer: Optional existing buffer to copy data from

144

145

Notes:

146

- Uses BytesIO for in-memory storage

147

- No file system involvement

148

"""

149

150

def newfile(self):

151

"""

152

Create new BytesIO object.

153

154

Returns:

155

BytesIO: New in-memory file-like object

156

"""

157

```

158

159

### Temporary File Buffer

160

161

File-based buffer using temporary files for large data that exceeds memory limits.

162

163

```python { .api }

164

class TempfileBasedBuffer(FileBasedBuffer):

165

"""

166

File-based buffer using temporary files for storage.

167

168

Automatically handles large data by storing it in temporary

169

files, providing unlimited capacity limited only by disk space.

170

Files are automatically cleaned up when buffer is closed.

171

"""

172

173

def __init__(self, from_buffer=None):

174

"""

175

Initialize temporary file-based buffer.

176

177

Parameters:

178

- from_buffer: Optional existing buffer to copy data from

179

180

Notes:

181

- Creates temporary file for storage

182

- File is automatically deleted when closed

183

"""

184

185

def newfile(self):

186

"""

187

Create new temporary file.

188

189

Returns:

190

TemporaryFile: New temporary file object

191

192

Notes:

193

- File created in binary mode ("w+b")

194

- Automatically deleted when closed

195

"""

196

```

197

198

### Read-Only File Buffer

199

200

Specialized buffer for serving static files efficiently with WSGI file_wrapper support.

201

202

```python { .api }

203

class ReadOnlyFileBasedBuffer(FileBasedBuffer):

204

"""

205

Read-only buffer for serving existing files efficiently.

206

207

Optimized for serving static files as WSGI responses with

208

support for range requests and efficient streaming. Used

209

as wsgi.file_wrapper for optimal file serving performance.

210

"""

211

212

def __init__(self, file, block_size=32768):

213

"""

214

Initialize read-only file buffer.

215

216

Parameters:

217

- file: File-like object to read from

218

- block_size (int): Block size for iteration (default: 32KB)

219

220

Notes:

221

- File must be opened in binary read mode

222

- Supports seekable and non-seekable files

223

"""

224

225

block_size: int # Block size for iteration

226

seekable: callable # Seekable check function (if available)

227

228

def __iter__(self):

229

"""

230

Iterate over file contents in blocks.

231

232

Yields:

233

bytes: File data in block_size chunks

234

235

Notes:

236

- Efficient for WSGI response streaming

237

- Automatically handles file positioning

238

"""

239

240

def __next__(self):

241

"""

242

Get next block of file data.

243

244

Returns:

245

bytes: Next block of data

246

247

Raises:

248

StopIteration: When end of file reached

249

"""

250

251

def close(self):

252

"""

253

Close the underlying file.

254

255

Notes:

256

- Only closes if file has close method

257

- Safe to call multiple times

258

"""

259

```

260

261

### Overflowable Buffer

262

263

Advanced buffer that automatically switches between memory and file storage based on size.

264

265

```python { .api }

266

class OverflowableBuffer:

267

"""

268

Buffer that overflows from memory to temporary files.

269

270

Starts with in-memory storage for efficiency and automatically

271

switches to temporary file storage when data exceeds the

272

configured overflow threshold.

273

"""

274

275

def __init__(self, overflow_threshold):

276

"""

277

Initialize overflowable buffer.

278

279

Parameters:

280

- overflow_threshold (int): Byte limit before switching to file

281

282

Notes:

283

- Starts with BytesIOBasedBuffer

284

- Switches to TempfileBasedBuffer when threshold exceeded

285

"""

286

287

def append(self, data):

288

"""

289

Append data with automatic overflow handling.

290

291

Parameters:

292

- data (bytes): Data to append

293

294

Notes:

295

- Automatically switches to file storage if needed

296

- Transparent to caller after overflow

297

"""

298

299

def get(self, numbytes=-1, skip=False):

300

"""

301

Read data from buffer (delegates to underlying buffer).

302

303

Parameters:

304

- numbytes (int): Number of bytes to read

305

- skip (bool): Whether to consume data

306

307

Returns:

308

bytes: Read data

309

"""

310

311

def __len__(self):

312

"""Get number of bytes in buffer."""

313

314

def close(self):

315

"""Close buffer and clean up resources."""

316

```

317

318

### Buffer Constants

319

320

Important constants controlling buffer behavior and performance characteristics.

321

322

```python { .api }

323

# Buffer copy operations

324

COPY_BYTES: int = 262144 # 256KB - chunk size for copying data between buffers

325

326

# String buffer limits

327

STRBUF_LIMIT: int = 8192 # 8KB - maximum size for simple string buffers

328

```

329

330

### Buffer Usage Examples

331

332

Common patterns for working with waitress buffer system.

333

334

#### Basic Buffer Operations

335

336

```python

337

from waitress.buffers import BytesIOBasedBuffer, TempfileBasedBuffer

338

339

# Memory-based buffer for small data

340

memory_buffer = BytesIOBasedBuffer()

341

memory_buffer.append(b"Hello, ")

342

memory_buffer.append(b"World!")

343

344

# Read data without consuming

345

data = memory_buffer.get()

346

print(data) # b"Hello, World!"

347

print(len(memory_buffer)) # 13

348

349

# Read and consume data

350

consumed = memory_buffer.get(5, skip=True)

351

print(consumed) # b"Hello"

352

print(len(memory_buffer)) # 8

353

354

# File-based buffer for large data

355

file_buffer = TempfileBasedBuffer()

356

large_data = b"x" * 1000000 # 1MB of data

357

file_buffer.append(large_data)

358

print(len(file_buffer)) # 1000000

359

```

360

361

#### Overflowable Buffer Usage

362

363

```python

364

from waitress.buffers import OverflowableBuffer

365

366

# Buffer that overflows at 64KB

367

buffer = OverflowableBuffer(65536)

368

369

# Add small amounts of data (stays in memory)

370

for i in range(1000):

371

buffer.append(f"Line {i}\n".encode())

372

373

# Add large amount that triggers overflow to file

374

large_chunk = b"x" * 100000

375

buffer.append(large_chunk) # Now using temporary file

376

377

# Usage is transparent after overflow

378

data = buffer.get(1000)

379

print(len(data)) # 1000 bytes

380

```

381

382

#### File Serving with ReadOnlyFileBuffer

383

384

```python

385

from waitress.buffers import ReadOnlyFileBasedBuffer

386

387

def serve_file_app(environ, start_response):

388

"""WSGI app that serves files efficiently."""

389

390

file_path = "/path/to/large/file.dat"

391

392

try:

393

with open(file_path, 'rb') as f:

394

# Create read-only buffer for efficient serving

395

file_buffer = ReadOnlyFileBasedBuffer(f, block_size=65536)

396

397

status = '200 OK'

398

headers = [

399

('Content-Type', 'application/octet-stream'),

400

('Content-Length', str(os.path.getsize(file_path)))

401

]

402

start_response(status, headers)

403

404

# Return buffer for efficient streaming

405

return file_buffer

406

407

except FileNotFoundError:

408

status = '404 Not Found'

409

headers = [('Content-Type', 'text/plain')]

410

start_response(status, headers)

411

return [b'File not found']

412

413

# The WSGI server will iterate over the buffer efficiently

414

```

415

416

#### Buffer Copying and Management

417

418

```python

419

from waitress.buffers import BytesIOBasedBuffer, TempfileBasedBuffer

420

421

# Create source buffer with data

422

source = BytesIOBasedBuffer()

423

source.append(b"Important data that needs to be copied")

424

425

# Create destination buffer from source

426

destination = TempfileBasedBuffer(from_buffer=source)

427

428

# Both buffers now contain the same data but are independent

429

source_data = source.get()

430

dest_data = destination.get()

431

assert source_data == dest_data

432

433

# Modifications to one don't affect the other

434

source.append(b" - modified")

435

assert source.get() != destination.get()

436

437

# Clean up

438

source.close()

439

destination.close()

440

```

441

442

### Performance Considerations

443

444

Guidelines for optimal buffer usage in different scenarios.

445

446

```python

447

# Buffer selection guidelines:

448

SMALL_DATA = "Use BytesIOBasedBuffer (< 8KB)" # Fastest, in-memory

449

MEDIUM_DATA = "Use OverflowableBuffer (8KB-1MB)" # Adaptive

450

LARGE_DATA = "Use TempfileBasedBuffer (> 1MB)" # File-based

451

STATIC_FILES = "Use ReadOnlyFileBasedBuffer" # Optimized serving

452

453

# Memory usage patterns:

454

MEMORY_EFFICIENT = "Use file-based buffers for large data"

455

SPEED_OPTIMIZED = "Use memory buffers for frequently accessed data"

456

BALANCED = "Use OverflowableBuffer for variable-size data"

457

458

# Buffer lifecycle:

459

CLEANUP_IMPORTANT = "Always call close() on file-based buffers"

460

TEMPORARY_FILES = "Automatically cleaned up when closed"

461

MEMORY_BUFFERS = "Cleaned up by garbage collector"

462

```

463

464

### Integration with HTTP Processing

465

466

How buffers integrate with waitress HTTP processing pipeline.

467

468

```python

469

# Request body buffering:

470

REQUEST_SMALL = "Stored in BytesIOBasedBuffer initially"

471

REQUEST_LARGE = "Overflows to TempfileBasedBuffer automatically"

472

REQUEST_STREAMING = "Processed incrementally as data arrives"

473

474

# Response buffering:

475

RESPONSE_HEADERS = "Buffered in memory for efficiency"

476

RESPONSE_BODY = "Uses appropriate buffer based on size"

477

RESPONSE_FILES = "Uses ReadOnlyFileBasedBuffer for static files"

478

479

# Connection management:

480

KEEP_ALIVE = "Buffers reused across requests on same connection"

481

PIPELINING = "Multiple request buffers managed per connection"

482

CLEANUP = "Buffers automatically cleaned up on connection close"

483

```