-
-
Notifications
You must be signed in to change notification settings - Fork 377
/
naming.py
880 lines (622 loc) · 21.5 KB
/
naming.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
"""
Naming is hard! It is, in fact, one of the two hardest problems.
These checks are required to make your application easier to read
and understand by multiple people over the long period of time.
Naming convention
-----------------
Our naming convention tries to cover all possible cases.
It is partially automated with this linter, but:
- Some rules are still WIP
- Some rules will never be automated, code reviews to the rescue!
General
~~~~~~~
- Use only ``ASCII`` characters for names
- Do not use transliteration from any other languages, translate names instead
- Use clear names, do not use words that do not mean anything like ``obj``
- Use names of an appropriate length: not too short, not too long
- Do not mask builtins
- Do not use unreadable character sequences like ``O0`` and ``Il``
- Protected members should use underscore as the first char
- Private names with two leading underscores are not allowed
- If you need to explicitly state that the variable is unused,
prefix it with ``_`` or just use ``_`` as a name
- Do not use variables that are stated to be unused,
rename them when actually using them
- Do not define unused variables unless you are unpacking other values as well
- Do not use multiple underscores (``__``) to create unused variables
- Whenever you want to name your variable similar to a keyword or builtin,
use trailing ``_``
- Do not use consecutive underscores
- When writing abbreviations in ``UpperCase``
capitalize all letters: ``HTTPAddress``
- When writing abbreviations in ``snake_case`` use lowercase: ``http_address``
- When writing numbers in ``snake_case``
do not use extra ``_`` before numbers as in ``http2_protocol``
Packages
~~~~~~~~
- Packages must use ``snake_case``
- One word for a package is the most preferable name
Modules
~~~~~~~
- Modules must use ``snake_case``
- Module names must not overuse magic names
- Module names must be valid Python identifiers
Classes
~~~~~~~
- Classes must use ``UpperCase``
- Python's built-in classes, however, are typically lowercase words
- Exception classes must end with ``Error``
Instance attributes
~~~~~~~~~~~~~~~~~~~
- Instance attributes must use ``snake_case`` with no exceptions
Class attributes
~~~~~~~~~~~~~~~~
- Class attributes must use ``snake_case`` with no exceptions
- Enum fields also must use ``snake_case``
Functions and methods
~~~~~~~~~~~~~~~~~~~~~
- Functions and methods must use ``snake_case`` with no exceptions
Method and function arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Instance methods must have their first argument named ``self``
- Class methods must have their first argument named ``cls``
- Metaclass methods must have their first argument named ``mcs``
- Python's ``*args`` and ``**kwargs`` should be default names
when just passing these values to some other method/function,
unless you want to use these values in place, then name them explicitly
Global (module level) variables
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Global variables must use ``CONSTANT_CASE``
- Unless other is required by the API, example: ``urlpatterns`` in Django
Variables
~~~~~~~~~
- Variables must use ``snake_case`` with no exceptions
- When a variable is unused it must be prefixed with an underscore: ``_user``
Type aliases
~~~~~~~~~~~~
- Must use ``UpperCase`` as real classes
- Must not contain word ``type`` in its name
Type variables
~~~~~~~~~~~~~~
- Type variables should be named clearly and properly,
not just ``T`` or ``_VT``
Pattern matching
~~~~~~~~~~~~~~~~
- All rules from local variables apply
- Explicit ``as`` patterns must be used:
``case ... as _var_name`` is not allowed
- However, mapping or sequence patterns can contain unused variables:
``case {"a_key": _not_used_value}:``
.. currentmodule:: wemake_python_styleguide.violations.naming
Summary
-------
.. autosummary::
:nosignatures:
WrongModuleNameViolation
WrongModuleMagicNameViolation
WrongModuleNamePatternViolation
WrongVariableNameViolation
TooShortNameViolation
PrivateNameViolation
SameAliasImportViolation
UnderscoredNumberNameViolation
UpperCaseAttributeViolation
ConsecutiveUnderscoresInNameViolation
ReservedArgumentNameViolation
TooLongNameViolation
UnicodeNameViolation
TrailingUnderscoreViolation
UnusedVariableIsUsedViolation
UnusedVariableIsDefinedViolation
WrongUnusedVariableNameViolation
UnreadableNameViolation
BuiltinShadowingViolation
Module names
------------
.. autoclass:: WrongModuleNameViolation
.. autoclass:: WrongModuleMagicNameViolation
.. autoclass:: WrongModuleNamePatternViolation
General names
-------------
.. autoclass:: WrongVariableNameViolation
.. autoclass:: TooShortNameViolation
.. autoclass:: PrivateNameViolation
.. autoclass:: SameAliasImportViolation
.. autoclass:: UnderscoredNumberNameViolation
.. autoclass:: UpperCaseAttributeViolation
.. autoclass:: ConsecutiveUnderscoresInNameViolation
.. autoclass:: ReservedArgumentNameViolation
.. autoclass:: TooLongNameViolation
.. autoclass:: UnicodeNameViolation
.. autoclass:: TrailingUnderscoreViolation
.. autoclass:: UnusedVariableIsUsedViolation
.. autoclass:: UnusedVariableIsDefinedViolation
.. autoclass:: WrongUnusedVariableNameViolation
.. autoclass:: UnreadableNameViolation
.. autoclass:: BuiltinShadowingViolation
"""
from typing_extensions import final
from wemake_python_styleguide.violations.base import (
ASTViolation,
MaybeASTViolation,
SimpleViolation,
ViolationPostfixes,
)
@final
class WrongModuleNameViolation(SimpleViolation):
"""
Forbid blacklisted module names.
Reasoning:
Some module names are not expressive enough.
It is hard to tell what you can find inside the ``utils.py`` module.
Solution:
Rename your module, reorganize the contents.
See
:py:data:`~wemake_python_styleguide.constants.MODULE_NAMES_BLACKLIST`
for the full list of bad module names.
Example::
# Correct:
github.py
views.py
# Wrong:
utils.py
helpers.py
See also:
https://tonsky.me/blog/utils/
.. versionadded:: 0.1.0
"""
error_template = 'Found wrong module name'
code = 100
@final
class WrongModuleMagicNameViolation(SimpleViolation):
"""
Forbid magic names (except some whitelisted ones).
Reasoning:
Do not fall in love with magic. There's no good reason to use
magic names when you can use regular names.
See
:py:data:`~wemake_python_styleguide.constants.MAGIC_MODULE_NAMES_WHITELIST`
for the full list of allowed magic module names.
Example::
# Correct:
__init__.py
__main__.py
# Wrong:
__version__.py
.. versionadded:: 0.1.0
"""
error_template = 'Found wrong module magic name'
code = 101
@final
class WrongModuleNamePatternViolation(SimpleViolation):
"""
Forbid module names that do not match our pattern.
Reasoning:
Module names must be valid python identifiers.
And just like the variable names - module names should be consistent.
Ideally, they should follow the same rules.
For ``python`` world it is common to use ``snake_case`` notation.
We use
:py:data:`~wemake_python_styleguide.constants.MODULE_NAME_PATTERN`
to validate the module names.
Example::
# Correct:
__init__.py
some_module_name.py
test12.py
# Wrong:
_some.py
MyModule.py
0001_migration.py
.. versionadded:: 0.1.0
"""
error_template = 'Found incorrect module name pattern'
code = 102
# General names:
@final
class WrongVariableNameViolation(ASTViolation):
"""
Forbid blacklisted variable names.
Reasoning:
We have found some names that are not expressive enough.
However, they appear in the code more than often.
All names that we forbid to use could be improved.
Solution:
Try to use a more specific name instead.
If you really want to use any of the names from the list,
add a prefix or suffix to it. It will serve you well.
See
:py:data:`~wemake_python_styleguide.constants.VARIABLE_NAMES_BLACKLIST`
for the base list of blacklisted variable names.
Example::
# Correct:
html_node_item = None
# Wrong:
item = None
Configuration:
This rule is configurable with ``--allowed-domain-names``.
Default:
:str:`wemake_python_styleguide.options.defaults.ALLOWED_DOMAIN_NAMES`
And with ``--forbidden-domain-names``.
Default:
:str:`wemake_python_styleguide.options.defaults.FORBIDDEN_DOMAIN_NAMES`
The options listed above are used to create new variable names'
blacklist starting from
:py:data:`~wemake_python_styleguide.constants.VARIABLE_NAMES_BLACKLIST`.
.. versionadded:: 0.1.0
"""
error_template = 'Found wrong variable name: {0}'
code = 110
@final
class TooShortNameViolation(MaybeASTViolation):
"""
Forbid short variable or module names.
Reasoning:
It is hard to understand what the variable means and why it is used,
if its name is too short.
Solution:
Think of another name. Give more context to it.
This rule checks: modules, variables, attributes,
functions, methods, and classes.
We do not count trailing and leading underscores when calculating length.
Example::
# Correct:
x_coordinate = 1
abscissa = 2
# Wrong:
x = 1
y = 2
Configuration:
This rule is configurable with ``--min-name-length``.
Default:
:str:`wemake_python_styleguide.options.defaults.MIN_NAME_LENGTH`
.. versionadded:: 0.1.0
.. versionchanged:: 0.4.0
.. versionchanged:: 0.12.0
"""
error_template = 'Found too short name: {0}'
code = 111
postfix_template = ViolationPostfixes.less_than
@final
class PrivateNameViolation(MaybeASTViolation):
"""
Forbid private name pattern.
Reasoning:
Private is not private in ``python``.
So, why should we pretend it is?
This might lead to some serious design flaws.
Solution:
Rename your variable or method to be protected.
Think about your design, why do you want to make it private?
Are there any other ways to achieve what you want?
This rule checks: modules, variables, attributes, functions, and methods.
Example::
# Correct:
def _collect_coverage(self): ...
# Wrong:
def __collect_coverage(self): ...
.. versionadded:: 0.1.0
.. versionchanged:: 0.4.0
.. versionchanged:: 0.14.0
"""
error_template = 'Found private name pattern: {0}'
code = 112
@final
class SameAliasImportViolation(ASTViolation):
"""
Forbid using the same alias as the original name in imports.
Reasoning:
Why would you even do this in the first place?
Example::
# Correct:
from os import path
# Wrong:
from os import path as path
When `--i-control-code` is set to ``False``
you can reexport things with ``as``,
because ``mypy`` might require it
with ``implicit_reexport = False`` setting turned on.
Configuration:
This rule is configurable with ``--i-control-code``
and ``--i-dont-control-code``.
Default:
:str:`wemake_python_styleguide.options.defaults.I_CONTROL_CODE`
.. versionadded:: 0.1.0
.. versionchanged:: 0.13.0
.. versionchanged:: 0.14.0
"""
error_template = 'Found same alias import: {0}'
code = 113
@final
class UnderscoredNumberNameViolation(MaybeASTViolation):
"""
Forbid names with underscored numbers pattern.
Reasoning:
This is done for consistency in naming.
Solution:
Do not put an underscore between text and numbers, that is confusing.
Rename your variable or modules do not include underscored numbers.
This rule checks: modules, variables, attributes,
functions, method, and classes.
Please, note that putting an underscore that replaces ``-`` in some
names between numbers are fine, example: ``ISO-123-456`` would become
``iso123_456``.
Example::
# Correct:
star_wars_episode2 = 'awesome!'
iso123_456 = 'some data'
# Wrong:
star_wars_episode_2 = 'not so awesome'
iso_123_456 = 'some data'
.. versionadded:: 0.3.0
.. versionchanged:: 0.4.0
"""
error_template = 'Found underscored number name pattern: {0}'
code = 114
@final
class UpperCaseAttributeViolation(ASTViolation):
"""
Require ``snake_case`` for naming class attributes.
Reasoning:
Constants with upper-case names belong on a module level.
Solution:
Move your constants to the module level.
Rename your variables so that they conform
to ``snake_case`` convention.
Example::
# Correct:
MY_MODULE_CONSTANT = 1
class A:
my_attribute = 42
# Wrong:
class A:
MY_CONSTANT = 42
.. versionadded:: 0.3.0
"""
error_template = 'Found upper-case constant in a class: {0}'
code = 115
@final
class ConsecutiveUnderscoresInNameViolation(MaybeASTViolation):
"""
Forbid using more than one consecutive underscore in variable names.
Reasoning:
This is done to gain extra readability.
This naming rule already exists for module names.
Example::
# Correct:
some_value = 5
__magic__ = 5
# Wrong:
some__value = 5
This rule checks: modules, variables, attributes, functions, and methods.
.. versionadded:: 0.3.0
.. versionchanged:: 0.4.0
"""
error_template = 'Found consecutive underscores name: {0}'
code = 116
@final
class ReservedArgumentNameViolation(ASTViolation):
"""
Forbid naming variables ``self``, ``cls``, or ``mcs``.
Reasoning:
These names are special, they should only be used as first
arguments inside methods.
Example::
# Correct:
class Test:
def __init__(self):
...
# Wrong:
cls = 5
lambda self: self + 12
This rule checks: functions and methods.
Having any reserved names in ``lambda`` functions is not allowed.
.. versionadded:: 0.5.0
"""
error_template = 'Found name reserved for first argument: {0}'
code = 117
@final
class TooLongNameViolation(MaybeASTViolation):
"""
Forbid long variable or module names.
Reasoning:
Too long names are unreadable.
It is better to use a shorter alternative.
Long names also indicate that this variable is too complex,
maybe it may require some documentation.
Solution:
Think of another name. Give less context to it.
This rule checks: modules, variables, attributes,
functions, methods, and classes.
Example::
# Correct:
total_price = 25
average_age = 45
# Wrong:
final_price_after_fifteen_percent_sales_tax_and_gratuity = 30
total_age_of_all_participants_in_the_survey_divided_by_twelve = 2
Configuration:
This rule is configurable with ``--max-name-length``.
Default:
:str:`wemake_python_styleguide.options.defaults.MAX_NAME_LENGTH`
.. versionadded:: 0.5.0
"""
error_template = 'Found too long name: {0}'
code = 118
@final
class UnicodeNameViolation(MaybeASTViolation):
"""
Forbid unicode names.
Reasoning:
This should be forbidden for sanity, readability, and writability.
Solution:
Rename your entities so that they contain only ASCII symbols.
This rule checks: modules, variables, attributes,
functions, methods, and classes.
Example::
# Correct:
some_variable = 'Text with russian: русский язык'
# Wrong:
переменная = 42
some_變量 = ''
.. versionadded:: 0.5.0
"""
error_template = 'Found unicode name: {0}'
code = 119
@final
class TrailingUnderscoreViolation(ASTViolation):
"""
Forbid trailing ``_`` for names that do not need it.
Reasoning:
We use trailing underscore for a reason:
to indicate that this name shadows a built-in or keyword.
So, when overusing this feature for general names:
it just harms readability of your program.
Solution:
Rename your variable not to contain trailing underscores.
This rule checks: variables, attributes, functions, methods, and classes.
Example::
# Correct:
class_ = SomeClass
list_ = []
# Wrong:
some_variable_ = 1
.. versionadded:: 0.7.0
"""
error_template = 'Found regular name with trailing underscore: {0}'
code = 120
@final
class UnusedVariableIsUsedViolation(ASTViolation):
"""
Forbid using variables that are marked as unused.
We discourage using variables that start with ``_``
only inside functions and methods as local variables.
However, we allow to use ``_`` because tools like
``ipython``, ``babel``, and ``django`` enforce it.
Reasoning:
Sometimes you start to use new logic in your functions,
and you start to use variables that once were marked as unused.
But, you have not renamed them for some reason.
And now you have a lot of confusion: the variable is marked as unused,
but you are using it. Why? What's going on?
Solution:
Rename your variable to be a regular variable
without a leading underscore.
This way it is declared to be used.
Example::
# Correct:
def function():
first = 15
return first + 10
# Wrong:
def function():
_first = 15
return _first + 10
This rule checks: functions, methods, and ``lambda`` functions.
.. versionadded:: 0.7.0
.. versionchanged:: 0.12.0
.. versionchanged:: 0.14.0
"""
error_template = 'Found usage of a variable marked as unused: {0}'
code = 121
@final
class UnusedVariableIsDefinedViolation(ASTViolation):
"""
Forbid explicit unused variables.
Reasoning:
While it is ok to define unused variables when you have to,
like when unpacking a tuple, it is totally not ok to define explicit
unused variables in cases like assignment, function return,
exception handling, or context managers.
Why do you need this explicitly unused variables?
Solution:
Remove all unused variables definition.
Example::
# Correct:
my_function()
first, _second = some_tuple()
print(first)
# Wrong:
_ = my_function()
_first, _second = some_tuple()
This rule checks: assigns, context managers, except clauses.
.. versionadded:: 0.12.0
"""
error_template = 'Found all unused variables definition: {0}'
code = 122
@final
class WrongUnusedVariableNameViolation(ASTViolation):
"""
Forbid unused variables with multiple underscores.
Reasoning:
We only use ``_`` as a special definition for an unused variable.
Other variables are hard to read. It is unclear why would one use it.
Solution:
Rename unused variables to ``_``
or give it some more context with an explicit name: ``_context``.
Example::
# Correct:
some_element, _next_element, _ = some_tuple()
some_element, _, _ = some_tuple()
some_element, _ = some_tuple()
# Wrong:
some_element, _, __ = some_tuple()
.. versionadded:: 0.12.0
"""
error_template = 'Found wrong unused variable name: {0}'
code = 123
@final
class UnreadableNameViolation(MaybeASTViolation):
"""
Forbid variable or module names which could be difficult to read.
Reasoning:
Currently one can name your classes like so: ``ZerO0``
Inside it is just ``O`` and ``0``, but we cannot tell it from the word.
There are a lot other combinations which are unreadable.
Solution:
Rename your entity not to contain unreadable sequences.
This rule checks: modules, variables, attributes,
functions, methods, and classes.
See
:py:data:`~wemake_python_styleguide.constants.UNREADABLE_CHARACTER_COMBINATIONS`
for full list of unreadable combinations.
Example::
# Correct:
ControlStatement
AveragePrice
# Wrong:
Memo0Output
.. versionadded:: 0.14
"""
error_template = 'Found unreadable characters combination: {0}'
code = 124
@final
class BuiltinShadowingViolation(ASTViolation):
"""
Forbid variable or module names which shadow builtin names.
Reasoning:
Your code simply breaks Python. After you create ``list = 1``,
you cannot not call ``builtin`` function ``list``
and what can be worse than that?
Solution:
Rename your entity to not shadow Python builtins.
Example::
# Correct:
my_list = list(some_other)
# Wrong:
str = ''
list = [1, 2, 3]
This can also cause problems when defining class attributes, for example::
class A:
min = 5
max = min(10, 20) # TypeError: 'int' object is not callable
If you feel it is still necessary to use such a class attribute,
consider using a `noqa` comment with caution.
See
:py:data:`~wemake_python_styleguide.constants.BUILTINS_WHITELIST`
for full list of builtins we allow to shadow.
.. versionadded:: 0.14
.. versionchanged:: 0.15
"""
error_template = 'Found builtin shadowing: {0}'
code = 125