or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-clients.mddirectory-client.mdfile-client.mdindex.mdlease-client.mdmodels.mdsas-generation.mdservice-client.mdshare-client.md

lease-client.mddocs/

0

# ShareLeaseClient - Lease Management

1

2

The ShareLeaseClient provides lease management operations for files and shares, enabling exclusive access control through lease acquisition, renewal, release, and breaking operations.

3

4

## Import and Initialization

5

6

```python { .api }

7

from azure.storage.fileshare import ShareLeaseClient, ShareClient, ShareFileClient

8

from typing import Union, Any, Optional

9

```

10

11

## Constructor

12

13

```python { .api }

14

class ShareLeaseClient:

15

def __init__(

16

self,

17

client: Union[ShareClient, ShareFileClient],

18

lease_id: Optional[str] = None

19

) -> None:

20

"""

21

Create a ShareLeaseClient for managing leases.

22

23

Parameters:

24

client: ShareClient or ShareFileClient to manage leases for

25

lease_id: Optional existing lease ID (UUID format)

26

"""

27

```

28

29

## Lease Operations

30

31

```python { .api }

32

def acquire(

33

self,

34

**kwargs: Any

35

) -> None:

36

"""

37

Requests a new lease for the file or share.

38

39

Parameters:

40

lease_duration: Duration of the lease in seconds (-1 for infinite, default: -1)

41

timeout: Request timeout in seconds

42

43

Note:

44

- For files: lease_duration can be 15-60 seconds or -1 for infinite

45

- For shares: lease_duration is always infinite (-1)

46

- After acquisition, the lease_id property will contain the lease ID

47

"""

48

49

def renew(

50

self,

51

**kwargs: Any

52

) -> None:

53

"""

54

Renews the lease for the file or share.

55

56

Parameters:

57

timeout: Request timeout in seconds

58

59

Note:

60

- Lease must be in 'leased' state to be renewed

61

- Extends the lease for the same duration as originally acquired

62

"""

63

64

def release(

65

self,

66

**kwargs: Any

67

) -> None:

68

"""

69

Releases the lease for the file or share.

70

71

Parameters:

72

timeout: Request timeout in seconds

73

74

Note:

75

- Makes the file/share available for other operations immediately

76

- Lease cannot be renewed after release

77

"""

78

79

def change(

80

self,

81

proposed_lease_id: str,

82

**kwargs: Any

83

) -> None:

84

"""

85

Changes the lease ID of an active lease.

86

87

Parameters:

88

proposed_lease_id: New lease ID (UUID format)

89

timeout: Request timeout in seconds

90

91

Note:

92

- Lease must be in 'leased' state to change ID

93

- Updates the lease_id property to the new ID

94

"""

95

96

def break_lease(

97

self,

98

**kwargs: Any

99

) -> int:

100

"""

101

Breaks the lease, if the file or share has an active lease.

102

103

Parameters:

104

lease_break_period: Time to wait before lease is broken (0-60 seconds)

105

timeout: Request timeout in seconds

106

107

Returns:

108

int: Time remaining until lease is broken (seconds)

109

110

Note:

111

- If lease_break_period is not specified, lease breaks immediately

112

- Returns 0 if lease is broken immediately

113

"""

114

```

115

116

## Properties

117

118

```python { .api }

119

@property

120

def id(self) -> str:

121

"""

122

The lease ID for the lease.

123

124

Returns:

125

str: UUID string representing the lease ID

126

"""

127

128

@property

129

def etag(self) -> Optional[str]:

130

"""

131

The ETag of the lease.

132

133

Returns:

134

Optional[str]: ETag from the last lease operation

135

"""

136

137

@property

138

def last_modified(self) -> Optional[datetime]:

139

"""

140

The last modified timestamp of the lease.

141

142

Returns:

143

Optional[datetime]: Last modified time from the last lease operation

144

"""

145

```

146

147

## Context Manager Support

148

149

