or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-tools.mddocstring-parsing.mdhooks.mdindex.mdsphinx-extension.mdvalidation.md

hooks.mddocs/

0

# Git Hooks

1

2

The numpydoc hooks module provides pre-commit integration for automated docstring validation. It enables project-wide enforcement of docstring quality standards through Git hooks and continuous integration workflows.

3

4

## Core Hook Functionality

5

6

### Main Hook Function

7

8

```python { .api }

9

def run_hook(files, config=None, ignore=None):

10

"""

11

Main hook function for pre-commit validation.

12

13

Processes a list of Python files for docstring validation,

14

using AST parsing to extract and validate docstrings from

15

functions, classes, and methods.

16

17

Parameters

18

----------

19

files : list of str

20

List of file paths to validate

21

config : dict, optional

22

Configuration dictionary with validation settings

23

If None, attempts to load from project configuration files

24

ignore : set of str, optional

25

Set of validation error codes to ignore

26

27

Returns

28

-------

29

int

30

Exit code (0 for success, non-zero if validation errors found)

31

32

Examples

33

--------

34

>>> from numpydoc.hooks.validate_docstrings import run_hook

35

>>> exit_code = run_hook(['src/mymodule.py'])

36

>>> print(f"Validation result: {exit_code}")

37

"""

38

```

39

40

### Configuration Parsing

41

42

```python { .api }

43

def parse_config(dir_path=None):

44

"""

45

Parse validation config from pyproject.toml/setup.cfg.

46

47

Searches for numpydoc validation configuration in standard

48

Python project configuration files, with pyproject.toml

49

taking precedence over setup.cfg.

50

51

Parameters

52

----------

53

dir_path : str, optional

54

Directory to search for config files

55

If None, uses current working directory

56

57

Returns

58

-------

59

dict

60

Configuration dictionary with keys:

61

- 'checks': set of validation check codes to apply

62

- 'ignore': set of error codes to ignore

63

- 'exclude': set of file patterns to exclude

64

- 'override': dict mapping object patterns to rule overrides

65

66

Examples

67

--------

68

>>> config = parse_config()

69

>>> print(config['checks'])

70

{'all', 'GL08'}

71

>>> print(config['exclude'])

72

{'tests/.*', '.*/_private.py'}

73

"""

74

```

75

76

### File Processing

77

78

```python { .api }

79

def process_file(filepath: str, config: dict):

80

"""

81

Process single file for validation.

82

83

Uses AST parsing to extract docstrings from Python source

84

code and validates them according to the provided configuration.

85

Handles syntax errors gracefully and reports validation issues.

86

87

Parameters

88

----------

89

filepath : str

90

Path to Python file to process

91

config : dict

92

Configuration dictionary with validation settings

93

94

Returns

95

-------

96

list of tuple

97

List of (line_number, error_code, message) validation errors

98

99

Examples

100

--------

101

>>> config = {'checks': {'all'}, 'ignore': set()}

102

>>> errors = process_file('src/mymodule.py', config)

103

>>> for line, code, msg in errors:

104

... print(f"{line}: {code}: {msg}")

105

"""

106

```

107

108

## AST-Based Validation

109

110

### AST Validator

111

112

```python { .api }

113

class AstValidator(validate.Validator):

114

"""

115

AST-based validator extending base Validator class.

116

117

Specialized validator that works with AST nodes to validate

118

docstrings extracted from Python source code. Handles the

119

relationship between AST nodes and their docstring content.

120

121

Parameters

122

----------

123

node : ast.AST

124

AST node (FunctionDef, ClassDef, etc.) to validate

125

obj_name : str

126

Qualified name of the object

127

**kwargs

128

Additional validation configuration options

129

130

Attributes

131

----------

132

node : ast.AST

133

The AST node being validated

134

obj_name : str

135

Qualified object name for error reporting

136

"""

137

```

138

139

### AST Visitor

140

141

```python { .api }

142

class DocstringVisitor(ast.NodeVisitor):

143

"""

144

AST visitor for extracting docstrings from Python source.

145

146

Traverses the AST to find function and class definitions,

147

extracts their docstrings, and applies validation rules.

148

Handles nested classes and methods properly.

149

150

Parameters

151

----------

152

config : dict

153

Validation configuration

154

filepath : str

155

Path to file being processed (for error reporting)

156

157

Attributes

158

----------

159

config : dict

160

Validation configuration dictionary

161

filepath : str

162

Current file path

163

errors : list

164

Accumulated validation errors

165

"""

166

167

def visit_FunctionDef(self, node):

168

"""

169

Visit function definition nodes.

170

171

Extracts and validates docstrings from function definitions,

172

including methods within classes.

173

174

Parameters

175

----------

176

node : ast.FunctionDef

177

Function definition AST node

178

"""

179

180

def visit_ClassDef(self, node):

181

"""

182

Visit class definition nodes.

183

184

Extracts and validates docstrings from class definitions

185

and recursively processes methods within the class.

186

187

Parameters

188

----------

189

node : ast.ClassDef

190

Class definition AST node

191

"""

192

```

193

194

## Utility Functions

195

196

### Project Detection

197

198

```python { .api }

199

def find_project_root(srcs: List[str]) -> str:

200

"""

201

Find project root from config files.

202

203

Searches up the directory tree from the given source files

204

to find the project root, identified by configuration files

205

like pyproject.toml, setup.cfg, setup.py, or .git directory.

206

207

Parameters

208

----------

209

srcs : list of str

210

List of source file paths to start search from

211

212

Returns

213

-------

214

str

215

Path to project root directory

216

217

Examples

218

--------

219

>>> root = find_project_root(['src/mymodule.py'])

220

>>> print(root)

221

'/path/to/project'

222

"""

223

```

