From 93de805fd24b886d44cd161b1a81cf4a9b77a620 Mon Sep 17 00:00:00 2001 From: John Kurkowski Date: Sat, 24 Oct 2020 12:37:36 -0700 Subject: [PATCH 1/6] Add test env for just linting Speeds up developing against lint errors. Catches the linter not running at all. --- .travis.yml | 1 + tox.ini | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cfa095b4..30d36a9c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ matrix: - python: pypy3 env: TOXENV=pypy3 - env: TOXENV=codestyle + - env: TOXENV=lint python: 3.7 install: pip install tox script: tox diff --git a/tox.ini b/tox.ini index e399ddfa..c7f49212 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py{35,36,37,38,py3},codestyle +envlist = py{35,36,37,38,py3},codestyle,lint [testenv] deps = @@ -16,6 +16,14 @@ commands = pytest {posargs} deps = pycodestyle commands = pycodestyle tldextract tests {posargs} +[testenv:lint] +deps = + pytest + pytest-gitignore + pytest-pylint + responses +commands = pytest --pylint -m pylint {posargs} + [pycodestyle] # E203 - whitespace before; disagrees with PEP8 https://github.com/psf/black/issues/354#issuecomment-397684838 # E501 - line too long From c8ed9f14eab68507a6ce256402498dce39ed5854 Mon Sep 17 00:00:00 2001 From: John Kurkowski Date: Sat, 24 Oct 2020 08:37:21 -0700 Subject: [PATCH 2/6] Accept output of `pylint --generate-rcfile` --- pylintrc | 663 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 422 insertions(+), 241 deletions(-) diff --git a/pylintrc b/pylintrc index 79757b0f..7cc00917 100644 --- a/pylintrc +++ b/pylintrc @@ -1,11 +1,12 @@ [MASTER] -# Specify a configuration file. -#rcfile= +# 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= -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= +# Specify a score threshold to be exceeded before program exits with error. +fail-under=10.0 # Add files or directories to the blacklist. They should be base names, not # paths. @@ -15,230 +16,332 @@ ignore=CVS # regex matches against base names, not paths. ignore-patterns= -# Pickle collected data for later comparisons. -persistent=yes +# 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 -# List of plugins (as comma separated values of python modules names) to load, +# 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= -# Use multiple processes to speed up Pylint. -jobs=1 +# Pickle collected data for later comparisons. +persistent=yes + +# 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 -# 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= - -# Allow optimization of some AST trees. This will activate a peephole AST -# optimizer, which will apply various small optimizations. For instance, it can -# be used to obtain the result of joining multiple strings with the addition -# operator. Joining a lot of strings can lead to a maximum recursion error in -# Pylint and this flag can prevent that. It has one side effect, the resulting -# AST will be different than the one from reality. This option is deprecated -# and it will be removed in Pylint 2.0. -optimize-ast=no - [MESSAGES CONTROL] # Only show warnings with the listed confidence levels. Leave empty to show -# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED. confidence= -# 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= - # 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 +# 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=import-star-module-level,old-octal-literal,oct-method,print-statement,unpacking-in-except,parameter-unpacking,backtick,old-raise-syntax,old-ne-operator,long-suffix,dict-view-method,dict-iter-method,metaclass-assignment,next-method-called,raising-string,indexing-exception,raw_input-builtin,long-builtin,file-builtin,execfile-builtin,coerce-builtin,cmp-builtin,buffer-builtin,basestring-builtin,apply-builtin,filter-builtin-not-iterating,using-cmp-argument,useless-suppression,range-builtin-not-iterating,suppressed-message,no-absolute-import,old-division,cmp-method,reload-builtin,zip-builtin-not-iterating,intern-builtin,unichr-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,input-builtin,round-builtin,hex-method,nonzero-method,map-builtin-not-iterating,useless-object-inheritance,import-outside-toplevel +# 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 + +# 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] -# Set the output format. Available formats are text, parseable, colorized, msvs -# (visual studio) and html. You can also give a reporter class, eg +# 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 -# Put messages in a separate file for each module / package specified on the -# command line instead of printing them on stdout. Reports (if any) will be -# written in a file name "pylint_global.[txt|html]". This option is deprecated -# and it will be removed in Pylint 2.0. -files-output=no +# Tells whether to display a full report or only the messages. +reports=no -# Tells whether to display a full report or only the messages -reports=yes +# Activate the evaluation score. +score=yes -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This 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= +[REFACTORING] +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 -[BASIC] +# 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 -# Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,ex,Run,_ -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata +[LOGGING] -# Colon-delimited sets of names that determine each other's naming style when -# the name regexes allow several styles. -name-group= +# The type of string formatting that logging methods do. `old` means using % +# formatting, `new` is for `{}` formatting. +logging-format-style=old -# Include a hint for the correct naming format with invalid-name -include-naming-hint=no +# Logging modules to check that the string format arguments are in logging +# function parameter format. +logging-modules=logging -# List of decorators that produce properties, such as abc.abstractproperty. Add -# to this list to register other decorators that produce valid properties. -property-classes=abc.abstractproperty -# Regular expression matching correct function names -function-rgx=[a-z_][a-z0-9_]{2,50}$ +[SPELLING] -# Naming hint for function names -function-name-hint=[a-z_][a-z0-9_]{2,50}$ +# Limits count of emitted suggestions for spelling mistakes. +max-spelling-suggestions=4 -# Regular expression matching correct variable names -variable-rgx=[a-z_][a-z0-9_]{2,30}$ +# Spelling dictionary name. Available dictionaries: none. To make it work, +# install the python-enchant package. +spelling-dict= -# Naming hint for variable names -variable-name-hint=[a-z_][a-z0-9_]{2,30}$ +# List of comma separated words that should not be checked. +spelling-ignore-words= -# Regular expression matching correct constant names -const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ +# A path to a file that contains the private dictionary; one word per line. +spelling-private-dict-file= -# Naming hint for constant names -const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ +# 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 -# Regular expression matching correct attribute names -attr-rgx=[a-z_][a-z0-9_]{2,30}$ -# Naming hint for attribute names -attr-name-hint=[a-z_][a-z0-9_]{2,30}$ +[MISCELLANEOUS] -# Regular expression matching correct argument names -argument-rgx=[a-z_][a-z0-9_]{2,30}$ +# List of note tags to take in consideration, separated by a comma. +notes=FIXME, + XXX, + TODO -# Naming hint for argument names -argument-name-hint=[a-z_][a-z0-9_]{2,30}$ +# Regular expression of note tags to take in consideration. +#notes-rgx= -# Regular expression matching correct class attribute names -class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ -# Naming hint for class attribute names -class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ +[TYPECHECK] -# Regular expression matching correct inline iteration names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ +# 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 -# Naming hint for inline iteration names -inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ +# 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= -# Regular expression matching correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ +# 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 -# Naming hint for class names -class-name-hint=[A-Z_][a-zA-Z0-9]+$ +# Tells whether to warn about missing members when the owner of the attribute +# is inferred to be None. +ignore-none=yes -# Regular expression matching correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ +# 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 -# Naming hint for module names -module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ +# 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 -# Regular expression matching correct method names -method-rgx=[a-z_][a-z0-9_]{2,50}$ +# 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= -# Naming hint for method names -method-name-hint=[a-z_][a-z0-9_]{2,50}$ +# 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 -# Regular expression which should only match function or class names that do -# not require a docstring. -no-docstring-rgx=(__.*__|test_.*|.*_test) +# 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 -# Minimum line length for functions/classes that require docstrings, shorter -# ones are exempt. -docstring-min-length=10 +# 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= -[ELIF] -# Maximum number of nested blocks for function / method body -max-nested-blocks=5 +[VARIABLES] +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid defining new builtins when possible. +additional-builtins= -[FORMAT] +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes -# Maximum number of characters on a single line. -max-line-length=100 +# 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 -# Regexp for a line that is allowed to be longer than the limit. -ignore-long-lines=^\s*(# )??$ +# 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_ -# 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 +# Argument names that match this expression will be ignored. Default to name +# with leading underscore. +ignored-argument-names=_.*|^ignored_|^unused_ -# 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 +# Tells whether we should check for unused import in __init__ files. +init-import=no -# Maximum number of lines in a module -max-module-lines=1000 +# 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 used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' -# Number of spaces of indent required inside a hanging or continued line. -indent-after-paren=4 +[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*(# )??$ -[LOGGING] +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 -# Logging modules to check that the string format arguments are in logging -# function parameter format -logging-modules=logging +# 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 -[MISCELLANEOUS] +# Maximum number of lines in a module. +max-module-lines=1000 -# List of note tags to take in consideration, separated by a comma. -notes= +# 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 -[SIMILARITIES] -# Minimum lines number of a similarity. -min-similarity-lines=4 +[SIMILARITIES] # Ignore comments when computing similarities. ignore-comments=yes @@ -249,142 +352,165 @@ ignore-docstrings=yes # Ignore imports when computing similarities. ignore-imports=no +# Minimum lines number of a similarity. +min-similarity-lines=4 -[SPELLING] - -# Spelling dictionary name. Available dictionaries: none. To make it working -# install python-enchant package. -spelling-dict= -# List of comma separated words that should not be checked. -spelling-ignore-words= +[BASIC] -# A path to a file that contains private dictionary; one word per line. -spelling-private-dict-file= +# Naming style matching correct argument names. +argument-naming-style=snake_case -# Tells whether to store unknown words to indicated private dictionary in -# --spelling-private-dict-file option instead of raising a message. -spelling-store-unknown-words=no +# Regular expression matching correct argument names. Overrides argument- +# naming-style. +#argument-rgx= +# Naming style matching correct attribute names. +attr-naming-style=snake_case -[TYPECHECK] +# Regular expression matching correct attribute names. Overrides attr-naming- +# style. +#attr-rgx= -# 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 +# Bad variable names which should always be refused, separated by a comma. +bad-names=foo, + bar, + baz, + toto, + tutu, + tata -# 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= +# Bad variable names regexes, separated by a comma. If names match any regex, +# they will always be refused +bad-names-rgxs= -# 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 +# Naming style matching correct class attribute names. +class-attribute-naming-style=any -# 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= +# Regular expression matching correct class attribute names. Overrides class- +# attribute-naming-style. +#class-attribute-rgx= -# 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 +# Naming style matching correct class names. +class-naming-style=PascalCase +# Regular expression matching correct class names. Overrides class-naming- +# style. +#class-rgx= -[VARIABLES] +# Naming style matching correct constant names. +const-naming-style=UPPER_CASE -# Tells whether we should check for unused import in __init__ files. -init-import=no +# Regular expression matching correct constant names. Overrides const-naming- +# style. +#const-rgx= -# A regular expression matching the name of dummy variables (i.e. expectedly -# not used). -dummy-variables-rgx=(_+[a-zA-Z0-9]*?$)|dummy +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= +# Naming style matching correct function names. +function-naming-style=snake_case -# 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 +# Regular expression matching correct function names. Overrides function- +# naming-style. +#function-rgx= -# List of qualified module names which can have objects that can redefine -# builtins. -redefining-builtins-modules=six.moves,future.builtins +# Good variable names which should always be accepted, separated by a comma. +good-names=i, + j, + k, + ex, + Run, + _ +# Good variable names regexes, separated by a comma. If names match any regex, +# they will always be accepted +good-names-rgxs= -[CLASSES] +# Include a hint for the correct naming format with invalid-name. +include-naming-hint=no -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp +# Naming style matching correct inline iteration names. +inlinevar-naming-style=any -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls +# Regular expression matching correct inline iteration names. Overrides +# inlinevar-naming-style. +#inlinevar-rgx= -# List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=mcs +# Naming style matching correct method names. +method-naming-style=snake_case -# List of member names, which should be excluded from the protected access -# warning. -exclude-protected=_asdict,_fields,_replace,_source,_make +# Regular expression matching correct method names. Overrides method-naming- +# style. +#method-rgx= +# Naming style matching correct module names. +module-naming-style=snake_case -[DESIGN] +# Regular expression matching correct module names. Overrides module-naming- +# style. +#module-rgx= -# Maximum number of arguments for function / method -max-args=5 +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.* +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ -# Maximum number of locals for function / method body -max-locals=15 +# 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 -# Maximum number of return / yield for function / method body -max-returns=6 +# Naming style matching correct variable names. +variable-naming-style=snake_case -# Maximum number of branch for function / method body -max-branches=12 +# Regular expression matching correct variable names. Overrides variable- +# naming-style. +#variable-rgx= -# Maximum number of statements in function / method body -max-statements=50 -# Maximum number of parents for a class (see R0901). -max-parents=7 +[STRING] -# Maximum number of attributes for a class (see R0902). -max-attributes=8 +# This flag controls whether inconsistent-quotes generates a warning when the +# character used as a quote delimiter is used inconsistently within a module. +check-quote-consistency=no -# Minimum number of public methods for a class (see R0903). -min-public-methods=1 +# This flag controls whether the implicit-str-concat should generate a warning +# on implicit string concatenation in sequences defined over several lines. +check-str-concat-over-line-jumps=no -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 -# Maximum number of boolean expressions in a if statement -max-bool-expr=5 +[IMPORTS] +# List of modules that can be imported at any level, not just the top level +# one. +allow-any-import-level= -[IMPORTS] +# Allow wildcard imports from modules that define __all__. +allow-wildcard-with-all=no -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub,TERMIOS,Bastion,rexec +# 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 -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled) -import-graph= +# 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) +# 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) +# not be disabled). int-import-graph= # Force import order to recognize a module as part of the standard @@ -394,14 +520,69 @@ known-standard-library= # Force import order to recognize a module as part of a third party library. known-third-party=enchant -# 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 +# Couples of modules and preferred modules, separated by a comma. +preferred-modules= + + +[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 + + +[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 -# "Exception" -overgeneral-exceptions=Exception +# "BaseException, Exception". +overgeneral-exceptions=BaseException, + Exception From 7cb8057d4e415a8d9ec6ebb78fb2f38b918012b9 Mon Sep 17 00:00:00 2001 From: John Kurkowski Date: Sat, 24 Oct 2020 12:43:51 -0700 Subject: [PATCH 3/6] Work around pylint all files deselected --- pylintrc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pylintrc b/pylintrc index 7cc00917..204aafa8 100644 --- a/pylintrc +++ b/pylintrc @@ -14,7 +14,9 @@ ignore=CVS # Add files or directories matching the regex patterns to the blacklist. The # regex matches against base names, not paths. -ignore-patterns= +# +# See https://github.com/carsongee/pytest-pylint/issues/137 +# ignore-patterns= # Python code to execute, usually for sys.path manipulation such as # pygtk.require(). From 4d3d2b58492ad2e807696feb580f834a3e8af179 Mon Sep 17 00:00:00 2001 From: John Kurkowski Date: Sat, 24 Oct 2020 12:52:17 -0700 Subject: [PATCH 4/6] Restore previous custom pylint rules --- pylintrc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pylintrc b/pylintrc index 204aafa8..5c4bac2d 100644 --- a/pylintrc +++ b/pylintrc @@ -220,9 +220,7 @@ spelling-store-unknown-words=no [MISCELLANEOUS] # List of note tags to take in consideration, separated by a comma. -notes=FIXME, - XXX, - TODO +notes= # Regular expression of note tags to take in consideration. #notes-rgx= @@ -460,7 +458,7 @@ name-group= # Regular expression which should only match function or class names that do # not require a docstring. -no-docstring-rgx=^_ +no-docstring-rgx=(^_|test_.*|.*_test) # List of decorators that produce properties, such as abc.abstractproperty. Add # to this list to register other decorators that produce valid properties. @@ -555,7 +553,7 @@ valid-metaclass-classmethod-first-arg=cls max-args=5 # Maximum number of attributes for a class (see R0902). -max-attributes=7 +max-attributes=8 # Maximum number of boolean expressions in an if statement (see R0916). max-bool-expr=5 From 0357f979670806a885c591cbf586d213a85624d7 Mon Sep 17 00:00:00 2001 From: John Kurkowski Date: Sat, 24 Oct 2020 13:08:48 -0700 Subject: [PATCH 5/6] Fix lint errors --- tests/conftest.py | 5 ++++- tests/custom_suffix_test.py | 6 ++--- tests/helpers.py | 10 --------- tests/main_test.py | 11 ++++----- tldextract/cache.py | 14 ++++-------- tldextract/cli.py | 5 ++--- tldextract/remote.py | 1 - tldextract/suffix_list.py | 45 ++++++++++++++++++++----------------- tldextract/tldextract.py | 14 +++++++----- 9 files changed, 52 insertions(+), 59 deletions(-) delete mode 100644 tests/helpers.py diff --git a/tests/conftest.py b/tests/conftest.py index eaa02134..f3d93c84 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,9 +1,12 @@ -'''py.test standard config file.''' +"""py.test standard config file.""" import logging + import pytest @pytest.fixture(autouse=True) def reset_log_level(): + """Automatically reset log level verbosity between tests. Generally want + test output the Unix way: silence is golden.""" logging.getLogger().setLevel(logging.WARN) diff --git a/tests/custom_suffix_test.py b/tests/custom_suffix_test.py index 48ce8bd9..9a862ae3 100644 --- a/tests/custom_suffix_test.py +++ b/tests/custom_suffix_test.py @@ -1,9 +1,9 @@ '''tldextract unit tests with a custom suffix list.''' import os +import tempfile import tldextract -from .helpers import temporary_dir FAKE_SUFFIX_LIST_URL = "file://" + os.path.join( os.path.dirname(os.path.abspath(__file__)), @@ -13,7 +13,7 @@ # pylint: disable=invalid-name extract_using_fake_suffix_list = tldextract.TLDExtract( - cache_dir=temporary_dir(), + cache_dir=tempfile.mkdtemp(), suffix_list_urls=[FAKE_SUFFIX_LIST_URL] ) extract_using_fake_suffix_list_no_cache = tldextract.TLDExtract( @@ -30,7 +30,7 @@ def test_private_extraction(): tld = tldextract.TLDExtract( - cache_dir=temporary_dir(), + cache_dir=tempfile.mkdtemp(), suffix_list_urls=[] ) diff --git a/tests/helpers.py b/tests/helpers.py deleted file mode 100644 index 8993e3ca..00000000 --- a/tests/helpers.py +++ /dev/null @@ -1,10 +0,0 @@ -'''tldextract test helpers.''' - -from subprocess import CalledProcessError, PIPE, Popen -import tempfile - - -def temporary_dir(): - """ Make a writable temporary file and return its absolute path. - """ - return tempfile.mkdtemp() diff --git a/tests/main_test.py b/tests/main_test.py index 2f116b16..5e25833b 100644 --- a/tests/main_test.py +++ b/tests/main_test.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- '''Main tldextract unit tests.''' -import sys +import tempfile import pytest import responses @@ -9,13 +9,12 @@ from tldextract.cache import DiskCache from tldextract.suffix_list import SuffixListNotFound from tldextract.tldextract import ExtractResult -from .helpers import temporary_dir # pylint: disable=invalid-name -extract = tldextract.TLDExtract(cache_dir=temporary_dir()) +extract = tldextract.TLDExtract(cache_dir=tempfile.mkdtemp()) extract_no_cache = tldextract.TLDExtract(cache_dir=False) -extract_using_real_local_suffix_list = tldextract.TLDExtract(cache_dir=temporary_dir()) +extract_using_real_local_suffix_list = tldextract.TLDExtract(cache_dir=tempfile.mkdtemp()) extract_using_real_local_suffix_list_no_cache = tldextract.TLDExtract(cache_dir=False) extract_using_fallback_to_snapshot_no_cache = tldextract.TLDExtract( cache_dir=None, @@ -266,6 +265,8 @@ def test_tlds_property(): def test_global_extract(): - assert tldextract.extract("foo.blogspot.com") == ExtractResult(subdomain='foo', domain='blogspot', suffix='com') + assert tldextract.extract("foo.blogspot.com") == ExtractResult( + subdomain="foo", domain="blogspot", suffix="com" + ) assert tldextract.extract("foo.blogspot.com", include_psl_private_domains=True) == \ ExtractResult(subdomain='', domain='foo', suffix='blogspot.com') diff --git a/tldextract/cache.py b/tldextract/cache.py index 66f7d84e..ff013a44 100644 --- a/tldextract/cache.py +++ b/tldextract/cache.py @@ -8,18 +8,10 @@ from filelock import FileLock -try: - FileNotFoundError -except NameError: - - class FileNotFoundError(Exception): - pass - - LOG = logging.getLogger(__name__) -class DiskCache(object): +class DiskCache: """Disk _cache that only works for jsonable values""" def __init__(self, cache_dir, lock_timeout=20): @@ -43,7 +35,9 @@ def get(self, namespace, key): return json.load(cache_file) except (OSError, ValueError) as exc: LOG.error("error reading TLD cache file %s: %s", cache_filepath, exc) - raise KeyError("namespace: " + namespace + " key: " + repr(key)) + raise KeyError( # pylint: disable=raise-missing-from + "namespace: " + namespace + " key: " + repr(key) + ) def set(self, namespace, key, value): """Set a value in the disk cache""" diff --git a/tldextract/cli.py b/tldextract/cli.py index ae418f65..140b4043 100644 --- a/tldextract/cli.py +++ b/tldextract/cli.py @@ -1,6 +1,7 @@ '''tldextract CLI''' +import argparse import logging import sys @@ -10,8 +11,6 @@ def main(): '''tldextract CLI main command.''' - import argparse - logging.basicConfig() parser = argparse.ArgumentParser( @@ -43,4 +42,4 @@ def main(): return for i in args.input: - print(' '.join(tld_extract(i))) # pylint: disable=superfluous-parens + print(' '.join(tld_extract(i))) diff --git a/tldextract/remote.py b/tldextract/remote.py index f783fdf3..906f2ce8 100644 --- a/tldextract/remote.py +++ b/tldextract/remote.py @@ -2,7 +2,6 @@ import re import socket -import sys from urllib.parse import scheme_chars diff --git a/tldextract/suffix_list.py b/tldextract/suffix_list.py index bec96708..a4371c83 100644 --- a/tldextract/suffix_list.py +++ b/tldextract/suffix_list.py @@ -1,49 +1,52 @@ -'tldextract helpers for testing and fetching remote resources.' +"tldextract helpers for testing and fetching remote resources." import logging import pkgutil import re -import sys import requests from requests_file import FileAdapter -LOG = logging.getLogger('tldextract') +LOG = logging.getLogger("tldextract") -PUBLIC_SUFFIX_RE = re.compile(r'^(?P[.*!]*\w[\S]*)', re.UNICODE | re.MULTILINE) -PUBLIC_PRIVATE_SUFFIX_SEPARATOR = '// ===BEGIN PRIVATE DOMAINS===' +PUBLIC_SUFFIX_RE = re.compile(r"^(?P[.*!]*\w[\S]*)", re.UNICODE | re.MULTILINE) +PUBLIC_PRIVATE_SUFFIX_SEPARATOR = "// ===BEGIN PRIVATE DOMAINS===" class SuffixListNotFound(LookupError): - pass + """A recoverable error while looking up a suffix list. Recoverable because + you can specify backups, or use this library's bundled snapshot.""" def find_first_response(cache, urls, cache_fetch_timeout=None): - """ Decode the first successfully fetched URL, from UTF-8 encoding to + """Decode the first successfully fetched URL, from UTF-8 encoding to Python unicode. """ with requests.Session() as session: - session.mount('file://', FileAdapter()) + session.mount("file://", FileAdapter()) for url in urls: try: - return cache.cached_fetch_url(session=session, url=url, timeout=cache_fetch_timeout) - except requests.exceptions.RequestException: - LOG.exception( - 'Exception reading Public Suffix List url %s', - url + return cache.cached_fetch_url( + session=session, url=url, timeout=cache_fetch_timeout ) + except requests.exceptions.RequestException: + LOG.exception("Exception reading Public Suffix List url %s", url) raise SuffixListNotFound( - 'No Public Suffix List found. Consider using a mirror or constructing ' - 'your TLDExtract with `suffix_list_urls=None`.' + "No Public Suffix List found. Consider using a mirror or constructing " + "your TLDExtract with `suffix_list_urls=None`." ) def extract_tlds_from_suffix_list(suffix_list_text): - public_text, _, private_text = suffix_list_text.partition(PUBLIC_PRIVATE_SUFFIX_SEPARATOR) + """Parse the raw suffix list text for its different designations of + suffixes.""" + public_text, _, private_text = suffix_list_text.partition( + PUBLIC_PRIVATE_SUFFIX_SEPARATOR + ) - public_tlds = [m.group('suffix') for m in PUBLIC_SUFFIX_RE.finditer(public_text)] - private_tlds = [m.group('suffix') for m in PUBLIC_SUFFIX_RE.finditer(private_text)] + public_tlds = [m.group("suffix") for m in PUBLIC_SUFFIX_RE.finditer(public_text)] + private_tlds = [m.group("suffix") for m in PUBLIC_SUFFIX_RE.finditer(private_text)] return public_tlds, private_tlds @@ -58,7 +61,7 @@ def get_suffix_lists(cache, urls, cache_fetch_timeout, fallback_to_snapshot): "cache_fetch_timeout": cache_fetch_timeout, "fallback_to_snapshot": fallback_to_snapshot, }, - hashed_argnames=["urls", "fallback_to_snapshot"] + hashed_argnames=["urls", "fallback_to_snapshot"], ) @@ -69,9 +72,9 @@ def _get_suffix_lists(cache, urls, cache_fetch_timeout, fallback_to_snapshot): text = find_first_response(cache, urls, cache_fetch_timeout=cache_fetch_timeout) except SuffixListNotFound as exc: if fallback_to_snapshot: - text = pkgutil.get_data('tldextract', '.tld_set_snapshot') + text = pkgutil.get_data("tldextract", ".tld_set_snapshot") if not isinstance(text, str): - text = str(text, 'utf-8') + text = str(text, "utf-8") else: raise exc diff --git a/tldextract/tldextract.py b/tldextract/tldextract.py index f113d4c3..8e808995 100644 --- a/tldextract/tldextract.py +++ b/tldextract/tldextract.py @@ -126,15 +126,15 @@ def ipv4(self): return "" -class TLDExtract(object): +class TLDExtract: """A callable for extracting, subdomain, domain, and suffix components from a URL.""" # TODO: Agreed with Pylint: too-many-arguments - def __init__( + def __init__( # pylint: disable=too-many-arguments self, cache_dir=CACHE_DIR, - suffix_list_urls=PUBLIC_SUFFIX_LIST_URLS, # pylint: disable=too-many-arguments + suffix_list_urls=PUBLIC_SUFFIX_LIST_URLS, fallback_to_snapshot=True, include_psl_private_domains=False, extra_suffixes=(), @@ -242,6 +242,7 @@ def __call__(self, url, include_psl_private_domains=None): return ExtractResult(subdomain, domain, suffix) def update(self, fetch_now=False): + """Force fetch the latest suffix list definitions.""" self._extractor = None self._cache.clear() if fetch_now: @@ -293,12 +294,14 @@ def _get_tld_extractor(self): @wraps(TLD_EXTRACTOR.__call__) -def extract(url, include_psl_private_domains=False): +def extract( + url, include_psl_private_domains=False +): # pylint: disable=missing-function-docstring return TLD_EXTRACTOR(url, include_psl_private_domains=include_psl_private_domains) @wraps(TLD_EXTRACTOR.update) -def update(*args, **kwargs): +def update(*args, **kwargs): # pylint: disable=missing-function-docstring return TLD_EXTRACTOR.update(*args, **kwargs) @@ -318,6 +321,7 @@ def __init__( self.tlds_excl_private = frozenset(public_tlds + extra_tlds) def tlds(self, include_psl_private_domains=None): + """Get the currently filtered list of suffixes.""" if include_psl_private_domains is None: include_psl_private_domains = self.include_psl_private_domains From df65b480294a9d752fbcd09fb380e85cb457b6e7 Mon Sep 17 00:00:00 2001 From: John Kurkowski Date: Sat, 24 Oct 2020 14:09:39 -0700 Subject: [PATCH 6/6] Remove unused lint disables --- conftest.py | 4 ---- tests/custom_suffix_test.py | 2 -- tests/main_test.py | 8 +++----- tests/test_parallel.py | 4 ++-- tldextract/tldextract.py | 1 - 5 files changed, 5 insertions(+), 14 deletions(-) diff --git a/conftest.py b/conftest.py index 95ce8c70..1ae092bf 100644 --- a/conftest.py +++ b/conftest.py @@ -1,7 +1,3 @@ '''py.test standard config file.''' -# pylint: disable=invalid-name - collect_ignore = ('setup.py',) - -# pylint: enable=invalid-name diff --git a/tests/custom_suffix_test.py b/tests/custom_suffix_test.py index 9a862ae3..f0621932 100644 --- a/tests/custom_suffix_test.py +++ b/tests/custom_suffix_test.py @@ -11,7 +11,6 @@ ) EXTRA_SUFFIXES = ['foo1', 'bar1', 'baz1'] -# pylint: disable=invalid-name extract_using_fake_suffix_list = tldextract.TLDExtract( cache_dir=tempfile.mkdtemp(), suffix_list_urls=[FAKE_SUFFIX_LIST_URL] @@ -25,7 +24,6 @@ suffix_list_urls=[FAKE_SUFFIX_LIST_URL], extra_suffixes=EXTRA_SUFFIXES ) -# pylint: enable=invalid-name def test_private_extraction(): diff --git a/tests/main_test.py b/tests/main_test.py index 5e25833b..96c55339 100644 --- a/tests/main_test.py +++ b/tests/main_test.py @@ -11,7 +11,6 @@ from tldextract.tldextract import ExtractResult -# pylint: disable=invalid-name extract = tldextract.TLDExtract(cache_dir=tempfile.mkdtemp()) extract_no_cache = tldextract.TLDExtract(cache_dir=False) extract_using_real_local_suffix_list = tldextract.TLDExtract(cache_dir=tempfile.mkdtemp()) @@ -20,7 +19,6 @@ cache_dir=None, suffix_list_urls=None ) -# pylint: enable=invalid-name def assert_extract( # pylint: disable=missing-docstring @@ -236,11 +234,11 @@ def test_result_as_dict(): assert result._asdict() == expected_dict -@responses.activate # pylint: disable=no-member +@responses.activate def test_cache_timeouts(tmpdir): server = 'http://some-server.com' - responses.add( # pylint: disable=no-member - responses.GET, # pylint: disable=no-member + responses.add( + responses.GET, server, status=408 ) diff --git a/tests/test_parallel.py b/tests/test_parallel.py index c7ea3353..bd451e92 100644 --- a/tests/test_parallel.py +++ b/tests/test_parallel.py @@ -36,8 +36,8 @@ def _run_extractor(cache_dir): @responses.activate def test_cache_cleared_by_other_process(tmpdir, monkeypatch): """Simulate a file being deleted after we check for existence but before we try to delete it""" - responses.add( # pylint: disable=no-member - responses.GET, # pylint: disable=no-member + responses.add( + responses.GET, PUBLIC_SUFFIX_LIST_URLS[0], status=208, body="uk.com" diff --git a/tldextract/tldextract.py b/tldextract/tldextract.py index 8e808995..dcf12cd2 100644 --- a/tldextract/tldextract.py +++ b/tldextract/tldextract.py @@ -266,7 +266,6 @@ def _get_tld_extractor(self): 2. Local system _cache file 3. Remote PSL, over HTTP 4. Bundled PSL snapshot file""" - # pylint: disable=no-else-return if self._extractor: return self._extractor