or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-programming-patterns.mdauthentication-and-credentials.mdconfiguration-and-settings.mddistributed-tracing-and-diagnostics.mderror-handling-and-exceptions.mdhttp-pipeline-and-policies.mdindex.mdpaging-and-result-iteration.mdpolling-and-long-running-operations.mdrest-api-abstraction.mdtransport-and-networking.mdutilities-and-helpers.md

paging-and-result-iteration.mddocs/

0

# Paging and Result Iteration

1

2

Azure Core provides comprehensive pagination support for handling large result sets from Azure services. The paging system supports both synchronous and asynchronous operations with automatic continuation token management, error recovery, and flexible iteration patterns.

3

4

## Core Components

5

6

### ItemPaged

7

8

Iterator for paging through individual items across multiple pages with lazy evaluation and continuation token support.

9

10

```python { .api }

11

from azure.core.paging import ItemPaged

12

from typing import Iterator, Optional, TypeVar, Callable, Tuple, Iterable, Any

13

14

ReturnType = TypeVar('ReturnType')

15

ResponseType = TypeVar('ResponseType')

16

17

class ItemPaged(Iterator[ReturnType]):

18

def __init__(

19

self,

20

get_next: Callable[[Optional[str]], ResponseType],

21

extract_data: Callable[[ResponseType], Tuple[str, Iterable[ReturnType]]],

22

continuation_token: Optional[str] = None,

23

*,

24

page_iterator_class: type = PageIterator

25

): ...

26

27

def by_page(self, continuation_token: Optional[str] = None) -> Iterator[Iterator[ReturnType]]: ...

28

29

def __iter__(self) -> Iterator[ReturnType]: ...

30

31

def __next__(self) -> ReturnType: ...

32

```

33

34

### PageIterator

35

36

Iterator for accessing results page by page with continuation token management and error recovery.

37

38

```python { .api }

39

from azure.core.paging import PageIterator

40

41

class PageIterator(Iterator[Iterator[ReturnType]]):

42

def __init__(

43

self,

44

get_next: Callable[[Optional[str]], ResponseType],

45

extract_data: Callable[[ResponseType], Tuple[str, Iterable[ReturnType]]],

46

continuation_token: Optional[str] = None,

47

): ...

48

49

def __iter__(self) -> Iterator[Iterator[ReturnType]]: ...

50

51

def __next__(self) -> Iterator[ReturnType]: ...

52

```

53

54

## Basic Usage

55

56

### Item-by-Item Iteration

57

58

```python

59

from azure.core.paging import ItemPaged

60

61

def get_next(continuation_token=None):

62

"""Fetch next page of results from service"""

63

if not continuation_token:

64

return {

65

"nextLink": "page2",

66

"value": ["item1", "item2", "item3"]

67

}

68

elif continuation_token == "page2":

69

return {

70

"nextLink": None,

71

"value": ["item4", "item5"]

72

}

73

return {"nextLink": None, "value": []}

74

75

def extract_data(response):

76

"""Extract continuation token and items from response"""

77

next_link = response.get("nextLink")

78

items = response.get("value", [])

79

return next_link, iter(items)

80

81

# Create pager and iterate over all items

82

pager = ItemPaged(get_next, extract_data)

83

84

# Iterate through all items across all pages

85

all_items = []

86

for item in pager:

87

all_items.append(item)

88

print(f"Got item: {item}")

89

90

# Result: ["item1", "item2", "item3", "item4", "item5"]

91

```

92

93

### Page-by-Page Iteration

94

95

```python

96

# Iterate page by page for more control

97

pager = ItemPaged(get_next, extract_data)

98

99

for page in pager.by_page():

100

page_items = list(page)

101

print(f"Page contains {len(page_items)} items: {page_items}")

102

103

# Process each item in the current page

104

for item in page_items:

105

process_item(item)

106

```

107

108

### Continuation Token Usage

109

110

