def _ensure_underscores(self, node: ast.AST, name: str):
        if access.is_private(name):
            self._error_callback(
                naming.PrivateNameViolation(node, text=name),
            )

        if logical.does_contain_underscored_number(name):
            self._error_callback(
                naming.UnderscoredNumberNameViolation(node, text=name),
            )

        if logical.does_contain_consecutive_underscores(name):
            self._error_callback(
                naming.ConsecutiveUnderscoresInNameViolation(
                    node, text=name,
                ),
            )

        if builtins.is_wrong_alias(name):
            self._error_callback(
                naming.TrailingUnderscoreViolation(node, text=name),
            )

        if access.is_unused(name) and len(name) > 1:
            self._error_callback(
                naming.WrongUnusedVariableNameViolation(node, text=name),
            )
 def _exclude_unused(self, names: Set[str]) -> Set[str]:
     """Removes unused variables from set of names."""
     return {
         var_name  # we allow to reuse explicit `_` variables
         for var_name in names
         if not access.is_unused(var_name)
     }
    def _ensure_complex_naming(
        self,
        node: ast.AST,
        name: str,
        *,
        is_first_argument: bool,
    ) -> None:
        if logical.is_wrong_name(name, self._variable_names_blacklist):
            self._error_callback(
                naming.WrongVariableNameViolation(node, text=name), )

        if not is_first_argument:
            if logical.is_wrong_name(name, SPECIAL_ARGUMENT_NAMES_WHITELIST):
                self._error_callback(
                    naming.ReservedArgumentNameViolation(node, text=name), )

        if access.is_unused(name) and len(name) > 1:
            self._error_callback(
                naming.WrongUnusedVariableNameViolation(node, text=name), )

        unreadable_sequence = alphabet.get_unreadable_characters(
            name,
            UNREADABLE_CHARACTER_COMBINATIONS,
        )
        if unreadable_sequence:
            self._error_callback(
                naming.UnreadableNameViolation(node,
                                               text=unreadable_sequence), )
Beispiel #4
0
def is_constant(name: str) -> bool:
    """
    Checks whether the given ``name`` is a constant.

    >>> is_constant('CONST')
    True

    >>> is_constant('ALLOWED_EMPTY_LINE_TOKEN')
    True

    >>> is_constant('Some')
    False

    >>> is_constant('_')
    False

    >>> is_constant('lower_case')
    False

    """
    if is_unused(name):
        return False

    return all(
        # We check that constant names consist of:
        # UPPERCASE LETTERS and `_` char
        character.isupper() or character == '_'
        for character in name
    )
Beispiel #5
0
def is_too_short_name(
    name: str,
    min_length: int,
    *,
    trim: bool = True,
) -> bool:
    """
    Checks for too short names.

    >>> is_too_short_name('test', min_length=2)
    False

    >>> is_too_short_name('o', min_length=2)
    True

    >>> is_too_short_name('_', min_length=2)
    False

    >>> is_too_short_name('_', min_length=1)
    False

    >>> is_too_short_name('z1', min_length=2)
    False

    >>> is_too_short_name('z', min_length=1)
    False

    >>> is_too_short_name('_z', min_length=2, trim=True)
    True

    >>> is_too_short_name('z_', min_length=2, trim=True)
    True

    >>> is_too_short_name('z_', min_length=2, trim=False)
    False

    >>> is_too_short_name('__z', min_length=2, trim=True)
    True

    >>> is_too_short_name('xy', min_length=2, trim=True)
    False

    >>> is_too_short_name('np', min_length=3)
    False

    """
    if name in ALIAS_NAMES_WHITELIST:
        return False

    if access.is_unused(name):
        return False

    if trim:
        name = name.strip(UNUSED_PLACEHOLDER)

    return len(name) < min_length
 def add_to_scope(
     self,
     names: Set[str],
     is_local: bool = False,
 ) -> None:
     """Adds a set of names to the specified scope."""
     scope = self._get_scope(is_local=is_local)
     scope[self._context] = scope[self._context].union({
         var_name  # we allow to reuse explicit `_` variable
         for var_name in names
         if not access.is_unused(var_name)
     })
