or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

actions.mdapi-client.mdapps.mdexceptions.mdhttp-implementations.mdindex.mdrouting.mdsansio.md

api-client.mddocs/

0

# API Client

1

2

High-level GitHub API interface providing HTTP method implementations (GET, POST, PUT, PATCH, DELETE) with authentication, caching, and GraphQL support. The abstract base class defines the interface that concrete HTTP implementations must fulfill.

3

4

## Capabilities

5

6

### Abstract Base Class

7

8

The core abstract class that defines the GitHub API interface.

9

10

```python { .api }

11

import abc

12

from typing import Any, AsyncGenerator, Dict, Mapping, MutableMapping, Optional, Tuple

13

from uritemplate import variable

14

from gidgethub.sansio import RateLimit

15

import gidgethub.sansio as sansio

16

17

# Cache type definition

18

CACHE_TYPE = MutableMapping[str, Tuple[Optional[str], Optional[str], Any, Optional[str]]]

19

20

class GitHubAPI(abc.ABC):

21

"""Provide an idiomatic API for making calls to GitHub's API."""

22

23

def __init__(

24

self,

25

requester: str,

26

*,

27

oauth_token: Optional[str] = None,

28

cache: Optional[CACHE_TYPE] = None,

29

base_url: str = "https://api.github.com"

30

) -> None:

31

"""

32

Initialize GitHub API client.

33

34

Parameters:

35

- requester: User agent identifier (username or project name)

36

- oauth_token: Personal access token for authentication

37

- cache: Optional cache for GET requests (etag/last-modified based)

38

- base_url: GitHub API base URL

39

"""

40

41

# Abstract methods that implementations must provide

42

@abc.abstractmethod

43

async def _request(

44

self,

45

method: str,

46

url: str,

47

headers: Mapping[str, str],

48

body: bytes = b""

49

) -> Tuple[int, Mapping[str, str], bytes]:

50

"""Make an HTTP request."""

51

52

@abc.abstractmethod

53

async def sleep(self, seconds: float) -> None:

54

"""Sleep for the specified number of seconds."""

55

56

# Attributes

57

requester: str

58

oauth_token: Optional[str]

59

rate_limit: Optional[RateLimit]

60

base_url: str

61

```

62

63

### GET Methods

64

65

Methods for retrieving data from the GitHub API.

66

67

```python { .api }

68

async def getitem(

69

self,

70

url: str,

71

url_vars: Optional[variable.VariableValueDict] = {},

72

*,

73

accept: str = sansio.accept_format(),

74

jwt: Optional[str] = None,

75

oauth_token: Optional[str] = None,

76

extra_headers: Optional[Dict[str, str]] = None,

77

) -> Any:

78

"""

79

Send a GET request for a single item to the specified endpoint.

80

81

Parameters:

82

- url: API endpoint URL (absolute or relative)

83

- url_vars: Variables for URI template expansion

84

- accept: Accept header value for API version/format

85

- jwt: JWT token for GitHub App authentication

86

- oauth_token: OAuth token (overrides instance token)

87

- extra_headers: Additional headers to include

88

89

Returns:

90

- Parsed JSON response data

91

"""

92

93

async def getstatus(

94

self,

95

url: str,

96

url_vars: Optional[variable.VariableValueDict] = {},

97

*,

98

accept: str = sansio.accept_format(),

99

jwt: Optional[str] = None,

100

oauth_token: Optional[str] = None,

101

) -> int:

102

"""

103

Send a GET request and return only the status code.

104

105

Parameters:

106

- url: API endpoint URL

107

- url_vars: Variables for URI template expansion

108

- accept: Accept header value

109

- jwt: JWT token for GitHub App authentication

110

- oauth_token: OAuth token (overrides instance token)

111

112

Returns:

113

- HTTP status code (even for error responses)

114

"""

115

116

async def getiter(

117

self,

118

url: str,

119

url_vars: Optional[variable.VariableValueDict] = {},

120

*,

121

accept: str = sansio.accept_format(),

122

jwt: Optional[str] = None,

123

oauth_token: Optional[str] = None,

124

extra_headers: Optional[Dict[str, str]] = None,

125

iterable_key: Optional[str] = "items",

126

) -> AsyncGenerator[Any, None]:

127

"""

128

Return an async iterable for all items at a specified endpoint.

129

Automatically handles pagination using Link headers.

130

131

Parameters:

132

- url: API endpoint URL

133

- url_vars: Variables for URI template expansion

134

- accept: Accept header value

135

- jwt: JWT token for GitHub App authentication

136

- oauth_token: OAuth token (overrides instance token)

137

- extra_headers: Additional headers to include

138

- iterable_key: Key containing items in paginated responses

139

140

Yields:

141

- Individual items from paginated API responses

142

"""

143

```