```python { .api }

150

def __enter__(self) -> ShareLeaseClient:

151

"""

152

Enter context manager and acquire lease.

153

154

Returns:

155

ShareLeaseClient: Self for use in with statement

156

"""

157

158

def __exit__(self, exc_type, exc_val, exc_tb) -> None:

159

"""

160

Exit context manager and release lease.

161

162

Parameters:

163

exc_type: Exception type if exception occurred

164

exc_val: Exception value if exception occurred

165

exc_tb: Exception traceback if exception occurred

166

"""

167

```

168

169

## Usage Examples

170

171

### Basic Lease Operations

172

173

```python { .api }

174

from azure.storage.fileshare import ShareFileClient, ShareLeaseClient

175

from azure.core.credentials import AzureNamedKeyCredential

176

import uuid

177

178

# Initialize file client

179

credential = AzureNamedKeyCredential("myaccount", "mykey")

180

file_client = ShareFileClient(

181

account_url="https://myaccount.file.core.windows.net",

182

share_name="documents",

183

file_path="important_file.txt",

184

credential=credential

185

)

186

187

# Acquire lease with specific ID

188

lease_id = str(uuid.uuid4())

189

lease_client = ShareLeaseClient(file_client, lease_id=lease_id)

190

lease_client.acquire(lease_duration=60) # 60-second lease

191

print(f"Lease acquired: {lease_client.id}")

192

193

# Perform operations with lease

194

try:

195

# File operations now require lease_id

196

file_client.set_file_metadata(

197

{"locked": "true", "locked_by": "process_123"},

198

lease_id=lease_client.id

199

)

200

201

# Upload new content with lease protection

202

file_client.upload_file(

203

data=b"Updated content under lease",

204

overwrite=True,

205

lease_id=lease_client.id

206

)

207

208

finally:

209

# Always release the lease

210

lease_client.release()

211

print("Lease released")

212

```

213

214

### Lease Management with Context Manager

215

216

```python { .api }

217

# Automatic lease management using context manager

218

with ShareLeaseClient(file_client) as lease:

219

print(f"Lease automatically acquired: {lease.id}")

220

221

# Perform protected operations

222

file_client.upload_file(

223

data=b"Content updated with automatic lease management",

224

overwrite=True,

225

lease_id=lease.id

226

)

227

228

properties = file_client.get_file_properties()

229

print(f"File size: {properties.size} bytes")

230

231

# Lease is automatically released when exiting context

232

print("Lease automatically released")

233

```

234

235

### Share-Level Lease Management

236

237

```python { .api }

238

from azure.storage.fileshare import ShareClient

239

240

# Initialize share client

241

share_client = ShareClient(

242

account_url="https://myaccount.file.core.windows.net",

243

share_name="protected-share",

244

credential=credential

245

)

246

247

# Acquire infinite lease on share

248

share_lease = ShareLeaseClient(share_client)

249

share_lease.acquire() # Share leases are always infinite

250

print(f"Share lease acquired: {share_lease.id}")

251

252

try:

253

# Share operations require lease_id

254

share_client.set_share_metadata(

255

{"maintenance_mode": "true", "locked_by": "admin"},

256

lease_id=share_lease.id

257

)

258

259

# Create directory with share lease

260

directory_client = share_client.create_directory(

261

"maintenance",

262

lease_id=share_lease.id

263

)

264

265

finally:

266

share_lease.release()

267

print("Share lease released")

268

```

269

270

### Lease Renewal and Extension

271

272

```python { .api }

273

import time

274

275

# Acquire short-term lease

276

lease_client = ShareLeaseClient(file_client)

277

lease_client.acquire(lease_duration=30) # 30-second lease

278

print(f"Initial lease acquired: {lease_client.id}")

279

280

# Simulate long-running operation with lease renewal

281

for i in range(5):

282

# Perform some work

283

print(f"Processing step {i+1}...")

284

time.sleep(10)

285

286

# Renew lease before it expires

287

try:

288

lease_client.renew()

289

print("Lease renewed successfully")

290

except Exception as e:

291

print(f"Failed to renew lease: {e}")

292

break

293

294

lease_client.release()

295

```

296

297

### Lease ID Management and Change

298

299

