or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

auth-service.mdcompute-service.mdcore-framework.mdflows-service.mdgcs-service.mdgroups-service.mdindex.mdsearch-service.mdtimers-service.mdtransfer-service.md

core-framework.mddocs/

0

# Core Framework

1

2

Foundation classes for authorization, HTTP clients, response handling, scope management, and error handling that provide consistent patterns across all Globus services. The core framework establishes the fundamental patterns and infrastructure used throughout the Globus SDK for reliable service integration.

3

4

## Capabilities

5

6

### Base Client Architecture

7

8

Foundation client class providing consistent HTTP operations, authentication, and response handling across all Globus services.

9

10

```python { .api }

11

class BaseClient:

12

"""

13

Abstract base class for all Globus API clients.

14

15

Provides consistent HTTP operations, authentication handling, error processing,

16

and response wrapping across all Globus service clients with standardized

17

initialization patterns and request/response lifecycle management.

18

"""

19

20

def __init__(

21

self,

22

*,

23

app: GlobusApp | None = None,

24

app_scopes: list[Scope] | None = None,

25

authorizer: GlobusAuthorizer | None = None,

26

app_name: str | None = None,

27

base_url: str | None = None,

28

environment: str | None = None,

29

transport_params: dict[str, Any] | None = None

30

) -> None: ...

31

32

@property

33

def default_scope_requirements(self) -> list[Scope]:

34

"""

35

Default scopes required for client operations.

36

37

Returns the scopes that will automatically be added to the

38

client's app scope requirements during initialization.

39

"""

40

41

@property

42

def resource_server(self) -> str | None:

43

"""

44

Resource server identifier for this client.

45

46

Returns the resource server name associated with this client's

47

scopes and authentication requirements.

48

"""

49

50

@property

51

def app_name(self) -> str | None:

52

"""Application name for User-Agent headers."""

53

54

def attach_globus_app(

55

self,

56

app: GlobusApp,

57

app_scopes: list[Scope] | None = None

58

) -> None:

59

"""

60

Attach a GlobusApp to this client.

61

62

Registers the client with the app and adds scope requirements

63

for automatic authentication and token management.

64

65

Parameters:

66

- app: GlobusApp instance to attach

67

- app_scopes: Optional custom scopes instead of defaults

68

"""

69

70

def add_app_scope(

71

self,

72

scope_collection: ScopeCollectionType

73

) -> BaseClient:

74

"""

75

Add additional scopes to the client's app requirements.

76

77

Extends the scope requirements beyond default scopes for

78

accessing additional resources or permissions.

79

80

Parameters:

81

- scope_collection: Scopes to add to requirements

82

83

Returns:

84

Self for method chaining

85

"""

86

87

def get(

88

self,

89

path: str,

90

*,

91

query_params: dict[str, Any] | None = None,

92

headers: dict[str, str] | None = None,

93

automatic_authorization: bool = True

94

) -> GlobusHTTPResponse:

95

"""

96

Make a GET request to the specified path.

97

98

Parameters:

99

- path: Request path (relative to base_url)

100

- query_params: URL query parameters

101

- headers: Additional HTTP headers

102

- automatic_authorization: Use client's authorizer

103

104

Returns:

105

GlobusHTTPResponse with response data and metadata

106

"""

107

108

def post(

109

self,

110

path: str,

111

*,

112

query_params: dict[str, Any] | None = None,

113

data: Any = None,

114

headers: dict[str, str] | None = None,

115

encoding: str | None = None,

116

automatic_authorization: bool = True

117

) -> GlobusHTTPResponse:

118

"""

119

Make a POST request to the specified path.

120

121

Parameters:

122

- path: Request path

123

- query_params: URL query parameters

124

- data: Request body data

125

- headers: Additional headers

126

- encoding: Data encoding (json, form, text)

127

- automatic_authorization: Use client's authorizer

128

129

Returns:

130

GlobusHTTPResponse with response data

131

"""

132

133

def put(

134

self,

135

path: str,

136

*,

137

query_params: dict[str, Any] | None = None,

138

data: Any = None,

139

headers: dict[str, str] | None = None,

140

encoding: str | None = None,

141

automatic_authorization: bool = True

142

) -> GlobusHTTPResponse:

143

"""Make a PUT request to the specified path."""

144

145

def patch(

146

self,

147

path: str,

148

*,

149

query_params: dict[str, Any] | None = None,

150

data: Any = None,

151

headers: dict[str, str] | None = None,

152

encoding: str | None = None,

153

automatic_authorization: bool = True

154

) -> GlobusHTTPResponse:

155

"""Make a PATCH request to the specified path."""

156

157

def delete(

158

self,

159

path: str,

160

*,

161

query_params: dict[str, Any] | None = None,

162

headers: dict[str, str] | None = None,

163

automatic_authorization: bool = True

164

) -> GlobusHTTPResponse:

165

"""Make a DELETE request to the specified path."""

166

167

def request(

168

self,

169

method: str,

170

path: str,

171

*,

172

query_params: dict[str, Any] | None = None,

173

data: Any = None,

174

headers: dict[str, str] | None = None,

175

encoding: str | None = None,

176

allow_redirects: bool = True,

177

stream: bool = False,

178

automatic_authorization: bool = True

179

) -> GlobusHTTPResponse:

180

"""

181

Send an HTTP request with full parameter control.

182

183

Provides complete control over HTTP request parameters with

184

consistent error handling and response processing.

185

186

Parameters:

187

- method: HTTP method (GET, POST, PUT, PATCH, DELETE)

188

- path: Request path

189

- query_params: URL query parameters

190

- data: Request body data

191

- headers: HTTP headers

192

- encoding: Data encoding method

193

- allow_redirects: Follow redirects automatically

194

- stream: Stream response without immediate download

195

- automatic_authorization: Use client authentication

196

197

Returns:

198

GlobusHTTPResponse wrapping the response

199

200

Raises:

201

GlobusAPIError for 4xx/5xx HTTP status codes

202

"""

203

```