144

145

### Mutation Methods

146

147

Methods for creating, updating, and deleting data via the GitHub API.

148

149

```python { .api }

150

async def post(

151

self,

152

url: str,

153

url_vars: Optional[variable.VariableValueDict] = {},

154

*,

155

data: Any,

156

accept: str = sansio.accept_format(),

157

jwt: Optional[str] = None,

158

oauth_token: Optional[str] = None,

159

extra_headers: Optional[Dict[str, str]] = None,

160

content_type: str = "application/json",

161

) -> Any:

162

"""

163

Send a POST request to create resources.

164

165

Parameters:

166

- url: API endpoint URL

167

- url_vars: Variables for URI template expansion

168

- data: Request body data (JSON serializable or bytes)

169

- accept: Accept header value

170

- jwt: JWT token for GitHub App authentication

171

- oauth_token: OAuth token (overrides instance token)

172

- extra_headers: Additional headers to include

173

- content_type: Content-Type header value

174

175

Returns:

176

- Parsed JSON response data

177

"""

178

179

async def patch(

180

self,

181

url: str,

182

url_vars: Optional[variable.VariableValueDict] = {},

183

*,

184

data: Any,

185

accept: str = sansio.accept_format(),

186

jwt: Optional[str] = None,

187

oauth_token: Optional[str] = None,

188

extra_headers: Optional[Dict[str, str]] = None,

189

) -> Any:

190

"""

191

Send a PATCH request to update resources.

192

193

Parameters:

194

- url: API endpoint URL

195

- url_vars: Variables for URI template expansion

196

- data: Request body data (JSON serializable)

197

- accept: Accept header value

198

- jwt: JWT token for GitHub App authentication

199

- oauth_token: OAuth token (overrides instance token)

200

- extra_headers: Additional headers to include

201

202

Returns:

203

- Parsed JSON response data

204

"""

205

206

async def put(

207

self,

208

url: str,

209

url_vars: Optional[variable.VariableValueDict] = {},

210

*,

211

data: Any = b"",

212

accept: str = sansio.accept_format(),

213

jwt: Optional[str] = None,

214

oauth_token: Optional[str] = None,

215

extra_headers: Optional[Dict[str, str]] = None,

216

) -> Any:

217

"""

218

Send a PUT request to create or replace resources.

219

220

Parameters:

221

- url: API endpoint URL

222

- url_vars: Variables for URI template expansion

223

- data: Request body data (default: empty)

224

- accept: Accept header value

225

- jwt: JWT token for GitHub App authentication

226

- oauth_token: OAuth token (overrides instance token)

227

- extra_headers: Additional headers to include

228

229

Returns:

230

- Parsed JSON response data

231

"""

232

233

async def delete(

234

self,

235

url: str,

236

url_vars: Optional[variable.VariableValueDict] = {},

237

*,

238

data: Any = b"",

239

accept: str = sansio.accept_format(),

240

jwt: Optional[str] = None,

241

oauth_token: Optional[str] = None,

242

extra_headers: Optional[Dict[str, str]] = None,

243

) -> None:

244

"""

245

Send a DELETE request to remove resources.

246

247

Parameters:

248

- url: API endpoint URL

249

- url_vars: Variables for URI template expansion

250

- data: Request body data (default: empty)

251

- accept: Accept header value

252

- jwt: JWT token for GitHub App authentication

253

- oauth_token: OAuth token (overrides instance token)

254

- extra_headers: Additional headers to include

255

256

Returns:

257

- None (DELETE responses typically have no body)

258

"""

259

```

260

261

### GraphQL Support

262

263

Methods for querying GitHub's GraphQL v4 API.

264

265

```python { .api }

266

async def graphql(

267

self,

268

query: str,

269

*,

270

endpoint: str = "https://api.github.com/graphql",

271

**variables: Any,

272

) -> Any:

273

"""

274

Query the GraphQL v4 API.

275

276

Parameters:

277

- query: GraphQL query string

278

- endpoint: GraphQL endpoint URL

279

- **variables: Query variables as keyword arguments

280

281

Returns:

282

- GraphQL response data

283

284

Raises:

285

- GraphQLException: For malformed responses

286

- GraphQLAuthorizationFailure: For 401 responses

287

- BadGraphQLRequest: For 4XX responses

288

- QueryError: For GraphQL query errors

289

- GitHubBroken: For 5XX responses

290

"""

291

```