```python

111

# Start from beginning

112

pager = ItemPaged(get_next, extract_data)

113

114

# Get some items and stop

115

items_so_far = []

116

page_iter = pager.by_page()

117

118

# Process first page

119

first_page = next(page_iter)

120

items_so_far.extend(list(first_page))

121

122

# Resume from a specific token later

123

token = "page2" # This would come from your service

124

resumed_pager = ItemPaged(get_next, extract_data).by_page(continuation_token=token)

125

126

for page in resumed_pager:

127

remaining_items = list(page)

128

items_so_far.extend(remaining_items)

129

```

130

131

## Async Support

132

133

### AsyncItemPaged

134

135

Asynchronous version of ItemPaged for use with async/await patterns.

136

137

```python { .api }

138

from azure.core.async_paging import AsyncItemPaged

139

from typing import AsyncIterator, Awaitable

140

141

class AsyncItemPaged(AsyncIterator[ReturnType]):

142

def __init__(

143

self,

144

get_next: Callable[[Optional[str]], Awaitable[ResponseType]],

145

extract_data: Callable[[ResponseType], Awaitable[Tuple[str, AsyncIterator[ReturnType]]]],

146

continuation_token: Optional[str] = None,

147

*,

148

page_iterator_class: type = AsyncPageIterator

149

): ...

150

151

def by_page(self, continuation_token: Optional[str] = None) -> AsyncIterator[AsyncIterator[ReturnType]]: ...

152

153

async def __anext__(self) -> ReturnType: ...

154

```

155

156

### AsyncPageIterator

157

158

Asynchronous page iterator with async continuation token handling.

159

160

```python { .api }

161

from azure.core.async_paging import AsyncPageIterator

162

163

class AsyncPageIterator(AsyncIterator[AsyncIterator[ReturnType]]):

164

def __init__(

165

self,

166

get_next: Callable[[Optional[str]], Awaitable[ResponseType]],

167

extract_data: Callable[[ResponseType], Awaitable[Tuple[str, AsyncIterator[ReturnType]]]],

168

continuation_token: Optional[str] = None,

169

): ...

170

171

async def __anext__(self) -> AsyncIterator[ReturnType]: ...

172

```

173

174

### Async Usage Examples

175

176

```python

177

import asyncio

178

from azure.core.async_paging import AsyncItemPaged, AsyncList

179

180

async def async_get_next(continuation_token=None):

181

"""Async version of get_next"""

182

await asyncio.sleep(0.1) # Simulate API call

183

if not continuation_token:

184

return {

185

"nextLink": "page2",

186

"value": ["async_item1", "async_item2"]

187

}

188

elif continuation_token == "page2":

189

return {

190

"nextLink": None,

191

"value": ["async_item3", "async_item4"]

192

}

193

return {"nextLink": None, "value": []}

194

195

async def async_extract_data(response):

196

"""Extract data for async iteration"""

197

next_link = response.get("nextLink")

198

items = response.get("value", [])

199

# Wrap sync iterable for async iteration

200

return next_link, AsyncList(items)

201

202

async def async_paging_example():

203

# Async item-by-item iteration

204

pager = AsyncItemPaged(async_get_next, async_extract_data)

205

206

async for item in pager:

207

print(f"Async item: {item}")

208

209

# Async page-by-page iteration

210

pager = AsyncItemPaged(async_get_next, async_extract_data)

211

212

async for page in pager.by_page():

213

async for item in page:

214

print(f"Page item: {item}")

215

216

# Run the async example

217

asyncio.run(async_paging_example())

218

```

219

220

## Real-World Service Integration

221

222

### Azure Service Client Pattern

223

224

