Coverage for src/griffe/_internal/docstrings/models.py: 92.16%

192 statements  

« prev     ^ index     » next       coverage.py v7.10.2, created at 2025-08-11 13:44 +0200

1# This module contains the models for storing docstrings structured data. 

2 

3from __future__ import annotations 

4 

5from typing import TYPE_CHECKING 

6 

7from griffe._internal.enumerations import DocstringSectionKind 

8from griffe._internal.expressions import ExprTuple 

9 

10if TYPE_CHECKING: 

11 from collections.abc import Sequence 

12 from typing import Any, Literal 

13 

14 from griffe._internal.expressions import Expr 

15 

16 

17# Elements ----------------------------------------------- 

18class DocstringElement: 

19 """This base class represents annotated, nameless elements.""" 

20 

21 def __init__(self, *, description: str, annotation: str | Expr | None = None) -> None: 

22 """Initialize the element. 

23 

24 Parameters: 

25 annotation: The element annotation, if any. 

26 description: The element description. 

27 """ 

28 self.description: str = description 

29 """The element description.""" 

30 self.annotation: str | Expr | None = annotation 

31 """The element annotation.""" 

32 

33 def as_dict(self, **kwargs: Any) -> dict[str, Any]: # noqa: ARG002 

34 """Return this element's data as a dictionary. 

35 

36 Parameters: 

37 **kwargs: Additional serialization options. 

38 

39 Returns: 

40 A dictionary. 

41 """ 

42 return { 

43 "annotation": self.annotation, 

44 "description": self.description, 

45 } 

46 

47 

48class DocstringNamedElement(DocstringElement): 

49 """This base class represents annotated, named elements.""" 

50 

51 def __init__( 

52 self, 

53 name: str, 

54 *, 

55 description: str, 

56 annotation: str | Expr | None = None, 

57 value: str | Expr | None = None, 

58 ) -> None: 

59 """Initialize the element. 

60 

61 Parameters: 

62 name: The element name. 

63 description: The element description. 

64 annotation: The element annotation, if any. 

65 value: The element value, as a string. 

66 """ 

67 super().__init__(description=description, annotation=annotation) 

68 self.name: str = name 

69 """The element name.""" 

70 self.value: str | Expr | None = value 

71 """The element value, if any""" 

72 

73 def as_dict(self, **kwargs: Any) -> dict[str, Any]: 

74 """Return this element's data as a dictionary. 

75 

76 Parameters: 

77 **kwargs: Additional serialization options. 

78 

79 Returns: 

80 A dictionary. 

81 """ 

82 base = {"name": self.name, **super().as_dict(**kwargs)} 

83 if self.value is not None: 

84 base["value"] = self.value 

85 return base 

86 

87 

88class DocstringAdmonition(DocstringElement): 

89 """This class represents an admonition.""" 

90 

91 @property 

92 def kind(self) -> str | Expr | None: 

93 """The kind of this admonition.""" 

94 return self.annotation 

95 

96 @kind.setter 

97 def kind(self, value: str | Expr) -> None: 

98 self.annotation = value 

99 

100 @property 

101 def contents(self) -> str: 

102 """The contents of this admonition.""" 

103 return self.description 

104 

105 @contents.setter 

106 def contents(self, value: str) -> None: 

107 self.description = value 

108 

109 

110class DocstringDeprecated(DocstringElement): 

111 """This class represents a documented deprecated item.""" 

112 

113 @property 

114 def version(self) -> str: 

115 """The version of this deprecation.""" 

116 return self.annotation # type: ignore[return-value] 

117 

118 @version.setter 

119 def version(self, value: str) -> None: 

120 self.annotation = value 

121 

122 

123class DocstringRaise(DocstringElement): 

124 """This class represents a documented raise value.""" 

125 

126 

127class DocstringWarn(DocstringElement): 

128 """This class represents a documented warn value.""" 

129 

130 

131class DocstringReturn(DocstringNamedElement): 

132 """This class represents a documented return value.""" 

133 

134 

135class DocstringYield(DocstringNamedElement): 

136 """This class represents a documented yield value.""" 

137 

138 

139class DocstringReceive(DocstringNamedElement): 