```python { .api }

300

import uuid

301

302

# Start with specific lease ID

303

original_lease_id = str(uuid.uuid4())

304

lease_client = ShareLeaseClient(file_client, lease_id=original_lease_id)

305

lease_client.acquire(lease_duration=-1) # Infinite lease

306

print(f"Original lease ID: {lease_client.id}")

307

308

# Change lease ID (useful for transferring lease ownership)

309

new_lease_id = str(uuid.uuid4())

310

lease_client.change(proposed_lease_id=new_lease_id)

311

print(f"Changed lease ID to: {lease_client.id}")

312

313

# Verify the change worked

314

assert lease_client.id == new_lease_id

315

print("Lease ID change confirmed")

316

317

# Operations now use new lease ID

318

file_client.set_file_metadata(

319

{"lease_changed": "true"},

320

lease_id=lease_client.id

321

)

322

323

lease_client.release()

324

```

325

326

### Lease Breaking and Recovery

327

328

```python { .api }

329

# Scenario: Another process needs to break an existing lease

330

lease_client = ShareLeaseClient(file_client)

331

lease_client.acquire(lease_duration=-1) # Infinite lease

332

print(f"Lease acquired: {lease_client.id}")

333

334

# Simulate another process that needs to break the lease

335

breaker_lease = ShareLeaseClient(file_client)

336

337

# Break the lease with 30-second break period

338

remaining_time = breaker_lease.break_lease(lease_break_period=30)

339

print(f"Lease break initiated, {remaining_time} seconds remaining")

340

341

# Original lease operations will now fail

342

try:

343

file_client.upload_file(

344

data=b"This will fail",

345

lease_id=lease_client.id

346

)

347

except Exception as e:

348

print(f"Operation failed as expected: {e}")

349

350

# Wait for lease to be broken or break immediately

351

if remaining_time > 0:

352

print("Waiting for lease to break naturally...")

353

time.sleep(remaining_time + 1)

354

else:

355

print("Lease broken immediately")

356

357

# Now operations work without lease

358

file_client.upload_file(data=b"This works after lease break", overwrite=True)

359

print("Operation successful after lease break")

360

```

361

362

### Error Handling and Lease States

363

364

```python { .api }

365

from azure.core.exceptions import HttpResponseError

366

367

def safe_lease_operations(file_client):

368

"""Demonstrate safe lease handling with error recovery."""

369

lease_client = ShareLeaseClient(file_client)

370

371

try:

372

# Attempt to acquire lease

373

lease_client.acquire(lease_duration=60)

374

print(f"Lease acquired successfully: {lease_client.id}")

375

376

# Perform operations

377

return perform_lease_operations(file_client, lease_client)

378

379

except HttpResponseError as e:

380

if e.error_code == "LeaseAlreadyPresent":

381

print("File is already leased by another client")

382

# Try to break existing lease

383

existing_lease = ShareLeaseClient(file_client)

384

existing_lease.break_lease(lease_break_period=0) # Break immediately

385

print("Broke existing lease, retrying...")

386

387

# Retry acquisition

388

lease_client.acquire(lease_duration=60)

389

return perform_lease_operations(file_client, lease_client)

390

else:

391

print(f"Lease operation failed: {e.message}")

392

raise

393

394

except Exception as e:

395

print(f"Unexpected error: {e}")

396

raise

397

398

finally:

399

# Ensure lease is released

400

try:

401

lease_client.release()

402

print("Lease released in cleanup")

403

except:

404

pass # Ignore release errors in cleanup

405

406

def perform_lease_operations(file_client, lease_client):

407

"""Perform file operations under lease protection."""

408

try:

409

# Update file metadata

410

file_client.set_file_metadata(

411

{"processing": "true", "start_time": time.time()},

412

lease_id=lease_client.id

413

)

414

415

# Simulate processing

416

print("Performing protected operations...")

417

time.sleep(2)

418

419

# Update content

420

file_client.upload_file(

421

data=b"Processed content",

422

overwrite=True,

423

lease_id=lease_client.id

424

)

425

426

# Final metadata update

427

file_client.set_file_metadata(

428

{"processing": "complete", "end_time": time.time()},

429

lease_id=lease_client.id

430

)

431

432

return True

433

434

except HttpResponseError as e:

435

if e.error_code in ["LeaseIdMissing", "LeaseIdMismatch", "LeaseNotPresent"]:

436

print("Lease was lost during operation")

437

return False

438

raise

439

440

# Use the safe lease operations

441

success = safe_lease_operations(file_client)

442

print(f"Operation completed successfully: {success}")

443

```

