PK!uh$wemake_python_styleguide/__init__.py# -*- coding: utf-8 -*- PK!̎r  #wemake_python_styleguide/checker.py# -*- coding: utf-8 -*- from ast import Module from typing import Generator from flake8.options.manager import OptionManager from wemake_python_styleguide.compat import maybe_set_parent from wemake_python_styleguide.options.config import Configuration from wemake_python_styleguide.types import ( CheckResult, ConfigurationOptions, VisitorSequence, ) from wemake_python_styleguide.version import version from wemake_python_styleguide.visitors.complexity.counts import ( MethodMembersVisitor, ModuleMembersVisitor, ) from wemake_python_styleguide.visitors.complexity.function import ( FunctionComplexityVisitor, ) from wemake_python_styleguide.visitors.complexity.nested import ( NestedComplexityVisitor, ) from wemake_python_styleguide.visitors.complexity.offset import OffsetVisitor from wemake_python_styleguide.visitors.wrong_class import WrongClassVisitor from wemake_python_styleguide.visitors.wrong_function_call import ( WrongFunctionCallVisitor, ) from wemake_python_styleguide.visitors.wrong_import import WrongImportVisitor from wemake_python_styleguide.visitors.wrong_keyword import ( WrongKeywordVisitor, WrongRaiseVisitor, ) from wemake_python_styleguide.visitors.wrong_name import ( WrongModuleMetadataVisitor, WrongNameVisitor, ) #: Visitors that should be working by default: ENABLED_VISITORS: VisitorSequence = [ # Styling and correctness: WrongRaiseVisitor, WrongFunctionCallVisitor, WrongImportVisitor, WrongKeywordVisitor, WrongNameVisitor, WrongModuleMetadataVisitor, WrongClassVisitor, # Complexity: FunctionComplexityVisitor, NestedComplexityVisitor, OffsetVisitor, ModuleMembersVisitor, MethodMembersVisitor, ] class Checker(object): """ Main checker class. Runs all checks that are bundled with this package. If you want to add new checks they should be added to ``ENABLED_VISITORS``. """ name = 'wemake-python-styleguide' version = version config = Configuration() options: ConfigurationOptions def __init__(self, tree: Module, filename: str = 'stdin') -> None: """Creates new checker instance.""" self.tree = maybe_set_parent(tree) self.filename = filename @classmethod def add_options(cls, parser: OptionManager): """Calls Configuration instance method for registering options.""" cls.config.register_options(parser) @classmethod def parse_options(cls, options: ConfigurationOptions): """Parses registered options for providing to the visiter.""" cls.options = options def run(self) -> Generator[CheckResult, None, None]: """ Runs the checker. This method is used by `flake8` API. After all configuration is parsed and passed. """ for visitor_class in ENABLED_VISITORS: visiter = visitor_class(self.options, filename=self.filename) visiter.visit(self.tree) for error in visiter.errors: yield (*error.node_items(), type(self)) PK!Y"wemake_python_styleguide/compat.py# -*- coding: utf-8 -*- """ This module contains ugly hacks and fixes for version compat issues. Do not be over-exited to add anything here. """ import ast def maybe_set_parent(tree: ast.AST) -> ast.AST: """Sets parents for all nodes that do not have this prop.""" for statement in ast.walk(tree): for child in ast.iter_child_nodes(statement): if not hasattr(child, 'parent'): # noqa: Z113 setattr(child, 'parent', statement) return tree PK!)11%wemake_python_styleguide/constants.py# -*- coding: utf-8 -*- """ This module contains list of white- and black-listed ``python`` members. It contains lists of keywords and built-in functions we discourage to use. It also contains some exceptions that we allow to use in our codebase. """ import sys from typing import Tuple # TODO: 'stdin' filename should be a constant #: List of functions we forbid to use. BAD_FUNCTIONS = frozenset(( # Code generation: 'eval', 'exec', 'compile', # Magic: 'globals', 'locals', 'vars', 'dir', # IO: 'input', # Attribute access: 'hasattr', 'delattr', # Misc: 'copyright', 'help', # Dynamic imports: '__import__', # OOP: 'staticmethod', )) #: List of module metadata we forbid to use. BAD_MODULE_METADATA_VARIABLES = frozenset(( '__author__', '__all__', '__version__', '__about__', )) _BAD_VARIABLE_NAMES: Tuple[str, ...] = ( 'data', 'result', 'results', 'item', 'items', 'value', 'values', 'val', 'vals', 'var', 'vars', 'content', 'contents', 'info', 'handle', 'handler', 'file', 'klass', 'foo', 'bar', 'baz', ) if sys.version_info < (3, 7): # pragma: no cover _BAD_VARIABLE_NAMES += ( # Compatibility with `python3.7`: 'async', 'await', ) #: List of variable names we forbid to use. BAD_VARIABLE_NAMES = frozenset(_BAD_VARIABLE_NAMES) #: List of magic methods that are forbiden to use. BAD_MAGIC_METHODS = frozenset(( # Since we don't use `del`: '__del__', '__delitem__', '__delete__', '__dir__', # since we don't use `dir()` '__delattr__', # since we don't use `delattr()` )) #: List of nested classes' names we allow to use. NESTED_CLASSES_WHITELIST = frozenset(( 'Meta', )) #: List of nested functions' names we allow to use. NESTED_FUNCTIONS_WHITELIST = frozenset(( 'decorator', 'factory', )) #: List of allowed ``__future__`` imports. FUTURE_IMPORTS_WHITELIST = frozenset(( 'annotations', 'generator_stop', )) PK!uh+wemake_python_styleguide/errors/__init__.py# -*- coding: utf-8 -*- PK!@'wemake_python_styleguide/errors/base.py# -*- coding: utf-8 -*- from ast import AST from typing import Tuple class BaseStyleViolation(object): """ This is a base class for all style errors. It basically just defines how to create any error and how to format this error later on. Each subclass must define ``_error_tmpl`` and ``_code`` fields. """ _error_tmpl: str _code: str def __init__(self, node: AST, text: str = None) -> None: """Creates new instance of style error.""" self.node = node if text is None: self._text = node.__class__.__name__.lower() else: self._text = text def message(self) -> str: """ Returns error's formated message. >>> import ast >>> from wemake_python_styleguide.errors.general import ( ... WrongKeywordViolation, ... ) >>> error = WrongKeywordViolation(ast.Pass()) >>> error.message() 'Z110 Found wrong keyword "pass"' >>> error = WrongKeywordViolation(ast.Delete(), text='del') >>> error.message() 'Z110 Found wrong keyword "del"' """ return self._error_tmpl.format(self._code, self._text) def node_items(self) -> Tuple[int, int, str]: """Returns `Tuple` to match `flake8` API format.""" lineno = getattr(self.node, 'lineno', 0) col_offset = getattr(self.node, 'col_offset', 0) return lineno, col_offset, self.message() PK!eHH*wemake_python_styleguide/errors/classes.py# -*- coding: utf-8 -*- """These rules checks ``class``es to be defined correctly.""" from wemake_python_styleguide.errors.base import BaseStyleViolation class StaticMethodViolation(BaseStyleViolation): """ This rule forbids to use ``@staticmethod`` decorator. Use regular methods, ``classmethods``, or raw functions instead. Note: Returns Z300 as error code """ _error_tmpl = '{0} Found using staticmethod "{1}"' _code = 'Z300' class BadMagicMethodViolation(BaseStyleViolation): """ This rule forbids to use some magic methods. Note: Returns Z301 as error code """ _error_tmpl = '{0} Found using restricted magic method "{1}"' _code = 'Z301' class RequiredBaseClassViolation(BaseStyleViolation): """ This rule forbids to write classes without base classes. Example:: # Correct: class Some(object): ... # Wrong: class Some: ... Note: Returns Z302 as error code """ _error_tmpl = '{0} Found class without a base class "{1}"' _code = 'Z302' PK! 8##-wemake_python_styleguide/errors/complexity.py# -*- coding: utf-8 -*- """ These checks finds flaws in your application design. What we call "design flaws": 1. Complex code (there are a lof of complexity checks!) 2. Nested classes, functions """ from wemake_python_styleguide.errors.base import BaseStyleViolation class NestedFunctionViolation(BaseStyleViolation): """ This rule forbids to have nested functions. Just write flat functions, there's no need to nest them. However, there are some whitelisted names like, see ``NESTED_FUNCTIONS_WHITELIST`` for the whole list. We also disallow to nest ``lambda``s. Example:: # Correct: def do_some(): ... def other(): ... # Wrong: def do_some(): def inner(): ... Note: Returns Z200 as error code """ _error_tmpl = '{0} Found nested function "{1}"' _code = 'Z200' class NestedClassViolation(BaseStyleViolation): """ This rule forbids to have nested classes. Just write flat classes, there's no need nest them. However, there are some whitelisted class names like: ``Meta``. Example:: # Wrong: class Some: class Inner: ... Note: Returns Z201 as error code """ _error_tmpl = '{0} Found nested class "{1}"' _code = 'Z201' class TooManyLocalsViolation(BaseStyleViolation): """ This rule forbids to have too many local variables in the unit of code. If you have too many variables in a function, you have to refactor it. What counts as a local variable? We only count variable as local in the following case: it is assigned inside the function body. Example:: def first_function(param): first_var = 1 def second_function(argument): second_var = 1 argument = int(argument) third_var, _ = some_call() In this example we will count as locals only several variables: 1. `first_var`, because it is assigned inside the function's body 2. `second_var`, because it is assigned inside the function's body 3. `argument`, because it is reassigned inside the function's body 4. `third_var`, because it is assigned inside the function's body Please, note that `_` is a special case. It is not counted as a local variable. Since by design it means: do not count me as a real variable. Note: Returns Z202 as error code """ _error_tmpl = '{0} Found too many local variables "{1}"' _code = 'Z202' class TooManyArgumentsViolation(BaseStyleViolation): """ This rule forbids to have too many arguments for a function or method. This is an indecator of a bad desing. When function requires many arguments it shows that it is required to refactor this piece of code. Note: Returns Z203 as error code """ _error_tmpl = '{0} Found too many arguments "{1}"' _code = 'Z203' class TooManyElifsViolation(BaseStyleViolation): """ This rule forbids to use many `elif` branches. This rule is specifically important, becase many `elif` branches indicate a complex flow in your design: you are reimplementing `switch` in python. There are different design patters to use instead. Note: Returns Z204 as error code """ _error_tmpl = '{0} Found too many "{1}" branches' _code = 'Z204' class TooManyReturnsViolation(BaseStyleViolation): """ This rule forbids placing too many ``return`` statements into the function. When there are too many ``return`` keywords, functions are hard to test. They are also hard to read and hard to change and read. Note: Returns Z205 as error code """ _error_tmpl = '{0} Found too many return statements "{1}"' _code = 'Z205' class TooManyExpressionsViolation(BaseStyleViolation): """ This rule forbids putting to many expression is a unit of code. Because when there are too many expression, it means, that code has some logical or structural problems. We only have to identify them. Note: Returns Z206 as error code """ _error_tmpl = '{0} Found too many expressions "{1}"' _code = 'Z206' class TooDeepNestingViolation(BaseStyleViolation): """ This rule forbids nesting blocks too deep. If nesting is too deep that indicates of another problem, that there's to many things going on at the same time. So, we need to check these cases before they have made their way to production. Note: Returns Z207 as error code """ _error_tmpl = '{0} Found too deep nesting "{1}"' _code = 'Z207' class TooManyModuleMembersViolation(BaseStyleViolation): """ This rule forbids to have many classes and functions in a single module. Having many classes and functions in a single module is a bad thing. Because soon it will be hard to read this code and understand it. It is better to split this module into several modules or a package. We do not make any differences between classes and functions in this check. They are treated as the same unit of logic. We also do no care about functions and classes been public or not. However, methods are counted separatelly on a per-class basis. Note: Returns Z208 as error code """ _error_tmpl = '{0} Found too many members "{1}"' _code = 'Z208' class TooManyMethodsViolation(BaseStyleViolation): """ This rule forbids to have many methods in a single class. We do not make any difference between instance and class methods. We also do no care about functions and classes been public or not. What to do if you have too many methods in a single class? Split this class in several classes. Then use composition or inheritance to refactor your code. This will protect you from "God object" anti-pattern. See: https://en.wikipedia.org/wiki/God_object This rule do not count attributes of a class. Note: Returns Z209 as error code """ _error_tmpl = '{0} Found too many methods "{1}"' _code = 'Z209' PK!l4*wemake_python_styleguide/errors/general.py# -*- coding: utf-8 -*- """ These rules checks some general rules. Like: 1. Naming 2. Using some builtins 3. Using keywords 4. Working with exceptions """ from wemake_python_styleguide.errors.base import BaseStyleViolation class WrongKeywordViolation(BaseStyleViolation): """ This rule forbids to use some keywords from ``python``. We do this, since some keywords are anti-patterns. Example:: # Wrong: pass exec eval Note: Returns Z110 as error code """ _error_tmpl = '{0} Found wrong keyword "{1}"' _code = 'Z110' class BareRiseViolation(BaseStyleViolation): """ This rule forbids using bare `raise` keyword outside of `except` block. This may be a serious error in your application, so we should prevent that. Example:: # Correct: raise ValueError('Value is too low') # Wrong: raise Note: Returns Z111 as error code """ _error_tmpl = '{0} Found bare raise outside of except "{1}"' _code = 'Z111' class RaiseNotImplementedViolation(BaseStyleViolation): """ This rule forbids to use `NotImplemented` error. These two errors have different use cases. Use cases of `NotImplemented` is too limited to be generally available. Example:: # Correct: raise NotImplementedError('To be done') # Wrong: raise NotImplemented See Also: https://stackoverflow.com/a/44575926/4842742 Note: Returns Z112 as error code """ _error_tmpl = '{0} Found raise NotImplemented "{1}"' _code = 'Z112' class WrongFunctionCallViolation(BaseStyleViolation): """ This rule forbids to call some built-in functions. Since some functions are only suitable for very specific usecases, we forbid to use them in a free manner. Note: Returns Z113 as error code """ _error_tmpl = '{0} Found wrong function call "{1}"' _code = 'Z113' class WrongVariableNameViolation(BaseStyleViolation): """ This rule forbids to have blacklisted variable names. Example:: # Correct: html_node = None # Wrong: item = None Note: Returns Z114 as error code """ _error_tmpl = '{0} Found wrong variable name "{1}"' _code = 'Z114' class TooShortVariableNameViolation(BaseStyleViolation): """ This rule forbids to have too short variable names. Example:: # Correct: x_coord = 1 # Wrong: x = 1 Note: Returns Z115 as error code """ _error_tmpl = '{0} Found too short name "{1}"' _code = 'Z115' class PrivateNameViolation(BaseStyleViolation): """ This rule forbids to have private name pattern. It includes: variables, attributes, functions, and methods. Example:: # Correct: def _collect_coverage(self): ... # Wrong: def __collect_coverage(self): ... Note: Returns Z116 as error code """ _error_tmpl = '{0} Found private name pattern "{1}"' _code = 'Z116' class WrongModuleMetadataViolation(BaseStyleViolation): """ This rule forbids to have some module level variables. We discourage using module variables like ``__author__``, because there's no need in them. Use proper docstrings and classifiers. Packaging should not be done in code. Example:: # Wrong: __author__ = 'Nikita Sobolev' Note: Returns Z117 as error code """ _error_tmpl = '{0} Found wrong metadata variable {1}' _code = 'Z117' class FormattedStringViolation(BaseStyleViolation): """ This rule forbids to use `f` strings. Example:: # Wrong: f'Result is: {2 + 2}' # Correct: 'Result is: {0}'.format(2 + 2) Note: Returns Z118 as error code """ _error_tmpl = '{0} Found `f` string {1}' _code = 'Z118' PK!VkQ Q *wemake_python_styleguide/errors/imports.py# -*- coding: utf-8 -*- """These rules checks ``import``s to be defined correctly.""" from wemake_python_styleguide.errors.base import BaseStyleViolation class LocalFolderImportViolation(BaseStyleViolation): """ This rule forbids to have imports relative to the current folder. Example:: # Correct: from my_package.version import get_version # Wrong: from .version import get_version from ..drivers import MySQLDriver Note: Returns Z100 as error code """ _error_tmpl = '{0} Found local folder import "{1}"' _code = 'Z100' class NestedImportViolation(BaseStyleViolation): """ This rule forbids to have nested imports in functions. Nested imports show that there's an issue with you design. So, you don't need nested imports, you need to refactor your code. Example:: # Wrong: def some(): from my_module import some_function Note: Returns Z101 as error code """ _error_tmpl = '{0} Found nested import "{1}"' _code = 'Z101' class FutureImportViolation(BaseStyleViolation): """ This rule forbids to use ``__future__`` imports. Almost all ``__future__`` imports are legacy ``python2`` compatibility tools that are no longer required. Except, there are some new ones for ``python4`` support. Example:: # Correct: from __future__ import annotations # Wrong: from __future__ import print_function Note: Returns Z102 as error code """ _error_tmpl = '{0} Found future import "{1}"' _code = 'Z102' class DottedRawImportViolation(BaseStyleViolation): """ This rule forbids to use imports like ``import os.path``. Example:: # Correct: from os import path # Wrong: import os.path Note: Returns Z103 as error code """ _error_tmpl = '{0} Found dotted raw import "{1}"' _code = 'Z103' class SameAliasImportViolation(BaseStyleViolation): """ This rule forbids to use the same alias as the original name in imports. Example:: # Correct: from os import path # Wrong: from os import path as path Note: Returns Z104 as error code """ _error_tmpl = '{0} Found same alias import "{1}"' _code = 'Z104' PK!uh+wemake_python_styleguide/logics/__init__.py# -*- coding: utf-8 -*- PK![Һ,wemake_python_styleguide/logics/functions.py# -*- coding: utf-8 -*- from ast import Call from typing import Iterable, Optional def given_function_called(node: Call, to_check: Iterable[str]) -> str: """ Returns function name if it is called and contained in the `to_check`. >>> import ast >>> module = ast.parse('print("some value")') >>> given_function_called(module.body[0].value, ['print']) 'print' """ function_name = getattr(node.func, 'id', None) function_value = getattr(node.func, 'value', None) function_inner_id = getattr(function_value, 'id', None) function_attr = getattr(node.func, 'attr', None) is_restricted_function_attribute = ( function_inner_id in to_check and function_attr in to_check ) if function_name in to_check or is_restricted_function_attribute: return function_name return '' def is_method(function_type: Optional[str]) -> bool: """ Returns either or not given function type belongs to a class. >>> is_method('function') False >>> is_method(None) False >>> is_method('method') True >>> is_method('classmethod') True >>> is_method('') False """ return function_type in ['method', 'classmethod'] PK!\rr*wemake_python_styleguide/logics/imports.py# -*- coding: utf-8 -*- import ast from wemake_python_styleguide.types import AnyImport def get_error_text(node: AnyImport) -> str: """Returns correct error text for import nodes.""" module = getattr(node, 'module', None) if module is not None: return module if isinstance(node, ast.Import): return node.names[0].name return '.' PK!=)wemake_python_styleguide/logics/limits.py# -*- coding: utf-8 -*- def has_just_exceeded_limit(current_value: int, limit: int) -> bool: """ Check either value has just exceeded its limit or not. >>> has_just_exceeded_limit(1, 2) False >>> has_just_exceeded_limit(1, 1) False >>> has_just_exceeded_limit(2, 1) True >>> has_just_exceeded_limit(3, 1) False """ return current_value == limit + 1 PK!BSS,wemake_python_styleguide/logics/variables.py# -*- coding: utf-8 -*- from typing import Iterable, Optional def is_wrong_variable_name(name: str, to_check: Iterable[str]) -> bool: """ Checks that variable is not prohibited by explicitly listing it's name. >>> is_wrong_variable_name('wrong', ['wrong']) True >>> is_wrong_variable_name('correct', ['wrong']) False >>> is_wrong_variable_name('_wrong', ['wrong']) True >>> is_wrong_variable_name('wrong_', ['wrong']) True >>> is_wrong_variable_name('wrong__', ['wrong']) False >>> is_wrong_variable_name('__wrong', ['wrong']) False """ for name_to_check in to_check: choices_to_check = [ name_to_check, '_{0}'.format(name_to_check), '{0}_'.format(name_to_check), ] if name in choices_to_check: return True return False def is_too_short_variable_name( name: Optional[str], min_length: int = 2, ) -> bool: """ Checks for too short variable names. >>> is_too_short_variable_name('test') False >>> is_too_short_variable_name(None) False >>> is_too_short_variable_name('o') True >>> is_too_short_variable_name('_') False >>> is_too_short_variable_name('z1') False >>> is_too_short_variable_name('z', min_length=1) False """ return name is not None and name != '_' and len(name) < min_length def is_private_variable(name: Optional[str]) -> bool: """ Checks if variable has private name pattern. >>> is_private_variable(None) False >>> is_private_variable('regular') False >>> is_private_variable('__private') True >>> is_private_variable('_protected') False >>> is_private_variable('__magic__') False """ return ( name is not None and name.startswith('__') and not name.endswith('__') ) PK!uh,wemake_python_styleguide/options/__init__.py# -*- coding: utf-8 -*- PK!*wemake_python_styleguide/options/config.py# -*- coding: utf-8 -*- from typing import Dict, Sequence, Union from flake8.options.manager import OptionManager from wemake_python_styleguide.options import defaults class _Option(object): """This class represent `flake8` option object.""" def __init__( self, name: str, default_value: int, help_text: str, option_type: type = int, parse_from_config: bool = True, ) -> None: self.name = name self.default_value = default_value self.help_text = help_text self.option_type = option_type self.parse_from_config = parse_from_config def to_option(self) -> Dict[str, Union[str, int, type]]: return { 'parse_from_config': self.parse_from_config, 'type': self.option_type, 'default': self.default_value, 'help': self.help_text, } class Configuration(object): """ Provides configuration options for `wemake-python-styleguide` plugin. You can adjust configuration via CLI option: Example:: flake8 --max-returns 7 You can also provide configuration options in `tox.ini` or `setup.cfg`: Example:: [flake8] max-returns = 7 We support the following options: - `max-returns` - maximum allowed number of ``return`` statements in one function, defaults to ``MAX_RETURNS`` - `max-local-variables` - maximum allowed number of local variables in one function, defaults to ``MAX_LOCAL_VARIABLES`` - `max-expressions` - maximum allowed number of expressions in one function, defaults to ``MAX_EXPRESSIONS`` - `max-arguments` - maximum allowed number of arguments in one function, defaults to ``MAX_ARGUMENTS`` - `min-variable-length` - minimum number of chars to define a valid variable name, defaults to ``MIN_VARIABLE_LENGTH`` - `max_offset_blocks` - maximum number of block to nest expressions, defaults to ``MAX_OFFSET_BLOCKS`` - `max_elifs` - maximum number of `elif` blocks, defaults to ``MAX_ELIFS`` - `max_module_members` - maximum number of classes and functions in a single module, defaults to ``MAX_MODULE_MEMBERS`` - `max_methods` - maximum number of methods in a single class, defaults to ``MAX_METHODS`` """ def _all_options(self) -> Sequence[_Option]: return [ _Option( '--max-returns', defaults.MAX_RETURNS, 'Maximum allowed number of return statements in one function.', ), _Option( '--max-local-variables', defaults.MAX_LOCAL_VARIABLES, 'Maximum allowed number of local variables in one function.', ), _Option( '--max-expressions', defaults.MAX_EXPRESSIONS, 'Maximum allowed number of expressions in one function.', ), _Option( '--max-arguments', defaults.MAX_ARGUMENTS, 'Maximum allowed number of arguments in one function.', ), _Option( '--min-variable-length', defaults.MIN_VARIABLE_LENGTH, 'Minimum required length of the variable name.', ), _Option( '--max-offset-blocks', defaults.MAX_OFFSET_BLOCKS, 'Maximum number of blocks to nest different structures.', ), _Option( '--max_elifs', defaults.MAX_ELIFS, 'Maximum number of `elif` blocks.', ), _Option( '--max_module_members', defaults.MAX_MODULE_MEMBERS, 'Maximum number of classes and functions in a single module.', ), _Option( '--max_methods', defaults.MAX_METHODS, 'Maximum number of methods in a single class.', ), ] def register_options(self, parser: OptionManager) -> None: """Registers options for our plugin.""" options = self._all_options() for option in options: parser.add_option(option.name, **option.to_option()) PK!C֙,wemake_python_styleguide/options/defaults.py# -*- coding: utf-8 -*- """ Constants with default values for configuration. We try to stick to "the magical 7 ± 2 number". https://en.wikipedia.org/wiki/The_Magical_Number_Seven,_Plus_or_Minus_Two What does it mean? It means that we choose these values based on our mind capacity. And it is really hard to keep in mind more that 9 objects at the same time. These values can be changed in the `setup.cfg` file, if you find them too strict or too permissive. """ #: Maximum number of `return` statements allowed in a single function: MAX_RETURNS = 5 #: Maximum number of local variables in a function: MAX_LOCAL_VARIABLES = 5 #: Maximum number of expressions in a single function: MAX_EXPRESSIONS = 9 #: Maximum number of arguments for functions or method, `self` is not counted: MAX_ARGUMENTS = 5 #: Minimum variable's name length: MIN_VARIABLE_LENGTH = 2 #: Maximum number of blocks to nest different structures: MAX_OFFSET_BLOCKS = 5 #: Maximum number of `elif` blocks in a single `if` condition: MAX_ELIFS = 2 #: Maximum number of classes and functions in a single module: MAX_MODULE_MEMBERS = 7 #: Maximum number of methods in a single class: MAX_METHODS = 7 PK!Х+!wemake_python_styleguide/types.py# -*- coding: utf-8 -*- """ This module contains custom `mypy` types that we commonly use. General rule is: if there's a complex type, put it here. """ import ast from typing import TYPE_CHECKING, Sequence, Tuple, Type, Union if TYPE_CHECKING: # pragma: no cover from typing_extensions import Protocol # noqa: Z101 # This solves cycle imports problem: from .visitors.base import visitor # noqa: Z100,Z101,F401 else: # We do not need to do anything if typechecker is not working: Protocol = object #: Visitors container, that has all enable visitors' classes: VisitorSequence = Sequence[Type['visitor.BaseNodeVisitor']] #: In cases we need to work with both import types: AnyImport = Union[ast.Import, ast.ImportFrom] #: Flake8 API format to return error messages: CheckResult = Tuple[int, int, str, type] #: Code members that we count in a module: ModuleMembers = Union[ast.FunctionDef, ast.ClassDef] class ConfigurationOptions(Protocol): """ This class provides structure for the options we use in our checker. It uses structural subtyping, and does not represent any kind of a real class or structure. See: https://mypy.readthedocs.io/en/latest/protocols.html """ max_arguments: int max_local_variables: int max_returns: int max_expressions: int min_variable_length: int max_offset_blocks: int max_elifs: int max_module_members: int max_methods: int PK!e[#wemake_python_styleguide/version.py# -*- coding: utf-8 -*- import pkg_resources #: We store the version number inside the `pyproject.toml`: version = pkg_resources.get_distribution('wemake-python-styleguide').version PK!uh-wemake_python_styleguide/visitors/__init__.py# -*- coding: utf-8 -*- PK!uh2wemake_python_styleguide/visitors/base/__init__.py# -*- coding: utf-8 -*- PK!#+1wemake_python_styleguide/visitors/base/visitor.py# -*- coding: utf-8 -*- from ast import NodeVisitor from typing import List from wemake_python_styleguide.errors.base import BaseStyleViolation from wemake_python_styleguide.types import ConfigurationOptions class BaseNodeVisitor(NodeVisitor): """ This class allows to store errors while traversing node tree. Attributes: options: contains the options objects passed and parsed by `flake8`. filename: filename passed by `flake8`. errors: list of errors for the specific checker. """ def __init__( self, options: ConfigurationOptions, filename: str = 'stdin', ) -> None: """Creates new visitor instance.""" super().__init__() self.options = options self.filename = filename self.errors: List[BaseStyleViolation] = [] def add_error(self, error: BaseStyleViolation) -> None: """Adds error to the visitor.""" self.errors.append(error) PK!uh8wemake_python_styleguide/visitors/complexity/__init__.py# -*- coding: utf-8 -*- PK!`b b 6wemake_python_styleguide/visitors/complexity/counts.py# -*- coding: utf-8 -*- import ast from collections import defaultdict from typing import DefaultDict from wemake_python_styleguide.errors.complexity import ( TooManyMethodsViolation, TooManyModuleMembersViolation, ) from wemake_python_styleguide.logics.functions import is_method from wemake_python_styleguide.logics.limits import has_just_exceeded_limit from wemake_python_styleguide.types import ModuleMembers from wemake_python_styleguide.visitors.base.visitor import BaseNodeVisitor class ModuleMembersVisitor(BaseNodeVisitor): """Counts classes and functions in a module.""" def __init__(self, *args, **kwargs) -> None: """Creates a counter for tracked metrics.""" super().__init__(*args, **kwargs) self._public_items_count = 0 def _check_members_count(self, node: ModuleMembers): """This method increases the number of module members.""" parent = getattr(node, 'parent', None) is_real_method = is_method(getattr(node, 'function_type', None)) if isinstance(parent, ast.Module) and not is_real_method: self._public_items_count += 1 max_members = self.options.max_module_members if has_just_exceeded_limit(self._public_items_count, max_members): self.add_error( TooManyModuleMembersViolation(node, text=self.filename), ) def visit_ClassDef(self, node: ast.ClassDef): """ Counts the number of `class`es in a single module. Raises: TooManyModuleMembersViolation """ self._check_members_count(node) self.generic_visit(node) def visit_FunctionDef(self, node: ast.FunctionDef): """ Counts the number of functions in a single module. Raises: TooManyModuleMembersViolation """ self._check_members_count(node) self.generic_visit(node) class MethodMembersVisitor(BaseNodeVisitor): """Counts methods in a single class.""" def __init__(self, *args, **kwargs) -> None: """Creates a counter for tracked methods in different classes.""" super().__init__(*args, **kwargs) self._methods: DefaultDict[ast.ClassDef, int] = defaultdict(int) def _check_method(self, node: ast.FunctionDef): parent = getattr(node, 'parent', None) if isinstance(parent, ast.ClassDef): self._methods[parent] += 1 max_methods = self.options.max_methods if has_just_exceeded_limit(self._methods[parent], max_methods): self.add_error(TooManyMethodsViolation(node, text=parent.name)) def visit_FunctionDef(self, node: ast.FunctionDef): """ Counts the number of methods in a single class. Raises: TooManyMethodsViolation """ self._check_method(node) self.generic_visit(node) PK!^8wemake_python_styleguide/visitors/complexity/function.py# -*- coding: utf-8 -*- import ast from collections import defaultdict from typing import DefaultDict, List, Type from wemake_python_styleguide.errors.base import BaseStyleViolation from wemake_python_styleguide.errors.complexity import ( TooManyArgumentsViolation, TooManyElifsViolation, TooManyExpressionsViolation, TooManyLocalsViolation, TooManyReturnsViolation, ) from wemake_python_styleguide.logics.functions import is_method from wemake_python_styleguide.logics.limits import has_just_exceeded_limit from wemake_python_styleguide.visitors.base.visitor import BaseNodeVisitor class _ComplexityCounter(object): """Helper class to encapsulate logics from the visitor.""" def __init__(self, delegate: 'FunctionComplexityVisitor') -> None: self.delegate = delegate self.expressions: DefaultDict[str, int] = defaultdict(int) self.variables: DefaultDict[str, List[str]] = defaultdict(list) self.returns: DefaultDict[str, int] = defaultdict(int) def _update_variables(self, function: ast.FunctionDef, variable_name: str): """ Increases the counter of local variables. What is treated as a local variable? Check ``TooManyLocalsViolation`` documentation. """ function_variables = self.variables[function.name] if variable_name not in function_variables and variable_name != '_': function_variables.append(variable_name) limit_exceeded = has_just_exceeded_limit( len(function_variables), self.delegate.options.max_local_variables, ) if limit_exceeded: self.delegate.add_error( TooManyLocalsViolation(function, text=function.name), ) def _update_counter( self, function: ast.FunctionDef, counter: DefaultDict[str, int], max_value: int, exception: Type[BaseStyleViolation], ): counter[function.name] += 1 limit_exceeded = has_just_exceeded_limit( counter[function.name], max_value, ) if limit_exceeded: self.delegate.add_error(exception(function, text=function.name)) def _update_elifs(self, node: ast.If, count: int = 0): if node.orelse and isinstance(node.orelse[0], ast.If): self._update_elifs(node.orelse[0], count=count + 1) else: if count > self.delegate.options.max_elifs: self.delegate.add_error(TooManyElifsViolation(node)) def _check_sub_node(self, node: ast.FunctionDef, sub_node): is_variable = isinstance(sub_node, ast.Name) context = getattr(sub_node, 'ctx', None) if is_variable and isinstance(context, ast.Store): self._update_variables(node, getattr(sub_node, 'id')) if isinstance(sub_node, ast.Return): self._update_counter( node, self.returns, self.delegate.options.max_returns, TooManyReturnsViolation, ) if isinstance(sub_node, ast.Expr): self._update_counter( node, self.expressions, self.delegate.options.max_expressions, TooManyExpressionsViolation, ) if isinstance(sub_node, ast.If): self._update_elifs(sub_node) def check_arguments_count(self, node: ast.FunctionDef): """Checks the number of the arguments in a function.""" counter = 0 has_extra_arg = 0 if is_method(getattr(node, 'function_type', None)): has_extra_arg = 1 counter += len(node.args.args) + len(node.args.kwonlyargs) if node.args.vararg: counter += 1 if node.args.kwarg: counter += 1 if counter > self.delegate.options.max_arguments + has_extra_arg: self.delegate.add_error( TooManyArgumentsViolation(node, text=node.name), ) def check_function_complexity(self, node: ast.FunctionDef): """ In this function we iterate all the internal body's node. We check different complexity metrics based on these internals. """ for body_item in node.body: for sub_node in ast.walk(body_item): self._check_sub_node(node, sub_node) class FunctionComplexityVisitor(BaseNodeVisitor): """ This class checks for complexity inside functions. This includes: 1. Number of arguments 2. Number of `return`s 3. Number of expressions 4. Number of local variables 5. Number of `elif`s """ def __init__(self, *args, **kwargs) -> None: """Creates a counter for tracked metrics.""" super().__init__(*args, **kwargs) self._counter = _ComplexityCounter(self) def visit_FunctionDef(self, node: ast.FunctionDef): """ Checks function's internal complexity. Raises: TooManyExpressionsViolation TooManyReturnsViolation TooManyLocalsViolation TooManyArgumentsViolation TooManyElifsViolation """ self._counter.check_arguments_count(node) self._counter.check_function_complexity(node) self.generic_visit(node) PK!@. . 6wemake_python_styleguide/visitors/complexity/nested.py# -*- coding: utf-8 -*- import ast from wemake_python_styleguide.constants import ( NESTED_CLASSES_WHITELIST, NESTED_FUNCTIONS_WHITELIST, ) from wemake_python_styleguide.errors.complexity import ( NestedClassViolation, NestedFunctionViolation, ) from wemake_python_styleguide.visitors.base.visitor import BaseNodeVisitor class NestedComplexityVisitor(BaseNodeVisitor): """ This class checks that structures are not nested. We disallow to use nested functions and nested classes. Because flat is better than nested. We allow to nest function inside classes, that's called methods. """ def visit_ClassDef(self, node: ast.ClassDef): """ Used to find nested classes in other classes and functions. Uses ``NESTED_CLASSES_WHITELIST`` to respect some nested classes. Raises: NestedClassViolation """ parent = getattr(node, 'parent', None) is_inside_class = isinstance(parent, ast.ClassDef) is_inside_function = isinstance(parent, ast.FunctionDef) if is_inside_class and node.name not in NESTED_CLASSES_WHITELIST: self.add_error(NestedClassViolation(node, text=node.name)) elif is_inside_function: self.add_error(NestedClassViolation(node, text=node.name)) self.generic_visit(node) def visit_FunctionDef(self, node: ast.FunctionDef): """ Used to find nested functions. Uses ``NESTED_FUNCTIONS_WHITELIST`` to respect some nested functions. Respected usecases for nested functions: 1. decorator 2. factory function Raises: NestedFunctionViolation """ parent = getattr(node, 'parent', None) is_inside_function = isinstance(parent, ast.FunctionDef) if is_inside_function and node.name not in NESTED_FUNCTIONS_WHITELIST: self.add_error(NestedFunctionViolation(node, text=node.name)) self.generic_visit(node) def visit_Lambda(self, node: ast.Lambda): """ Used to find nested ``lambda``s. Raises: NestedFunctionViolation """ parent = getattr(node, 'parent', None) if isinstance(parent, ast.Lambda): self.add_error(NestedFunctionViolation(node)) self.generic_visit(node) PK!r.6wemake_python_styleguide/visitors/complexity/offset.py# -*- coding: utf-8 -*- import ast from wemake_python_styleguide.errors.complexity import TooDeepNestingViolation from wemake_python_styleguide.visitors.base.visitor import BaseNodeVisitor class OffsetVisitor(BaseNodeVisitor): """This visitor checks offset values for some nodes.""" def _check_offset(self, node: ast.AST): offset = getattr(node, 'col_offset', None) if offset is not None and offset > self.options.max_offset_blocks * 4: self.add_error(TooDeepNestingViolation(node)) def visit_Expr(self, node: ast.AST): """ Checks statement's offset. We check only several nodes, because other nodes might have different offsets, which is fine. For example, `Name` node has inline offset, which can take values from 0 to ~80. But `Name` node is allowed to behave like so. Raises: TooDeepNestingViolation """ self._check_offset(node) self.generic_visit(node) visit_Try = visit_ExceptHandler = visit_Expr visit_For = visit_With = visit_While = visit_If = visit_Expr visit_Raise = visit_Return = visit_Continue = visit_Break = visit_Expr visit_Assign = visit_Expr PK!>YY0wemake_python_styleguide/visitors/wrong_class.py# -*- coding: utf-8 -*- import ast from wemake_python_styleguide.constants import BAD_MAGIC_METHODS from wemake_python_styleguide.errors.classes import ( BadMagicMethodViolation, RequiredBaseClassViolation, StaticMethodViolation, ) from wemake_python_styleguide.visitors.base.visitor import BaseNodeVisitor class WrongClassVisitor(BaseNodeVisitor): """ This class is responsible for restricting some ``class`` antipatterns. Here we check for stylistic issues and design patterns. """ def _check_decorators(self, node: ast.FunctionDef): decorators = getattr(node, 'decorator_list', []) for decorator in decorators: name = getattr(decorator, 'id', None) if name == 'staticmethod': self.add_error(StaticMethodViolation(node, text=node.name)) def _check_magic_methods(self, node: ast.FunctionDef): if node.name in BAD_MAGIC_METHODS: self.add_error(BadMagicMethodViolation(node, text=node.name)) def _check_base_class(self, node: ast.ClassDef): if len(node.bases) == 0: self.add_error(RequiredBaseClassViolation(node, text=node.name)) def visit_ClassDef(self, node: ast.ClassDef): """ Checking class definitions. Used to find: 1. Base class violations Raises: RequiredBaseClassViolation """ self._check_base_class(node) self.generic_visit(node) def visit_FunctionDef(self, node: ast.FunctionDef): """ Checking class methods. Used to find: 1. `@staticmethod` decorators 2. Detect forbiden magic methods Raises: StaticMethodViolation BadMagicMethodViolation """ self._check_decorators(node) self._check_magic_methods(node) self.generic_visit(node) PK!aԨ8wemake_python_styleguide/visitors/wrong_function_call.py# -*- coding: utf-8 -*- import ast from wemake_python_styleguide.constants import BAD_FUNCTIONS from wemake_python_styleguide.errors.general import WrongFunctionCallViolation from wemake_python_styleguide.logics.functions import given_function_called from wemake_python_styleguide.visitors.base.visitor import BaseNodeVisitor class WrongFunctionCallVisitor(BaseNodeVisitor): """ This class is responsible for restricting some dangerous function calls. All these functions are defined in `BAD_FUNCTIONS`. """ def visit_Call(self, node: ast.Call): """ Used to find `BAD_FUNCTIONS` calls. Raises: WrongFunctionCallViolation """ function_name = given_function_called(node, BAD_FUNCTIONS) if function_name: self.add_error(WrongFunctionCallViolation( node, text=function_name, )) self.generic_visit(node) PK!Js| | 1wemake_python_styleguide/visitors/wrong_import.py# -*- coding: utf-8 -*- import ast from wemake_python_styleguide.constants import FUTURE_IMPORTS_WHITELIST from wemake_python_styleguide.errors.imports import ( DottedRawImportViolation, FutureImportViolation, LocalFolderImportViolation, NestedImportViolation, SameAliasImportViolation, ) from wemake_python_styleguide.logics.imports import get_error_text from wemake_python_styleguide.types import AnyImport from wemake_python_styleguide.visitors.base.visitor import BaseNodeVisitor class _ImportsChecker(object): def __init__(self, delegate: 'WrongImportVisitor') -> None: self.delegate = delegate def check_nested_import(self, node: AnyImport): text = get_error_text(node) parent = getattr(node, 'parent', None) if not isinstance(parent, ast.Module): self.delegate.add_error(NestedImportViolation(node, text=text)) def check_local_import(self, node: ast.ImportFrom): text = get_error_text(node) if node.level != 0: self.delegate.add_error( LocalFolderImportViolation(node, text=text), ) def check_future_import(self, node: ast.ImportFrom): if node.module == '__future__': for alias in node.names: if alias.name not in FUTURE_IMPORTS_WHITELIST: self.delegate.add_error( FutureImportViolation(node, text=alias.name), ) def check_dotted_raw_import(self, node: ast.Import): for alias in node.names: if '.' in alias.name: self.delegate.add_error( DottedRawImportViolation(node, text=alias.name), ) def check_alias(self, node: AnyImport): for alias in node.names: if alias.asname == alias.name: self.delegate.add_error( SameAliasImportViolation(node, text=alias.name), ) class WrongImportVisitor(BaseNodeVisitor): """This class is responsible for finding wrong imports.""" def __init__(self, *args, **kwargs) -> None: """Creates a checher for tracked violations.""" super().__init__(*args, **kwargs) self._checker = _ImportsChecker(self) def visit_Import(self, node: ast.Import): """ Used to find wrong `import` statements. Raises: SameAliasImportViolation DottedRawImportViolation NestedImportViolation """ self._checker.check_nested_import(node) self._checker.check_dotted_raw_import(node) self._checker.check_alias(node) self.generic_visit(node) def visit_ImportFrom(self, node: ast.ImportFrom): """ Used to find wrong `from import` statements. Raises: SameAliasImportViolation NestedImportViolation LocalFolderImportViolation FutureImportViolation """ self._checker.check_local_import(node) self._checker.check_nested_import(node) self._checker.check_future_import(node) self._checker.check_alias(node) self.generic_visit(node) PK!M^ 2wemake_python_styleguide/visitors/wrong_keyword.py# -*- coding: utf-8 -*- import ast from wemake_python_styleguide.errors.general import ( BareRiseViolation, RaiseNotImplementedViolation, WrongKeywordViolation, ) from wemake_python_styleguide.visitors.base.visitor import BaseNodeVisitor class WrongRaiseVisitor(BaseNodeVisitor): """This class finds wrong `raise` keywords.""" def _check_exception_type(self, node: ast.Raise, exception) -> None: exception_func = getattr(exception, 'func', None) if exception_func: exception = exception_func exception_name = getattr(exception, 'id', None) if exception_name == 'NotImplemented': self.add_error( RaiseNotImplementedViolation(node, text=exception_name), ) def _check_bare_raise(self, node: ast.Raise) -> None: parent = getattr(node, 'parent', None) if not isinstance(parent, ast.ExceptHandler): self.add_error(BareRiseViolation(node)) def visit_Raise(self, node: ast.Raise) -> None: """ Checks how `raise` keyword is used. Raises: RaiseNotImplementedViolation BareRiseViolation """ exception = getattr(node, 'exc', None) if not exception: self._check_bare_raise(node) else: self._check_exception_type(node, exception) self.generic_visit(node) class WrongKeywordVisitor(BaseNodeVisitor): """This class is responsible for finding wrong keywords.""" def visit_Global(self, node: ast.Global): """ Used to find `global` keyword. Raises: WrongKeywordViolation """ self.add_error(WrongKeywordViolation(node)) self.generic_visit(node) def visit_Nonlocal(self, node: ast.Nonlocal): """ Used to find `nonlocal` keyword. Raises: WrongKeywordViolation """ self.add_error(WrongKeywordViolation(node)) self.generic_visit(node) def visit_Delete(self, node: ast.Delete): """ Used to find `del` keyword. Raises: WrongKeywordViolation """ self.add_error(WrongKeywordViolation(node, text='del')) self.generic_visit(node) def visit_Pass(self, node: ast.Pass): """ Used to find `pass` keyword. Raises: WrongKeywordViolation """ self.add_error(WrongKeywordViolation(node)) self.generic_visit(node) PK!(==/wemake_python_styleguide/visitors/wrong_name.py# -*- coding: utf-8 -*- import ast from wemake_python_styleguide.constants import ( BAD_MODULE_METADATA_VARIABLES, BAD_VARIABLE_NAMES, ) from wemake_python_styleguide.errors.general import ( PrivateNameViolation, TooShortVariableNameViolation, WrongModuleMetadataViolation, WrongVariableNameViolation, ) from wemake_python_styleguide.logics.variables import ( is_private_variable, is_too_short_variable_name, is_wrong_variable_name, ) from wemake_python_styleguide.types import AnyImport from wemake_python_styleguide.visitors.base.visitor import BaseNodeVisitor class WrongNameVisitor(BaseNodeVisitor): """ This class performs checks based on variable names. It is responsible for finding short and blacklisted variables, functions, and arguments. """ def _check_name(self, node: ast.AST, arg: str) -> None: if is_wrong_variable_name(arg, BAD_VARIABLE_NAMES): self.add_error(WrongVariableNameViolation(node, text=arg)) min_length = self.options.min_variable_length if is_too_short_variable_name(arg, min_length=min_length): self.add_error(TooShortVariableNameViolation(node, text=arg)) if is_private_variable(arg): self.add_error(PrivateNameViolation(node, text=arg)) def _check_function_signature(self, node: ast.FunctionDef) -> None: for arg in node.args.args: self._check_name(node, arg.arg) for arg in node.args.kwonlyargs: self._check_name(node, arg.arg) if node.args.vararg: self._check_name(node, node.args.vararg.arg) if node.args.kwarg: self._check_name(node, node.args.kwarg.arg) def visit_Attribute(self, node: ast.Attribute): """ Used to find wrong attribute names inside classes. Raises: WrongVariableNameViolation TooShortVariableNameViolation PrivateNameViolation """ context = getattr(node, 'ctx', None) if isinstance(context, ast.Store): self._check_name(node, node.attr) self.generic_visit(node) def visit_FunctionDef(self, node: ast.FunctionDef): """ Used to find wrong function and method parameters. Raises: WrongVariableNameViolation TooShortVariableNameViolation PrivateNameViolation """ name = getattr(node, 'name', None) self._check_name(node, name) self._check_function_signature(node) self.generic_visit(node) def visit_ExceptHandler(self, node: ast.ExceptHandler): """ Used to find wrong exception instances in ``try``/``except``. Raises: WrongVariableNameViolation TooShortVariableNameViolation PrivateNameViolation """ name = getattr(node, 'name', None) self._check_name(node, name) self.generic_visit(node) def visit_Name(self, node: ast.Name): """ Used to find wrong regular variables. Raises: WrongVariableNameViolation TooShortVariableNameViolation PrivateNameViolation """ context = getattr(node, 'ctx', None) if isinstance(context, ast.Store): self._check_name(node, node.id) self.generic_visit(node) def visit_Import(self, node: AnyImport): """ Used to check wrong import alias names. Raises: WrongVariableNameViolation TooShortVariableNameViolation PrivateNameViolation """ for alias in node.names: if alias.asname: self._check_name(node, alias.asname) self.generic_visit(node) visit_ImportFrom = visit_Import class WrongModuleMetadataVisitor(BaseNodeVisitor): """This class finds wrong metadata information of a module.""" def _check_metadata(self, node: ast.Assign): node_parent = getattr(node, 'parent', None) if not isinstance(node_parent, ast.Module): return for target_node in node.targets: target_node_id = getattr(target_node, 'id', None) if target_node_id in BAD_MODULE_METADATA_VARIABLES: self.add_error( WrongModuleMetadataViolation(node, text=target_node_id), ) def visit_Assign(self, node: ast.Assign): """ Used to find the bad metadata variable names. Raises: WrongModuleMetadataViolation """ self._check_metadata(node) self.generic_visit(node) PK!1wemake_python_styleguide/visitors/wrong_string.py# -*- coding: utf-8 -*- from wemake_python_styleguide.errors.general import FormattedStringViolation from wemake_python_styleguide.visitors.base.visitor import BaseNodeVisitor class WrongStringVisitor(BaseNodeVisitor): """Restricts to use `f` strings.""" def visit_JoinedStr(self, node): # type is not defined in `ast` yet """ Restricts to use `f` strings. Raises: FormattedStringViolation """ self.add_error(FormattedStringViolation(node)) self.generic_visit(node) PK!H";?9wemake_python_styleguide-0.0.9.dist-info/entry_points.txtNINK(I+ϋ劲-O TdT椦f%g&gY9Ch..PK!f000wemake_python_styleguide-0.0.9.dist-info/LICENSEMIT License Copyright (c) 2018 wemake.services Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK!H_zTT.wemake_python_styleguide-0.0.9.dist-info/WHEEL A н#Z;/"d&F[xzw@Zpy3Fv]n0H*J>mlcAPK!H6_21wemake_python_styleguide-0.0.9.dist-info/METADATAWms8_c Ir!M^۹b+ؖ+oe;MH0`[>]AQ*j^MRvIVZ<6ZlͪY$"*M2LXϩ܋P`$@X\ZĒ @D6U u,GՂĝtIRgK9O^q&(WIgq%db_yġNY4ɀ-d²xl D-؊ה (#$6VhTJ6gǰ'ĊLU$&ia NdǙ, y,ކHW`p -ͶޏN= ZAܐ-%>D%63-o jZ*r]AjC|$#pFc?Škg#^*oƔ' >W+*`#DMGP@>9^|EJCĖ2cq4LT%yN"ypB|کԬZtgϪWv,ĘLz[9?-rO:lDDBVD@ɆY,< rlu]ae6c3̂ǫ/gS}ycgQnօ~޽-awx2\άs3gk[>#ȿ˛~ʾ{7To-kv<8w`pm~<_\^@=W yۣްgۓѭ9.Yb$Wmg~thg:bqceyhHJ%,.gw,dp!y6v#!s'aebrx6p{[oy!#Pz'|7Әb$-^fFT-z*] `Wyգb7!~R}i?CSj[= 2$ @L,V 0@},YMRLTKzi]oz$VDM xG͙Q #h c2KE ZϪpa\=0Ip:EJVpE24$|&QMqhpSAr W{;a[r0^N* KpV (AWM%$3 I"3.ZŽCnL9> c@ߚMy['N5?Ge2g!rkbdEqCw2>sƸ  / ?L+~a{Lsȣ"ﲻ7%wM^צh]dg|Un7pܷHҳ~3t?WB.012PK!HMePK/wemake_python_styleguide-0.0.9.dist-info/RECORDIF,aY(2*l2B1_;o;כ,:KG(9 A x4؉PFw68 d띎bNu~O#L@L+Ss#? vX Q+.E/'A_[GfNvC q w\0s9 jg_X-wK(l0 ,$pCϞi'ַ2Ep!n_>\k>wo>eE'4Z7 ~1tۧGor7ݐƁfl^ԹÑNDW3~*\ \T;bFߋFgLa͆!epl.A%; kg{sY^;uW e@ NY- ze/ZlMqVq7ţ|"i6fN0iAͦ;…Y%=#~NHʺUP!+thlm趗g^nl*,2 P2¯ȴ?;7x}3@EO0ph)gSM((un[A&A M(TqT7,aR;4ƨ(`Opx( ϒ ּNiV'bc7^b`,CTۊCHUAX1O3'6eI(yJO*iIhDCrYk}6+X]˰%>Io!![Tp&z~!2{g \5S꣉B/tURW_N 7(ƍ}nn8Iռ43?4Y ֱcdecC!ѼHmVQ}fgkg?.?ܝ$i߭~#]'pCإ߄Nbom7!/'.+qe8h &"60Il[Ӎmt.Ϻ"YDPK!uh$wemake_python_styleguide/__init__.pyPK!̎r  #Zwemake_python_styleguide/checker.pyPK!Y" wemake_python_styleguide/compat.pyPK!)11%wemake_python_styleguide/constants.pyPK!uh+Nwemake_python_styleguide/errors/__init__.pyPK!@'wemake_python_styleguide/errors/base.pyPK!eHH*wemake_python_styleguide/errors/classes.pyPK! 8##-C"wemake_python_styleguide/errors/complexity.pyPK!l4*:wemake_python_styleguide/errors/general.pyPK!VkQ Q *Jwemake_python_styleguide/errors/imports.pyPK!uh+*Twemake_python_styleguide/logics/__init__.pyPK![Һ,Twemake_python_styleguide/logics/functions.pyPK!\rr*Ywemake_python_styleguide/logics/imports.pyPK!=)X[wemake_python_styleguide/logics/limits.pyPK!BSS,3]wemake_python_styleguide/logics/variables.pyPK!uh,dwemake_python_styleguide/options/__init__.pyPK!*2ewemake_python_styleguide/options/config.pyPK!C֙,`vwemake_python_styleguide/options/defaults.pyPK!Х+!C{wemake_python_styleguide/types.pyPK!e[#+wemake_python_styleguide/version.pyPK!uh-$wemake_python_styleguide/visitors/__init__.pyPK!uh2wemake_python_styleguide/visitors/base/__init__.pyPK!#+1wemake_python_styleguide/visitors/base/visitor.pyPK!uh8wemake_python_styleguide/visitors/complexity/__init__.pyPK!`b b 6gwemake_python_styleguide/visitors/complexity/counts.pyPK!^8wemake_python_styleguide/visitors/complexity/function.pyPK!@. . 6^wemake_python_styleguide/visitors/complexity/nested.pyPK!r.6wemake_python_styleguide/visitors/complexity/offset.pyPK!>YY0wemake_python_styleguide/visitors/wrong_class.pyPK!aԨ8wemake_python_styleguide/visitors/wrong_function_call.pyPK!Js| | 1wemake_python_styleguide/visitors/wrong_import.pyPK!M^ 2gwemake_python_styleguide/visitors/wrong_keyword.pyPK!(==/wemake_python_styleguide/visitors/wrong_name.pyPK!1wemake_python_styleguide/visitors/wrong_string.pyPK!H";?9|wemake_python_styleguide-0.0.9.dist-info/entry_points.txtPK!f000wemake_python_styleguide-0.0.9.dist-info/LICENSEPK!H_zTT.wemake_python_styleguide-0.0.9.dist-info/WHEELPK!H6_21,wemake_python_styleguide-0.0.9.dist-info/METADATAPK!HMePK/Twemake_python_styleguide-0.0.9.dist-info/RECORDPK''