```python

225

from azure.core.paging import ItemPaged

226

from azure.core import PipelineClient

227

228

class MyAzureServiceClient:

229

def __init__(self, endpoint: str, credential):

230

self._client = PipelineClient(base_url=endpoint, credential=credential)

231

232

def list_resources(self, **kwargs) -> ItemPaged[dict]:

233

"""List resources with automatic paging"""

234

235

def get_next(next_link=None):

236

if next_link:

237

# Use provided next link

238

request = HttpRequest("GET", next_link)

239

else:

240

# Build initial request

241

request = HttpRequest("GET", "/api/resources")

242

if kwargs.get('filter'):

243

request.url += f"?$filter={kwargs['filter']}"

244

245

# Execute request through pipeline

246

response = self._client.send_request(request)

247

response.raise_for_status()

248

return response.json()

249

250

def extract_data(response_data):

251

# Extract items and continuation token from response

252

items = response_data.get("value", [])

253

next_link = response_data.get("nextLink") or response_data.get("@odata.nextLink")

254

return next_link, iter(items)

255

256

return ItemPaged(get_next, extract_data)

257

258

# Usage

259

client = MyAzureServiceClient("https://api.service.azure.com", credential)

260

261

# Iterate over all resources across all pages

262

for resource in client.list_resources(filter="status eq 'active'"):

263

print(f"Resource: {resource['name']}")

264

265

# Or process page by page for better memory management

266

for page in client.list_resources().by_page():

267

resources = list(page)

268

print(f"Processing {len(resources)} resources in this page")

269

process_resource_batch(resources)

270

```

271

272

### Error Handling and Recovery

273

274

```python

275

from azure.core.exceptions import AzureError

276

277

def robust_paging_example():

278

pager = ItemPaged(get_next, extract_data)

279

page_iterator = pager.by_page()

280

281

processed_items = []

282

continuation_token = None

283

284

try:

285

for page in page_iterator:

286

# Process current page

287

page_items = list(page)

288

processed_items.extend(page_items)

289

290

# Save progress periodically

291

if len(processed_items) % 100 == 0:

292

save_progress(processed_items, continuation_token)

293

294

except AzureError as e:

295

print(f"Error occurred: {e}")

296

# The iterator preserves continuation token for recovery

297

if hasattr(page_iterator, 'continuation_token'):

298

print(f"Can resume from token: {page_iterator.continuation_token}")

299

# Resume processing later

300

resumed_pager = ItemPaged(get_next, extract_data).by_page(

301

continuation_token=page_iterator.continuation_token

302

)

303

```

304

305

## Advanced Features

306

307

### Custom Page Iterator

308

309

```python

310

class CustomPageIterator(PageIterator):

311

def __init__(self, *args, **kwargs):

312

super().__init__(*args, **kwargs)

313

self.pages_processed = 0

314

315

def __next__(self):

316

result = super().__next__()

317

self.pages_processed += 1

318

print(f"Processed {self.pages_processed} pages so far")

319

return result

320

321

# Use custom page iterator

322

pager = ItemPaged(

323

get_next,

324

extract_data,

325

page_iterator_class=CustomPageIterator

326

)

327

```

328

329

### Memory-Efficient Processing

330

331

```python

332

def process_large_dataset(pager: ItemPaged, batch_size: int = 100):

333

"""Process large datasets in batches to manage memory usage"""

334

batch = []

335

336

for item in pager:

337

batch.append(item)

338

339

if len(batch) >= batch_size:

340

# Process batch and clear memory

341

process_batch(batch)

342

batch.clear()

343

344

# Process remaining items

345

if batch:

346

process_batch(batch)

347

348

# Usage with a service that returns millions of items

349

large_pager = client.list_all_items()

350

process_large_dataset(large_pager, batch_size=1000)

351

```

352

353

## Key Features

354

355

**Lazy Evaluation**: Items and pages are fetched on-demand, minimizing memory usage for large datasets.

356

357

**Continuation Token Support**: Built-in support for resuming interrupted operations from any point.

358

359

**Error Recovery**: Errors preserve continuation state, allowing for robust error handling and recovery.

360

361

**Type Safety**: Full generic typing support with proper type hints for items and responses.

362

363

**Dual Interface**: Both item-by-item and page-by-page iteration patterns for different use cases.

364

365

**Sync/Async Parity**: Matching APIs for both synchronous and asynchronous operations.

366

367

**Flexible Construction**: Support for custom page iterator classes and extraction logic.

368

369

The paging system provides a robust, efficient way to handle large result sets from Azure services while maintaining simplicity for common use cases and flexibility for advanced scenarios.