444

445

### Concurrent Access Control

446

447

```python { .api }

448

import threading

449

import time

450

451

def worker_with_lease(worker_id, file_client, work_duration=5):

452

"""Worker function that tries to acquire lease and perform work."""

453

print(f"Worker {worker_id}: Starting")

454

455

lease_client = ShareLeaseClient(file_client)

456

457

try:

458

# Try to acquire lease

459

lease_client.acquire(lease_duration=work_duration + 5) # Extra buffer

460

print(f"Worker {worker_id}: Lease acquired {lease_client.id}")

461

462

# Perform exclusive work

463

for i in range(work_duration):

464

print(f"Worker {worker_id}: Working... step {i+1}")

465

466

# Update file to show work progress

467

file_client.set_file_metadata(

468

{

469

"worker": str(worker_id),

470

"step": str(i+1),

471

"timestamp": str(time.time())

472

},

473

lease_id=lease_client.id

474

)

475

476

time.sleep(1)

477

478

print(f"Worker {worker_id}: Work completed")

479

480

except HttpResponseError as e:

481

if e.error_code == "LeaseAlreadyPresent":

482

print(f"Worker {worker_id}: File is locked by another worker")

483

else:

484

print(f"Worker {worker_id}: Error - {e.message}")

485

486

except Exception as e:

487

print(f"Worker {worker_id}: Unexpected error - {e}")

488

489

finally:

490

try:

491

lease_client.release()

492

print(f"Worker {worker_id}: Lease released")

493

except:

494

pass

495

496

# Start multiple workers (only one will get the lease)

497

threads = []

498

for i in range(3):

499

thread = threading.Thread(target=worker_with_lease, args=(i, file_client))

500

threads.append(thread)

501

thread.start()

502

503

# Wait for all workers to complete

504

for thread in threads:

505

thread.join()

506

507

print("All workers finished")

508

```

509

510

### Lease Monitoring and Diagnostics

511

512

```python { .api }

513

def monitor_lease_status(file_client, lease_client):

514

"""Monitor and report lease status."""

515

properties = file_client.get_file_properties()

516

lease_props = properties.lease

517

518

print(f"Lease Status Report:")

519

print(f" Status: {lease_props.status}") # locked/unlocked

520

print(f" State: {lease_props.state}") # available/leased/expired/breaking/broken

521

print(f" Duration: {lease_props.duration}") # infinite/fixed

522

523

if lease_props.state == "leased":

524

print(f" Current lease ID: {lease_client.id}")

525

print(f" Lease ETag: {lease_client.etag}")

526

print(f" Last modified: {lease_client.last_modified}")

527

528

return lease_props.state

529

530

# Demonstrate lease monitoring

531

lease_client = ShareLeaseClient(file_client)

532

533

# Before lease

534

print("Before acquiring lease:")

535

monitor_lease_status(file_client, lease_client)

536

537

# Acquire lease

538

lease_client.acquire(lease_duration=60)

539

print("\nAfter acquiring lease:")

540

state = monitor_lease_status(file_client, lease_client)

541

542

# Renew lease

543

if state == "leased":

544

lease_client.renew()

545

print("\nAfter renewing lease:")

546

monitor_lease_status(file_client, lease_client)

547

548

# Release lease

549

lease_client.release()

550

print("\nAfter releasing lease:")

551

monitor_lease_status(file_client, lease_client)

552

```

553

554

The ShareLeaseClient provides robust lease management capabilities for controlling exclusive access to files and shares, ensuring data consistency and preventing concurrent modification conflicts in multi-client scenarios.