204

205

### Authorization Framework

206

207

Comprehensive authorization system supporting multiple authentication flows and token management patterns with consistent interfaces.

208

209

```python { .api }

210

class GlobusAuthorizer(metaclass=ABCMeta):

211

"""

212

Abstract base class for all authorization handlers.

213

214

Defines the interface for generating Authorization headers and

215

handling authorization failures with consistent patterns across

216

different authentication methods.

217

"""

218

219

@abstractmethod

220

def get_authorization_header(self) -> str | None:

221

"""

222

Generate Authorization header value.

223

224

Returns the complete Authorization header value to be included

225

in HTTP requests, or None if no authorization should be used.

226

227

Returns:

228

Authorization header string or None

229

"""

230

231

def handle_missing_authorization(self) -> bool:

232

"""

233

Handle 401 Unauthorized responses.

234

235

Called when a request returns 401 status to allow the authorizer

236

to attempt recovery (e.g., token refresh). Returns True if the

237

authorizer believes it has fixed the issue.

238

239

Returns:

240

True if authorization was updated, False otherwise

241

"""

242

243

class AccessTokenAuthorizer(StaticGlobusAuthorizer):

244

"""

245

Authorization using a single access token.

246

247

Provides Bearer token authorization for requests using a static

248

access token without refresh capabilities.

249

"""

250

251

def __init__(self, access_token: str) -> None: ...

252

253

@property

254

def access_token(self) -> str:

255

"""The access token used for authorization."""

256

257

@property

258

def access_token_hash(self) -> str:

259

"""SHA256 hash of the access token for logging."""

260

261

class RefreshTokenAuthorizer(GlobusAuthorizer):

262

"""

263

Authorization using refresh tokens for automatic token renewal.

264

265

Automatically refreshes access tokens when they expire using

266

stored refresh tokens with configurable retry and caching.

267

"""

268

269

def __init__(

270

self,

271

refresh_token: str,

272

auth_client: AuthClient,

273

access_token: str | None = None,

274

expires_at: int | None = None,

275

on_refresh: Callable[[OAuthTokenResponse], None] | None = None

276

) -> None: ...

277

278

def ensure_valid_token(self) -> str:

279

"""Ensure access token is valid, refreshing if necessary."""

280

281

class ClientCredentialsAuthorizer(GlobusAuthorizer):

282

"""

283

Authorization using OAuth2 Client Credentials flow.

284

285

Automatically obtains and refreshes access tokens using client

286

credentials (client ID and secret) for service-to-service authentication.

287

"""

288

289

def __init__(

290

self,

291

confidential_client: ConfidentialAppAuthClient,

292

scopes: str | Iterable[str] | None = None,

293

access_token: str | None = None,

294

expires_at: int | None = None

295

) -> None: ...

296

297

class BasicAuthorizer(StaticGlobusAuthorizer):

298

"""

299

HTTP Basic authentication authorizer.

300

301

Provides HTTP Basic authentication using username and password

302

with base64 encoding according to RFC 7617.

303

"""

304

305

def __init__(self, username: str, password: str) -> None: ...

306

307

class NullAuthorizer(GlobusAuthorizer):

308

"""

309

No-authentication authorizer.

310

311

Ensures no Authorization header is sent with requests, useful

312

for public APIs or when authentication is handled elsewhere.

313

"""

314

315

def get_authorization_header(self) -> None:

316

"""Always returns None (no authorization)."""

317

```