Beispiel #7
0
 def visit_any_for(self, node: AnyFor) -> None:
     """Checks that we cannot create explicit unused loops."""
     target_names = name_nodes.get_variables_from_node(node.target)
     is_target_no_op_variable = (len(target_names) == 1
                                 and access.is_unused(target_names[0]))
     if not is_target_no_op_variable:  # see issue 1406
         self._check_assign_unused(
             node,
             target_names,
             is_local=True,
         )
     self.generic_visit(node)
def is_too_short_name(
    name: str,
    min_length: int,
    *,
    trim: bool = True,
) -> bool:
    """
    Checks for too short names.

    >>> is_too_short_name('test', min_length=2)
    False

    >>> is_too_short_name('o', min_length=2)
    True

    >>> is_too_short_name('_', min_length=2)
    False

    >>> is_too_short_name('_', min_length=1)
    False

    >>> is_too_short_name('z1', min_length=2)
    False

    >>> is_too_short_name('z', min_length=1)
    False

    >>> is_too_short_name('_z', min_length=2, trim=True)
    True

    >>> is_too_short_name('z_', min_length=2, trim=True)
    True

    >>> is_too_short_name('z_', min_length=2, trim=False)
    False

    >>> is_too_short_name('__z', min_length=2, trim=True)
    True

    >>> is_too_short_name('xy', min_length=2, trim=True)
    False

    """
    if access.is_unused(name):
        return False

    if trim:
        name = name.strip('_')

    return len(name) < min_length
    def _check_variable_used(
        self,
        node: ast.AST,
        assigned_name: Optional[str],
        *,
        is_created: bool,
    ) -> None:
        if not assigned_name or not access.is_unused(assigned_name):
            return

        if not is_created:
            self.add_violation(
                naming.UnusedVariableIsUsedViolation(node,
                                                     text=assigned_name), )
Beispiel #10
0
 def _check_unique_assignment(
     self,
     node: AnyAssign,
     names: List[str],
 ) -> None:
     used_names = filter(
         lambda assigned_name: not access.is_unused(assigned_name),
         names,
     )
     for used_name, count in Counter(used_names).items():
         if count > 1:
             self.add_violation(
                 best_practices.ReassigningVariableToItselfViolation(
                     node,
                     text=used_name,
                 ), )
Beispiel #11
0
    def _check_variable_used(
        self,
        node: ast.AST,
        assigned_name: Optional[str],
        *,
        is_created: bool,
    ) -> None:
        if not assigned_name or not access.is_unused(assigned_name):
            return

        if assigned_name == '_':  # This is a special case for django's
            return  # gettext and similar tools.

        if not is_created:
            self.add_violation(
                naming.UnusedVariableIsUsedViolation(node,
                                                     text=assigned_name), )
Beispiel #12
0
    def _check_assign_unused(
        self,
        node: ast.AST,
        all_names: Iterable[str],
        *,
        is_local: bool = True,
    ) -> None:
        all_names = list(all_names)  # we are using it twice
        all_unused = all(
            is_local if access.is_protected(vn) else access.is_unused(vn)
            for vn in all_names)

        if all_names and all_unused:
            self.add_violation(
                naming.UnusedVariableIsDefinedViolation(
                    node,
                    text=', '.join(all_names),
                ), )
    def _check_variable_used(
        self,
        node: ast.AST,
        assigned_name: str,
        *,
        is_created: bool,
    ) -> None:
        if not access.is_unused(assigned_name):
            return

        if assigned_name == UNUSED_PLACEHOLDER:
            # This is a special case for django's
            # gettext and similar tools.
            return

        if not is_created:
            self.add_violation(
                naming.UnusedVariableIsUsedViolation(node,
                                                     text=assigned_name), )
