Extract Python API signatures and detect breaking changes for documentation generation.
npx @tessl/cli install tessl/pypi-griffe@1.13.00
# Griffe
1
2
Griffe is a comprehensive Python library that extracts signatures and API information from entire Python programs. It provides both static analysis (AST parsing) and dynamic analysis (runtime inspection) capabilities to generate API documentation, detect breaking changes, and support development workflows requiring detailed code structure analysis.
3
4
## Package Information
5
6
- **Package Name**: griffe
7
- **Language**: Python
8
- **Installation**: `pip install griffe`
9
- **CLI Tool**: Available as `griffe` command-line tool
10
- **Git Support**: `pip install griffe[pypi]` for enhanced Git/PyPI integration
11
12
## Core Imports
13
14
```python
15
import griffe
16
```
17
18
Common imports for specific functionality:
19
20
```python
21
# Loading packages
22
from griffe import load, load_git, load_pypi
23
24
# CLI functions
25
from griffe import main, check, dump
26
27
# Core models
28
from griffe import Module, Class, Function, Attribute, Alias
29
30
# Analysis agents
31
from griffe import visit, inspect
32
33
# Breaking change detection
34
from griffe import find_breaking_changes, Breakage
35
36
# Docstring parsing
37
from griffe import parse, parse_auto, parse_google, parse_numpy, parse_sphinx
38
39
# Serialization
40
from griffe import JSONEncoder, json_decoder
41
```
42
43
## Basic Usage
44
45
### Loading Python Package Data
46
47
```python
48
import griffe
49
50
# Load a package from the current environment
51
package = griffe.load("requests")
52
print(f"Package: {package.name}")
53
print(f"Modules: {list(package.modules.keys())}")
54
55
# Load from specific Git reference
56
old_version = griffe.load_git("mypackage", ref="v1.0.0")
57
current_version = griffe.load("mypackage")
58
59
# Load from PyPI
60
pypi_package = griffe.load_pypi("django", "Django", "4.2.0")
61
```
62
63
### Detecting API Breaking Changes
64
65
```python
66
import griffe
67
68
# Compare two versions of a package
69
old_api = griffe.load_git("mypackage", ref="v1.0.0")
70
new_api = griffe.load("mypackage")
71
72
# Find breaking changes
73
breakages = griffe.find_breaking_changes(old_api, new_api)
74
for breakage in breakages:
75
print(f"Breaking change: {breakage}")
76
```
77
78
### CLI Usage
79
80
```bash
81
# Dump package API as JSON
82
griffe dump fastapi httpx
83
84
# Check for breaking changes
85
griffe check mypackage --verbose
86
87
# With src layout
88
griffe check --search src mypackage --verbose
89
```
90
91
## Architecture
92
93
Griffe is built around several key architectural concepts:
94
95
- **Agents**: Static analysis via `visit()` (AST parsing) and dynamic analysis via `inspect()` (runtime inspection)
96
- **Models**: Core object representations (`Module`, `Class`, `Function`, `Attribute`, `Alias`) that form the API structure
97
- **Loaders**: High-level functions (`load`, `load_git`, `load_pypi`) that orchestrate the analysis process
98
- **Extensions**: Pluggable system for custom analysis and processing during code examination
99
- **Expressions**: Abstract syntax tree representations of Python code snippets (decorators, annotations, etc.)
100
101
## Capabilities
102
103
### CLI Entry Points
104
105
Command-line interface functions that can be called from Python or as CLI commands.
106
107
```python { .api }
108
def main() -> int:
109
"""
110
Run the main griffe program.
111
112
Returns:
113
int: Exit code (0 for success)
114
"""
115
116
def check(*args, **kwargs) -> int:
117
"""
118
Check for API breaking changes between versions.
119
120
Returns:
121
int: Exit code (0 if no breaking changes)
122
"""
123
124
def dump(*args, **kwargs) -> int:
125
"""
126
Load packages and dump API data as JSON.
127
128
Returns:
129
int: Exit code (0 for success)
130
"""
131
```
132
133
[CLI Functions](./cli.md)
134
135
### Package Loading
136
137
High-level functions for loading Python packages and modules from different sources.
138
139
```python { .api }
140
def load(
141
objspec: str | Path | None = None,
142
/,
143
*,
144
submodules: bool = True,
145
try_relative_path: bool = True,
146
extensions: Extensions | None = None,
147
search_paths: Sequence[str | Path] | None = None,
148
docstring_parser: DocstringStyle | Parser | None = None,
149
docstring_options: dict[str, Any] | None = None,
150
lines_collection: LinesCollection | None = None,
151
modules_collection: ModulesCollection | None = None,
152
allow_inspection: bool = True,
153
force_inspection: bool = False,
154
store_source: bool = True,
155
find_stubs_package: bool = False,
156
resolve_aliases: bool = False,
157
resolve_external: bool | None = None,
158
resolve_implicit: bool = False,
159
) -> Object | Alias: ...
160
161
def load_git(
162
objspec: str,
163
ref: str = "HEAD",
164
*,
165
repo: str | Path = ".",
166
submodules: bool = True,
167
**load_kwargs: Any,
168
) -> Object | Alias: ...
169
170
def load_pypi(
171
package: str,
172
distribution: str,
173
version_spec: str,
174
*,
175
submodules: bool = True,
176
extensions: Extensions | None = None,
177
search_paths: Sequence[str | Path] | None = None,
178
docstring_parser: DocstringStyle | Parser | None = None,
179
docstring_options: dict[str, Any] | None = None,
180
lines_collection: LinesCollection | None = None,
181
modules_collection: ModulesCollection | None = None,
182
allow_inspection: bool = True,
183
force_inspection: bool = False,
184
find_stubs_package: bool = False,
185
) -> Object | Alias: ...
186
```
187
188
[Loaders](./loaders.md)
189
190
### Core Object Models
191
192
The primary classes representing Python API elements.
193
194
```python { .api }
195
class Object:
196
"""Base class for all Griffe objects."""
197
198
@property
199
def name(self) -> str: ...
200
201
@property
202
def path(self) -> str: ...
203
204
def serialize(self, **kwargs: Any) -> dict[str, Any]: ...
205
206
class Module(Object):
207
"""A Python module."""
208
209
@property
210
def filepath(self) -> Path | None: ...
211
212
@property
213
def modules(self) -> dict[str, Module]: ...
214
215
@property
216
def classes(self) -> dict[str, Class]: ...
217
218
@property
219
def functions(self) -> dict[str, Function]: ...
220
221
@property
222
def attributes(self) -> dict[str, Attribute]: ...
223
224
class Class(Object):
225
"""A Python class."""
226
227
@property
228
def bases(self) -> list[Expr]: ...
229
230
@property
231
def decorators(self) -> list[Decorator]: ...
232
233
@property
234
def methods(self) -> dict[str, Function]: ...
235
236
class Function(Object):
237
"""A Python function or method."""
238
239
@property
240
def parameters(self) -> Parameters: ...
241
242
@property
243
def returns(self) -> Expr | None: ...
244
245
@property
246
def decorators(self) -> list[Decorator]: ...
247
248
class Attribute(Object):
249
"""A Python attribute."""
250
251
@property
252
def annotation(self) -> Expr | None: ...
253
254
@property
255
def value(self) -> Expr | None: ...
256
257
class Alias(Object):
258
"""An alias or import reference to an object."""
259
260
@property
261
def target_path(self) -> str: ...
262
263
def resolve(self) -> Object | None: ...
264
```
265
266
[Models](./models.md)
267
268
### Analysis Agents
269
270
Static and dynamic analysis functions for extracting API information.
271
272
```python { .api }
273
def visit(
274
module: Module,
275
filepath: str | Path,
276
code: str | None = None,
277
extensions: Extensions | None = None,
278
parent: Module | None = None,
279
in_try_block: bool = False,
280
) -> Module: ...
281
282
def inspect(
283
module_name: str,
284
filepath: str | Path | None = None,
285
parent: Module | None = None,
286
) -> Module: ...
287
```
288
289
[Agents](./agents.md)
290
291
### API Breakage Detection
292
293
Functions and classes for detecting breaking changes between API versions.
294
295
```python { .api }
296
def find_breaking_changes(
297
old_object: Object,
298
new_object: Object,
299
**kwargs: Any,
300
) -> Iterator[Breakage]: ...
301
302
class Breakage:
303
"""Base class for API breakages."""
304
305
@property
306
def kind(self) -> BreakageKind: ...
307
308
@property
309
def object_path(self) -> str: ...
310
311
class ObjectRemovedBreakage(Breakage):
312
"""A public object was removed."""
313
314
class ParameterAddedRequiredBreakage(Breakage):
315
"""A required parameter was added to a function."""
316
317
class ReturnChangedTypeBreakage(Breakage):
318
"""A function's return type annotation changed."""
319
```
320
321
[Breaking Changes](./breaking-changes.md)
322
323
### Serialization
324
325
JSON encoding and decoding for Griffe objects.
326
327
```python { .api }
328
class JSONEncoder(json.JSONEncoder):
329
"""JSON encoder for Griffe objects."""
330
331
def default(self, obj: Any) -> Any: ...
332
333
def json_decoder(dct: dict[str, Any]) -> dict[str, Any] | Object:
334
"""
335
Decode Griffe objects from JSON.
336
337
Args:
338
dct: Dictionary from JSON decoder
339
340
Returns:
341
Decoded object or dictionary
342
"""
343
```
344
345
[Serialization](./serialization.md)
346
347
### Docstring Parsing
348
349
Comprehensive docstring parsing supporting multiple formats.
350
351
```python { .api }
352
def parse(
353
text: str,
354
parser: Parser | str | None = None,
355
**options: Any,
356
) -> list[DocstringSection]: ...
357
358
def parse_auto(text: str, **options: Any) -> list[DocstringSection]: ...
359
360
def parse_google(text: str, **options: Any) -> list[DocstringSection]: ...
361
362
def parse_numpy(text: str, **options: Any) -> list[DocstringSection]: ...
363
364
def parse_sphinx(text: str, **options: Any) -> list[DocstringSection]: ...
365
```
366
367
[Docstrings](./docstrings.md)
368
369
### Extensions
370
371
Extensible plugin system for custom analysis.
372
373
```python { .api }
374
class Extension:
375
"""Base class for Griffe extensions."""
376
377
def on_package_loaded(self, *, pkg: Module) -> None: ...
378
379
def on_module_loaded(self, *, mod: Module) -> None: ...
380
381
def on_class_loaded(self, *, cls: Class) -> None: ...
382
383
def on_function_loaded(self, *, func: Function) -> None: ...
384
385
def load_extensions(
386
extensions: list[LoadableExtensionType] | None = None
387
) -> Extensions: ...
388
```
389
390
[Extensions](./extensions.md)
391
392
## Types
393
394
### Core Type Aliases
395
396
```python { .api }
397
from pathlib import Path
398
from typing import Any, Sequence, IO
399
400
# Collection types
401
LinesCollection = dict[str, dict[int, str]]
402
ModulesCollection = dict[str, Module]
403
Extensions = dict[str, Extension]
404
405
# Docstring and parser types
406
DocstringStyle = str
407
ExplanationStyle = str
408
```
409
410
### Core Enumerations
411
412
```python { .api }
413
from enum import Enum
414
415
class Kind(Enum):
416
"""Object kinds."""
417
MODULE = "module"
418
CLASS = "class"
419
FUNCTION = "function"
420
ATTRIBUTE = "attribute"
421
422
class ParameterKind(Enum):
423
"""Parameter kinds."""
424
POSITIONAL_ONLY = 0
425
POSITIONAL_OR_KEYWORD = 1
426
VAR_POSITIONAL = 2
427
KEYWORD_ONLY = 3
428
VAR_KEYWORD = 4
429
430
class Parser(Enum):
431
"""Docstring parser types."""
432
AUTO = "auto"
433
GOOGLE = "google"
434
NUMPY = "numpy"
435
SPHINX = "sphinx"
436
437
class BreakageKind(Enum):
438
"""API breakage types."""
439
OBJECT_REMOVED = "object_removed"
440
PARAMETER_ADDED_REQUIRED = "parameter_added_required"
441
PARAMETER_REMOVED = "parameter_removed"
442
RETURN_CHANGED_TYPE = "return_changed_type"
443
```
444
445
### Parameter Types
446
447
```python { .api }
448
class Parameter:
449
"""A function parameter."""
450
451
def __init__(
452
self,
453
name: str,
454
annotation: Expr | None = None,
455
default: Expr | None = None,
456
kind: ParameterKind = ParameterKind.POSITIONAL_OR_KEYWORD,
457
) -> None: ...
458
459
@property
460
def name(self) -> str: ...
461
462
@property
463
def annotation(self) -> Expr | None: ...
464
465
@property
466
def default(self) -> Expr | None: ...
467
468
class Parameters:
469
"""Container for function parameters."""
470
471
def __iter__(self) -> Iterator[Parameter]: ...
472
473
def __getitem__(self, key: int | str) -> Parameter: ...
474
475
def __len__(self) -> int: ...
476
```
477
478
### Expression Types
479
480
```python { .api }
481
class Expr:
482
"""Base expression class."""
483
484
def __str__(self) -> str: ...
485
486
class ExprName(Expr):
487
"""A name expression."""
488
489
def __init__(self, name: str) -> None: ...
490
491
class ExprAttribute(Expr):
492
"""An attribute access expression like a.b."""
493
494
def __init__(self, value: Expr, attr: str) -> None: ...
495
496
class ExprCall(Expr):
497
"""A function call expression."""
498
499
def __init__(
500
self,
501
function: Expr,
502
arguments: list[Expr] | None = None,
503
) -> None: ...
504
```