140 """This class represents a documented receive value.""" 

141 

142 

143class DocstringParameter(DocstringNamedElement): 

144 """This class represent a documented function parameter.""" 

145 

146 @property 

147 def default(self) -> str | Expr | None: 

148 """The default value of this parameter.""" 

149 return self.value 

150 

151 @default.setter 

152 def default(self, value: str) -> None: 

153 self.value = value 

154 

155 

156class DocstringTypeParameter(DocstringNamedElement): 

157 """This class represent a documented type parameter.""" 

158 

159 @property 

160 def default(self) -> str | Expr | None: 

161 """The default value of this type parameter.""" 

162 return self.value 

163 

164 @default.setter 

165 def default(self, value: str) -> None: 

166 self.value = value 

167 

168 @property 

169 def bound(self) -> str | Expr | None: 

170 """The bound of this type parameter.""" 

171 if not isinstance(self.annotation, ExprTuple): 

172 return self.annotation 

173 return None 

174 

175 @bound.setter 

176 def bound(self, bound: str | Expr | None) -> None: 

177 self.annotation = bound 

178 

179 @property 

180 def constraints(self) -> tuple[str | Expr, ...] | None: 

181 """The constraints of this type parameter.""" 

182 if isinstance(self.annotation, ExprTuple): 

183 return tuple(self.annotation.elements) 

184 return None 

185 

186 @constraints.setter 

187 def constraints(self, constraints: Sequence[str | Expr] | None) -> None: 

188 if constraints is not None: 

189 self.annotation = ExprTuple(constraints) 

190 else: 

191 self.annotation = None 

192 

193 

194class DocstringAttribute(DocstringNamedElement): 

195 """This class represents a documented module/class attribute.""" 

196 

197 

198class DocstringFunction(DocstringNamedElement): 

199 """This class represents a documented function.""" 

200 

201 @property 

202 def signature(self) -> str | Expr | None: 

203 """The function signature.""" 

204 return self.annotation 

205 

206 

207class DocstringClass(DocstringNamedElement): 

208 """This class represents a documented class.""" 

209 

210 @property 

211 def signature(self) -> str | Expr | None: 

212 """The class signature.""" 

213 return self.annotation 

214 

215 

216class DocstringTypeAlias(DocstringNamedElement): 

217 """This class represents a documented type alias.""" 

218 

219 

220class DocstringModule(DocstringNamedElement): 

221 """This class represents a documented module.""" 

222 

223 

224# Sections ----------------------------------------------- 

225class DocstringSection: 

226 """This class represents a docstring section.""" 

227 

228 kind: DocstringSectionKind 

229 """The section kind.""" 

230 

231 def __init__(self, title: str | None = None) -> None: 

232 """Initialize the section. 

233 

234 Parameters: 

235 title: An optional title. 

236 """ 

237 self.title: str | None = title 

238 """The section title.""" 

239 self.value: Any = None 

240 """The section value.""" 

241 

242 def __bool__(self) -> bool: 

243 """Whether this section has a true-ish value.""" 

244 return bool(self.value) 

245 

246 def as_dict(self, **kwargs: Any) -> dict[str, Any]: 

247 """Return this section's data as a dictionary. 

248 

249 Parameters: 

250 **kwargs: Additional serialization options. 

251 

252 Returns: 

253 A dictionary. 

254 """ 

255 if hasattr(self.value, "as_dict"): # noqa: SIM108 255 ↛ 256line 255 didn't jump to line 256 because the condition on line 255 was never true

256 serialized_value = self.value.as_dict(**kwargs) 

257 else: 

258 serialized_value = self.value 

259 base = {"kind": self.kind.value, "value": serialized_value} 

260 if self.title: 260 ↛ 261line 260 didn't jump to line 261 because the condition on line 260 was never true

261 base["title"] = self.title 

262 return base 

263 

264 

265class DocstringSectionText(DocstringSection): 

266 """This class represents a text section.""" 

267 

268 kind: DocstringSectionKind = DocstringSectionKind.text 

269 

270 def __init__(self, value: str, title: str | None = None) -> None: 