Beispiel #14
0
    def _maybe_update_variable(
        self,
        sub_node: _LocalVariable,
        var_name: str,
        local_variables: Dict[str, List[_LocalVariable]],
    ) -> None:
        defs = local_variables.get(var_name)
        if defs is not None:
            if not var_name or access.is_unused(var_name):
                # We check unused variable usage in a different place:
                # see `visitors/ast/naming.py`
                return
            defs.append(sub_node)
            return

        is_name_def = (isinstance(sub_node, ast.Name)
                       and isinstance(sub_node.ctx, ast.Store))

        if is_name_def or isinstance(sub_node, ast.ExceptHandler):
            local_variables[var_name] = []
Beispiel #15
0
    def _update_variables(
        self,
        function: AnyFunctionDef,
        variable_def: ast.Name,
    ) -> None:
        """
        Increases the counter of local variables.

        What is treated as a local variable?
        Check ``TooManyLocalsViolation`` documentation.
        """
        function_variables = self.variables[function]
        if variable_def.id not in function_variables:
            if access.is_unused(variable_def.id):
                return

            if isinstance(get_parent(variable_def), self._not_contain_locals):
                return

            function_variables.append(variable_def.id)
Beispiel #16
0
def is_wrong_alias(variable_name: str) -> bool:
    """
    Tells whether a variable is wrong builtins alias or not.

    >>> is_wrong_alias('regular_name_')
    True

    >>> is_wrong_alias('_')
    False

    >>> is_wrong_alias('_async')
    False

    >>> is_wrong_alias('_await')
    False

    >>> is_wrong_alias('regular_name')
    False

    >>> is_wrong_alias('class_')
    False

    >>> is_wrong_alias('list_')
    False

    >>> is_wrong_alias('list')
    False

    >>> is_wrong_alias('__spec__')
    False

    """
    if is_magic(variable_name):
        return False

    if is_unused(variable_name) or not variable_name.endswith('_'):
        return False

    return not is_builtin_name(variable_name[:-1])
    def _maybe_update_variable(
        self,
        sub_node: LocalVariable,
        var_name: str,
        local_variables: Dict[str, List[LocalVariable]],
    ) -> None:
        if var_name in local_variables:
            if access.is_unused(var_name):
                # We check unused variable usage in a different place:
                # see `visitors/ast/naming.py`
                return
            local_variables[var_name].append(sub_node)
            return

        is_name_def = isinstance(
            sub_node, ast.Name,
        ) and isinstance(
            sub_node.ctx, ast.Store,
        )

        if is_name_def or isinstance(sub_node, ast.ExceptHandler):
            local_variables[var_name] = []
class _SimpleNameValidator(object):
    """Utility class to separate logic from the naming visitor."""

    _naming_predicates: ClassVar[Iterable[_NamingPredicate]] = (
        _NamingPredicate(
            access.is_private,
            naming.PrivateNameViolation,
        ),
        _NamingPredicate(
            alphabet.does_contain_unicode,
            naming.UnicodeNameViolation,
        ),
        _NamingPredicate(
            lambda name: access.is_unused(name) and len(name) > 1,
            naming.WrongUnusedVariableNameViolation,
        ),
    )

    def __init__(
        self,
        error_callback: _ErrorCallback,
        options: ConfigurationOptions,
    ) -> None:
        """Creates new instance of a name validator."""
        self._error_callback = error_callback
        self._options = options
        self._variable_names_blacklist = (
            blacklists.variable_names_blacklist_from(options)
        )

    def check_name(
        self,
        node: ast.AST,
        name: str,
        *,
        is_first_argument: bool = False,
    ) -> None:
        for predicate in self._naming_predicates:
            if predicate.is_applicable(node) and predicate.is_correct(name):
                self._error_callback(predicate.violation(node, text=name))

        self._ensure_reserved_name(
            node, name, is_first_argument=is_first_argument,
        )

    def _ensure_reserved_name(
        self,
        node: ast.AST,
        name: str,
        *,
        is_first_argument: bool,
    ) -> None:
        if is_first_argument:
            return

        if not logical.is_wrong_name(name, SPECIAL_ARGUMENT_NAMES_WHITELIST):
            return

        self._error_callback(
            naming.ReservedArgumentNameViolation(node, text=name),
        )