318

319

### HTTP Response Framework

320

321

Comprehensive response handling with dictionary-like access, iteration support, and metadata preservation for consistent data access patterns.

322

323

```python { .api }

324

class GlobusHTTPResponse:

325

"""

326

Response wrapper providing dict-like access to API response data.

327

328

Wraps HTTP responses with convenient data access methods, error handling,

329

and metadata preservation while maintaining access to raw response data.

330

"""

331

332

def __init__(

333

self,

334

response: Response | GlobusHTTPResponse,

335

client: BaseClient | None = None

336

) -> None: ...

337

338

@property

339

def data(self) -> Any:

340

"""

341

Parsed JSON response data.

342

343

Returns the JSON-parsed response body, or None if the response

344

was not valid JSON or contained no data.

345

"""

346

347

@property

348

def text(self) -> str:

349

"""Raw response text content."""

350

351

@property

352

def binary_content(self) -> bytes:

353

"""Raw response binary content."""

354

355

@property

356

def http_status(self) -> int:

357

"""HTTP status code from the response."""

358

359

@property

360

def http_reason(self) -> str:

361

"""HTTP reason phrase from the response."""

362

363

@property

364

def headers(self) -> dict[str, str]:

365

"""HTTP response headers as a dictionary."""

366

367

@property

368

def content_type(self) -> str | None:

369

"""Content-Type header value."""

370

371

def __getitem__(self, key: str) -> Any:

372

"""

373

Dictionary-style access to response data.

374

375

Provides convenient access to JSON response fields using

376

bracket notation for dict-like usage patterns.

377

"""

378

379

def __contains__(self, key: str) -> bool:

380

"""Check if key exists in response data."""

381

382

def __bool__(self) -> bool:

383

"""Response truthiness based on HTTP success."""

384

385

def get(self, key: str, default: Any = None) -> Any:

386

"""

387

Get response data field with default fallback.

388

389

Parameters:

390

- key: Field name to retrieve

391

- default: Default value if key not found

392

393

Returns:

394

Field value or default

395

"""

396

397

class IterableResponse(GlobusHTTPResponse):

398

"""

399

Response class for paginated data with iteration support.

400

401

Provides iteration over response data arrays with automatic

402

key resolution and consistent iteration patterns across services.

403

"""

404

405

@property

406

def default_iter_key(self) -> str | None:

407

"""Default key name for iteration data."""

408

409

@property

410

def iter_key(self) -> str:

411

"""Key name used for iteration."""

412

413

def __iter__(self) -> Iterator[Any]:

414

"""

415

Iterate over response data items.

416

417

Automatically resolves the appropriate data array from the

418

response and provides iteration over individual items.

419

"""

420

421

class ArrayResponse(GlobusHTTPResponse):

422

"""

423

Response class for JSON array data with enhanced array operations.

424

425

Specialized for responses that contain JSON arrays at the top level

426

with length operations and efficient iteration.

427

"""

428

429

def __iter__(self) -> Iterator[Any]:

430

"""Iterate over array elements."""

431

432

def __len__(self) -> int:

433

"""Get number of elements in the array."""

434

```