292

293

## Usage Examples

294

295

### Basic Repository Information

296

297

```python

298

import asyncio

299

from gidgethub.aiohttp import GitHubAPI

300

import aiohttp

301

302

async def get_repo_info():

303

async with aiohttp.ClientSession() as session:

304

gh = GitHubAPI(session, "my-app/1.0")

305

306

# Get single repository

307

repo = await gh.getitem("/repos/octocat/Hello-World")

308

print(f"Repository: {repo['name']}")

309

print(f"Stars: {repo['stargazers_count']}")

310

311

# Check if repository exists (status only)

312

status = await gh.getstatus("/repos/octocat/Hello-World")

313

if status == 200:

314

print("Repository exists")

315

316

asyncio.run(get_repo_info())

317

```

318

319

### Pagination with Async Iteration

320

321

```python

322

async def list_all_issues():

323

async with aiohttp.ClientSession() as session:

324

gh = GitHubAPI(session, "my-app/1.0", oauth_token="your_token")

325

326

# Iterate through all issues across all pages

327

async for issue in gh.getiter("/repos/owner/repo/issues"):

328

print(f"Issue #{issue['number']}: {issue['title']}")

329

```

330

331

### Creating and Updating Resources

332

333

```python

334

async def manage_issues():

335

async with aiohttp.ClientSession() as session:

336

gh = GitHubAPI(session, "my-app/1.0", oauth_token="your_token")

337

338

# Create a new issue

339

new_issue = await gh.post(

340

"/repos/owner/repo/issues",

341

data={

342

"title": "Bug report",

343

"body": "Description of the bug",

344

"labels": ["bug", "urgent"]

345

}

346

)

347

issue_number = new_issue['number']

348

349

# Update the issue

350

updated_issue = await gh.patch(

351

f"/repos/owner/repo/issues/{issue_number}",

352

data={"state": "closed"}

353

)

354

355

# Add a comment

356

await gh.post(

357

f"/repos/owner/repo/issues/{issue_number}/comments",

358

data={"body": "Fixed in latest release"}

359

)

360

```

361

362

### GraphQL Queries

363

364

```python

365

async def graphql_example():

366

async with aiohttp.ClientSession() as session:

367

gh = GitHubAPI(session, "my-app/1.0", oauth_token="your_token")

368

369

query = """

370

query($owner: String!, $name: String!) {

371

repository(owner: $owner, name: $name) {

372

name

373

description

374

stargazerCount

375

forkCount

376

issues(first: 10) {

377

nodes {

378

title

379

state

380

}

381

}

382

}

383

}

384

"""

385

386

result = await gh.graphql(query, owner="octocat", name="Hello-World")

387

repo = result['repository']

388

print(f"Repository: {repo['name']}")

389

print(f"Issues: {len(repo['issues']['nodes'])}")

390

```

391

392

### URL Template Variables

393

394

```python

395

async def template_variables():

396

async with aiohttp.ClientSession() as session:

397

gh = GitHubAPI(session, "my-app/1.0")

398

399

# Use template variables for dynamic URLs

400

repo_data = await gh.getitem(

401

"/repos/{owner}/{repo}",

402

{"owner": "octocat", "repo": "Hello-World"}

403

)

404

405

# Get specific issue

406

issue = await gh.getitem(

407

"/repos/{owner}/{repo}/issues/{issue_number}",

408

{

409

"owner": "octocat",

410

"repo": "Hello-World",

411

"issue_number": 1

412

}

413

)

414

```

415

416

## Constants

417

418

```python { .api }

419

JSON_CONTENT_TYPE: str = "application/json"

420

UTF_8_CHARSET: str = "utf-8"

421

JSON_UTF_8_CHARSET: str = "application/json; charset=utf-8"

422

ITERABLE_KEY: str = "items"

423

```

424

425

## Types

426

427

```python { .api }

428

from typing import Any, AsyncGenerator, Dict, Mapping, MutableMapping, Optional, Tuple

429

from uritemplate import variable

430

431

# Cache type for HTTP caching

432

CACHE_TYPE = MutableMapping[str, Tuple[Optional[str], Optional[str], Any, Optional[str]]]

433

434

# From sansio module

435

RateLimit = gidgethub.sansio.RateLimit

436

```