diff --git a/Makefile b/Makefile index 5228da1..b9cd5bc 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,22 @@ venv/bin/activate: python3 -m venv venv + source venv/bin/activate && pip install --upgrade pip + source venv/bin/activate && pip install -r requirements.txt .PHONY: virtualenv virtualenv: venv/bin/activate - source venv/bin/activate && pip install --upgrade pip - source venv/bin/activate && pip install -r requirements.txt .PHONY: test-types -test-types: +test-types: venv/bin/activate source venv/bin/activate && mypy -m unittest test: test-types +.PHONY: test-lint +test-lint: venv/bin/activate + source venv/bin/activate && pylint pydevicetree +test: test-lint + .PHONY: test test: venv/bin/activate source venv/bin/activate && python3 -m unittest diff --git a/pydevicetree/__init__.py b/pydevicetree/__init__.py index 42ebeb7..e5a0d9b 100644 --- a/pydevicetree/__init__.py +++ b/pydevicetree/__init__.py @@ -1,3 +1 @@ -#!/usr/bin/env python3 - -from pydevicetree.ast import Devicetree +#!/usr/bin/env python3 diff --git a/pydevicetree/ast/classes.py b/pydevicetree/ast/classes.py index 72018fb..9b7122d 100644 --- a/pydevicetree/ast/classes.py +++ b/pydevicetree/ast/classes.py @@ -3,13 +3,13 @@ import os import re -from typing import List, Union, Optional, TypeVar, Type, Iterable, Callable, cast, Any, Pattern +from typing import List, Union, Optional, Iterable, Callable, cast, Any, Pattern -# These type names are just used in the constructors for these clasess +# These names are just used in the constructors for these clasess ElementList = Iterable[Union['Node', 'Property', 'Directive']] DirectiveOption = List[Any] -# Callback type signatures for Devicetree.match() and Devicetree.chosen() +# Callback isinstance signatures for Devicetree.match() and Devicetree.chosen() MatchCallback = Optional[Callable[['Node'], None]] ChosenCallback = Optional[Callable[['PropertyValues'], None]] @@ -19,12 +19,12 @@ def formatLevel(level: int, s: str) -> str: def wrapStrings(values: List[Any], formatHex: bool = False) -> List[Any]: wrapped = [] for v in values: - if type(v) is str: + if isinstance(v, str): if v[0] != '&': wrapped.append("\"%s\"" % v) else: wrapped.append(v) - elif type(v) is int: + elif isinstance(v, int): if formatHex: wrapped.append("0x%x" % v) else: @@ -34,7 +34,7 @@ def wrapStrings(values: List[Any], formatHex: bool = False) -> List[Any]: return wrapped class PropertyValues: - def __init__(self, values: List[Any] = []): + def __init__(self, values: List[Any] = None): self.values = values def __repr__(self) -> str: @@ -58,21 +58,20 @@ def __getitem__(self, key) -> Any: def __eq__(self, other) -> bool: if isinstance(other, PropertyValues): return self.values == other.values - else: - return self.values == other + return self.values == other class Bytestring(PropertyValues): - def __init__(self, bytelist: List[int] = []): + def __init__(self, bytelist: List[int] = None): PropertyValues.__init__(self, bytearray(bytelist)) def __repr__(self) -> str: return "" def to_dts(self, formatHex: bool = False) -> str: - return "[" + " ".join("%02x" % v for v in self.values) + "]"; + return "[" + " ".join("%02x" % v for v in self.values) + "]" class CellArray(PropertyValues): - def __init__(self, cells: List[Any] = []): + def __init__(self, cells: List[Any] = None): PropertyValues.__init__(self, cells) def __repr__(self) -> str: @@ -82,7 +81,7 @@ def to_dts(self, formatHex: bool = False) -> str: return "<" + " ".join(wrapStrings(self.values, formatHex)) + ">" class StringList(PropertyValues): - def __init__(self, strings: List[str] = []): + def __init__(self, strings: List[str] = None): PropertyValues.__init__(self, strings) def __repr__(self) -> str: @@ -104,17 +103,16 @@ def __str__(self) -> str: def to_dts(self, level: int = 0) -> str: if self.name in ["reg", "ranges"]: - value = self.values.to_dts(formatHex = True) + value = self.values.to_dts(formatHex=True) else: - value = self.values.to_dts(formatHex = False) + value = self.values.to_dts(formatHex=False) if value != "": return formatLevel(level, "%s = %s;\n" % (self.name, value)) - else: - return formatLevel(level, "%s;\n" % self.name) + return formatLevel(level, "%s;\n" % self.name) class Directive: - def __init__(self, directive: str, options: DirectiveOption = []): + def __init__(self, directive: str, options: DirectiveOption = None): self.directive = directive self.options = options @@ -127,13 +125,15 @@ def __str__(self) -> str: def to_dts(self, level: int = 0) -> str: if self.options: return formatLevel(level, "%s %s;\n" % (self.directive, self.options)) - else: - return formatLevel(level, "%s;\n" % self.directive) + return formatLevel(level, "%s;\n" % self.directive) class Node: - def __init__(self, name: str, label: Optional[str] = None, address: Optional[str] = None, properties: List[Property] = [], directives: List[Directive] = [], children: List['Node'] = []): + # pylint: disable=too-many-arguments + def __init__(self, name: str, label: Optional[str] = None, address: Optional[str] = None, + properties: List[Property] = None, directives: List[Directive] = None, + children: List['Node'] = None): self.name = name - self.parent = None # type: Optional['Node'] + self.parent = None # isinstance: Optional['Node'] self.label = label self.address = address @@ -144,17 +144,17 @@ def __init__(self, name: str, label: Optional[str] = None, address: Optional[str def __repr__(self) -> str: if self.address: return "" % (self.name, self.address) - else: - return "" % self.name + return "" % self.name def __str__(self) -> str: return self.to_dts() def to_dts(self, level: int = 0) -> str: out = "" - if type(self.address) is int and self.label: - out += formatLevel(level, "%s: %s@%x {\n" % (self.label, self.name, cast(int, self.address))) - elif type(self.address) is int: + if isinstance(self.address, int) and self.label: + out += formatLevel(level, + "%s: %s@%x {\n" % (self.label, self.name, cast(int, self.address))) + elif isinstance(self.address, int): out += formatLevel(level, "%s@%x {\n" % (self.name, cast(int, self.address))) elif self.label: out += formatLevel(level, "%s: %s {\n" % (self.label, self.name)) @@ -196,7 +196,7 @@ def address_cells(self): cells = self.get_field("#address-cells") if cells is not None: return cells - elif self.parent is not None: + if self.parent is not None: return self.parent.address_cells() # No address cells found return 0 @@ -205,26 +205,27 @@ def size_cells(self): cells = self.get_field("#size-cells") if cells is not None: return cells - elif self.parent is not None: + if self.parent is not None: return self.parent.size_cells() # No size cells found return 0 class Devicetree(Node): - def __init__(self, elements: ElementList = []): + def __init__(self, elements: ElementList = None): properties = [] # type: List[Property] directives = [] # type: List[Directive] children = [] # type: List[Node] for e in elements: - if type(e) is Node: + if isinstance(e, Node): children.append(cast(Node, e)) - elif type(e) is Property: + elif isinstance(e, Property): properties.append(cast(Property, e)) - elif type(e) is Directive: + elif isinstance(e, Directive): directives.append(cast(Directive, e)) - Node.__init__(self, name="", properties=properties, directives=directives, children=children) + Node.__init__(self, name="", + properties=properties, directives=directives, children=children) def __repr__(self) -> str: name = self.root().get_field("compatible") @@ -244,6 +245,7 @@ def to_dts(self, level: int = 0) -> str: @staticmethod def parseFile(filename: str, followIncludes: bool = False) -> 'Devicetree': + # pylint: disable=import-outside-toplevel,cyclic-import from pydevicetree.source import parseTree with open(filename, 'r') as f: contents = f.read() @@ -288,4 +290,3 @@ def match_chosen(node: Node) -> bool: return p.values return None - diff --git a/pydevicetree/source/__init__.py b/pydevicetree/source/__init__.py index cb60cde..975a1db 100644 --- a/pydevicetree/source/__init__.py +++ b/pydevicetree/source/__init__.py @@ -1,3 +1,3 @@ #!/usr/bin/env python3 -from pydevicetree.source.parser import printTree, parseTree +from pydevicetree.source.parser import * diff --git a/pydevicetree/source/grammar.py b/pydevicetree/source/grammar.py index 1b8ffde..bee3277 100644 --- a/pydevicetree/source/grammar.py +++ b/pydevicetree/source/grammar.py @@ -12,9 +12,13 @@ label_creation = p.Combine(label + p.Literal(":")) string = p.QuotedString(quoteChar='"') stringlist = p.delimitedList(string) -node_path = p.Combine(p.Literal("/") + p.delimitedList(node_name, delim="/") + p.Optional(p.Literal("@") + unit_address)) -reference = p.Combine(p.Literal("&") + ((p.Literal("{") + node_path("path") + p.Literal("}")) ^ label)) -directive = p.QuotedString(quoteChar="/", unquoteResults=False).setResultsName("directive") + p.Optional(string ^ property_name ^ node_name ^ reference ^ (integer * 2)).setResultsName("option") + p.Literal(";").suppress() +node_path = p.Combine(p.Literal("/") + p.delimitedList(node_name, delim="/") + \ + p.Optional(p.Literal("@") + unit_address)) +reference = p.Combine(p.Literal("&") + \ + ((p.Literal("{") + node_path("path") + p.Literal("}")) ^ label)) +directive = p.QuotedString(quoteChar="/", unquoteResults=False).setResultsName("directive") + \ + p.Optional(string ^ property_name ^ node_name ^ reference ^ \ + (integer * 2)).setResultsName("option") + p.Literal(";").suppress() operator = p.oneOf("~ ! * / + - << >> < <= > >= == != & ^ | && ||") arith_expr = p.Forward() @@ -22,14 +26,21 @@ ternary_expr = ternary_element + p.Literal("?") + ternary_element + p.Literal(":") + ternary_element arith_expr = p.nestedExpr(content=(p.OneOrMore(operator ^ integer) ^ ternary_expr)) -cell_array = p.Literal("<").suppress() + p.ZeroOrMore(integer ^ arith_expr ^ string ^ reference ^ label_creation) + p.Literal(">").suppress() -bytestring = p.Literal("[").suppress() + (p.OneOrMore(p.Word(p.hexnums, exact=2) ^ label_creation)) + p.Literal("]").suppress() -property_assignment = property_name("property_name") + p.Optional(p.Literal("=").suppress() + (cell_array ^ bytestring ^ stringlist)).setResultsName("value") + p.Literal(";").suppress() +cell_array = p.Literal("<").suppress() + \ + p.ZeroOrMore(integer ^ arith_expr ^ string ^ reference ^ label_creation) + \ + p.Literal(">").suppress() +bytestring = p.Literal("[").suppress() + \ + (p.OneOrMore(p.Word(p.hexnums, exact=2) ^ label_creation)) + p.Literal("]").suppress() +property_assignment = property_name("property_name") + p.Optional(p.Literal("=").suppress() + \ + (cell_array ^ bytestring ^ stringlist)).setResultsName("value") + p.Literal(";").suppress() -node_opener = p.Optional(label_creation) + node_name("node_name") + p.Optional(p.Literal("@").suppress() + unit_address("address")) + p.Literal("{").suppress() +node_opener = p.Optional(label_creation) + node_name("node_name") + \ + p.Optional(p.Literal("@").suppress() + unit_address("address")) + p.Literal("{").suppress() node_closer = p.Literal("}").suppress() + p.Literal(";").suppress() node_definition = p.Forward() -node_definition << node_opener + p.ZeroOrMore(property_assignment ^ directive ^ node_definition) + node_closer +# pylint: disable=expression-not-assigned +node_definition << node_opener + p.ZeroOrMore(property_assignment ^ directive ^ node_definition) + \ + node_closer devicetree = p.ZeroOrMore(directive ^ node_definition) diff --git a/pydevicetree/source/parser.py b/pydevicetree/source/parser.py index cdf5969..87c3ae5 100644 --- a/pydevicetree/source/parser.py +++ b/pydevicetree/source/parser.py @@ -1,24 +1,25 @@ #!/usr/bin/env python3 -from pydevicetree.source.grammar import * -from pydevicetree.ast.classes import * - from itertools import chain +from pydevicetree.source.grammar import * +from pydevicetree.ast import * + def transformNode(string, location, tokens): - properties = [e for e in tokens.asList() if type(e) is Property] - directives = [e for e in tokens.asList() if type(e) is Directive] - children = [e for e in tokens.asList() if type(e) is Node] + properties = [e for e in tokens.asList() if isinstance(e, Property)] + directives = [e for e in tokens.asList() if isinstance(e, Directive)] + children = [e for e in tokens.asList() if isinstance(e, Node)] - return Node(tokens.node_name, tokens.label, tokens.address, properties=properties, directives=directives, children=children) + return Node(tokens.node_name, tokens.label, tokens.address, properties=properties, + directives=directives, children=children) def transformPropertyAssignment(string, location, tokens): for v in tokens.value: - if type(v) is PropertyValues: + if isinstance(v, PropertyValues): return Property(tokens.property_name, v) - if type(v) is CellArray: + if isinstance(v, CellArray): return Property(tokens.property_name, v) - if type(v) is StringList: + if isinstance(v, StringList): return Property(tokens.property_name, v) return Property(tokens.property_name, PropertyValues([])) @@ -29,10 +30,12 @@ def transformDirective(string, location, tokens): def evaluateArithExpr(string, location, tokens): flat_tokens = list(chain.from_iterable(tokens.asList())) expr = " ".join(str(t) for t in flat_tokens) + # pylint: disable=eval-used return eval(expr) def transformTernary(string, location, tokens): - return eval(str(tokens[2]) +" if " + str(tokens[0]) + " else " + str(tokens[4])) + # pylint: disable=eval-used + return eval(str(tokens[2]) +" if " + str(tokens[0]) + " else " + str(tokens[4])) def transformStringList(string, location, tokens): return StringList(tokens.asList()) @@ -61,7 +64,7 @@ def printlevel(level, s): print(" " * level + s) for item in tree: - if type(item) is Node: + if isinstance(item, Node): if item.address: printlevel(level, "Node %s@%x" % (item.name, item.address)) else: @@ -76,12 +79,12 @@ def printlevel(level, s): printTree(item.properties, level=(level + 1)) printTree(item.children, level=(level + 1)) - elif type(item) is Property: + elif isinstance(item, Property): if item.values: printlevel(level, "Property %s: %s" % (item.name, item.values)) else: printlevel(level, "Property %s" % item.name) - elif type(item) is Directive: + elif isinstance(item, Directive): if item.options: printlevel(level, "Directive %s: %s" % (item.directive, item.options)) else: @@ -89,13 +92,13 @@ def printlevel(level, s): def parentNodes(tree, parent=None): for item in tree: - if type(item) is Node: + if isinstance(item, Node): item.parent = parent parentNodes(item.children, item) def recurseIncludeFiles(elements, pwd): for e in elements: - if type(e) is Directive: + if isinstance(e, Directive): if e.directive == "/include/": # Prefix with current directory if path is not absolute if e.options[0] != '/': @@ -127,4 +130,3 @@ def parseTree(dts, pwd="", followIncludes=False): else: print("Please pass the devicetree source file as an argument") sys.exit(1) - diff --git a/pylintrc b/pylintrc new file mode 100644 index 0000000..f0d28a9 --- /dev/null +++ b/pylintrc @@ -0,0 +1,589 @@ +[MASTER] + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code. +extension-pkg-whitelist= + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS + +# Add files or directories matching the regex patterns to the blacklist. The +# regex matches against base names, not paths. +ignore-patterns= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the +# number of processors available to use. +jobs=1 + +# Control the amount of potential inferred values when inferring a single +# object. This can help the performance when dealing with large functions or +# complex, nested conditions. +limit-inference-results=100 + +# List of plugins (as comma separated values of python module names) to load, +# usually to register additional checkers. +load-plugins= + +# Pickle collected data for later comparisons. +persistent=yes + +# Specify a configuration file. +#rcfile= + +# When enabled, pylint would attempt to guess common misconfiguration and emit +# user-friendly hints instead of false-positive error messages. +suggestion-mode=yes + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED. +confidence= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once). You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use "--disable=all --enable=classes +# --disable=W". +disable=print-statement, + parameter-unpacking, + unpacking-in-except, + old-raise-syntax, + backtick, + long-suffix, + old-ne-operator, + old-octal-literal, + import-star-module-level, + non-ascii-bytes-literal, + raw-checker-failed, + bad-inline-option, + locally-disabled, + file-ignored, + suppressed-message, + useless-suppression, + deprecated-pragma, + use-symbolic-message-instead, + apply-builtin, + basestring-builtin, + buffer-builtin, + cmp-builtin, + coerce-builtin, + execfile-builtin, + file-builtin, + long-builtin, + raw_input-builtin, + reduce-builtin, + standarderror-builtin, + unicode-builtin, + xrange-builtin, + coerce-method, + delslice-method, + getslice-method, + setslice-method, + no-absolute-import, + old-division, + dict-iter-method, + dict-view-method, + next-method-called, + metaclass-assignment, + indexing-exception, + raising-string, + reload-builtin, + oct-method, + hex-method, + nonzero-method, + cmp-method, + input-builtin, + round-builtin, + intern-builtin, + unichr-builtin, + map-builtin-not-iterating, + zip-builtin-not-iterating, + range-builtin-not-iterating, + filter-builtin-not-iterating, + using-cmp-argument, + eq-without-hash, + div-method, + idiv-method, + rdiv-method, + exception-message-attribute, + invalid-str-codec, + sys-max-int, + bad-python3-import, + deprecated-string-function, + deprecated-str-translate-call, + deprecated-itertools-function, + deprecated-types-field, + next-method-defined, + dict-items-not-iterating, + dict-keys-not-iterating, + dict-values-not-iterating, + deprecated-operator-function, + deprecated-urllib-function, + xreadlines-attribute, + deprecated-sys-function, + exception-escape, + comprehension-escape, + missing-module-docstring, + missing-class-docstring, + missing-function-docstring, + wildcard-import, + unused-wildcard-import, + invalid-name, + unused-argument, + redefined-outer-name + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +enable=c-extension-no-member + + +[REPORTS] + +# Python expression which should return a score less than or equal to 10. You +# have access to the variables 'error', 'warning', 'refactor', and 'convention' +# which contain the number of messages in each category, as well as 'statement' +# which is the total number of statements analyzed. This score is used by the +# global evaluation report (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details. +#msg-template= + +# Set the output format. Available formats are text, parseable, colorized, json +# and msvs (visual studio). You can also give a reporter class, e.g. +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Tells whether to display a full report or only the messages. +reports=no + +# Activate the evaluation score. +score=yes + + +[REFACTORING] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + +# Complete name of functions that never returns. When checking for +# inconsistent-return-statements if a never returning function is called then +# it will be considered as an explicit return statement and no message will be +# printed. +never-returning-functions=sys.exit + + +[VARIABLES] + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid defining new builtins when possible. +additional-builtins= + +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_, + _cb + +# A regular expression matching the name of dummy variables (i.e. expected to +# not be used). +dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore. +ignored-argument-names=_.*|^ignored_|^unused_ + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io + + +[STRING] + +# This flag controls whether the implicit-str-concat-in-sequence should +# generate a warning on implicit string concatenation in sequences defined over +# several lines. +check-str-concat-over-line-jumps=no + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME, + XXX, + TODO + + +[BASIC] + +# Naming style matching correct argument names. +argument-naming-style=snake_case + +# Regular expression matching correct argument names. Overrides argument- +# naming-style. +#argument-rgx= + +# Naming style matching correct attribute names. +attr-naming-style=snake_case + +# Regular expression matching correct attribute names. Overrides attr-naming- +# style. +#attr-rgx= + +# Bad variable names which should always be refused, separated by a comma. +bad-names=foo, + bar, + baz, + toto, + tutu, + tata + +# Naming style matching correct class attribute names. +class-attribute-naming-style=any + +# Regular expression matching correct class attribute names. Overrides class- +# attribute-naming-style. +#class-attribute-rgx= + +# Naming style matching correct class names. +class-naming-style=PascalCase + +# Regular expression matching correct class names. Overrides class-naming- +# style. +#class-rgx= + +# Naming style matching correct constant names. +const-naming-style=UPPER_CASE + +# Regular expression matching correct constant names. Overrides const-naming- +# style. +#const-rgx= + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + +# Naming style matching correct function names. +function-naming-style=snake_case + +# Regular expression matching correct function names. Overrides function- +# naming-style. +#function-rgx= + +# Good variable names which should always be accepted, separated by a comma. +good-names=i, + j, + k, + ex, + Run, + _ + +# Include a hint for the correct naming format with invalid-name. +include-naming-hint=no + +# Naming style matching correct inline iteration names. +inlinevar-naming-style=any + +# Regular expression matching correct inline iteration names. Overrides +# inlinevar-naming-style. +#inlinevar-rgx= + +# Naming style matching correct method names. +method-naming-style=snake_case + +# Regular expression matching correct method names. Overrides method-naming- +# style. +#method-rgx= + +# Naming style matching correct module names. +module-naming-style=snake_case + +# Regular expression matching correct module names. Overrides module-naming- +# style. +#module-rgx= + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +# These decorators are taken in consideration only for invalid-name. +property-classes=abc.abstractproperty + +# Naming style matching correct variable names. +variable-naming-style=snake_case + +# Regular expression matching correct variable names. Overrides variable- +# naming-style. +#variable-rgx= + + +[LOGGING] + +# Format style used to check logging format string. `old` means using % +# formatting, `new` is for `{}` formatting,and `fstr` is for f-strings. +logging-format-style=old + +# Logging modules to check that the string format arguments are in logging +# function parameter format. +logging-modules=logging + + +[FORMAT] + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Maximum number of characters on a single line. +max-line-length=100 + +# Maximum number of lines in a module. +max-module-lines=1000 + +# List of optional constructs for which whitespace checking is disabled. `dict- +# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. +# `trailing-comma` allows a space between comma and closing bracket: (a, ). +# `empty-line` allows space-only lines. +no-space-check=trailing-comma, + dict-separator + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +single-line-class-stmt=no + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# Tells whether to warn about missing members when the owner of the attribute +# is inferred to be None. +ignore-none=yes + +# This flag controls whether pylint should warn about no-member and similar +# checks whenever an opaque object is returned when inferring. The inference +# can return multiple potential results while evaluating a Python object, but +# some branches might not be evaluated, which results in partial inference. In +# that case, it might be useful to still emit no-member and other checks for +# the rest of the inferred objects. +ignore-on-opaque-inference=yes + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis). It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# Show a hint with possible names when a member name was not found. The aspect +# of finding the hint is based on edit distance. +missing-member-hint=yes + +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance=1 + +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices=1 + +# List of decorators that change the signature of a decorated function. +signature-mutators= + + +[SPELLING] + +# Limits count of emitted suggestions for spelling mistakes. +max-spelling-suggestions=4 + +# Spelling dictionary name. Available dictionaries: none. To make it work, +# install the python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains the private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to the private dictionary (see the +# --spelling-private-dict-file option) instead of raising a message. +spelling-store-unknown-words=no + + +[SIMILARITIES] + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + +# Minimum lines number of a similarity. +min-similarity-lines=4 + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__, + __new__, + setUp, + __post_init__ + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict, + _fields, + _replace, + _source, + _make + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=cls + + +[IMPORTS] + +# List of modules that can be imported at any level, not just the top level +# one. +allow-any-import-level= + +# Allow wildcard imports from modules that define __all__. +allow-wildcard-with-all=no + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + +# Deprecated modules which should not be used, separated by a comma. +deprecated-modules=optparse,tkinter.tix + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled). +ext-import-graph= + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled). +import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled). +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant + +# Couples of modules and preferred modules, separated by a comma. +preferred-modules= + + +[DESIGN] + +# Maximum number of arguments for function / method. +max-args=5 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Maximum number of boolean expressions in an if statement (see R0916). +max-bool-expr=5 + +# Maximum number of branch for function / method body. +max-branches=12 + +# Maximum number of locals for function / method body. +max-locals=15 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of return / yield for function / method body. +max-returns=6 + +# Maximum number of statements in function / method body. +max-statements=50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "BaseException, Exception". +overgeneral-exceptions=BaseException, + Exception diff --git a/requirements.txt b/requirements.txt index 7373ed3..2aa074c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,12 @@ +astroid==2.3.2 +isort==4.3.21 +lazy-object-proxy==1.4.3 +mccabe==0.6.1 mypy==0.740 mypy-extensions==0.4.3 +pylint==2.4.3 pyparsing==2.4.2 +six==1.12.0 typed-ast==1.4.0 typing-extensions==3.7.4.1 +wrapt==1.11.2