271 """Initialize the section. 

272 

273 Parameters: 

274 value: The section text. 

275 title: An optional title. 

276 """ 

277 super().__init__(title) 

278 self.value: str = value 

279 

280 

281class DocstringSectionParameters(DocstringSection): 

282 """This class represents a parameters section.""" 

283 

284 kind: DocstringSectionKind = DocstringSectionKind.parameters 

285 

286 def __init__(self, value: list[DocstringParameter], title: str | None = None) -> None: 

287 """Initialize the section. 

288 

289 Parameters: 

290 value: The section parameters. 

291 title: An optional title. 

292 """ 

293 super().__init__(title) 

294 self.value: list[DocstringParameter] = value 

295 

296 

297class DocstringSectionOtherParameters(DocstringSectionParameters): 

298 """This class represents an other parameters section.""" 

299 

300 kind: DocstringSectionKind = DocstringSectionKind.other_parameters 

301 

302 

303class DocstringSectionTypeParameters(DocstringSection): 

304 """This class represents a type parameters section.""" 

305 

306 kind: DocstringSectionKind = DocstringSectionKind.type_parameters 

307 

308 def __init__(self, value: list[DocstringTypeParameter], title: str | None = None) -> None: 

309 """Initialize the section. 

310 

311 Parameters: 

312 value: The section type parameters. 

313 title: An optional title. 

314 """ 

315 super().__init__(title) 

316 self.value: list[DocstringTypeParameter] = value 

317 

318 

319class DocstringSectionRaises(DocstringSection): 

320 """This class represents a raises section.""" 

321 

322 kind: DocstringSectionKind = DocstringSectionKind.raises 

323 

324 def __init__(self, value: list[DocstringRaise], title: str | None = None) -> None: 

325 """Initialize the section. 

326 

327 Parameters: 

328 value: The section exceptions. 

329 title: An optional title. 

330 """ 

331 super().__init__(title) 

332 self.value: list[DocstringRaise] = value 

333 

334 

335class DocstringSectionWarns(DocstringSection): 

336 """This class represents a warns section.""" 

337 

338 kind: DocstringSectionKind = DocstringSectionKind.warns 

339 

340 def __init__(self, value: list[DocstringWarn], title: str | None = None) -> None: 

341 """Initialize the section. 

342 

343 Parameters: 

344 value: The section warnings. 

345 title: An optional title. 

346 """ 

347 super().__init__(title) 

348 self.value: list[DocstringWarn] = value 

349 

350 

351class DocstringSectionReturns(DocstringSection): 

352 """This class represents a returns section.""" 

353 

354 kind: DocstringSectionKind = DocstringSectionKind.returns 

355 

356 def __init__(self, value: list[DocstringReturn], title: str | None = None) -> None: 

357 """Initialize the section. 

358 

359 Parameters: 

360 value: The section returned items. 

361 title: An optional title. 

362 """ 

363 super().__init__(title) 

364 self.value: list[DocstringReturn] = value 

365 

366 

367class DocstringSectionYields(DocstringSection): 

368 """This class represents a yields section.""" 

369 

370 kind: DocstringSectionKind = DocstringSectionKind.yields 

371 

372 def __init__(self, value: list[DocstringYield], title: str | None = None) -> None: 

373 """Initialize the section. 

374 

375 Parameters: 

376 value: The section yielded items. 

377 title: An optional title. 

378 """ 

379 super().__init__(title) 

380 self.value: list[DocstringYield] = value 

381 

382 

383class DocstringSectionReceives(DocstringSection): 

384 """This class represents a receives section.""" 

385 

386 kind: DocstringSectionKind = DocstringSectionKind.receives 

387 

388 def __init__(self, value: list[DocstringReceive], title: str | None = None) -> None: 

389 """Initialize the section. 

390 

391 Parameters: 

392 value: The section received items. 

393 title: An optional title. 

394 """ 

395 super().__init__(title) 

396 self.value: list[DocstringReceive] = value 

397 

398 

399class DocstringSectionExamples(DocstringSection): 

400 """This class represents an examples section.""" 

401 

402 kind: DocstringSectionKind = DocstringSectionKind.examples 

403 