435

436

### Scope Management System

437

438

Type-safe scope construction and management with service-specific builders and dependency handling for complex permission requirements.

439

440

```python { .api }

441

class Scope:

442

"""

443

Representation of a Globus scope with dependency management.

444

445

Represents a single scope string with support for dependent scopes,

446

optional scopes, and scope relationships for complex permission structures.

447

"""

448

449

def __init__(

450

self,

451

scope: str,

452

*,

453

optional: bool = False,

454

dependencies: Iterable[Scope] | None = None

455

) -> None: ...

456

457

@property

458

def scope_string(self) -> str:

459

"""The scope string value."""

460

461

@property

462

def optional(self) -> bool:

463

"""Whether this scope is optional."""

464

465

@property

466

def dependencies(self) -> list[Scope]:

467

"""List of dependent scopes."""

468

469

def add_dependency(self, scope: Scope) -> None:

470

"""

471

Add a dependent scope.

472

473

Creates a dependency relationship where this scope requires

474

the dependent scope to be granted as well.

475

476

Parameters:

477

- scope: Scope that this scope depends on

478

"""

479

480

def serialize(self) -> str:

481

"""

482

Serialize scope and dependencies to string format.

483

484

Converts the scope and its dependency tree to the string

485

representation used in OAuth2 flows and API requests.

486

487

Returns:

488

Serialized scope string with dependencies

489

"""

490

491

class ScopeBuilder:

492

"""

493

Base class for service-specific scope builders.

494

495

Provides a foundation for constructing scopes with service-specific

496

patterns and relationships while maintaining type safety.

497

"""

498

499

@property

500

def resource_server(self) -> str:

501

"""Resource server identifier for this scope builder."""

502

503

class MutableScope:

504

"""

505

Mutable scope object for dynamic scope construction.

506

507

Allows modification of scope properties and dependencies after

508

creation for complex scope building scenarios.

509

"""

510

511

def __init__(

512

self,

513

scope_string: str,

514

*,

515

optional: bool = False,

516

dependencies: list[MutableScope] | None = None

517

) -> None: ...

518

519

def add_dependency(self, scope: MutableScope) -> None:

520

"""Add a dependency to this scope."""

521

522

def freeze(self) -> Scope:

523

"""

524

Convert to immutable Scope object.

525

526

Freezes the mutable scope into an immutable Scope instance

527

with all current dependencies and properties preserved.

528

529

Returns:

530

Immutable Scope representation

531

"""

532

533

# Service-specific scope builders

534

class AuthScopes(ScopeBuilder):

535

"""Scope builder for Auth service scopes."""

536

537

openid: str = "openid"

538

profile: str = "profile"

539

email: str = "email"

540

view_identity_set: str = "urn:globus:auth:scope:auth.globus.org:view_identity_set"

541

542

class TransferScopes(ScopeBuilder):

543

"""Scope builder for Transfer service scopes."""

544

545

all: str = "urn:globus:auth:scope:transfer.api.globus.org:all"

546

547

class ComputeScopes(ScopeBuilder):

548

"""Scope builder for Compute service scopes."""

549

550

all: str = "urn:globus:auth:scope:compute.api.globus.org:all"

551

552

class FlowsScopes(ScopeBuilder):

553

"""Scope builder for Flows service scopes."""

554

555

all: str = "urn:globus:auth:scope:flows.api.globus.org:all"

556

manage_flows: str = "urn:globus:auth:scope:flows.api.globus.org:manage_flows"

557

run_manage: str = "urn:globus:auth:scope:flows.api.globus.org:run_manage"

558

559

# Dynamic scope builders for resource-specific scopes

560

class GCSCollectionScopeBuilder(ScopeBuilder):

561

"""Dynamic scope builder for GCS collection-specific scopes."""

562

563

def __init__(self, collection_id: str) -> None: ...

564

565

@property

566

def data_access(self) -> str:

567

"""Data access scope for this collection."""

568

569

class GCSEndpointScopeBuilder(ScopeBuilder):

570

"""Dynamic scope builder for GCS endpoint-specific scopes."""

571

572

def __init__(self, endpoint_id: str) -> None: ...

573

574

@property

575

def manage_collections(self) -> str:

576

"""Collection management scope for this endpoint."""

577

578

# Utility functions

579

def scopes_to_str(scopes: ScopeCollectionType) -> str:

580

"""

581

Convert scope collection to space-separated string.

582

583

Parameters:

584

- scopes: Collection of scopes to convert

585

586

Returns:

587

Space-separated scope string for OAuth2 flows

588

"""

589

590

def scopes_to_scope_list(scopes: ScopeCollectionType) -> list[Scope]:

591

"""

592

Normalize scope collection to list of Scope objects.

593

594

Parameters:

595

- scopes: Mixed collection of scopes to normalize

596

597

Returns:

598

Normalized list of Scope objects

599

"""

600

```

