A flake8 plugin that enforces PEP 8 naming conventions in Python code
npx @tessl/cli install tessl/pypi-pep8-naming@0.15.00
# pep8-naming
1
2
A flake8 plugin that enforces PEP 8 naming conventions in Python code. The plugin automatically detects various naming violations including improper class names, function names, variable names, constant names, and import naming issues. It integrates seamlessly with flake8's existing workflow and provides configurable options for customizing behavior.
3
4
## Package Information
5
6
- **Package Name**: pep8-naming
7
- **Language**: Python
8
- **Installation**: `pip install pep8-naming`
9
- **Requirements**: Python ≥3.9, flake8 ≥5.0.0
10
11
## Core Imports
12
13
The plugin is automatically loaded by flake8 when both packages are installed:
14
15
```python
16
# The plugin is used through flake8, not directly imported
17
# But if you need to use components programmatically:
18
from pep8ext_naming import NamingChecker, BaseASTCheck, FunctionType, NameSet
19
from pep8ext_naming import ClassNameCheck, FunctionNameCheck, FunctionArgNamesCheck
20
from pep8ext_naming import ImportAsCheck, VariablesCheck, TypeVarNameCheck
21
from pep8ext_naming import is_mixed_case, _extract_names, _build_decorator_to_type
22
23
# For working with AST nodes:
24
import ast
25
from collections import deque
26
from collections.abc import Sequence, Iterator
27
```
28
29
## Basic Usage
30
31
The plugin is used through flake8's command line interface:
32
33
```bash
34
# Install both flake8 and pep8-naming
35
pip install flake8 pep8-naming
36
37
# Run flake8 on your code - the naming plugin is automatically enabled
38
flake8 myproject/
39
40
# Check specific files
41
flake8 myfile.py
42
43
# Use configuration options
44
flake8 --ignore-names="setUp,tearDown" --classmethod-decorators="classmethod,declared_attr" myproject/
45
```
46
47
Configuration can also be placed in setup.cfg, tox.ini, or .flake8:
48
49
```ini
50
[flake8]
51
ignore-names = setUp,tearDown,setUpClass,tearDownClass
52
classmethod-decorators = classmethod,declared_attr
53
staticmethod-decorators = staticmethod
54
```
55
56
## Architecture
57
58
The plugin uses flake8's AST visitor pattern with the following key components:
59
60
- **NamingChecker**: Main plugin class that coordinates all checks and integrates with flake8
61
- **BaseASTCheck**: Abstract base class for all naming checks with error reporting functionality
62
- **Checker Classes**: Specialized classes for different types of naming violations (ClassNameCheck, FunctionNameCheck, etc.)
63
- **Configuration System**: Flexible options for customizing ignored names and decorator recognition
64
65
## Capabilities
66
67
### Main Plugin Interface
68
69
The primary interface for flake8 integration, providing all configuration options and error detection coordination.
70
71
```python { .api }
72
class NamingChecker:
73
"""Main flake8 plugin checker for PEP-8 naming conventions."""
74
name = 'naming'
75
version = '0.15.1'
76
77
def __init__(self, tree, filename):
78
"""Initialize checker with AST tree and filename."""
79
80
@classmethod
81
def add_options(cls, parser):
82
"""Add command-line options to flake8 parser."""
83
84
@classmethod
85
def parse_options(cls, options):
86
"""Parse and store configuration from flake8 options."""
87
88
def run(self):
89
"""Run all checks and yield violations as (line, col, message, type) tuples."""
90
91
def visit_tree(self, node, parents):
92
"""
93
Recursively visit AST tree nodes and yield violations.
94
95
Args:
96
node: AST node to visit
97
parents: deque of parent nodes for context
98
99
Yields:
100
Tuples of (line, col, message, checker) for each violation found
101
"""
102
103
def visit_node(self, node, parents):
104
"""
105
Visit individual AST node and call appropriate visitor methods.
106
107
Args:
108
node: AST node to process
109
parents: Sequence of parent nodes for context
110
111
Yields:
112
Tuples of (line, col, message, checker) for each violation found
113
"""
114
115
def tag_class_functions(self, cls_node):
116
"""
117
Tag functions if they are methods, classmethods, staticmethods.
118
119
Args:
120
cls_node: ast.ClassDef node to analyze
121
"""
122
123
def set_function_nodes_types(self, nodes, ismetaclass, late_decoration):
124
"""
125
Set function_type attributes on AST function nodes.
126
127
Args:
128
nodes: Iterator of AST nodes to process
129
ismetaclass: Whether the containing class is a metaclass
130
late_decoration: Dict mapping function names to decorator types
131
"""
132
133
@classmethod
134
def find_decorator_name(cls, d):
135
"""
136
Extract decorator name from AST decorator node.
137
138
Args:
139
d: AST decorator node (ast.Name, ast.Attribute, or ast.Call)
140
141
Returns:
142
Decorator name as string, or None if not found
143
"""
144
145
@staticmethod
146
def find_global_defs(func_def_node):
147
"""
148
Find global variable declarations within function.
149
150
Args:
151
func_def_node: ast.FunctionDef or ast.AsyncFunctionDef node
152
"""
153
```
154
155
### Check Base Classes
156
157
Foundation classes for implementing naming convention checks.
158
159
```python { .api }
160
class BaseASTCheck:
161
"""Base class for AST-based naming checks."""
162
all = [] # Registry of all check instances
163
codes = () # Error codes handled by this checker
164
165
def err(self, node, code, **kwargs):
166
"""Create error tuple for a naming violation."""
167
168
class NameSet(frozenset):
169
"""Set of names supporting Unix shell-style wildcard matching."""
170
171
def __new__(cls, iterable):
172
"""Create NameSet with wildcard pattern detection."""
173
174
def __contains__(self, item):
175
"""Check membership with wildcard pattern matching support."""
176
```
177
178
### Function Type Classification
179
180
Enumeration and utilities for classifying different types of functions and methods.
181
182
```python { .api }
183
class FunctionType(enum.Enum):
184
"""Enumeration of function/method types for naming checks."""
185
CLASSMETHOD = 'classmethod'
186
STATICMETHOD = 'staticmethod'
187
FUNCTION = 'function'
188
METHOD = 'method'
189
```
190
191
### Naming Check Classes
192
193
Specialized checker classes that implement specific naming convention rules.
194
195
```python { .api }
196
class ClassNameCheck(BaseASTCheck):
197
"""Checks class names use CapWords convention and exception names end with Error."""
198
N801 = "class name '{name}' should use CapWords convention"
199
N818 = "exception name '{name}' should be named with an Error suffix"
200
201
def visit_classdef(self, node, parents, ignored):
202
"""Check class definition for naming violations."""
203
204
@classmethod
205
def get_classdef(cls, name, parents):
206
"""Find class definition by name in parent nodes."""
207
208
@classmethod
209
def superclass_names(cls, name, parents, _names=None):
210
"""Get names of all superclasses for inheritance checks."""
211
212
class FunctionNameCheck(BaseASTCheck):
213
"""Checks function names are lowercase and don't use double underscores improperly."""
214
N802 = "function name '{name}' should be lowercase"
215
N807 = "function name '{name}' should not start and end with '__'"
216
217
def visit_functiondef(self, node, parents, ignored):
218
"""Check function definition for naming violations."""
219
220
visit_asyncfunctiondef = visit_functiondef # Alias for async functions
221
222
@staticmethod
223
def has_override_decorator(node):
224
"""Check if function has typing.override decorator."""
225
226
class FunctionArgNamesCheck(BaseASTCheck):
227
"""Checks function argument names are lowercase and first arguments are 'self'/'cls' appropriately."""
228
N803 = "argument name '{name}' should be lowercase"
229
N804 = "first argument of a classmethod should be named 'cls'"
230
N805 = "first argument of a method should be named 'self'"
231
232
def visit_functiondef(self, node, parents, ignored):
233
"""Check function arguments for naming violations."""
234
235
visit_asyncfunctiondef = visit_functiondef # Alias for async functions
236
237
class ImportAsCheck(BaseASTCheck):
238
"""Checks import aliases maintain original naming conventions."""
239
N811 = "constant '{name}' imported as non constant '{asname}'"
240
N812 = "lowercase '{name}' imported as non lowercase '{asname}'"
241
N813 = "camelcase '{name}' imported as lowercase '{asname}'"
242
N814 = "camelcase '{name}' imported as constant '{asname}'"
243
N817 = "camelcase '{name}' imported as acronym '{asname}'"
244
245
def visit_importfrom(self, node, parents, ignored):
246
"""Check from-import aliases for naming violations."""
247
248
visit_import = visit_importfrom # Alias for regular imports
249
250
class VariablesCheck(BaseASTCheck):
251
"""Checks variable names in different scopes follow appropriate conventions."""
252
N806 = "variable '{name}' in function should be lowercase"
253
N815 = "variable '{name}' in class scope should not be mixedCase"
254
N816 = "variable '{name}' in global scope should not be mixedCase"
255
256
def visit_assign(self, node, parents, ignored):
257
"""Check assignment targets for naming violations."""
258
259
def visit_namedexpr(self, node, parents, ignored):
260
"""Check walrus operator targets for naming violations."""
261
262
visit_annassign = visit_namedexpr # Alias for annotated assignments
263
264
def visit_with(self, node, parents, ignored):
265
"""Check with statement targets for naming violations."""
266
267
visit_asyncwith = visit_with # Alias for async with statements
268
269
def visit_for(self, node, parents, ignored):
270
"""Check for loop targets for naming violations."""
271
272
visit_asyncfor = visit_for # Alias for async for loops
273
274
def visit_excepthandler(self, node, parents, ignored):
275
"""Check exception handler names for naming violations."""
276
277
def visit_generatorexp(self, node, parents, ignored):
278
"""Check generator expression targets for naming violations."""
279
280
visit_listcomp = visit_dictcomp = visit_setcomp = visit_generatorexp # Aliases for comprehensions
281
282
@staticmethod
283
def global_variable_check(name):
284
"""Check global variable name, return error code if invalid."""
285
286
@staticmethod
287
def class_variable_check(name):
288
"""Check class variable name, return error code if invalid."""
289
290
@staticmethod
291
def function_variable_check(func, var_name):
292
"""Check function variable name, return error code if invalid."""
293
294
@staticmethod
295
def is_namedtupe(node_value):
296
"""Check if assignment value is a namedtuple call."""
297
298
def _find_errors(self, assignment_target, parents, ignored):
299
"""
300
Find naming errors in assignment targets.
301
302
Args:
303
assignment_target: AST node representing assignment target
304
parents: Sequence of parent nodes for context
305
ignored: NameSet of names to ignore
306
307
Yields:
308
Error tuples for naming violations found
309
"""
310
311
class TypeVarNameCheck(BaseASTCheck):
312
"""Checks TypeVar names use CapWords convention with optional covariance/contravariance suffixes."""
313
N808 = "type variable name '{name}' should use CapWords convention and an optional '_co' or '_contra' suffix"
314
315
def visit_module(self, node, parents, ignored):
316
"""Check module-level TypeVar assignments for naming violations."""
317
```
318
319
### Utility Functions
320
321
Helper functions used throughout the naming checks.
322
323
```python { .api }
324
def is_mixed_case(name):
325
"""
326
Check if name uses mixedCase (starts lowercase, contains uppercase).
327
328
Args:
329
name: Variable name to check
330
331
Returns:
332
True if name is in mixedCase format
333
"""
334
335
def _extract_names(assignment_target):
336
"""
337
Extract all variable names from assignment target.
338
339
Args:
340
assignment_target: AST node representing assignment target
341
342
Yields:
343
Variable names found in the assignment target
344
"""
345
346
def _build_decorator_to_type(classmethod_decorators, staticmethod_decorators):
347
"""
348
Build mapping from decorator names to function types.
349
350
Args:
351
classmethod_decorators: List of classmethod decorator names
352
staticmethod_decorators: List of staticmethod decorator names
353
354
Returns:
355
Dictionary mapping decorator names to FunctionType values
356
"""
357
```
358
359
### Configuration Constants
360
361
Default values and constants used for configuration.
362
363
```python { .api }
364
__version__ = '0.15.1'
365
366
CLASS_METHODS = frozenset([
367
'__new__', '__init_subclass__', '__class_getitem__'
368
])
369
370
METACLASS_BASES = frozenset(['type', 'ABCMeta'])
371
372
METHOD_CONTAINER_NODES = {
373
ast.If, ast.While, ast.For, ast.With, ast.Try, ast.AsyncWith, ast.AsyncFor
374
}
375
376
FUNC_NODES = (ast.FunctionDef, ast.AsyncFunctionDef)
377
378
_default_ignored_names = [
379
'setUp', 'tearDown', 'setUpClass', 'tearDownClass',
380
'setUpModule', 'tearDownModule', 'asyncSetUp', 'asyncTearDown',
381
'setUpTestData', 'failureException', 'longMessage', 'maxDiff'
382
]
383
384
_default_classmethod_decorators = ['classmethod']
385
_default_staticmethod_decorators = ['staticmethod']
386
```
387
388
## Error Codes
389
390
The plugin detects the following PEP 8 naming violations:
391
392
| Code | Description |
393
|------|-------------|
394
| N801 | Class names should use CapWords convention |
395
| N802 | Function name should be lowercase |
396
| N803 | Argument name should be lowercase |
397
| N804 | First argument of a classmethod should be named 'cls' |
398
| N805 | First argument of a method should be named 'self' |
399
| N806 | Variable in function should be lowercase |
400
| N807 | Function name should not start and end with '__' |
401
| N808 | Type variable names should use CapWords with optional '_co'/'_contra' suffix |
402
| N811 | Constant imported as non-constant |
403
| N812 | Lowercase imported as non-lowercase |
404
| N813 | Camelcase imported as lowercase |
405
| N814 | Camelcase imported as constant |
406
| N815 | MixedCase variable in class scope |
407
| N816 | MixedCase variable in global scope |
408
| N817 | Camelcase imported as acronym |
409
| N818 | Exception name should be named with an Error suffix |
410
411
## Configuration Options
412
413
The plugin supports the following flake8 configuration options:
414
415
- **--ignore-names**: Comma-separated list of names or glob patterns to ignore
416
- **--classmethod-decorators**: List of decorators to treat as classmethods (default: classmethod)
417
- **--staticmethod-decorators**: List of decorators to treat as staticmethods (default: staticmethod)
418
419
Example configuration in setup.cfg:
420
421
```ini
422
[flake8]
423
ignore-names = setUp,tearDown,*Test*
424
classmethod-decorators = classmethod,declared_attr,expression,comparator
425
staticmethod-decorators = staticmethod
426
```