224

225

## Pre-commit Integration

226

227

### Hook Configuration

228

229

Add numpydoc validation to your `.pre-commit-config.yaml`:

230

231

```yaml

232

repos:

233

- repo: https://github.com/numpy/numpydoc

234

rev: v1.9.0

235

hooks:

236

- id: numpydoc-validation

237

files: \.py$

238

```

239

240

### Local Hook Setup

241

242

For local pre-commit hooks, use:

243

244

```yaml

245

repos:

246

- repo: local

247

hooks:

248

- id: numpydoc-validation

249

name: numpydoc docstring validation

250

entry: python -m numpydoc.hooks.validate_docstrings

251

language: system

252

files: \.py$

253

pass_filenames: true

254

```

255

256

## Configuration Examples

257

258

### pyproject.toml Configuration

259

260

```toml

261

[tool.numpydoc_validation]

262

checks = [

263

"all", # Enable all validation checks

264

"GL08", # Require docstrings

265

]

266

267

ignore = [

268

"GL01", # Allow docstring not starting immediately after quotes

269

"SS01", # Allow missing summary

270

]

271

272

exclude = [

273

"tests/.*", # Exclude test files

274

".*/_private.py", # Exclude private modules

275

"docs/conf.py", # Exclude Sphinx config

276

]

277

278

# Per-object validation overrides

279

[tool.numpydoc_validation.override]

280

"mypackage.legacy.*" = {all = false} # Disable all checks for legacy code

281

"mypackage.experimental.func" = {GL01 = false} # Disable specific check

282

```

283

284

### setup.cfg Configuration

285

286

```ini

287

[numpydoc_validation]

288

checks = all,GL08

289

ignore = GL01,SS01

290

exclude =

291

tests/.*

292

.*/_private.py

293

docs/conf.py

294

295

# Override format: object_pattern:error_code=false

296

override =

297

mypackage.legacy.*:all=false

298

mypackage.experimental.func:GL01=false

299

```

300

301

## Command-Line Usage

302

303

### Direct Hook Execution

304

305

```bash

306

# Run validation hook on specific files

307

python -m numpydoc.hooks.validate_docstrings src/mymodule.py src/utils.py

308

309

# Run with configuration file

310

python -m numpydoc.hooks.validate_docstrings --config pyproject.toml src/*.py

311

312

# Run with specific validation checks

313

python -m numpydoc.hooks.validate_docstrings --checks GL01,SS01 src/

314

```

315

316

### Pre-commit Integration

317

318

```bash

319

# Install pre-commit hooks

320

pre-commit install

321

322

# Run hooks manually

323

pre-commit run numpydoc-validation

324

325

# Run on all files

326

pre-commit run numpydoc-validation --all-files

327

328

# Run with verbose output

329

pre-commit run numpydoc-validation --verbose

330

```

331

332

## Usage Examples

333

334

### Basic Hook Usage

335

336

```python

337

from numpydoc.hooks.validate_docstrings import run_hook, parse_config

338

339

# Load project configuration

340

config = parse_config()

341

342

# Run validation on changed files

343

files = ['src/module1.py', 'src/module2.py']

344

exit_code = run_hook(files, config=config)

345

346

if exit_code == 0:

347

print("All docstrings valid!")

348

else:

349

print("Validation errors found")

350

```

351

352

### Custom Configuration

353

354

```python

355

from numpydoc.hooks.validate_docstrings import run_hook

356

357

# Custom validation configuration

358

config = {

359

'checks': {'GL01', 'SS01', 'PR01'},

360

'ignore': {'GL08'},

361

'exclude': {'tests/.*'},

362

'override': {

363

'mymodule.legacy_func': {'all': False}

364

}

365

}

366

367

# Run with custom config

368

exit_code = run_hook(['src/mymodule.py'], config=config)

369

```

370

371

### AST Processing Example

372

373

```python

374

import ast

375

from numpydoc.hooks.validate_docstrings import DocstringVisitor

376

377

# Parse Python source

378

with open('src/mymodule.py', 'r') as f:

379

source = f.read()

380

381

tree = ast.parse(source)

382

383

# Extract and validate docstrings

384

config = {'checks': {'all'}, 'ignore': set()}

385

visitor = DocstringVisitor(config, 'src/mymodule.py')

386

visitor.visit(tree)

387

388

# Print validation errors

389

for error in visitor.errors:

390

print(f"Line {error[0]}: {error[1]}: {error[2]}")

391

```

392

393

### Integration with CI/CD

394

395

```yaml

396

# GitHub Actions workflow

397

name: Docstring Validation

398

on: [push, pull_request]

399

400

jobs:

401

validate-docstrings:

402

runs-on: ubuntu-latest

403

steps:

404

- uses: actions/checkout@v2

405

- name: Set up Python

406

uses: actions/setup-python@v2

407

with:

408

python-version: '3.9'

409

- name: Install dependencies

410

run: |

411

pip install numpydoc

412

- name: Validate docstrings

413

run: |

414

python -m numpydoc.hooks.validate_docstrings src/

415

```

416

417

## Error Handling

418

419

The hooks module provides comprehensive error handling:

420

421

- **Syntax Errors**: Files with syntax errors are skipped with warnings

422

- **Import Errors**: Missing dependencies are handled gracefully

423

- **Configuration Errors**: Invalid config files produce clear error messages

424

- **File Access**: Permission and file system errors are reported appropriately

425

426

Exit codes follow standard conventions:

427

- **0**: Success (no validation errors)

428

- **1**: Validation errors found

429

- **2**: Configuration or argument errors

430

- **3**: File access or parsing errors