601

602

### Error Handling Framework

603

604

Comprehensive error hierarchy with service-specific errors, detailed error information, and consistent error handling patterns.

605

606

```python { .api }

607

class GlobusError(Exception):

608

"""

609

Base exception class for all Globus SDK errors.

610

611

Root of the Globus SDK exception hierarchy providing common

612

error handling patterns and metadata preservation.

613

"""

614

615

class GlobusSDKUsageError(GlobusError):

616

"""

617

Exception for SDK misuse and configuration errors.

618

619

Raised when the SDK is used incorrectly, such as invalid

620

parameter combinations or missing required configuration.

621

"""

622

623

class ValidationError(GlobusSDKUsageError):

624

"""

625

Exception for input validation failures.

626

627

Raised when user-provided data fails validation checks

628

before being sent to Globus services.

629

"""

630

631

class GlobusAPIError(GlobusError):

632

"""

633

Base exception for HTTP 4xx and 5xx API errors.

634

635

Provides access to HTTP response data, error details, and

636

structured error information from Globus services.

637

"""

638

639

def __init__(self, response: Response) -> None: ...

640

641

@property

642

def http_status(self) -> int:

643

"""HTTP status code from the error response."""

644

645

@property

646

def http_reason(self) -> str:

647

"""HTTP reason phrase from the error response."""

648

649

@property

650

def headers(self) -> dict[str, str]:

651

"""HTTP headers from the error response."""

652

653

@property

654

def text(self) -> str:

655

"""Raw error response text."""

656

657

@property

658

def binary_content(self) -> bytes:

659

"""Raw error response binary content."""

660

661

@property

662

def data(self) -> Any:

663

"""Parsed JSON error data if available."""

664

665

@property

666

def code(self) -> str:

667

"""Globus error code from the response."""

668

669

@property

670

def message(self) -> str:

671

"""Human-readable error message."""

672

673

def __getitem__(self, key: str) -> Any:

674

"""Dictionary-style access to error data."""

675

676

def __contains__(self, key: str) -> bool:

677

"""Check if key exists in error data."""

678

679

def get(self, key: str, default: Any = None) -> Any:

680

"""Get error data field with default."""

681

682

class ErrorSubdocument:

683

"""

684

Container for detailed error information from API responses.

685

686

Represents individual error details within structured error

687

responses with code, message, and additional metadata.

688

"""

689

690

def __init__(self, data: dict[str, Any]) -> None: ...

691

692

@property

693

def code(self) -> str:

694

"""Error code identifier."""

695

696

@property

697

def message(self) -> str:

698

"""Human-readable error message."""

699

700

@property

701

def detail(self) -> str:

702

"""Detailed error description."""

703

704

# Network-related errors

705

class NetworkError(GlobusError):

706

"""Base class for network connectivity errors."""

707

708

class GlobusTimeoutError(NetworkError):

709

"""Request timeout errors."""

710

711

class GlobusConnectionError(NetworkError):

712

"""Connection establishment errors."""

713

714

class GlobusConnectionTimeoutError(GlobusConnectionError):

715

"""Connection timeout errors."""

716

717

# Error information containers

718

class ErrorInfo:

719

"""

720

Container for structured error information.

721

722

Provides access to error details, codes, and additional

723

context information from API error responses.

724

"""

725

726

class ErrorInfoContainer:

727

"""

728

Collection of ErrorInfo objects.

729

730

Manages multiple error information objects with iteration

731

and lookup capabilities for complex error scenarios.

732

"""

733

734

class ConsentRequiredInfo(ErrorInfo):

735

"""

736

Specialized error info for consent required errors.

737

738

Provides structured information about required consents

739

and authorization parameters for resolving access issues.

740

"""

741

742

@property

743

def required_scopes(self) -> list[str]:

744

"""Scopes requiring user consent."""

745

746

@property

747

def authorization_parameters(self) -> dict[str, Any]:

748

"""OAuth2 parameters for consent flow."""

749

750

# Warnings

751

class RemovedInV4Warning(UserWarning):

752

"""

753

Warning for features that will be removed in SDK v4.0.

754

755

Indicates deprecated functionality that should be migrated

756

to newer alternatives before the next major version.

757

"""

758

```