404 def __init__( 

405 self, 

406 value: list[tuple[Literal[DocstringSectionKind.text, DocstringSectionKind.examples], str]], 

407 title: str | None = None, 

408 ) -> None: 

409 """Initialize the section. 

410 

411 Parameters: 

412 value: The section examples. 

413 title: An optional title. 

414 """ 

415 super().__init__(title) 

416 self.value: list[tuple[Literal[DocstringSectionKind.text, DocstringSectionKind.examples], str]] = value 

417 

418 

419class DocstringSectionAttributes(DocstringSection): 

420 """This class represents an attributes section.""" 

421 

422 kind: DocstringSectionKind = DocstringSectionKind.attributes 

423 

424 def __init__(self, value: list[DocstringAttribute], title: str | None = None) -> None: 

425 """Initialize the section. 

426 

427 Parameters: 

428 value: The section attributes. 

429 title: An optional title. 

430 """ 

431 super().__init__(title) 

432 self.value: list[DocstringAttribute] = value 

433 

434 

435class DocstringSectionFunctions(DocstringSection): 

436 """This class represents a functions/methods section.""" 

437 

438 kind: DocstringSectionKind = DocstringSectionKind.functions 

439 

440 def __init__(self, value: list[DocstringFunction], title: str | None = None) -> None: 

441 """Initialize the section. 

442 

443 Parameters: 

444 value: The section functions. 

445 title: An optional title. 

446 """ 

447 super().__init__(title) 

448 self.value: list[DocstringFunction] = value 

449 

450 

451class DocstringSectionClasses(DocstringSection): 

452 """This class represents a classes section.""" 

453 

454 kind: DocstringSectionKind = DocstringSectionKind.classes 

455 

456 def __init__(self, value: list[DocstringClass], title: str | None = None) -> None: 

457 """Initialize the section. 

458 

459 Parameters: 

460 value: The section classes. 

461 title: An optional title. 

462 """ 

463 super().__init__(title) 

464 self.value: list[DocstringClass] = value 

465 

466 

467class DocstringSectionTypeAliases(DocstringSection): 

468 """This class represents a type aliases section.""" 

469 

470 kind: DocstringSectionKind = DocstringSectionKind.type_aliases 

471 

472 def __init__(self, value: list[DocstringTypeAlias], title: str | None = None) -> None: 

473 """Initialize the section. 

474 

475 Parameters: 

476 value: The section classes. 

477 title: An optional title. 

478 """ 

479 super().__init__(title) 

480 self.value: list[DocstringTypeAlias] = value 

481 

482 

483class DocstringSectionModules(DocstringSection): 

484 """This class represents a modules section.""" 

485 

486 kind: DocstringSectionKind = DocstringSectionKind.modules 

487 

488 def __init__(self, value: list[DocstringModule], title: str | None = None) -> None: 

489 """Initialize the section. 

490 

491 Parameters: 

492 value: The section modules. 

493 title: An optional title. 

494 """ 

495 super().__init__(title) 

496 self.value: list[DocstringModule] = value 

497 

498 

499class DocstringSectionDeprecated(DocstringSection): 

500 """This class represents a deprecated section.""" 

501 

502 kind: DocstringSectionKind = DocstringSectionKind.deprecated 

503 

504 def __init__(self, version: str, text: str, title: str | None = None) -> None: 

505 """Initialize the section. 

506 

507 Parameters: 

508 version: The deprecation version. 

509 text: The deprecation text. 

510 title: An optional title. 

511 """ 

512 super().__init__(title) 

513 self.value: DocstringDeprecated = DocstringDeprecated(annotation=version, description=text) 

514 

515 

516class DocstringSectionAdmonition(DocstringSection): 

517 """This class represents an admonition section.""" 

518 

519 kind: DocstringSectionKind = DocstringSectionKind.admonition 

520 

521 def __init__(self, kind: str, text: str, title: str | None = None) -> None: 

522 """Initialize the section. 

523 

524 Parameters: 

525 kind: The admonition kind. 

526 text: The admonition text. 

527 title: An optional title. 

528 """ 

529 super().__init__(title) 

530 self.value: DocstringAdmonition = DocstringAdmonition(annotation=kind, description=text)