-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Experimental: Unify NamingSchemes. #3704
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,7 +62,6 @@ | |
import itertools | ||
import re | ||
import sys | ||
from typing import Pattern | ||
|
||
import astroid | ||
import astroid.bases | ||
|
@@ -81,83 +80,69 @@ | |
|
||
|
||
class NamingStyle: | ||
# It may seem counterintuitive that single naming style | ||
# has multiple "accepted" forms of regular expressions, | ||
# but we need to special-case stuff like dunder names | ||
# in method names. | ||
CLASS_NAME_RGX = None # type: Pattern[str] | ||
MOD_NAME_RGX = None # type: Pattern[str] | ||
CONST_NAME_RGX = None # type: Pattern[str] | ||
COMP_VAR_RGX = None # type: Pattern[str] | ||
DEFAULT_NAME_RGX = None # type: Pattern[str] | ||
CLASS_ATTRIBUTE_RGX = None # type: Pattern[str] | ||
|
||
@classmethod | ||
def get_regex(cls, name_type): | ||
return { | ||
"module": cls.MOD_NAME_RGX, | ||
"const": cls.CONST_NAME_RGX, | ||
"class": cls.CLASS_NAME_RGX, | ||
"function": cls.DEFAULT_NAME_RGX, | ||
"method": cls.DEFAULT_NAME_RGX, | ||
"attr": cls.DEFAULT_NAME_RGX, | ||
"argument": cls.DEFAULT_NAME_RGX, | ||
"variable": cls.DEFAULT_NAME_RGX, | ||
"class_attribute": cls.CLASS_ATTRIBUTE_RGX, | ||
"inlinevar": cls.COMP_VAR_RGX, | ||
}[name_type] | ||
|
||
name_template = r"[^\W\d_%s][^\W%s]%s" | ||
|
||
def __init__(self, head_exclude: str, tail_exclude: str, min_length: int): | ||
self.head_exclude = head_exclude | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMHO it could be interesting to add comments explaining what do you call head and tail. From what i understand, head is only one character long whereas tail is all the rest. I'm i right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, exactly. As in head and tail of a snake -- the tail is everything but the head. |
||
self.tail_exclude = tail_exclude | ||
self.min_length = min_length | ||
|
||
if min_length == 1: | ||
tail_length = "*" | ||
elif min_length == 2: | ||
tail_length = "+" | ||
elif min_length > 2: | ||
tail_length = "{%i,}" % (min_length - 1) | ||
else: | ||
raise AssertionError(tail_length) | ||
|
||
class SnakeCaseStyle(NamingStyle): | ||
"""Regex rules for snake_case naming style.""" | ||
word = self.name_template % (head_exclude, tail_exclude, tail_length) | ||
snake_word = self.name_template % ("A-Z", "A-Z", tail_length) | ||
|
||
CLASS_NAME_RGX = re.compile(r"[^\W\dA-Z][^\WA-Z]+$") | ||
MOD_NAME_RGX = re.compile(r"[^\W\dA-Z][^\WA-Z]*$") | ||
CONST_NAME_RGX = re.compile(r"([^\W\dA-Z][^\WA-Z]*|__.*__)$") | ||
COMP_VAR_RGX = re.compile(r"[^\W\dA-Z][^\WA-Z]*$") | ||
DEFAULT_NAME_RGX = re.compile( | ||
r"([^\W\dA-Z][^\WA-Z]{2,}|_[^\WA-Z]*|__[^\WA-Z\d_][^\WA-Z]+__)$" | ||
) | ||
CLASS_ATTRIBUTE_RGX = re.compile(r"([^\W\dA-Z][^\WA-Z]{2,}|__.*__)$") | ||
name = r"_{0,2}%s" % word | ||
dunder = r"__%s__" % snake_word | ||
|
||
self.NAME_RGX = re.compile("^(%s)$" % name) | ||
self.ATTR_RGX = re.compile("^(%s|%s)$" % (name, dunder)) | ||
|
||
class CamelCaseStyle(NamingStyle): | ||
"""Regex rules for camelCase naming style.""" | ||
|
||
CLASS_NAME_RGX = re.compile(r"[^\W\dA-Z][^\W_]+$") | ||
MOD_NAME_RGX = re.compile(r"[^\W\dA-Z][^\W_]*$") | ||
CONST_NAME_RGX = re.compile(r"([^\W\dA-Z][^\W_]*|__.*__)$") | ||
COMP_VAR_RGX = re.compile(r"[^\W\dA-Z][^\W_]*$") | ||
DEFAULT_NAME_RGX = re.compile(r"([^\W\dA-Z][^\W_]{2,}|__[^\W\dA-Z_]\w+__)$") | ||
CLASS_ATTRIBUTE_RGX = re.compile(r"([^\W\dA-Z][^\W_]{2,}|__.*__)$") | ||
def get_regex(self, name_type): | ||
# It may seem counterintuitive that single naming style | ||
# has multiple "accepted" forms of regular expressions, | ||
# but we need to special-case stuff like dunder names | ||
# in method names. | ||
return { | ||
"module": self.NAME_RGX, | ||
"const": self.ATTR_RGX, | ||
"class": self.NAME_RGX, | ||
"function": self.ATTR_RGX, | ||
"method": self.ATTR_RGX, | ||
"attr": self.ATTR_RGX, | ||
"argument": self.ATTR_RGX, | ||
"variable": self.ATTR_RGX, | ||
"class_attribute": self.ATTR_RGX, | ||
"inlinevar": self.NAME_RGX, | ||
}[name_type] | ||
|
||
|
||
class PascalCaseStyle(NamingStyle): | ||
"""Regex rules for PascalCase naming style.""" | ||
# Regex rules for snake_case naming style. | ||
SnakeCaseStyle = NamingStyle("A-Z", "A-Z", 3) | ||
|
||
CLASS_NAME_RGX = re.compile(r"[^\W\da-z][^\W_]+$") | ||
MOD_NAME_RGX = re.compile(r"[^\W\da-z][^\W_]+$") | ||
CONST_NAME_RGX = re.compile(r"([^\W\da-z][^\W_]*|__.*__)$") | ||
COMP_VAR_RGX = re.compile(r"[^\W\da-z][^\W_]+$") | ||
DEFAULT_NAME_RGX = re.compile(r"([^\W\da-z][^\W_]{2,}|__[^\W\dA-Z_]\w+__)$") | ||
CLASS_ATTRIBUTE_RGX = re.compile(r"[^\W\da-z][^\W_]{2,}$") | ||
# Regex rules for camelCase naming style. | ||
CamelCaseStyle = NamingStyle("A-Z", "_", 3) | ||
|
||
# Regex rules for PascalCase naming style. | ||
PascalCaseStyle = NamingStyle("a-z", "_", 3) | ||
|
||
class UpperCaseStyle(NamingStyle): | ||
"""Regex rules for UPPER_CASE naming style.""" | ||
# Regex rules for UPPER_CASE naming style. | ||
UpperCaseStyle = NamingStyle("a-z", "a-z", 3) | ||
|
||
CLASS_NAME_RGX = re.compile(r"[^\W\da-z][^\Wa-z]+$") | ||
MOD_NAME_RGX = re.compile(r"[^\W\da-z][^\Wa-z]+$") | ||
CONST_NAME_RGX = re.compile(r"([^\W\da-z][^\Wa-z]*|__.*__)$") | ||
COMP_VAR_RGX = re.compile(r"[^\W\da-z][^\Wa-z]+$") | ||
DEFAULT_NAME_RGX = re.compile(r"([^\W\da-z][^\Wa-z]{2,}|__[^\W\dA-Z_]\w+__)$") | ||
CLASS_ATTRIBUTE_RGX = re.compile(r"[^\W\da-z][^\Wa-z]{2,}$") | ||
AnyStyle = NamingStyle("", "", 1) | ||
|
||
|
||
class AnyStyle(NamingStyle): | ||
@classmethod | ||
def get_regex(cls, name_type): | ||
return re.compile(".*") | ||
class NoStyle(NamingStyle): | ||
@staticmethod | ||
def get_regex(name_type): | ||
return re.compile(".+") | ||
|
||
|
||
NAMING_STYLES = { | ||
|
@@ -166,6 +151,7 @@ def get_regex(cls, name_type): | |
"PascalCase": PascalCaseStyle, | ||
"UPPER_CASE": UpperCaseStyle, | ||
"any": AnyStyle, | ||
"none": NoStyle, | ||
} | ||
|
||
# do not require a doc string on private/system methods | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
[pytest] | ||
python_files=*test_*.py | ||
addopts=-m "not acceptance" | ||
addopts=-m "not acceptance" --tb=short | ||
DanielNoord marked this conversation as resolved.
Show resolved
Hide resolved
|
||
markers = | ||
acceptance |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
# pylint: disable=literal-comparison,missing-docstring,misplaced-comparison-constant | ||
# pylint: disable=literal-comparison,missing-docstring,misplaced-comparison-constant,invalid-name | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I find a little bit damageable if |
||
|
||
X = 123 | ||
Y = len('test') | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[basics] | ||
good-names=___private3 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
invalid-name:3::"Constant name ""SOME_CONSTANT"" doesn't conform to camelCase naming style ('([^\\W\\dA-Z][^\\W_]*|__.*__)$' pattern)" | ||
invalid-name:10:MyClass:"Class name ""MyClass"" doesn't conform to camelCase naming style ('[^\\W\\dA-Z][^\\W_]+$' pattern)" | ||
invalid-name:22:say_hello:"Function name ""say_hello"" doesn't conform to camelCase naming style ('([^\\W\\dA-Z][^\\W_]{2,}|__[^\\W\\dA-Z_]\\w+__)$' pattern)" | ||
invalid-name:3::"Constant name ""SOME_CONSTANT"" doesn't conform to camelCase naming style ('^(_{0,2}[^\\W\\d_A-Z][^\\W_]{2,}|__[^\\W\\d_A-Z][^\\WA-Z]{2,}__)$' pattern)" | ||
invalid-name:10:MyClass:"Class name ""MyClass"" doesn't conform to camelCase naming style ('^(_{0,2}[^\\W\\d_A-Z][^\\W_]{2,})$' pattern)" | ||
invalid-name:22:say_hello:"Function name ""say_hello"" doesn't conform to camelCase naming style ('^(_{0,2}[^\\W\\d_A-Z][^\\W_]{2,}|__[^\\W\\d_A-Z][^\\WA-Z]{2,}__)$' pattern)" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
blacklisted-name:5::"Black listed name ""explicit_bad_some_constant""" | ||
invalid-name:7::"Constant name ""snake_case_bad_SOME_CONSTANT"" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]*|__.*__)$' pattern)" | ||
invalid-name:7::"Constant name ""snake_case_bad_SOME_CONSTANT"" doesn't conform to snake_case naming style ('^(_{0,2}[^\\W\\d_A-Z][^\\WA-Z]{2,}|__[^\\W\\d_A-Z][^\\WA-Z]{2,}__)$' pattern)" | ||
blacklisted-name:19:blacklisted_2_snake_case:"Black listed name ""blacklisted_2_snake_case""" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
invalid-name:3::"Constant name ""SOME_CONSTANT"" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]*|__.*__)$' pattern)" | ||
invalid-name:10:MyClass:"Class name ""MyClass"" doesn't conform to snake_case naming style ('[^\\W\\dA-Z][^\\WA-Z]+$' pattern)" | ||
invalid-name:22:sayHello:"Function name ""sayHello"" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]{2,}|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)" | ||
invalid-name:3::"Constant name ""SOME_CONSTANT"" doesn't conform to snake_case naming style ('^(_{0,2}[^\\W\\d_A-Z][^\\WA-Z]{2,}|__[^\\W\\d_A-Z][^\\WA-Z]{2,}__)$' pattern)" | ||
invalid-name:10:MyClass:"Class name ""MyClass"" doesn't conform to snake_case naming style ('^(_{0,2}[^\\W\\d_A-Z][^\\WA-Z]{2,})$' pattern)" | ||
invalid-name:22:sayHello:"Function name ""sayHello"" doesn't conform to snake_case naming style ('^(_{0,2}[^\\W\\d_A-Z][^\\WA-Z]{2,}|__[^\\W\\d_A-Z][^\\WA-Z]{2,}__)$' pattern)" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
[testoptions] | ||
min_pyver=3.6 | ||
[basics] | ||
good-names=IN |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[basics] | ||
good-names=i,j,k,ex,Run,_,_dt | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Once again i think it is very risky to forbid using single character named variable... |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
"""Checks import position rule""" | ||
# pylint: disable=unused-import,pointless-string-statement | ||
A = 1 | ||
_ = 1 | ||
import os # [wrong-import-position] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
"""Checks import position rule""" | ||
# pylint: disable=unused-import,no-name-in-module | ||
A = 1 | ||
_ = 1 | ||
from sys import x # [wrong-import-position] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
R: 1: Similar lines in 2 files | ||
==input.func_w0801:3 | ||
==input.w0801_same:3 | ||
==input.func_w0801:4 | ||
==input.w0801_same:4 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this change needed? |
||
__revision__ = 'id' | ||
A = 2 | ||
B = 3 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is that not recommended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not recommended because even for those deeply familiar with regex (few) it is much too easy to make regex with unintended matches / exclusions.