0
# Utility APIs
1
2
Comprehensive set of utility classes and functions for programmatic docstring analysis, AST processing, and argument handling.
3
4
## Capabilities
5
6
### Argument Handling Classes
7
8
Classes for representing and manipulating function arguments from both AST nodes and docstring parameters.
9
10
```python { .api }
11
class Arg:
12
"""
13
Represents a function argument with name and type hint information.
14
15
Provides methods for comparing arguments and checking type hint presence,
16
with factory methods for creating from different sources.
17
"""
18
19
name: str
20
typeHint: str
21
22
def __init__(self, name: str, typeHint: str) -> None:
23
"""
24
Initialize argument with name and type hint.
25
26
Parameters:
27
- name: Argument name
28
- typeHint: Type hint string (empty string if no type hint)
29
"""
30
31
def nameEquals(self, other: 'Arg') -> bool:
32
"""
33
Check if argument names are equal.
34
35
Parameters:
36
- other: Another Arg object to compare with
37
38
Returns:
39
bool: True if names match
40
"""
41
42
def hasTypeHint(self) -> bool:
43
"""
44
Check if argument has a type hint.
45
46
Returns:
47
bool: True if type hint is present and non-empty
48
"""
49
50
def isStarArg(self) -> bool:
51
"""
52
Check if this is a star argument (*args or **kwargs).
53
54
Returns:
55
bool: True if argument name starts with * or **
56
"""
57
58
def notStarArg(self) -> bool:
59
"""
60
Check if this is not a star argument.
61
62
Returns:
63
bool: True if argument name doesn't start with * or **
64
"""
65
66
@classmethod
67
def fromDocstringParam(cls, param: DocstringParam) -> 'Arg':
68
"""
69
Create Arg from docstring parameter.
70
71
Parameters:
72
- param: Docstring parameter object
73
74
Returns:
75
Arg: New argument object
76
"""
77
78
@classmethod
79
def fromDocstringAttr(cls, attr: DocstringAttr) -> 'Arg':
80
"""
81
Create Arg from docstring attribute.
82
83
Parameters:
84
- attr: Docstring attribute object
85
86
Returns:
87
Arg: New argument object representing class attribute
88
"""
89
90
@classmethod
91
def fromAstArg(cls, astArg: ast.arg) -> 'Arg':
92
"""
93
Create Arg from AST argument node.
94
95
Parameters:
96
- astArg: AST argument node
97
98
Returns:
99
Arg: New argument object
100
"""
101
102
class ArgList:
103
"""
104
Container for multiple Arg objects with list-like operations.
105
106
Provides methods for comparing argument lists, filtering, and
107
various operations needed for docstring validation.
108
"""
109
110
infoList: list[Arg]
111
112
def __init__(self, infoList: list[Arg]) -> None:
113
"""
114
Initialize argument list.
115
116
Parameters:
117
- infoList: List of Arg objects
118
"""
119
120
@classmethod
121
def fromDocstringParam(cls, params: list[DocstringParam]) -> 'ArgList':
122
"""
123
Create ArgList from docstring parameters.
124
125
Parameters:
126
- params: List of docstring parameter objects
127
128
Returns:
129
ArgList: New argument list
130
"""
131
132
@classmethod
133
def fromDocstringAttr(cls, attrs: list[DocstringAttr]) -> 'ArgList':
134
"""
135
Create ArgList from docstring attributes.
136
137
Parameters:
138
- attrs: List of docstring attribute objects
139
140
Returns:
141
ArgList: New argument list for class attributes
142
"""
143
144
def noTypeHints(self) -> bool:
145
"""
146
Check if no arguments have type hints.
147
148
Returns:
149
bool: True if no arguments have type hints
150
"""
151
152
def notAllArgsHaveTypeHints(self) -> bool:
153
"""
154
Check if not all arguments have type hints.
155
156
Returns:
157
bool: True if some arguments lack type hints
158
"""
159
160
def exists(self) -> bool:
161
"""
162
Check if argument list is not empty.
163
164
Returns:
165
bool: True if list contains arguments
166
"""
167
168
def length(self) -> int:
169
"""
170
Get number of arguments.
171
172
Returns:
173
int: Number of arguments in list
174
"""
175
176
def equals(self, other: 'ArgList') -> bool:
177
"""
178
Check if two argument lists have same names.
179
180
Parameters:
181
- other: Another ArgList to compare
182
183
Returns:
184
bool: True if argument names match
185
"""
186
187
def subtract(self, other: 'ArgList') -> 'ArgList':
188
"""
189
Subtract another argument list from this one.
190
191
Parameters:
192
- other: ArgList to subtract
193
194
Returns:
195
ArgList: New list with arguments not in other list
196
"""
197
```
198
199
### Docstring Representation
200
201
Class for parsing and representing docstring content with style-aware parsing.
202
203
```python { .api }
204
class Doc:
205
"""
206
Represents a parsed docstring with style-aware section extraction.
207
208
Parses docstrings in numpy, google, or sphinx style and provides
209
access to different sections like arguments, returns, yields, etc.
210
"""
211
212
def __init__(self, docstring: str, style: str = 'numpy') -> None:
213
"""
214
Initialize docstring parser.
215
216
Parameters:
217
- docstring: Raw docstring text
218
- style: Docstring style ('numpy', 'google', 'sphinx')
219
"""
220
221
@property
222
def isShortDocstring(self) -> bool:
223
"""
224
Check if docstring contains only a short summary.
225
226
Returns:
227
bool: True if docstring has no parameter/return sections
228
"""
229
230
@property
231
def argList(self) -> ArgList:
232
"""
233
Get argument list from docstring parameters section.
234
235
Returns:
236
ArgList: Arguments documented in docstring
237
"""
238
239
@property
240
def attrList(self) -> ArgList:
241
"""
242
Get attribute list from docstring attributes section.
243
244
Returns:
245
ArgList: Class attributes documented in docstring
246
"""
247
248
@property
249
def hasReturnsSection(self) -> bool:
250
"""
251
Check if docstring has a returns section.
252
253
Returns:
254
bool: True if returns section is present
255
"""
256
257
@property
258
def hasYieldsSection(self) -> bool:
259
"""
260
Check if docstring has a yields section.
261
262
Returns:
263
bool: True if yields section is present
264
"""
265
266
@property
267
def hasRaisesSection(self) -> bool:
268
"""
269
Check if docstring has a raises section.
270
271
Returns:
272
bool: True if raises section is present
273
"""
274
275
@property
276
def returns(self) -> list[DocstringParam]:
277
"""
278
Get returns section parameters.
279
280
Returns:
281
list[DocstringParam]: Return value documentation
282
"""
283
284
@property
285
def yields(self) -> list[DocstringParam]:
286
"""
287
Get yields section parameters.
288
289
Returns:
290
list[DocstringParam]: Yield value documentation
291
"""
292
293
@property
294
def raises(self) -> list[DocstringParam]:
295
"""
296
Get raises section parameters.
297
298
Returns:
299
list[DocstringParam]: Exception documentation
300
"""
301
```
302
303
### Return and Yield Representations
304
305
Data classes for representing return and yield information.
306
307
```python { .api }
308
@dataclass
309
class ReturnArg:
310
"""
311
Represents return value information from docstring or annotation.
312
313
Contains type information and description for function return values.
314
"""
315
316
type: str
317
description: str
318
319
def __post_init__(self) -> None:
320
"""Post-initialization processing."""
321
322
@dataclass
323
class YieldArg:
324
"""
325
Represents yield value information from docstring or annotation.
326
327
Contains type information and description for generator yield values.
328
"""
329
330
type: str
331
description: str
332
333
def __post_init__(self) -> None:
334
"""Post-initialization processing."""
335
```
336
337
### AST Analysis Utilities
338
339
Functions for analyzing AST nodes to extract return, yield, and raise information.
340
341
```python { .api }
342
def hasReturnAnnotation(node: FuncOrAsyncFuncDef) -> bool:
343
"""
344
Check if function has return type annotation.
345
346
Parameters:
347
- node: Function or async function AST node
348
349
Returns:
350
bool: True if return annotation is present
351
"""
352
353
def isReturnAnnotationNone(node: FuncOrAsyncFuncDef) -> bool:
354
"""
355
Check if return annotation is None.
356
357
Parameters:
358
- node: Function or async function AST node
359
360
Returns:
361
bool: True if return annotation is None
362
"""
363
364
def isReturnAnnotationNoReturn(node: FuncOrAsyncFuncDef) -> bool:
365
"""
366
Check if return annotation is NoReturn.
367
368
Parameters:
369
- node: Function or async function AST node
370
371
Returns:
372
bool: True if return annotation is NoReturn
373
"""
374
375
def hasGeneratorAsReturnAnnotation(node: FuncOrAsyncFuncDef) -> bool:
376
"""
377
Check if return annotation is a Generator type.
378
379
Parameters:
380
- node: Function or async function AST node
381
382
Returns:
383
bool: True if return annotation indicates generator
384
"""
385
386
def hasIteratorOrIterableAsReturnAnnotation(node: FuncOrAsyncFuncDef) -> bool:
387
"""
388
Check if return annotation is Iterator or Iterable.
389
390
Parameters:
391
- node: Function or async function AST node
392
393
Returns:
394
bool: True if return annotation is Iterator/Iterable
395
"""
396
397
def hasYieldStatements(node: FuncOrAsyncFuncDef) -> bool:
398
"""
399
Check if function contains yield statements.
400
401
Parameters:
402
- node: Function or async function AST node
403
404
Returns:
405
bool: True if function yields values
406
"""
407
408
def hasReturnStatements(node: FuncOrAsyncFuncDef) -> bool:
409
"""
410
Check if function contains return statements.
411
412
Parameters:
413
- node: Function or async function AST node
414
415
Returns:
416
bool: True if function has return statements
417
"""
418
419
def hasBareReturnStatements(node: FuncOrAsyncFuncDef) -> bool:
420
"""
421
Check if function contains bare return statements (return without value).
422
423
Parameters:
424
- node: Function or async function AST node
425
426
Returns:
427
bool: True if function has bare return statements
428
"""
429
430
def hasRaiseStatements(node: FuncOrAsyncFuncDef) -> bool:
431
"""
432
Check if function contains raise statements.
433
434
Parameters:
435
- node: Function or async function AST node
436
437
Returns:
438
bool: True if function raises exceptions
439
"""
440
441
def hasAssertStatements(node: FuncOrAsyncFuncDef) -> bool:
442
"""
443
Check if function contains assert statements.
444
445
Parameters:
446
- node: Function or async function AST node
447
448
Returns:
449
bool: True if function has assert statements
450
"""
451
452
def getRaisedExceptions(node: FuncOrAsyncFuncDef) -> list[str]:
453
"""
454
Get list of exceptions raised by function.
455
456
Parameters:
457
- node: Function or async function AST node
458
459
Returns:
460
list[str]: Names of exceptions that may be raised
461
"""
462
```
463
464
### Special Method Detection
465
466
Functions for detecting special method types and decorators.
467
468
```python { .api }
469
def checkIsAbstractMethod(node: FuncOrAsyncFuncDef) -> bool:
470
"""
471
Check if method is decorated with @abstractmethod.
472
473
Parameters:
474
- node: Function or async function AST node
475
476
Returns:
477
bool: True if method is abstract
478
"""
479
480
def checkIsPropertyMethod(node: FuncOrAsyncFuncDef) -> bool:
481
"""
482
Check if method is decorated with @property.
483
484
Parameters:
485
- node: Function or async function AST node
486
487
Returns:
488
bool: True if method is a property
489
"""
490
491
def checkMethodContainsSpecifiedDecorator(
492
node: FuncOrAsyncFuncDef,
493
decorator_name: str
494
) -> bool:
495
"""
496
Check if method has specific decorator.
497
498
Parameters:
499
- node: Function or async function AST node
500
- decorator_name: Name of decorator to check for
501
502
Returns:
503
bool: True if decorator is present
504
"""
505
```
506
507
### Docstring Parsing
508
509
Functions for parsing docstrings in different styles.
510
511
```python { .api }
512
def parseDocstring(
513
docstring: str,
514
style: str,
515
filename: str = '<unknown>',
516
lineNum: int = 0
517
) -> Doc | None:
518
"""
519
Parse docstring with error handling.
520
521
Parameters:
522
- docstring: Raw docstring text
523
- style: Docstring style ('numpy', 'google', 'sphinx')
524
- filename: Source filename for error reporting
525
- lineNum: Line number for error reporting
526
527
Returns:
528
Doc | None: Parsed docstring object, or None if parsing fails
529
"""
530
531
def parseDocstringInGivenStyle(docstring: str, style: str) -> Doc | None:
532
"""
533
Parse docstring in specific style without error handling.
534
535
Parameters:
536
- docstring: Raw docstring text
537
- style: Docstring style to use
538
539
Returns:
540
Doc | None: Parsed docstring object, or None if parsing fails
541
"""
542
```
543
544
### Generic Utility Functions
545
546
Core utility functions for AST processing and string manipulation.
547
548
```python { .api }
549
def collectFuncArgs(node: FuncOrAsyncFuncDef) -> list[ast.arg]:
550
"""
551
Collect all function arguments from AST node.
552
553
Parameters:
554
- node: Function or async function AST node
555
556
Returns:
557
list[ast.arg]: All function arguments
558
"""
559
560
def getFunctionId(node: FuncOrAsyncFuncDef) -> tuple[int, int, str]:
561
"""
562
Get function identifier information.
563
564
Parameters:
565
- node: Function or async function AST node
566
567
Returns:
568
tuple containing:
569
- int: Line number
570
- int: Column offset
571
- str: Function name
572
"""
573
574
def detectMethodType(node: FuncOrAsyncFuncDef) -> MethodType:
575
"""
576
Detect the type of method (function, method, classmethod, etc.).
577
578
Parameters:
579
- node: Function or async function AST node
580
581
Returns:
582
MethodType: Detected method type
583
"""
584
585
def getDocstring(node: ClassOrFunctionDef) -> str:
586
"""
587
Extract docstring from class or function node.
588
589
Parameters:
590
- node: Class or function definition AST node
591
592
Returns:
593
str: Docstring text, or empty string if none
594
"""
595
596
def getNodeName(node: ast.AST) -> str:
597
"""
598
Get name from AST node.
599
600
Parameters:
601
- node: AST node
602
603
Returns:
604
str: Node name if available, otherwise empty string
605
"""
606
607
def stripQuotes(string: str | None) -> str | None:
608
"""
609
Remove surrounding quotes from string.
610
611
Parameters:
612
- string: String that may have quotes
613
614
Returns:
615
str | None: String without quotes, or None if input is None
616
"""
617
618
def specialEqual(str1: str, str2: str) -> bool:
619
"""
620
Special equality check for type hints and arguments.
621
622
Parameters:
623
- str1: First string to compare
624
- str2: Second string to compare
625
626
Returns:
627
bool: True if strings are considered equal
628
"""
629
630
def stripCommentsFromTypeHints(typeHint: str) -> str:
631
"""
632
Remove comments from type hint strings.
633
634
Parameters:
635
- typeHint: Type hint string that may contain comments
636
637
Returns:
638
str: Type hint with comments removed
639
"""
640
```
641
642
### Custom Exceptions
643
644
```python { .api }
645
class EdgeCaseError(Exception):
646
"""
647
Exception raised for edge cases in docstring analysis.
648
649
Used to handle unusual or unexpected scenarios during
650
AST analysis and docstring parsing.
651
"""
652
pass
653
```
654
655
## Usage Examples
656
657
### Argument Analysis
658
659
```python
660
import ast
661
from pydoclint.utils.arg import Arg, ArgList
662
from pydoclint.utils.generic import collectFuncArgs
663
664
# Parse function and analyze arguments
665
source = '''
666
def example_func(x: int, y: str = "default", *args, **kwargs) -> bool:
667
"""Example function."""
668
return True
669
'''
670
671
tree = ast.parse(source)
672
func_node = tree.body[0]
673
674
# Get AST arguments
675
ast_args = collectFuncArgs(func_node)
676
677
# Create Arg objects
678
args = [Arg.fromAstArg(arg) for arg in ast_args]
679
arg_list = ArgList(args)
680
681
print(f"Function has {arg_list.length()} arguments")
682
print(f"All have type hints: {not arg_list.notAllArgsHaveTypeHints()}")
683
684
# Check individual arguments
685
for arg in args:
686
print(f"Arg '{arg.name}': type hint = '{arg.typeHint}', is star = {arg.isStarArg()}")
687
```
688
689
### Docstring Analysis
690
691
```python
692
from pydoclint.utils.parse_docstring import parseDocstring
693
from pydoclint.utils.doc import Doc
694
695
docstring = '''
696
Example function.
697
698
Parameters
699
----------
700
x : int
701
First parameter
702
y : str
703
Second parameter
704
705
Returns
706
-------
707
bool
708
Success flag
709
'''
710
711
# Parse docstring
712
doc = parseDocstring(docstring, "numpy")
713
714
if doc:
715
print(f"Is short docstring: {doc.isShortDocstring}")
716
print(f"Has returns section: {doc.hasReturnsSection}")
717
print(f"Arguments: {[arg.name for arg in doc.argList.infoList]}")
718
719
# Compare with function signature
720
# ... validation logic here
721
```
722
723
### AST Analysis
724
725
```python
726
from pydoclint.utils.return_yield_raise import (
727
hasReturnAnnotation, hasYieldStatements, hasRaiseStatements
728
)
729
730
# Analyze function characteristics
731
if hasReturnAnnotation(func_node):
732
print("Function has return annotation")
733
734
if hasYieldStatements(func_node):
735
print("Function is a generator")
736
737
if hasRaiseStatements(func_node):
738
exceptions = getRaisedExceptions(func_node)
739
print(f"Function may raise: {exceptions}")
740
```
741
742
## Types
743
744
```python { .api }
745
# Union types for AST nodes
746
FuncOrAsyncFuncDef = Union[ast.FunctionDef, ast.AsyncFunctionDef]
747
ClassOrFunctionDef = Union[ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef]
748
749
# Method type enumeration
750
class MethodType(Enum):
751
FUNCTION = "function"
752
METHOD = "method"
753
CLASSMETHOD = "classmethod"
754
STATICMETHOD = "staticmethod"
755
PROPERTY = "property"
756
757
# Docstring parsing types from docstring_parser_fork
758
DocstringParam = Any # Parameter from parsed docstring
759
DocstringAttr = Any # Attribute from parsed docstring
760
```