759

760

### Utility Classes and Functions

761

762

Helper classes and utility functions providing common functionality across the SDK with consistent patterns and type safety.

763

764

```python { .api }

765

class PayloadWrapper:

766

"""

767

Base class for API request payload helpers.

768

769

Provides a foundation for building structured request data with

770

validation, serialization, and convenience methods for API operations.

771

"""

772

773

def __init__(self) -> None: ...

774

775

def __getitem__(self, key: str) -> Any:

776

"""Dictionary-style access to payload data."""

777

778

def __setitem__(self, key: str, value: Any) -> None:

779

"""Dictionary-style assignment to payload data."""

780

781

def __contains__(self, key: str) -> bool:

782

"""Check if key exists in payload data."""

783

784

def get(self, key: str, default: Any = None) -> Any:

785

"""Get payload field with default fallback."""

786

787

class MissingType:

788

"""

789

Sentinel type for distinguishing missing values from None.

790

791

Used throughout the SDK to represent truly missing/unset values

792

as distinct from explicit None values.

793

"""

794

795

# Sentinel instance

796

MISSING: MissingType = MissingType()

797

798

# Utility functions

799

def filter_missing(data: dict[str, Any]) -> dict[str, Any]:

800

"""

801

Remove MISSING values from dictionary.

802

803

Filters out all keys with MISSING sentinel values to produce

804

clean dictionaries for API requests.

805

806

Parameters:

807

- data: Dictionary potentially containing MISSING values

808

809

Returns:

810

Dictionary with MISSING values removed

811

"""

812

813

def slash_join(*parts: str) -> str:

814

"""

815

Join URL path components with proper slash handling.

816

817

Joins path segments ensuring single slashes between components

818

and proper handling of leading/trailing slashes.

819

820

Parameters:

821

- *parts: Path components to join

822

823

Returns:

824

Properly formatted URL path

825

"""

826

827

def sha256_string(data: str) -> str:

828

"""

829

Compute SHA256 hash of a string.

830

831

Parameters:

832

- data: String to hash

833

834

Returns:

835

Hexadecimal SHA256 hash

836

"""

837

838

def b64str(data: str) -> str:

839

"""

840

Base64 encode a string.

841

842

Parameters:

843

- data: String to encode

844

845

Returns:

846

Base64 encoded string

847

"""

848

```

