Skip to content
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

Closes #1327 #1851

Merged
merged 16 commits into from Feb 7, 2021
Expand Up @@ -18,7 +18,7 @@
':',
'slice(1)',
'slice()',
'slice(1,3)',
'slice(1, 3)',
])
def test_slice_assignment(
assert_errors,
Expand Down
4 changes: 2 additions & 2 deletions wemake_python_styleguide/logic/naming/name_nodes.py
Expand Up @@ -66,8 +66,8 @@ def get_variables_from_node(node: ast.AST) -> List[str]:
Can be used with any nodes that operate with ``ast.Name`` or ``ast.Tuple``
as targets for the assignment.

Can be used with nodes like ``ast.Assign``, ``ast.Tuple``, ``ast.For``,
``ast.With``, etc.
Can be used with nodes like
``ast.Assign``, ``ast.Tuple``, ``ast.For``, ``ast.With``, etc.
"""
names: List[str] = []
naive_attempt = extract_name(node)
Expand Down
7 changes: 4 additions & 3 deletions wemake_python_styleguide/logic/tree/classes.py
Expand Up @@ -51,6 +51,7 @@ def is_forbidden_super_class(class_name: Optional[str]) -> bool:

def get_attributes(
node: ast.ClassDef,
*,
include_annotated: bool,
) -> _AllAttributes:
"""
Expand Down Expand Up @@ -102,7 +103,7 @@ def _get_class_attribute(
subnode: ast.AST,
) -> Optional[AnyAssign]:
return subnode if (
nodes.get_context(subnode) == node and
nodes.get_context(subnode) is node and
getattr(subnode, 'value', None) and
isinstance(subnode, AssignNodes)
) else None
Expand All @@ -113,7 +114,7 @@ def _get_annotated_class_attribute(
subnode: ast.AST,
) -> Optional[AnyAssign]:
return subnode if (
nodes.get_context(subnode) == node and
nodes.get_context(subnode) is node and
(
getattr(subnode, 'value', None) and
isinstance(subnode, AssignNodes)
Expand All @@ -124,7 +125,7 @@ def _get_annotated_class_attribute(
def find_getters_and_setters(node: ast.ClassDef) -> Iterable[AnyFunctionDef]:
"""Returns nodes of all getter or setter methods."""
for sub in ast.walk(node):
is_correct_context = nodes.get_context(sub) == node
is_correct_context = nodes.get_context(sub) is node
if isinstance(sub, FunctionNodes) and is_correct_context:
if sub.name[:GETTER_LENGTH] in _GetterSetterPrefixes:
yield sub
15 changes: 15 additions & 0 deletions wemake_python_styleguide/logic/tree/variables.py
@@ -1,6 +1,9 @@
import ast
from typing import Union

from wemake_python_styleguide.logic import nodes
from wemake_python_styleguide.types import AnyVariableDef

_VarDefinition = Union[ast.AST, ast.expr]
_LocalVariable = Union[ast.Name, ast.ExceptHandler]

Expand All @@ -12,6 +15,18 @@ def get_variable_name(node: _LocalVariable) -> str:
return getattr(node, 'name', '')


def looks_like_builtin(node: AnyVariableDef) -> bool:
"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[pep8] reported by reviewdog 🐶
P102 docstring does contain unindexed parameters

We allow attributes and class-level builtin overrides.

Like: ``self.map = {}`` or ``def map(self, function):``
"""
return (
not isinstance(node, ast.Attribute) and
not isinstance(nodes.get_context(node), ast.ClassDef)
)


def is_valid_block_variable_definition(node: _VarDefinition) -> bool:
"""Is used to check either block variables are correctly defined."""
if isinstance(node, ast.Tuple):
Expand Down
13 changes: 13 additions & 0 deletions wemake_python_styleguide/presets/topics/naming.py
@@ -0,0 +1,13 @@
from typing_extensions import Final

from wemake_python_styleguide.visitors.ast.naming import validation, variables

#: Used to store all naming related visitors to be later passed to checker:
PRESET: Final = (
validation.WrongNameVisitor,

variables.WrongModuleMetadataVisitor,
variables.WrongVariableAssignmentVisitor,
variables.UnusedVariableUsageVisitor,
variables.UnusedVariableDefinitionVisitor,
)
12 changes: 3 additions & 9 deletions wemake_python_styleguide/presets/types/tree.py
@@ -1,6 +1,6 @@
from typing_extensions import Final

from wemake_python_styleguide.presets.topics import complexity
from wemake_python_styleguide.presets.topics import complexity, naming
from wemake_python_styleguide.visitors.ast import ( # noqa: WPS235
annotations,
attributes,
Expand All @@ -16,7 +16,6 @@
keywords,
loops,
modules,
naming,
operators,
statements,
subscripts,
Expand Down Expand Up @@ -62,12 +61,6 @@

imports.WrongImportVisitor,

naming.WrongNameVisitor,
naming.WrongModuleMetadataVisitor,
naming.WrongVariableAssignmentVisitor,
naming.UnusedVariableUsageVisitor,
naming.UnusedVariableDefinitionVisitor,

builtins.WrongNumberVisitor,
builtins.WrongStringVisitor,
builtins.WrongFormatStringVisitor,
Expand Down Expand Up @@ -114,6 +107,7 @@
subscripts.ImplicitDictGetVisitor,
subscripts.CorrectKeyVisitor,

# Complexity:
# Topics:
*complexity.PRESET,
*naming.PRESET,
)
23 changes: 13 additions & 10 deletions wemake_python_styleguide/types.py
Expand Up @@ -61,6 +61,9 @@
#: In case we need to work with any loop: sync, async, and while.
AnyLoop = Union[AnyFor, ast.While]

#: This is how you can define a variable in Python.
AnyVariableDef = Union[ast.Name, ast.Attribute, ast.ExceptHandler]

#: All different comprehension types in one place.
AnyComprehension = Union[
ast.ListComp,
Expand All @@ -72,19 +75,9 @@
#: In cases we need to work with both sync and async context managers.
AnyWith = Union[ast.With, ast.AsyncWith]

#: Tuple of AST node types for declarative syntax.
AnyNodes = Tuple[Type[ast.AST], ...]

#: When we search for assign elements, we also need typed assign.
AnyAssign = Union[ast.Assign, ast.AnnAssign]

#: That's how we define context of operations.
ContextNodes = Union[
ast.Module,
ast.ClassDef,
AnyFunctionDef,
]

#: In cases we need to work with both access types.
AnyAccess = Union[
ast.Attribute,
Expand All @@ -98,9 +91,19 @@
ast.Call,
]

#: Tuple of AST node types for declarative syntax.
AnyNodes = Tuple[Type[ast.AST], ...]

#: We use this type to work with any text-like values. Related to `AnyText`.
AnyTextPrimitive = Union[str, bytes]

#: That's how we define context of operations.
ContextNodes = Union[
ast.Module,
ast.ClassDef,
AnyFunctionDef,
]

#: Flake8 API format to return error messages.
CheckResult = Tuple[int, int, str, type]

Expand Down
6 changes: 3 additions & 3 deletions wemake_python_styleguide/visitors/ast/classes.py
Expand Up @@ -125,10 +125,10 @@ def _check_getters_setters_methods(self, node: ast.ClassDef) -> None:
flat_class_attributes = name_nodes.flat_variable_names(class_attributes)

attributes_stripped = {
class_attribute.lstrip('_')
class_attribute.lstrip(constants.UNUSED_PLACEHOLDER)
for class_attribute in flat_class_attributes
}.union({
instance.attr.lstrip('_')
instance.attr.lstrip(constants.UNUSED_PLACEHOLDER)
for instance in instance_attributes
})

Expand Down Expand Up @@ -409,7 +409,7 @@ def _check_method_order(self, node: ast.ClassDef) -> None:

for subnode in ast.walk(node):
if isinstance(subnode, FunctionNodes):
if nodes.get_context(subnode) == node:
if nodes.get_context(subnode) is node:
method_nodes.append(subnode.name)

ideal = sorted(method_nodes, key=self._ideal_order, reverse=True)
Expand Down