849

850

## Common Usage Patterns

851

852

### Basic Client Initialization

853

854

```python

855

from globus_sdk import TransferClient, AccessTokenAuthorizer

856

857

# Simple token-based authorization

858

authorizer = AccessTokenAuthorizer("your_access_token")

859

client = TransferClient(authorizer=authorizer)

860

861

# Application-based initialization

862

from globus_sdk import UserApp

863

864

app = UserApp("my-app", client_id="your_client_id")

865

client = TransferClient(app=app)

866

```

867

868

### Custom Authorization Patterns

869

870

```python

871

from globus_sdk import RefreshTokenAuthorizer, AuthClient

872

873

# Refresh token authorization with callback

874

def token_refresh_callback(token_response):

875

# Save new tokens to persistent storage

876

save_tokens(token_response.by_resource_server)

877

878

auth_client = AuthClient()

879

authorizer = RefreshTokenAuthorizer(

880

refresh_token="your_refresh_token",

881

auth_client=auth_client,

882

on_refresh=token_refresh_callback

883

)

884

885

client = TransferClient(authorizer=authorizer)

886

```

887

888

### Scope Management

889

890

```python

891

from globus_sdk import TransferScopes, ComputeScopes, Scope

892

893

# Using service scope builders

894

base_scopes = [

895

Scope(TransferScopes.all),

896

Scope(ComputeScopes.all)

897

]

898

899

# Dynamic collection scopes

900

from globus_sdk import GCSCollectionScopeBuilder

901

902

collection_scope_builder = GCSCollectionScopeBuilder("collection-uuid")

903

data_access_scope = Scope(collection_scope_builder.data_access, optional=True)

904

905

# Scope with dependencies

906

transfer_scope = Scope(TransferScopes.all)

907

transfer_scope.add_dependency(data_access_scope)

908

```

909

910

### Error Handling Patterns

911

912

```python

913

from globus_sdk import GlobusAPIError, ConsentRequiredInfo

914

915

try:

916

response = client.submit_transfer(transfer_data)

917

except GlobusAPIError as e:

918

if e.http_status == 403:

919

# Check for consent required errors

920

if e.info.consent_required:

921

consent_info = ConsentRequiredInfo(e)

922

print(f"Consent required for scopes: {consent_info.required_scopes}")

923

924

# Handle consent flow

925

auth_params = consent_info.authorization_parameters

926

# Redirect user to consent URL...

927

else:

928

print(f"API Error {e.http_status}: {e.message}")

929

# Handle other API errors

930

except Exception as e:

931

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

932

```

933

934

### Response Handling

935

936

```python

937

# Dictionary-style access

938

response = client.get_endpoint("endpoint-uuid")

939

print(f"Endpoint name: {response['display_name']}")

940

941

# Iterate over paginated results

942

endpoints = client.endpoint_search("tutorial")

943

for endpoint in endpoints:

944

print(f"Found: {endpoint['display_name']}")

945

946

# Access response metadata

947

print(f"Status: {response.http_status}")

948

print(f"Headers: {response.headers}")

949

```

950

951

### Advanced Client Configuration

952

953

```python

954

from globus_sdk import BaseClient

955

956

class CustomClient(BaseClient):

957

service_name = "my_service"

958

error_class = MyCustomAPIError

959

960

@property

961

def default_scope_requirements(self):

962

return [Scope("https://my-service.org/scope")]

963

964

def custom_operation(self, data):

965

return self.post("/custom", data=data)

966

967

# Use custom transport parameters

968

custom_client = CustomClient(

969

authorizer=authorizer,

970

transport_params={

971

"timeout": 60,

972

"retries": 3,

973

"user_agent_suffix": "MyApp/1.0"

974

}

975

)

976

```