mirror of
https://github.com/PyCQA/flake8.git
synced 2026-04-15 08:44:46 +00:00
Merge branch 'origin/proposed/3.0' into master
This commit is contained in:
commit
cee691059f
167 changed files with 11120 additions and 3162 deletions
84
.bandit.yml
Normal file
84
.bandit.yml
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
tests:
|
||||||
|
skips:
|
||||||
|
- B404 # Ignore warnings about importing subprocess
|
||||||
|
- B603 # Ignore warnings about calling subprocess.Popen without shell=True
|
||||||
|
- B607 # Ignore warnings about calling subprocess.Popen without a full path to executable
|
||||||
|
|
||||||
|
### (optional) plugin settings - some test plugins require configuration data
|
||||||
|
### that may be given here, per-plugin. All bandit test plugins have a built in
|
||||||
|
### set of sensible defaults and these will be used if no configuration is
|
||||||
|
### provided. It is not necessary to provide settings for every (or any) plugin
|
||||||
|
### if the defaults are acceptable.
|
||||||
|
|
||||||
|
any_other_function_with_shell_equals_true:
|
||||||
|
no_shell: [os.execl, os.execle, os.execlp, os.execlpe, os.execv, os.execve, os.execvp,
|
||||||
|
os.execvpe, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe, os.spawnv, os.spawnve,
|
||||||
|
os.spawnvp, os.spawnvpe, os.startfile]
|
||||||
|
shell: [os.system, os.popen, os.popen2, os.popen3, os.popen4, popen2.popen2, popen2.popen3,
|
||||||
|
popen2.popen4, popen2.Popen3, popen2.Popen4, commands.getoutput, commands.getstatusoutput]
|
||||||
|
subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call, subprocess.check_output,
|
||||||
|
utils.execute, utils.execute_with_timeout]
|
||||||
|
execute_with_run_as_root_equals_true:
|
||||||
|
function_names: [ceilometer.utils.execute, cinder.utils.execute, neutron.agent.linux.utils.execute,
|
||||||
|
nova.utils.execute, nova.utils.trycmd]
|
||||||
|
hardcoded_tmp_directory:
|
||||||
|
tmp_dirs: [/tmp, /var/tmp, /dev/shm]
|
||||||
|
linux_commands_wildcard_injection:
|
||||||
|
no_shell: [os.execl, os.execle, os.execlp, os.execlpe, os.execv, os.execve, os.execvp,
|
||||||
|
os.execvpe, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe, os.spawnv, os.spawnve,
|
||||||
|
os.spawnvp, os.spawnvpe, os.startfile]
|
||||||
|
shell: [os.system, os.popen, os.popen2, os.popen3, os.popen4, popen2.popen2, popen2.popen3,
|
||||||
|
popen2.popen4, popen2.Popen3, popen2.Popen4, commands.getoutput, commands.getstatusoutput]
|
||||||
|
subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call, subprocess.check_output,
|
||||||
|
utils.execute, utils.execute_with_timeout]
|
||||||
|
password_config_option_not_marked_secret:
|
||||||
|
function_names: [oslo.config.cfg.StrOpt, oslo_config.cfg.StrOpt]
|
||||||
|
ssl_with_bad_defaults:
|
||||||
|
bad_protocol_versions: [PROTOCOL_SSLv2, SSLv2_METHOD, SSLv23_METHOD, PROTOCOL_SSLv3,
|
||||||
|
PROTOCOL_TLSv1, SSLv3_METHOD, TLSv1_METHOD]
|
||||||
|
ssl_with_bad_version:
|
||||||
|
bad_protocol_versions: [PROTOCOL_SSLv2, SSLv2_METHOD, SSLv23_METHOD, PROTOCOL_SSLv3,
|
||||||
|
PROTOCOL_TLSv1, SSLv3_METHOD, TLSv1_METHOD]
|
||||||
|
start_process_with_a_shell:
|
||||||
|
no_shell: [os.execl, os.execle, os.execlp, os.execlpe, os.execv, os.execve, os.execvp,
|
||||||
|
os.execvpe, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe, os.spawnv, os.spawnve,
|
||||||
|
os.spawnvp, os.spawnvpe, os.startfile]
|
||||||
|
shell: [os.system, os.popen, os.popen2, os.popen3, os.popen4, popen2.popen2, popen2.popen3,
|
||||||
|
popen2.popen4, popen2.Popen3, popen2.Popen4, commands.getoutput, commands.getstatusoutput]
|
||||||
|
subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call, subprocess.check_output,
|
||||||
|
utils.execute, utils.execute_with_timeout]
|
||||||
|
start_process_with_no_shell:
|
||||||
|
no_shell: [os.execl, os.execle, os.execlp, os.execlpe, os.execv, os.execve, os.execvp,
|
||||||
|
os.execvpe, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe, os.spawnv, os.spawnve,
|
||||||
|
os.spawnvp, os.spawnvpe, os.startfile]
|
||||||
|
shell: [os.system, os.popen, os.popen2, os.popen3, os.popen4, popen2.popen2, popen2.popen3,
|
||||||
|
popen2.popen4, popen2.Popen3, popen2.Popen4, commands.getoutput, commands.getstatusoutput]
|
||||||
|
subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call, subprocess.check_output,
|
||||||
|
utils.execute, utils.execute_with_timeout]
|
||||||
|
start_process_with_partial_path:
|
||||||
|
no_shell: [os.execl, os.execle, os.execlp, os.execlpe, os.execv, os.execve, os.execvp,
|
||||||
|
os.execvpe, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe, os.spawnv, os.spawnve,
|
||||||
|
os.spawnvp, os.spawnvpe, os.startfile]
|
||||||
|
shell: [os.system, os.popen, os.popen2, os.popen3, os.popen4, popen2.popen2, popen2.popen3,
|
||||||
|
popen2.popen4, popen2.Popen3, popen2.Popen4, commands.getoutput, commands.getstatusoutput]
|
||||||
|
subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call, subprocess.check_output,
|
||||||
|
utils.execute, utils.execute_with_timeout]
|
||||||
|
subprocess_popen_with_shell_equals_true:
|
||||||
|
no_shell: [os.execl, os.execle, os.execlp, os.execlpe, os.execv, os.execve, os.execvp,
|
||||||
|
os.execvpe, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe, os.spawnv, os.spawnve,
|
||||||
|
os.spawnvp, os.spawnvpe, os.startfile]
|
||||||
|
shell: [os.system, os.popen, os.popen2, os.popen3, os.popen4, popen2.popen2, popen2.popen3,
|
||||||
|
popen2.popen4, popen2.Popen3, popen2.Popen4, commands.getoutput, commands.getstatusoutput]
|
||||||
|
subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call, subprocess.check_output,
|
||||||
|
utils.execute, utils.execute_with_timeout]
|
||||||
|
subprocess_without_shell_equals_true:
|
||||||
|
no_shell: [os.execl, os.execle, os.execlp, os.execlpe, os.execv, os.execve, os.execvp,
|
||||||
|
os.execvpe, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe, os.spawnv, os.spawnve,
|
||||||
|
os.spawnvp, os.spawnvpe, os.startfile]
|
||||||
|
shell: [os.system, os.popen, os.popen2, os.popen3, os.popen4, popen2.popen2, popen2.popen3,
|
||||||
|
popen2.popen4, popen2.Popen3, popen2.Popen4, commands.getoutput, commands.getstatusoutput]
|
||||||
|
subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call, subprocess.check_output,
|
||||||
|
utils.execute, utils.execute_with_timeout]
|
||||||
|
try_except_continue: {check_typed_exception: false}
|
||||||
|
try_except_pass: {check_typed_exception: false}
|
||||||
|
|
||||||
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -1,7 +1,12 @@
|
||||||
*.pyc
|
*.pyc
|
||||||
.tox
|
.tox
|
||||||
|
.eggs
|
||||||
*.egg
|
*.egg
|
||||||
*.egg-info
|
*.egg-info
|
||||||
build
|
build
|
||||||
dist
|
dist
|
||||||
*.zip
|
*.zip
|
||||||
|
.cache
|
||||||
|
*.sw*
|
||||||
|
*.log
|
||||||
|
docs/build/html/*
|
||||||
|
|
|
||||||
378
.pylintrc
Normal file
378
.pylintrc
Normal file
|
|
@ -0,0 +1,378 @@
|
||||||
|
[MASTER]
|
||||||
|
|
||||||
|
# Specify a configuration file.
|
||||||
|
#rcfile=
|
||||||
|
|
||||||
|
# Python code to execute, usually for sys.path manipulation such as
|
||||||
|
# pygtk.require().
|
||||||
|
#init-hook=
|
||||||
|
|
||||||
|
# Add files or directories to the blacklist. They should be base names, not
|
||||||
|
# paths.
|
||||||
|
ignore=CVS,.git,flake8.egg-info
|
||||||
|
|
||||||
|
# Pickle collected data for later comparisons.
|
||||||
|
persistent=yes
|
||||||
|
|
||||||
|
# List of plugins (as comma separated values of python modules names) to load,
|
||||||
|
# usually to register additional checkers.
|
||||||
|
load-plugins=
|
||||||
|
|
||||||
|
# Use multiple processes to speed up Pylint.
|
||||||
|
jobs=4
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
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
|
||||||
|
confidence=INFERENCE_FAILURE
|
||||||
|
|
||||||
|
# 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. 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
|
||||||
|
# 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=intern-builtin,nonzero-method,parameter-unpacking,backtick,raw_input-builtin,dict-view-method,filter-builtin-not-iterating,long-builtin,unichr-builtin,input-builtin,unicode-builtin,file-builtin,map-builtin-not-iterating,delslice-method,apply-builtin,cmp-method,setslice-method,coerce-method,long-suffix,raising-string,import-star-module-level,buffer-builtin,reload-builtin,unpacking-in-except,print-statement,hex-method,old-octal-literal,metaclass-assignment,dict-iter-method,range-builtin-not-iterating,using-cmp-argument,indexing-exception,no-absolute-import,coerce-builtin,getslice-method,suppressed-message,execfile-builtin,round-builtin,useless-suppression,reduce-builtin,old-raise-syntax,zip-builtin-not-iterating,cmp-builtin,xrange-builtin,standarderror-builtin,old-division,oct-method,next-method-called,old-ne-operator,basestring-builtin
|
||||||
|
|
||||||
|
|
||||||
|
[REPORTS]
|
||||||
|
|
||||||
|
# Set the output format. Available formats are text, parseable, colorized, msvs
|
||||||
|
# (visual studio) and html. You can also give a reporter class, eg
|
||||||
|
# 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]".
|
||||||
|
files-output=no
|
||||||
|
|
||||||
|
# Tells whether to display a full report or only the messages
|
||||||
|
reports=no
|
||||||
|
|
||||||
|
# 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=
|
||||||
|
|
||||||
|
|
||||||
|
[BASIC]
|
||||||
|
|
||||||
|
# List of builtins function names that should not be used, separated by a comma
|
||||||
|
bad-functions=map,filter
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Colon-delimited sets of names that determine each other's naming style when
|
||||||
|
# the name regexes allow several styles.
|
||||||
|
name-group=
|
||||||
|
|
||||||
|
# Include a hint for the correct naming format with invalid-name
|
||||||
|
include-naming-hint=yes
|
||||||
|
|
||||||
|
# Regular expression matching correct argument names
|
||||||
|
argument-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||||
|
|
||||||
|
# Naming hint for argument names
|
||||||
|
argument-name-hint=[a-z_][a-z0-9_]{2,30}$
|
||||||
|
|
||||||
|
# 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}$
|
||||||
|
|
||||||
|
# Regular expression matching correct constant names
|
||||||
|
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
|
||||||
|
|
||||||
|
# Naming hint for constant names
|
||||||
|
const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
|
||||||
|
|
||||||
|
# Regular expression matching correct class names
|
||||||
|
class-rgx=[A-Z_][a-zA-Z0-9]+$
|
||||||
|
|
||||||
|
# Naming hint for class names
|
||||||
|
class-name-hint=[A-Z_][a-zA-Z0-9]+$
|
||||||
|
|
||||||
|
# Regular expression matching correct inline iteration names
|
||||||
|
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
|
||||||
|
|
||||||
|
# Naming hint for inline iteration names
|
||||||
|
inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
|
||||||
|
|
||||||
|
# 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}|(__.*__))$
|
||||||
|
|
||||||
|
# Regular expression matching correct function names
|
||||||
|
function-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||||
|
|
||||||
|
# Naming hint for function names
|
||||||
|
function-name-hint=[a-z_][a-z0-9_]{2,30}$
|
||||||
|
|
||||||
|
# Regular expression matching correct module names
|
||||||
|
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
|
||||||
|
|
||||||
|
# Naming hint for module names
|
||||||
|
module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
|
||||||
|
|
||||||
|
# Regular expression matching correct method names
|
||||||
|
method-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||||
|
|
||||||
|
# Naming hint for method names
|
||||||
|
method-name-hint=[a-z_][a-z0-9_]{2,30}$
|
||||||
|
|
||||||
|
# Regular expression matching correct variable names
|
||||||
|
variable-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||||
|
|
||||||
|
# Naming hint for variable names
|
||||||
|
variable-name-hint=[a-z_][a-z0-9_]{2,30}$
|
||||||
|
|
||||||
|
# Regular expression which should only match function or class names that do
|
||||||
|
# not require a docstring.
|
||||||
|
no-docstring-rgx=^_
|
||||||
|
|
||||||
|
# Minimum line length for functions/classes that require docstrings, shorter
|
||||||
|
# ones are exempt.
|
||||||
|
docstring-min-length=-1
|
||||||
|
|
||||||
|
|
||||||
|
[ELIF]
|
||||||
|
|
||||||
|
# Maximum number of nested blocks for function / method body
|
||||||
|
max-nested-blocks=5
|
||||||
|
|
||||||
|
|
||||||
|
[FORMAT]
|
||||||
|
|
||||||
|
# Maximum number of characters on a single line.
|
||||||
|
max-line-length=100
|
||||||
|
|
||||||
|
# Regexp for a line that is allowed to be longer than the limit.
|
||||||
|
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Maximum number of lines in a module
|
||||||
|
max-module-lines=1000
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
|
||||||
|
expected-line-ending-format=
|
||||||
|
|
||||||
|
|
||||||
|
[LOGGING]
|
||||||
|
|
||||||
|
# Logging modules to check that the string format arguments are in logging
|
||||||
|
# function parameter format
|
||||||
|
logging-modules=logging
|
||||||
|
|
||||||
|
|
||||||
|
[MISCELLANEOUS]
|
||||||
|
|
||||||
|
# List of note tags to take in consideration, separated by a comma.
|
||||||
|
notes=FIXME,XXX,TODO
|
||||||
|
|
||||||
|
|
||||||
|
[SIMILARITIES]
|
||||||
|
|
||||||
|
# Minimum lines number of a similarity.
|
||||||
|
min-similarity-lines=4
|
||||||
|
|
||||||
|
# Ignore comments when computing similarities.
|
||||||
|
ignore-comments=yes
|
||||||
|
|
||||||
|
# Ignore docstrings when computing similarities.
|
||||||
|
ignore-docstrings=yes
|
||||||
|
|
||||||
|
# Ignore imports when computing similarities.
|
||||||
|
ignore-imports=no
|
||||||
|
|
||||||
|
|
||||||
|
[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=
|
||||||
|
|
||||||
|
# A path to a file that contains private dictionary; one word per line.
|
||||||
|
spelling-private-dict-file=
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
[TYPECHECK]
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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=
|
||||||
|
|
||||||
|
# List of classes names for which member attributes should not be checked
|
||||||
|
# (useful for classes with attributes dynamically set). This supports can work
|
||||||
|
# with qualified names.
|
||||||
|
ignored-classes=
|
||||||
|
|
||||||
|
# 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=
|
||||||
|
|
||||||
|
|
||||||
|
[VARIABLES]
|
||||||
|
|
||||||
|
# Tells whether we should check for unused import in __init__ files.
|
||||||
|
init-import=no
|
||||||
|
|
||||||
|
# A regular expression matching the name of dummy variables (i.e. expectedly
|
||||||
|
# not used).
|
||||||
|
dummy-variables-rgx=_$|dummy
|
||||||
|
|
||||||
|
# List of additional names supposed to be defined in builtins. Remember that
|
||||||
|
# you should avoid to define new builtins when possible.
|
||||||
|
additional-builtins=
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
[CLASSES]
|
||||||
|
|
||||||
|
# List of method names used to declare (i.e. assign) instance attributes.
|
||||||
|
defining-attr-methods=__init__,__new__,setUp
|
||||||
|
|
||||||
|
# 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=mcs
|
||||||
|
|
||||||
|
# List of member names, which should be excluded from the protected access
|
||||||
|
# warning.
|
||||||
|
exclude-protected=_asdict,_fields,_replace,_source,_make
|
||||||
|
|
||||||
|
|
||||||
|
[DESIGN]
|
||||||
|
|
||||||
|
# Maximum number of arguments for function / method
|
||||||
|
max-args=20
|
||||||
|
|
||||||
|
# Argument names that match this expression will be ignored. Default to name
|
||||||
|
# with leading underscore
|
||||||
|
ignored-argument-names=_.*
|
||||||
|
|
||||||
|
# Maximum number of locals for function / method body
|
||||||
|
max-locals=20
|
||||||
|
|
||||||
|
# Maximum number of return / yield for function / method body
|
||||||
|
max-returns=6
|
||||||
|
|
||||||
|
# Maximum number of branch for function / method body
|
||||||
|
max-branches=12
|
||||||
|
|
||||||
|
# Maximum number of statements in function / method body
|
||||||
|
max-statements=50
|
||||||
|
|
||||||
|
# Maximum number of parents for a class (see R0901).
|
||||||
|
max-parents=7
|
||||||
|
|
||||||
|
# Maximum number of attributes for a class (see R0902).
|
||||||
|
max-attributes=10
|
||||||
|
|
||||||
|
# Minimum number of public methods for a class (see R0903).
|
||||||
|
min-public-methods=2
|
||||||
|
|
||||||
|
# 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]
|
||||||
|
|
||||||
|
# Deprecated modules which should not be used, separated by a comma
|
||||||
|
deprecated-modules=optparse
|
||||||
|
|
||||||
|
# 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 external dependencies in the given file (report RP0402 must
|
||||||
|
# not be disabled)
|
||||||
|
ext-import-graph=
|
||||||
|
|
||||||
|
# Create a graph of internal dependencies in the given file (report RP0402 must
|
||||||
|
# not be disabled)
|
||||||
|
int-import-graph=
|
||||||
|
|
||||||
|
|
||||||
|
[EXCEPTIONS]
|
||||||
|
|
||||||
|
# Exceptions that will emit a warning when being caught. Defaults to
|
||||||
|
# "Exception"
|
||||||
|
overgeneral-exceptions=Exception
|
||||||
14
.travis.yml
14
.travis.yml
|
|
@ -11,8 +11,6 @@ notifications:
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- python: 2.6
|
|
||||||
env: TOXENV=py26
|
|
||||||
- python: 2.7
|
- python: 2.7
|
||||||
env: TOXENV=py27
|
env: TOXENV=py27
|
||||||
- python: 3.3
|
- python: 3.3
|
||||||
|
|
@ -24,6 +22,14 @@ matrix:
|
||||||
- python: pypy
|
- python: pypy
|
||||||
env: TOXENV=pypy
|
env: TOXENV=pypy
|
||||||
- python: 2.7
|
- python: 2.7
|
||||||
env: TOXENV=py27-flake8
|
env: TOXENV=readme
|
||||||
- python: 3.4
|
- python: 3.4
|
||||||
env: TOXENV=py34-flake8
|
env: TOXENV=flake8
|
||||||
|
- python: 3.4
|
||||||
|
env: TOXENV=pylint
|
||||||
|
- python: 3.4
|
||||||
|
env: TOXENV=doc8
|
||||||
|
- python: 3.4
|
||||||
|
env: TOXENV=bandit
|
||||||
|
- python: 3.4
|
||||||
|
env: TOXENV=docs
|
||||||
|
|
|
||||||
362
CHANGES.rst
362
CHANGES.rst
|
|
@ -1,362 +0,0 @@
|
||||||
CHANGES
|
|
||||||
=======
|
|
||||||
|
|
||||||
2.6.1 - 2016-06-25
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- **Bug** Update the config files to search for to include ``setup.cfg`` and
|
|
||||||
``tox.ini``. This was broken in 2.5.5 when we stopped passing
|
|
||||||
``config_file`` to our Style Guide
|
|
||||||
|
|
||||||
2.6.0 - 2016-06-15
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- **Requirements Change** Switch to pycodestyle as all future pep8 releases
|
|
||||||
will use that package name
|
|
||||||
|
|
||||||
- **Improvement** Allow for Windows users on *select* versions of Python to
|
|
||||||
use ``--jobs`` and multiprocessing
|
|
||||||
|
|
||||||
- **Improvement** Update bounds on McCabe
|
|
||||||
|
|
||||||
- **Improvement** Update bounds on PyFlakes and blacklist known broken
|
|
||||||
versions
|
|
||||||
|
|
||||||
- **Improvement** Handle new PyFlakes warning with a new error code: F405
|
|
||||||
|
|
||||||
2.5.5 - 2016-06-14
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- **Bug** Fix setuptools integration when parsing config files
|
|
||||||
|
|
||||||
- **Bug** Don't pass the user's config path as the config_file when creating a
|
|
||||||
StyleGuide
|
|
||||||
|
|
||||||
2.5.4 - 2016-02-11
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- **Bug** Missed an attribute rename during the v2.5.3 release.
|
|
||||||
|
|
||||||
2.5.3 - 2016-02-11
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- **Bug** Actually parse ``output_file`` and ``enable_extensions`` from config
|
|
||||||
files
|
|
||||||
|
|
||||||
2.5.2 - 2016-01-30
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- **Bug** Parse ``output_file`` and ``enable_extensions`` from config files
|
|
||||||
|
|
||||||
- **Improvement** Raise upper bound on mccabe plugin to allow for version
|
|
||||||
0.4.0
|
|
||||||
|
|
||||||
2.5.1 - 2015-12-08
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- **Bug** Properly look for ``.flake8`` in current working directory
|
|
||||||
(`GitLab#103`_)
|
|
||||||
|
|
||||||
- **Bug** Monkey-patch ``pep8.stdin_get_value`` to cache the actual value in
|
|
||||||
stdin. This helps plugins relying on the function when run with
|
|
||||||
multiprocessing. (`GitLab#105`_, `GitLab#107`_)
|
|
||||||
|
|
||||||
.. _GitLab#103: https://gitlab.com/pycqa/flake8/issues/103
|
|
||||||
.. _GitLab#105: https://gitlab.com/pycqa/flake8/issues/105
|
|
||||||
.. _GitLab#107: https://gitlab.com/pycqa/flake8/issues/107
|
|
||||||
|
|
||||||
2.5.0 - 2015-10-26
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- **Improvement** Raise cap on PyFlakes for Python 3.5 support
|
|
||||||
|
|
||||||
- **Improvement** Avoid deprecation warnings when loading extensions
|
|
||||||
(`GitLab#59`_, `GitLab#90`_)
|
|
||||||
|
|
||||||
- **Improvement** Separate logic to enable "off-by-default" extensions
|
|
||||||
(`GitLab#67`_)
|
|
||||||
|
|
||||||
- **Bug** Properly parse options to setuptools Flake8 command (`GitLab!41`_)
|
|
||||||
|
|
||||||
- **Bug** Fix exceptions when output on stdout is truncated before Flake8
|
|
||||||
finishes writing the output (`GitLab#69`_)
|
|
||||||
|
|
||||||
- **Bug** Fix error on OS X where Flake8 can no longer acquire or create new
|
|
||||||
semaphores (`GitLab#74`_)
|
|
||||||
|
|
||||||
.. _GitLab!41: https://gitlab.com/pycqa/flake8/merge_requests/41
|
|
||||||
.. _GitLab#59: https://gitlab.com/pycqa/flake8/issues/59
|
|
||||||
.. _GitLab#67: https://gitlab.com/pycqa/flake8/issues/67
|
|
||||||
.. _GitLab#69: https://gitlab.com/pycqa/flake8/issues/69
|
|
||||||
.. _GitLab#74: https://gitlab.com/pycqa/flake8/issues/74
|
|
||||||
.. _GitLab#90: https://gitlab.com/pycqa/flake8/issues/90
|
|
||||||
|
|
||||||
2.4.1 - 2015-05-18
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- **Bug** Do not raise a ``SystemError`` unless there were errors in the
|
|
||||||
setuptools command. (`GitLab#39`_, `GitLab!23`_)
|
|
||||||
|
|
||||||
- **Bug** Do not verify dependencies of extensions loaded via entry-points.
|
|
||||||
|
|
||||||
- **Improvement** Blacklist versions of pep8 we know are broken
|
|
||||||
|
|
||||||
.. _GitLab#39: https://gitlab.com/pycqa/flake8/issues/39
|
|
||||||
.. _GitLab!23: https://gitlab.com/pycqa/flake8/merge_requests/23
|
|
||||||
|
|
||||||
2.4.0 - 2015-03-07
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- **Bug** Print filenames when using multiprocessing and ``-q`` option.
|
|
||||||
(`GitLab#31`_)
|
|
||||||
|
|
||||||
- **Bug** Put upper cap on dependencies. The caps for 2.4.0 are:
|
|
||||||
|
|
||||||
- ``pep8 < 1.6`` (Related to `GitLab#35`_)
|
|
||||||
|
|
||||||
- ``mccabe < 0.4``
|
|
||||||
|
|
||||||
- ``pyflakes < 0.9``
|
|
||||||
|
|
||||||
See also `GitLab#32`_
|
|
||||||
|
|
||||||
- **Bug** Files excluded in a config file were not being excluded when flake8
|
|
||||||
was run from a git hook. (`GitHub#2`_)
|
|
||||||
|
|
||||||
- **Improvement** Print warnings for users who are providing mutually
|
|
||||||
exclusive options to flake8. (`GitLab#8`_, `GitLab!18`_)
|
|
||||||
|
|
||||||
- **Feature** Allow git hook configuration to live in ``.git/config``.
|
|
||||||
See the updated `VCS hooks docs`_ for more details. (`GitLab!20`_)
|
|
||||||
|
|
||||||
.. _GitHub#2: https://github.com/pycqa/flake8/pull/2
|
|
||||||
.. _GitLab#8: https://gitlab.com/pycqa/flake8/issues/8
|
|
||||||
.. _GitLab#31: https://gitlab.com/pycqa/flake8/issues/31
|
|
||||||
.. _GitLab#32: https://gitlab.com/pycqa/flake8/issues/32
|
|
||||||
.. _GitLab#35: https://gitlab.com/pycqa/flake8/issues/35
|
|
||||||
.. _GitLab!18: https://gitlab.com/pycqa/flake8/merge_requests/18
|
|
||||||
.. _GitLab!20: https://gitlab.com/pycqa/flake8/merge_requests/20
|
|
||||||
.. _VCS hooks docs: https://flake8.readthedocs.io/en/latest/vcs.html
|
|
||||||
|
|
||||||
2.3.0 - 2015-01-04
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- **Feature**: Add ``--output-file`` option to specify a file to write to
|
|
||||||
instead of ``stdout``.
|
|
||||||
|
|
||||||
- **Bug** Fix interleaving of output while using multiprocessing
|
|
||||||
(`GitLab#17`_)
|
|
||||||
|
|
||||||
.. _GitLab#17: https://gitlab.com/pycqa/flake8/issues/17
|
|
||||||
|
|
||||||
2.2.5 - 2014-10-19
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- Flush standard out when using multiprocessing
|
|
||||||
|
|
||||||
- Make the check for "# flake8: noqa" more strict
|
|
||||||
|
|
||||||
2.2.4 - 2014-10-09
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- Fix bugs triggered by turning multiprocessing on by default (again)
|
|
||||||
|
|
||||||
Multiprocessing is forcibly disabled in the following cases:
|
|
||||||
|
|
||||||
- Passing something in via stdin
|
|
||||||
|
|
||||||
- Analyzing a diff
|
|
||||||
|
|
||||||
- Using windows
|
|
||||||
|
|
||||||
- Fix --install-hook when there are no config files present for pep8 or
|
|
||||||
flake8.
|
|
||||||
|
|
||||||
- Fix how the setuptools command parses excludes in config files
|
|
||||||
|
|
||||||
- Fix how the git hook determines which files to analyze (Thanks Chris
|
|
||||||
Buccella!)
|
|
||||||
|
|
||||||
2.2.3 - 2014-08-25
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- Actually turn multiprocessing on by default
|
|
||||||
|
|
||||||
2.2.2 - 2014-07-04
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- Re-enable multiprocessing by default while fixing the issue Windows users
|
|
||||||
were seeing.
|
|
||||||
|
|
||||||
2.2.1 - 2014-06-30
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- Turn off multiple jobs by default. To enable automatic use of all CPUs, use
|
|
||||||
``--jobs=auto``. Fixes #155 and #154.
|
|
||||||
|
|
||||||
2.2.0 - 2014-06-22
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- New option ``doctests`` to run Pyflakes checks on doctests too
|
|
||||||
- New option ``jobs`` to launch multiple jobs in parallel
|
|
||||||
- Turn on using multiple jobs by default using the CPU count
|
|
||||||
- Add support for ``python -m flake8`` on Python 2.7 and Python 3
|
|
||||||
- Fix Git and Mercurial hooks: issues #88, #133, #148 and #149
|
|
||||||
- Fix crashes with Python 3.4 by upgrading dependencies
|
|
||||||
- Fix traceback when running tests with Python 2.6
|
|
||||||
- Fix the setuptools command ``python setup.py flake8`` to read
|
|
||||||
the project configuration
|
|
||||||
|
|
||||||
|
|
||||||
2.1.0 - 2013-10-26
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- Add FLAKE8_LAZY and FLAKE8_IGNORE environment variable support to git and
|
|
||||||
mercurial hooks
|
|
||||||
- Force git and mercurial hooks to repsect configuration in setup.cfg
|
|
||||||
- Only check staged files if that is specified
|
|
||||||
- Fix hook file permissions
|
|
||||||
- Fix the git hook on python 3
|
|
||||||
- Ignore non-python files when running the git hook
|
|
||||||
- Ignore .tox directories by default
|
|
||||||
- Flake8 now reports the column number for PyFlakes messages
|
|
||||||
|
|
||||||
|
|
||||||
2.0.0 - 2013-02-23
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- Pyflakes errors are prefixed by an ``F`` instead of an ``E``
|
|
||||||
- McCabe complexity warnings are prefixed by a ``C`` instead of a ``W``
|
|
||||||
- Flake8 supports extensions through entry points
|
|
||||||
- Due to the above support, we **require** setuptools
|
|
||||||
- We publish the `documentation <https://flake8.readthedocs.io/>`_
|
|
||||||
- Fixes #13: pep8, pyflakes and mccabe become external dependencies
|
|
||||||
- Split run.py into main.py, engine.py and hooks.py for better logic
|
|
||||||
- Expose our parser for our users
|
|
||||||
- New feature: Install git and hg hooks automagically
|
|
||||||
- By relying on pyflakes (0.6.1), we also fixed #45 and #35
|
|
||||||
|
|
||||||
|
|
||||||
1.7.0 - 2012-12-21
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- Fixes part of #35: Exception for no WITHITEM being an attribute of Checker
|
|
||||||
for Python 3.3
|
|
||||||
- Support stdin
|
|
||||||
- Incorporate @phd's builtins pull request
|
|
||||||
- Fix the git hook
|
|
||||||
- Update pep8.py to the latest version
|
|
||||||
|
|
||||||
|
|
||||||
1.6.2 - 2012-11-25
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- fixed the NameError: global name 'message' is not defined (#46)
|
|
||||||
|
|
||||||
|
|
||||||
1.6.1 - 2012-11-24
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- fixed the mercurial hook, a change from a previous patch was not properly
|
|
||||||
applied
|
|
||||||
- fixed an assumption about warnings/error messages that caused an exception
|
|
||||||
to be thrown when McCabe is used
|
|
||||||
|
|
||||||
|
|
||||||
1.6 - 2012-11-16
|
|
||||||
----------------
|
|
||||||
|
|
||||||
- changed the signatures of the ``check_file`` function in flake8/run.py,
|
|
||||||
``skip_warning`` in flake8/util.py and the ``check``, ``checkPath``
|
|
||||||
functions in flake8/pyflakes.py.
|
|
||||||
- fix ``--exclude`` and ``--ignore`` command flags (#14, #19)
|
|
||||||
- fix the git hook that wasn't catching files not already added to the index
|
|
||||||
(#29)
|
|
||||||
- pre-emptively includes the addition to pep8 to ignore certain lines.
|
|
||||||
Add ``# nopep8`` to the end of a line to ignore it. (#37)
|
|
||||||
- ``check_file`` can now be used without any special prior setup (#21)
|
|
||||||
- unpacking exceptions will no longer cause an exception (#20)
|
|
||||||
- fixed crash on non-existent file (#38)
|
|
||||||
|
|
||||||
|
|
||||||
1.5 - 2012-10-13
|
|
||||||
----------------
|
|
||||||
|
|
||||||
- fixed the stdin
|
|
||||||
- make sure mccabe catches the syntax errors as warnings
|
|
||||||
- pep8 upgrade
|
|
||||||
- added max_line_length default value
|
|
||||||
- added Flake8Command and entry points if setuptools is around
|
|
||||||
- using the setuptools console wrapper when available
|
|
||||||
|
|
||||||
|
|
||||||
1.4 - 2012-07-12
|
|
||||||
----------------
|
|
||||||
|
|
||||||
- git_hook: Only check staged changes for compliance
|
|
||||||
- use pep8 1.2
|
|
||||||
|
|
||||||
|
|
||||||
1.3.1 - 2012-05-19
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- fixed support for Python 2.5
|
|
||||||
|
|
||||||
|
|
||||||
1.3 - 2012-03-12
|
|
||||||
----------------
|
|
||||||
|
|
||||||
- fixed false W402 warning on exception blocks.
|
|
||||||
|
|
||||||
|
|
||||||
1.2 - 2012-02-12
|
|
||||||
----------------
|
|
||||||
|
|
||||||
- added a git hook
|
|
||||||
- now Python 3 compatible
|
|
||||||
- mccabe and pyflakes have warning codes like pep8 now
|
|
||||||
|
|
||||||
|
|
||||||
1.1 - 2012-02-14
|
|
||||||
----------------
|
|
||||||
|
|
||||||
- fixed the value returned by --version
|
|
||||||
- allow the flake8: header to be more generic
|
|
||||||
- fixed the "hg hook raises 'physical lines'" bug
|
|
||||||
- allow three argument form of raise
|
|
||||||
- now uses setuptools if available, for 'develop' command
|
|
||||||
|
|
||||||
|
|
||||||
1.0 - 2011-11-29
|
|
||||||
----------------
|
|
||||||
|
|
||||||
- Deactivates by default the complexity checker
|
|
||||||
- Introduces the complexity option in the HG hook and the command line.
|
|
||||||
|
|
||||||
|
|
||||||
0.9 - 2011-11-09
|
|
||||||
----------------
|
|
||||||
|
|
||||||
- update pep8 version to 0.6.1
|
|
||||||
- mccabe check: gracefully handle compile failure
|
|
||||||
|
|
||||||
|
|
||||||
0.8 - 2011-02-27
|
|
||||||
----------------
|
|
||||||
|
|
||||||
- fixed hg hook
|
|
||||||
- discard unexisting files on hook check
|
|
||||||
|
|
||||||
|
|
||||||
0.7 - 2010-02-18
|
|
||||||
----------------
|
|
||||||
|
|
||||||
- Fix pep8 initialization when run through Hg
|
|
||||||
- Make pep8 short options work when run through the command line
|
|
||||||
- Skip duplicates when controlling files via Hg
|
|
||||||
|
|
||||||
|
|
||||||
0.6 - 2010-02-15
|
|
||||||
----------------
|
|
||||||
|
|
||||||
- Fix the McCabe metric on some loops
|
|
||||||
1
CONTRIBUTING.rst
Symbolic link
1
CONTRIBUTING.rst
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
docs/source/internal/contributing.rst
|
||||||
2
LICENSE
2
LICENSE
|
|
@ -1,7 +1,7 @@
|
||||||
== Flake8 License (MIT) ==
|
== Flake8 License (MIT) ==
|
||||||
|
|
||||||
Copyright (C) 2011-2013 Tarek Ziade <tarek@ziade.org>
|
Copyright (C) 2011-2013 Tarek Ziade <tarek@ziade.org>
|
||||||
Copyright (C) 2012-2013 Ian Cordasco <graffatcolmingov@gmail.com>
|
Copyright (C) 2012-2016 Ian Cordasco <graffatcolmingov@gmail.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
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
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
include *.rst
|
include *.rst
|
||||||
include CONTRIBUTORS.txt
|
include CONTRIBUTORS.txt
|
||||||
include LICENSE
|
include LICENSE
|
||||||
recursive-include flake8 *
|
recursive-include docs *
|
||||||
|
recursive-include tests *
|
||||||
|
recursive-include src *
|
||||||
|
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
"""\
|
|
||||||
Git patch to HG changeset patch converter.
|
|
||||||
|
|
||||||
USAGE: git-patch-to-hg-export.py < git.patch > hg.patch
|
|
||||||
"""
|
|
||||||
|
|
||||||
from email.utils import parsedate_tz, mktime_tz
|
|
||||||
import re
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def git_patch_to_hg(fin, fout):
|
|
||||||
fout.write('# HG changeset patch\n')
|
|
||||||
|
|
||||||
subject_re = re.compile(r'^(RE:)?\s*(\[[^]]*\])?\s*', re.I)
|
|
||||||
|
|
||||||
# headers
|
|
||||||
for line in fin:
|
|
||||||
if line.startswith('From: '):
|
|
||||||
fout.write('# User %s' % line[6:])
|
|
||||||
elif line.startswith('Date: '):
|
|
||||||
t = parsedate_tz(line[6:])
|
|
||||||
timestamp = mktime_tz(t)
|
|
||||||
timezone = -t[-1]
|
|
||||||
fout.write('# Date %d %d\n' % (timestamp, timezone))
|
|
||||||
elif line.startswith('Subject: '):
|
|
||||||
subject = subject_re.sub('', line[9:])
|
|
||||||
fout.write(subject + '\n')
|
|
||||||
elif line == '\n' or line == '\r\n':
|
|
||||||
break
|
|
||||||
|
|
||||||
# commit message
|
|
||||||
for line in fin:
|
|
||||||
if line == '---\n':
|
|
||||||
break
|
|
||||||
fout.write(line)
|
|
||||||
|
|
||||||
# skip over the diffstat
|
|
||||||
for line in fin:
|
|
||||||
if line.startswith('diff --git'):
|
|
||||||
fout.write('\n' + line)
|
|
||||||
break
|
|
||||||
|
|
||||||
# diff
|
|
||||||
# NOTE: there will still be an index line after each diff --git, but it
|
|
||||||
# will be ignored
|
|
||||||
for line in fin:
|
|
||||||
fout.write(line.encode('utf-8'))
|
|
||||||
|
|
||||||
# NOTE: the --/version will still be at the end, but it will be ignored
|
|
||||||
|
|
||||||
|
|
||||||
def open_file():
|
|
||||||
if len(sys.argv) > 1:
|
|
||||||
if re.match('https?://', sys.argv[1]):
|
|
||||||
import requests
|
|
||||||
import io
|
|
||||||
resp = requests.get(sys.argv[1])
|
|
||||||
if resp.ok:
|
|
||||||
return io.StringIO(resp.content.decode('utf-8'))
|
|
||||||
else:
|
|
||||||
return io.StringIO('')
|
|
||||||
elif os.path.exists(sys.argv[1]):
|
|
||||||
return open(sys.argv[1])
|
|
||||||
return sys.stdin
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
patch_fd = open_file()
|
|
||||||
git_patch_to_hg(patch_fd, sys.stdout)
|
|
||||||
|
|
||||||
|
|
||||||
__author__ = "Mark Lodato <lodatom@gmail.com>"
|
|
||||||
|
|
||||||
__license__ = """
|
|
||||||
This is the MIT license: http://www.opensource.org/licenses/mit-license.php
|
|
||||||
|
|
||||||
Copyright (c) 2009 Mark Lodato
|
|
||||||
|
|
||||||
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.
|
|
||||||
"""
|
|
||||||
|
|
@ -1,5 +1 @@
|
||||||
pycodestyle
|
tox
|
||||||
pyflakes
|
|
||||||
mccabe
|
|
||||||
mock
|
|
||||||
nose
|
|
||||||
|
|
|
||||||
130
docs/Makefile
130
docs/Makefile
|
|
@ -1,130 +0,0 @@
|
||||||
# Makefile for Sphinx documentation
|
|
||||||
#
|
|
||||||
|
|
||||||
# You can set these variables from the command line.
|
|
||||||
SPHINXOPTS =
|
|
||||||
SPHINXBUILD = sphinx-build
|
|
||||||
PAPER =
|
|
||||||
BUILDDIR = _build
|
|
||||||
|
|
||||||
# Internal variables.
|
|
||||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
|
||||||
PAPEROPT_letter = -D latex_paper_size=letter
|
|
||||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
|
||||||
|
|
||||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
|
|
||||||
|
|
||||||
help:
|
|
||||||
@echo "Please use \`make <target>' where <target> is one of"
|
|
||||||
@echo " html to make standalone HTML files"
|
|
||||||
@echo " dirhtml to make HTML files named index.html in directories"
|
|
||||||
@echo " singlehtml to make a single large HTML file"
|
|
||||||
@echo " pickle to make pickle files"
|
|
||||||
@echo " json to make JSON files"
|
|
||||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
|
||||||
@echo " qthelp to make HTML files and a qthelp project"
|
|
||||||
@echo " devhelp to make HTML files and a Devhelp project"
|
|
||||||
@echo " epub to make an epub"
|
|
||||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
|
||||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
|
||||||
@echo " text to make text files"
|
|
||||||
@echo " man to make manual pages"
|
|
||||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
|
||||||
@echo " linkcheck to check all external links for integrity"
|
|
||||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
|
||||||
|
|
||||||
clean:
|
|
||||||
-rm -rf $(BUILDDIR)/*
|
|
||||||
|
|
||||||
html:
|
|
||||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
|
||||||
|
|
||||||
dirhtml:
|
|
||||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
|
||||||
|
|
||||||
singlehtml:
|
|
||||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
|
||||||
|
|
||||||
pickle:
|
|
||||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can process the pickle files."
|
|
||||||
|
|
||||||
json:
|
|
||||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can process the JSON files."
|
|
||||||
|
|
||||||
htmlhelp:
|
|
||||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
|
||||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
|
||||||
|
|
||||||
qthelp:
|
|
||||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
|
||||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
|
||||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Raclette.qhcp"
|
|
||||||
@echo "To view the help file:"
|
|
||||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Raclette.qhc"
|
|
||||||
|
|
||||||
devhelp:
|
|
||||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished."
|
|
||||||
@echo "To view the help file:"
|
|
||||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/Raclette"
|
|
||||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Raclette"
|
|
||||||
@echo "# devhelp"
|
|
||||||
|
|
||||||
epub:
|
|
||||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
|
||||||
|
|
||||||
latex:
|
|
||||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
|
||||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
|
||||||
"(use \`make latexpdf' here to do that automatically)."
|
|
||||||
|
|
||||||
latexpdf:
|
|
||||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
|
||||||
@echo "Running LaTeX files through pdflatex..."
|
|
||||||
make -C $(BUILDDIR)/latex all-pdf
|
|
||||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
|
||||||
|
|
||||||
text:
|
|
||||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
|
||||||
|
|
||||||
man:
|
|
||||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
|
||||||
|
|
||||||
changes:
|
|
||||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
|
||||||
@echo
|
|
||||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
|
||||||
|
|
||||||
linkcheck:
|
|
||||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
|
||||||
@echo
|
|
||||||
@echo "Link check complete; look for any errors in the above output " \
|
|
||||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
|
||||||
|
|
||||||
doctest:
|
|
||||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
|
||||||
@echo "Testing of doctests in the sources finished, look at the " \
|
|
||||||
"results in $(BUILDDIR)/doctest/output.txt."
|
|
||||||
38
docs/api.rst
38
docs/api.rst
|
|
@ -1,38 +0,0 @@
|
||||||
==========
|
|
||||||
Flake8 API
|
|
||||||
==========
|
|
||||||
|
|
||||||
.. module:: flake8
|
|
||||||
|
|
||||||
flake8.engine
|
|
||||||
=============
|
|
||||||
|
|
||||||
.. autofunction:: flake8.engine.get_parser
|
|
||||||
|
|
||||||
.. autofunction:: flake8.engine.get_style_guide
|
|
||||||
|
|
||||||
flake8.hooks
|
|
||||||
============
|
|
||||||
|
|
||||||
.. autofunction:: flake8.hooks.git_hook
|
|
||||||
|
|
||||||
.. autofunction:: flake8.hooks.hg_hook
|
|
||||||
|
|
||||||
flake8.main
|
|
||||||
===========
|
|
||||||
|
|
||||||
.. autofunction:: flake8.main.main
|
|
||||||
|
|
||||||
.. autofunction:: flake8.main.check_file
|
|
||||||
|
|
||||||
.. autofunction:: flake8.main.check_code
|
|
||||||
|
|
||||||
.. autoclass:: flake8.main.Flake8Command
|
|
||||||
|
|
||||||
flake8.util
|
|
||||||
===========
|
|
||||||
|
|
||||||
For AST checkers, this module has the ``iter_child_nodes`` function and
|
|
||||||
handles compatibility for all versions of Python between 2.5 and 3.3. The
|
|
||||||
function was added to the ``ast`` module in Python 2.6 but is redefined in the
|
|
||||||
case where the user is running Python 2.5
|
|
||||||
0
docs/build/.keep
vendored
Normal file
0
docs/build/.keep
vendored
Normal file
|
|
@ -1,17 +0,0 @@
|
||||||
Buildout integration
|
|
||||||
=====================
|
|
||||||
|
|
||||||
In order to use Flake8 inside a buildout, edit your buildout.cfg and add this::
|
|
||||||
|
|
||||||
[buildout]
|
|
||||||
|
|
||||||
parts +=
|
|
||||||
...
|
|
||||||
flake8
|
|
||||||
|
|
||||||
[flake8]
|
|
||||||
recipe = zc.recipe.egg
|
|
||||||
eggs = flake8
|
|
||||||
${buildout:eggs}
|
|
||||||
entry-points =
|
|
||||||
flake8=flake8.main:main
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
Changes
|
|
||||||
=======
|
|
||||||
|
|
||||||
.. include:: ../CHANGES.rst
|
|
||||||
:start-line: 3
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
Configuration
|
|
||||||
=============
|
|
||||||
|
|
||||||
Configuration settings are applied in three ways: user, project, and the
|
|
||||||
``--config`` CLI argument. The user (global) configuration is read first. Next
|
|
||||||
the project configuration is loaded, and overrides any settings found in both
|
|
||||||
the user (global) and project configurations. Finally, if the ``--config``
|
|
||||||
argument is used on the command line, the specified file is loaded and
|
|
||||||
overrides any settings that overlap with the user (global) and project
|
|
||||||
configurations.
|
|
||||||
|
|
||||||
|
|
||||||
User (Global)
|
|
||||||
-------------
|
|
||||||
|
|
||||||
The user settings are read from the ``~/.config/flake8`` file (or the
|
|
||||||
``~/.flake8`` file on Windows).
|
|
||||||
Example::
|
|
||||||
|
|
||||||
[flake8]
|
|
||||||
ignore = E226,E302,E41
|
|
||||||
max-line-length = 160
|
|
||||||
exclude = tests/*
|
|
||||||
max-complexity = 10
|
|
||||||
|
|
||||||
Per-Project
|
|
||||||
-----------
|
|
||||||
|
|
||||||
At the project level, the ``tox.ini``, ``setup.cfg``, ``.pep8`` or ``.flake8``
|
|
||||||
files are read if present. Only the first file is considered. If this file
|
|
||||||
does not have a ``[flake8]`` section, no project specific configuration is
|
|
||||||
loaded.
|
|
||||||
|
|
||||||
Per Code Line
|
|
||||||
-------
|
|
||||||
|
|
||||||
To ignore one line of code add ``# NOQA`` as a line comment.
|
|
||||||
|
|
||||||
Default
|
|
||||||
-------
|
|
||||||
|
|
||||||
If the ``ignore`` option is not in the configuration and not in the arguments,
|
|
||||||
only the error codes ``E123/E133``, ``E226`` and ``E241/E242`` are ignored
|
|
||||||
(see the :ref:`warning and error codes <error-codes>`).
|
|
||||||
|
|
||||||
Settings
|
|
||||||
--------
|
|
||||||
|
|
||||||
This is a (likely incomplete) list of settings that can be used in your config
|
|
||||||
file. In general, any settings that ``pycodestyle`` supports we also support and
|
|
||||||
we add the ability to set ``max-complexity`` as well.
|
|
||||||
|
|
||||||
- ``exclude``: comma-separated filename and glob patterns
|
|
||||||
default: ``.svn,CVS,.bzr,.hg,.git,__pycache__``
|
|
||||||
|
|
||||||
- ``filename``: comma-separated filename and glob patterns
|
|
||||||
default: ``*.py``
|
|
||||||
|
|
||||||
- ``select``: select errors and warnings to enable which are off by default
|
|
||||||
|
|
||||||
- ``ignore``: skip errors or warnings
|
|
||||||
|
|
||||||
- ``max-line-length``: set maximum allowed line length
|
|
||||||
default: 79
|
|
||||||
|
|
||||||
- ``format``: set the error format
|
|
||||||
|
|
||||||
- ``max-complexity``: McCabe complexity threshold
|
|
||||||
|
|
@ -1,149 +0,0 @@
|
||||||
Writing an Extension for Flake8
|
|
||||||
===============================
|
|
||||||
|
|
||||||
Since Flake8 is now adding support for extensions, we require ``setuptools``
|
|
||||||
so we can manage extensions through entry points. If you are making an
|
|
||||||
existing tool compatible with Flake8 but do not already require
|
|
||||||
``setuptools``, you should probably add it to your list of requirements. Next,
|
|
||||||
you'll need to edit your ``setup.py`` file so that upon installation, your
|
|
||||||
extension is registered. If you define a class called ``PackageEntryClass``
|
|
||||||
then this would look something like the following::
|
|
||||||
|
|
||||||
|
|
||||||
setup(
|
|
||||||
# ...
|
|
||||||
entry_points={
|
|
||||||
'flake8.extension': ['P10 = package.PackageEntryClass'],
|
|
||||||
}
|
|
||||||
# ...
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
If you intend to publish your extension, choose a unique code prefix
|
|
||||||
following the convention for :ref:`error codes <error-codes>`.
|
|
||||||
In addition, you can open a request in the `issue tracker
|
|
||||||
<https://bitbucket.org/tarek/flake8/issues>`_ to register the prefix in the
|
|
||||||
documentation.
|
|
||||||
|
|
||||||
.. TODO: describe the API required for the 3 kind of extensions:
|
|
||||||
* physical line checkers
|
|
||||||
* logical line checkers
|
|
||||||
* AST checkers
|
|
||||||
|
|
||||||
|
|
||||||
A real example: McCabe
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
Below is an example from mccabe_ for how to write your ``setup.py`` file for
|
|
||||||
your Flake8 extension.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
# https://github.com/flintwork/mccabe/blob/0.2/setup.py#L38:L42
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from setuptools import setup
|
|
||||||
|
|
||||||
# ...
|
|
||||||
|
|
||||||
setup(
|
|
||||||
name='mccabe',
|
|
||||||
|
|
||||||
# ...
|
|
||||||
|
|
||||||
install_requires=[
|
|
||||||
'setuptools',
|
|
||||||
],
|
|
||||||
entry_points={
|
|
||||||
'flake8.extension': [
|
|
||||||
'C90 = mccabe:McCabeChecker',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
|
|
||||||
# ...
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
In ``mccabe.py`` you can see that extra options are added to the parser when
|
|
||||||
flake8 registers the extension:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
# https://github.com/flintwork/mccabe/blob/0.2/mccabe.py#L225:L254
|
|
||||||
class McCabeChecker(object):
|
|
||||||
"""McCabe cyclomatic complexity checker."""
|
|
||||||
name = 'mccabe'
|
|
||||||
version = __version__
|
|
||||||
_code = 'C901'
|
|
||||||
_error_tmpl = "C901 %r is too complex (%d)"
|
|
||||||
max_complexity = 0
|
|
||||||
|
|
||||||
def __init__(self, tree, filename):
|
|
||||||
self.tree = tree
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def add_options(cls, parser):
|
|
||||||
parser.add_option('--max-complexity', default=-1, action='store',
|
|
||||||
type='int', help="McCabe complexity threshold")
|
|
||||||
parser.config_options.append('max-complexity')
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def parse_options(cls, options):
|
|
||||||
cls.max_complexity = options.max_complexity
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
if self.max_complexity < 0:
|
|
||||||
return
|
|
||||||
visitor = PathGraphingAstVisitor()
|
|
||||||
visitor.preorder(self.tree, visitor)
|
|
||||||
for graph in visitor.graphs.values():
|
|
||||||
if graph.complexity() >= self.max_complexity:
|
|
||||||
text = self._error_tmpl % (graph.entity, graph.complexity())
|
|
||||||
yield graph.lineno, 0, text, type(self)
|
|
||||||
|
|
||||||
Since that is the defined entry point in the above ``setup.py``, flake8 finds
|
|
||||||
it and uses it to register the extension.
|
|
||||||
|
|
||||||
If we wanted the extension or a check to be optional, you can add
|
|
||||||
``off_by_default = True`` to our entry point. For example, we could
|
|
||||||
update ``mccabe.py`` with this variable as shown below:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
# https://github.com/flintwork/mccabe/blob/0.2/mccabe.py#L225:L254
|
|
||||||
class McCabeChecker(object):
|
|
||||||
"""McCabe cyclomatic complexity checker."""
|
|
||||||
name = 'mccabe'
|
|
||||||
version = __version__
|
|
||||||
off_by_default = True
|
|
||||||
|
|
||||||
If we wanted to run the optional extension or check, we need to specify the
|
|
||||||
error and warnings via the ``--enable-extension`` command line argument. In our
|
|
||||||
case, we could run ``flake8 --enable-extension=C90`` which would enable our
|
|
||||||
off_by_default example version of the mccabe extension.
|
|
||||||
|
|
||||||
|
|
||||||
Existing Extensions
|
|
||||||
===================
|
|
||||||
|
|
||||||
This is not at all a comprehensive listing of existing extensions but simply a
|
|
||||||
listing of the ones we are aware of:
|
|
||||||
|
|
||||||
* `flake8-debugger <https://github.com/JBKahn/flake8-debugger>`_
|
|
||||||
|
|
||||||
* `flake8-immediate <https://github.com/schlamar/flake8-immediate>`_
|
|
||||||
|
|
||||||
* `flake8-print <https://github.com/JBKahn/flake8-print>`_
|
|
||||||
|
|
||||||
* `flake8-todo <https://github.com/schlamar/flake8-todo>`_
|
|
||||||
|
|
||||||
* `pep8-naming <https://github.com/flintwork/pep8-naming>`_
|
|
||||||
|
|
||||||
* `radon <https://github.com/rubik/radon>`_
|
|
||||||
|
|
||||||
* `flake8-import-order <https://github.com/public/flake8-import-order>`_
|
|
||||||
|
|
||||||
* `flake8-respect-noqa <https://pypi.python.org/pypi/flake8-respect-noqa>`_
|
|
||||||
|
|
||||||
.. links
|
|
||||||
.. _mccabe: https://github.com/flintwork/mccabe
|
|
||||||
.. _PyPI: https://pypi.python.org/pypi/
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
.. include:: ../README.rst
|
|
||||||
|
|
||||||
|
|
||||||
Documentation
|
|
||||||
=============
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
config
|
|
||||||
warnings
|
|
||||||
vcs
|
|
||||||
buildout
|
|
||||||
setuptools
|
|
||||||
api
|
|
||||||
extensions
|
|
||||||
changes
|
|
||||||
|
|
||||||
Original Projects
|
|
||||||
=================
|
|
||||||
|
|
||||||
Flake8 is just a glue project, all the merits go to the creators and maintainers
|
|
||||||
of the original projects:
|
|
||||||
|
|
||||||
- pycodestyle: https://github.com/pycqa/pycodestyle
|
|
||||||
- PyFlakes: https://launchpad.net/pyflakes
|
|
||||||
- McCabe: http://nedbatchelder.com/blog/200803/python_code_complexity_microtool.html
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
Setuptools integration
|
|
||||||
======================
|
|
||||||
|
|
||||||
Upon installation, Flake8 enables a setuptools command that checks Python
|
|
||||||
files declared by your project.
|
|
||||||
|
|
||||||
Running ``python setup.py flake8`` on the command line will check the files
|
|
||||||
listed in your ``py_modules`` and ``packages``. If any warning is found,
|
|
||||||
the command will exit with an error code::
|
|
||||||
|
|
||||||
$ python setup.py flake8
|
|
||||||
|
|
||||||
Also, to allow users to be able to use the command without having to install
|
|
||||||
flake8 themselves, add flake8 to the setup_requires of your setup() like so::
|
|
||||||
|
|
||||||
setup(
|
|
||||||
name="project",
|
|
||||||
packages=["project"],
|
|
||||||
|
|
||||||
setup_requires=[
|
|
||||||
"flake8"
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
|
# flake8 documentation build configuration file, created by
|
||||||
|
# sphinx-quickstart on Tue Jan 19 07:14:10 2016.
|
||||||
|
#
|
||||||
# This file is execfile()d with the current directory set to its
|
# This file is execfile()d with the current directory set to its
|
||||||
# containing dir.
|
# containing dir.
|
||||||
#
|
#
|
||||||
|
|
@ -12,29 +15,35 @@
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
# This environment variable makes decorators not decorate functions, so their
|
|
||||||
# signatures in the generated documentation are still correct
|
|
||||||
os.environ['GENERATING_DOCUMENTATION'] = "flake8"
|
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
sys.path.insert(0, os.path.abspath('..'))
|
#sys.path.insert(0, os.path.abspath('.'))
|
||||||
import flake8
|
|
||||||
|
|
||||||
# -- General configuration ----------------------------------------------------
|
# -- General configuration ------------------------------------------------
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
#needs_sphinx = '1.0'
|
needs_sphinx = '1.3'
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
extensions = ['sphinx.ext.autodoc']
|
# ones.
|
||||||
|
extensions = [
|
||||||
|
'sphinx.ext.autodoc',
|
||||||
|
'sphinx.ext.doctest',
|
||||||
|
'sphinx.ext.intersphinx',
|
||||||
|
'sphinx.ext.todo',
|
||||||
|
'sphinx.ext.coverage',
|
||||||
|
'sphinx.ext.viewcode',
|
||||||
|
'sphinx-prompt',
|
||||||
|
]
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
templates_path = ['_templates']
|
templates_path = ['_templates']
|
||||||
|
|
||||||
# The suffix of source filenames.
|
# The suffix(es) of source filenames.
|
||||||
|
# You can specify multiple suffix as a list of string:
|
||||||
|
# source_suffix = ['.rst', '.md']
|
||||||
source_suffix = '.rst'
|
source_suffix = '.rst'
|
||||||
|
|
||||||
# The encoding of source files.
|
# The encoding of source files.
|
||||||
|
|
@ -45,8 +54,10 @@ master_doc = 'index'
|
||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u'flake8'
|
project = u'flake8'
|
||||||
copyright = u'2012-2013 - Tarek Ziade, Ian Cordasco, Florent Xicluna'
|
copyright = u'2016, Ian Cordasco'
|
||||||
|
author = u'Ian Cordasco'
|
||||||
|
|
||||||
|
import flake8
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
# |version| and |release|, also used in various other places throughout the
|
# |version| and |release|, also used in various other places throughout the
|
||||||
# built documents.
|
# built documents.
|
||||||
|
|
@ -54,11 +65,18 @@ copyright = u'2012-2013 - Tarek Ziade, Ian Cordasco, Florent Xicluna'
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = flake8.__version__
|
version = flake8.__version__
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = version
|
release = flake8.__version__
|
||||||
|
|
||||||
|
rst_epilog = """
|
||||||
|
.. |Flake8| replace:: :program:`Flake8`
|
||||||
|
"""
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
#language = None
|
#
|
||||||
|
# This is also used if you do content translation via gettext catalogs.
|
||||||
|
# Usually you set "language" from the command line for these cases.
|
||||||
|
language = None
|
||||||
|
|
||||||
# There are two options for replacing |today|: either, you set today to some
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
# non-false value, then it is used:
|
# non-false value, then it is used:
|
||||||
|
|
@ -68,10 +86,10 @@ release = version
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
# List of patterns, relative to source directory, that match files and
|
||||||
# directories to ignore when looking for source files.
|
# directories to ignore when looking for source files.
|
||||||
exclude_patterns = ['_build']
|
exclude_patterns = []
|
||||||
|
|
||||||
# The reST default role (used for this markup: `text`) to use for
|
# The reST default role (used for this markup: `text`) to use for all
|
||||||
# all documents.
|
# documents.
|
||||||
#default_role = None
|
#default_role = None
|
||||||
|
|
||||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
|
|
@ -86,17 +104,23 @@ exclude_patterns = ['_build']
|
||||||
#show_authors = False
|
#show_authors = False
|
||||||
|
|
||||||
# The name of the Pygments (syntax highlighting) style to use.
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
# pygments_style = 'flask_theme_support.FlaskyStyle'
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
# A list of ignored prefixes for module index sorting.
|
# A list of ignored prefixes for module index sorting.
|
||||||
#modindex_common_prefix = []
|
#modindex_common_prefix = []
|
||||||
|
|
||||||
|
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||||
|
#keep_warnings = False
|
||||||
|
|
||||||
# -- Options for HTML output --------------------------------------------------
|
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||||
|
todo_include_todos = True
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output ----------------------------------------------
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
# a list of builtin themes.
|
# a list of builtin themes.
|
||||||
#html_theme = 'nature'
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
# further. For a list of options available for each theme, see the
|
# further. For a list of options available for each theme, see the
|
||||||
|
|
@ -125,7 +149,12 @@ exclude_patterns = ['_build']
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
#html_static_path = ['_static']
|
# html_static_path = ['_static']
|
||||||
|
|
||||||
|
# Add any extra paths that contain custom files (such as robots.txt or
|
||||||
|
# .htaccess) here, relative to this directory. These files are copied
|
||||||
|
# directly to the root of the documentation.
|
||||||
|
#html_extra_path = []
|
||||||
|
|
||||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||||
# using the given strftime format.
|
# using the given strftime format.
|
||||||
|
|
@ -152,10 +181,10 @@ exclude_patterns = ['_build']
|
||||||
#html_split_index = False
|
#html_split_index = False
|
||||||
|
|
||||||
# If true, links to the reST sources are added to the pages.
|
# If true, links to the reST sources are added to the pages.
|
||||||
#html_show_sourcelink = False
|
#html_show_sourcelink = True
|
||||||
|
|
||||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||||
#html_show_sphinx = False
|
#html_show_sphinx = True
|
||||||
|
|
||||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||||
#html_show_copyright = True
|
#html_show_copyright = True
|
||||||
|
|
@ -168,24 +197,45 @@ exclude_patterns = ['_build']
|
||||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||||
#html_file_suffix = None
|
#html_file_suffix = None
|
||||||
|
|
||||||
|
# Language to be used for generating the HTML full-text search index.
|
||||||
|
# Sphinx supports the following languages:
|
||||||
|
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
|
||||||
|
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
|
||||||
|
#html_search_language = 'en'
|
||||||
|
|
||||||
|
# A dictionary with options for the search language support, empty by default.
|
||||||
|
# Now only 'ja' uses this config value
|
||||||
|
#html_search_options = {'type': 'default'}
|
||||||
|
|
||||||
|
# The name of a javascript file (relative to the configuration directory) that
|
||||||
|
# implements a search results scorer. If empty, the default will be used.
|
||||||
|
#html_search_scorer = 'scorer.js'
|
||||||
|
|
||||||
# Output file base name for HTML help builder.
|
# Output file base name for HTML help builder.
|
||||||
htmlhelp_basename = 'flake8_doc'
|
htmlhelp_basename = 'flake8doc'
|
||||||
|
|
||||||
|
# -- Options for LaTeX output ---------------------------------------------
|
||||||
|
|
||||||
# -- Options for LaTeX output -------------------------------------------------
|
latex_elements = {
|
||||||
|
# The paper size ('letterpaper' or 'a4paper').
|
||||||
# The paper size ('letter' or 'a4').
|
#'papersize': 'letterpaper',
|
||||||
#latex_paper_size = 'letter'
|
|
||||||
|
|
||||||
# The font size ('10pt', '11pt' or '12pt').
|
# The font size ('10pt', '11pt' or '12pt').
|
||||||
#latex_font_size = '10pt'
|
#'pointsize': '10pt',
|
||||||
|
|
||||||
|
# Additional stuff for the LaTeX preamble.
|
||||||
|
#'preamble': '',
|
||||||
|
|
||||||
|
# Latex figure (float) alignment
|
||||||
|
#'figure_align': 'htbp',
|
||||||
|
}
|
||||||
|
|
||||||
# Grouping the document tree into LaTeX files. List of tuples
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
# (source start file, target name, title,
|
# (source start file, target name, title,
|
||||||
# author, documentclass [howto/manual]).
|
# author, documentclass [howto, manual, or own class]).
|
||||||
latex_documents = [
|
latex_documents = [
|
||||||
('index', 'flake8.tex', u'flake8 Documentation',
|
(master_doc, 'flake8.tex', u'flake8 Documentation',
|
||||||
u'Tarek Ziade', 'manual'),
|
u'Ian Cordasco', 'manual'),
|
||||||
]
|
]
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top of
|
# The name of an image file (relative to this directory) to place at the top of
|
||||||
|
|
@ -202,9 +252,6 @@ latex_documents = [
|
||||||
# If true, show URL addresses after external links.
|
# If true, show URL addresses after external links.
|
||||||
#latex_show_urls = False
|
#latex_show_urls = False
|
||||||
|
|
||||||
# Additional stuff for the LaTeX preamble.
|
|
||||||
#latex_preamble = ''
|
|
||||||
|
|
||||||
# Documents to append as an appendix to all manuals.
|
# Documents to append as an appendix to all manuals.
|
||||||
#latex_appendices = []
|
#latex_appendices = []
|
||||||
|
|
||||||
|
|
@ -212,29 +259,42 @@ latex_documents = [
|
||||||
#latex_domain_indices = True
|
#latex_domain_indices = True
|
||||||
|
|
||||||
|
|
||||||
# -- Options for manual page output -------------------------------------------
|
# -- Options for manual page output ---------------------------------------
|
||||||
|
|
||||||
# One entry per manual page. List of tuples
|
# One entry per manual page. List of tuples
|
||||||
# (source start file, name, description, authors, manual section).
|
# (source start file, name, description, authors, manual section).
|
||||||
man_pages = [
|
man_pages = [
|
||||||
('index', 'flake8', u'flake8 Documentation',
|
(master_doc, 'flake8', u'flake8 Documentation',
|
||||||
[u'Tarek Ziade', u'Ian Cordasco', u'Florent Xicluna'], 1)
|
[author], 1)
|
||||||
]
|
]
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
# If true, show URL addresses after external links.
|
||||||
#man_show_urls = False
|
#man_show_urls = False
|
||||||
|
|
||||||
|
|
||||||
# -- Options for Texinfo output -----------------------------------------------
|
# -- Options for Texinfo output -------------------------------------------
|
||||||
|
|
||||||
# Grouping the document tree into Texinfo files. List of tuples
|
# Grouping the document tree into Texinfo files. List of tuples
|
||||||
# (source start file, target name, title, author,
|
# (source start file, target name, title, author,
|
||||||
# dir menu entry, description, category)
|
# dir menu entry, description, category)
|
||||||
texinfo_documents = [
|
texinfo_documents = [
|
||||||
('index', 'flake8', u'flake8 Documentation', u'Tarek Ziade',
|
('index', 'Flake8', u'Flake8 Documentation', u'Tarek Ziade',
|
||||||
'flake8', 'Code checking using pycodestyle, pyflakes and mccabe',
|
'Flake8', 'Code checking using pycodestyle, pyflakes and mccabe',
|
||||||
'Miscellaneous'),
|
'Miscellaneous'),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Documents to append as an appendix to all manuals.
|
# Documents to append as an appendix to all manuals.
|
||||||
texinfo_appendices = []
|
#texinfo_appendices = []
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#texinfo_domain_indices = True
|
||||||
|
|
||||||
|
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||||
|
#texinfo_show_urls = 'footnote'
|
||||||
|
|
||||||
|
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||||
|
#texinfo_no_detailmenu = False
|
||||||
|
|
||||||
|
|
||||||
|
# Example configuration for intersphinx: refer to the Python standard library.
|
||||||
|
intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None)}
|
||||||
56
docs/source/faq.rst
Normal file
56
docs/source/faq.rst
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
============================
|
||||||
|
Frequently Asked Questions
|
||||||
|
============================
|
||||||
|
|
||||||
|
When is Flake8 released?
|
||||||
|
========================
|
||||||
|
|
||||||
|
|Flake8| is released *as necessary*. Sometimes there are specific goals and
|
||||||
|
drives to get to a release. Usually, we release as users report and fix
|
||||||
|
bugs.
|
||||||
|
|
||||||
|
|
||||||
|
How can I help Flake8 release faster?
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
Look at the next milestone. If there's work you can help us complete, that
|
||||||
|
will help us get to the next milestone. If there's a show-stopping bug that
|
||||||
|
needs to be released, let us know but please be kind. |Flake8| is developed
|
||||||
|
and released entirely on volunteer time.
|
||||||
|
|
||||||
|
|
||||||
|
What is the next version of Flake8?
|
||||||
|
===================================
|
||||||
|
|
||||||
|
In general we try to use milestones to indicate this. If the last release
|
||||||
|
on PyPI is 3.1.5 and you see a milestone for 3.2.0 in GitLab, there's a
|
||||||
|
good chance that 3.2.0 is the next release.
|
||||||
|
|
||||||
|
|
||||||
|
Why does Flake8 use ranges for its dependencies?
|
||||||
|
================================================
|
||||||
|
|
||||||
|
|Flake8| uses ranges for mccabe, pyflakes, and pycodestyle because each of
|
||||||
|
those projects tend to add *new* checks in minor releases. It has been an
|
||||||
|
implicit design goal of |Flake8|'s to make the list of error codes stable in
|
||||||
|
its own minor releases. That way if you install something from the 2.5
|
||||||
|
series today, you will not find new checks in the same series in a month
|
||||||
|
from now when you install it again.
|
||||||
|
|
||||||
|
|Flake8|'s dependencies tend to avoid new checks in patch versions which is
|
||||||
|
why |Flake8| expresses its dependencies roughly as::
|
||||||
|
|
||||||
|
pycodestyle >= 2.0.0, < 2.1.0
|
||||||
|
pyflakes >= 0.8.0, != 1.2.0, != 1.2.1, != 1.2.2, < 1.3.0
|
||||||
|
mccabe >= 0.5.0, < 0.6.0
|
||||||
|
|
||||||
|
This allows those projects to release patch versions that fix bugs and for
|
||||||
|
|Flake8| users to consume those fixes.
|
||||||
|
|
||||||
|
|
||||||
|
Should I file an issue when a new version of a dependency is available?
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
**No.** The current Flake8 core team (of one person) is also
|
||||||
|
a core developer of pycodestyle, pyflakes, and mccabe. They are aware of
|
||||||
|
these releases.
|
||||||
56
docs/source/glossary.rst
Normal file
56
docs/source/glossary.rst
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
.. _glossary:
|
||||||
|
|
||||||
|
================================================
|
||||||
|
Glossary of Terms Used in Flake8 Documentation
|
||||||
|
================================================
|
||||||
|
|
||||||
|
.. glossary::
|
||||||
|
:sorted:
|
||||||
|
|
||||||
|
formatter
|
||||||
|
A :term:`plugin` that augments the output of |Flake8| when passed
|
||||||
|
to :option:`flake8 --format`.
|
||||||
|
|
||||||
|
plugin
|
||||||
|
A package that is typically installed from PyPI to augment the
|
||||||
|
behaviour of |Flake8| either through adding one or more additional
|
||||||
|
:term:`check`\ s or providing additional :term:`formatter`\ s.
|
||||||
|
|
||||||
|
check
|
||||||
|
A piece of logic that corresponds to an error code. A check may
|
||||||
|
be a style check (e.g., check the length of a given line against
|
||||||
|
the user configured maximum) or a lint check (e.g., checking for
|
||||||
|
unused imports) or some other check as defined by a plugin.
|
||||||
|
|
||||||
|
error
|
||||||
|
error code
|
||||||
|
The symbol associated with a specific :term:`check`. For example,
|
||||||
|
pycodestyle implements :term:`check`\ s that look for whitespace
|
||||||
|
around binary operators and will either return an error code of
|
||||||
|
``W503`` or ``W504``.
|
||||||
|
|
||||||
|
warning
|
||||||
|
Typically the ``W`` class of :term:`error code`\ s from pycodestyle.
|
||||||
|
|
||||||
|
class
|
||||||
|
error class
|
||||||
|
A larger grouping of related :term:`error code`\ s. For example,
|
||||||
|
``W503`` and ``W504`` are two codes related to whitespace. ``W50``
|
||||||
|
would be the most specific class of codes relating to whitespace.
|
||||||
|
``W`` would be the warning class that subsumes all whitespace
|
||||||
|
errors.
|
||||||
|
|
||||||
|
pyflakes
|
||||||
|
The project |Flake8| depends on to lint files (check for unused
|
||||||
|
imports, variables, etc.). This uses the ``F`` :term:`class` of
|
||||||
|
:term:`error code`\ s reported by |Flake8|.
|
||||||
|
|
||||||
|
pycodestyle
|
||||||
|
The project |Flake8| depends on to provide style enforcement.
|
||||||
|
pycodestyle implements :term:`check`\ s for :pep:`8`. This uses the
|
||||||
|
``E`` and ``W`` :term:`class`\ es of :term:`error code`\ s.
|
||||||
|
|
||||||
|
mccabe
|
||||||
|
The project |Flake8| depends on to calculate the McCabe complexity
|
||||||
|
of a unit of code (e.g., a function). This uses the ``C``
|
||||||
|
:term:`class` of :term`error code`\ s.
|
||||||
131
docs/source/index.rst
Normal file
131
docs/source/index.rst
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
.. flake8 documentation master file, created by
|
||||||
|
sphinx-quickstart on Tue Jan 19 07:14:10 2016.
|
||||||
|
You can adapt this file completely to your liking, but it should at least
|
||||||
|
contain the root `toctree` directive.
|
||||||
|
|
||||||
|
===============================================
|
||||||
|
Flake8: Your Tool For Style Guide Enforcement
|
||||||
|
===============================================
|
||||||
|
|
||||||
|
Quickstart
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. _installation-guide:
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
To install |Flake8|, open an interactive shell and run:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
python<version> -m pip install flake8
|
||||||
|
|
||||||
|
If you want |Flake8| to be installed for your default Python installation, you
|
||||||
|
can instead use:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
python -m pip install flake8
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
It is **very** important to install |Flake8| on the *correct* version of
|
||||||
|
Python for your needs. If you want |Flake8| to properly parse new language
|
||||||
|
features in Python 3.5 (for example), you need it to be installed on 3.5
|
||||||
|
for |Flake8| to understand those features. In many ways, Flake8 is tied to
|
||||||
|
the version of Python on which it runs.
|
||||||
|
|
||||||
|
Using Flake8
|
||||||
|
------------
|
||||||
|
|
||||||
|
To start using |Flake8|, open an interactive shell and run:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
flake8 path/to/code/to/check.py
|
||||||
|
# or
|
||||||
|
flake8 path/to/code/
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If you have installed |Flake8| on a particular version of Python (or on
|
||||||
|
several versions), it may be best to instead run ``python<version> -m
|
||||||
|
flake8``.
|
||||||
|
|
||||||
|
If you only want to see the instances of a specific warning or error, you can
|
||||||
|
*select* that error like so:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
flake8 --select E123,W503 path/to/code/
|
||||||
|
|
||||||
|
Alternatively, if you want to *ignore* only one specific warning or error:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
flake8 --ignore E24,W504 path/to/code/
|
||||||
|
|
||||||
|
Please read our user guide for more information about how to use and configure
|
||||||
|
|Flake8|.
|
||||||
|
|
||||||
|
FAQ and Glossary
|
||||||
|
================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
faq
|
||||||
|
glossary
|
||||||
|
|
||||||
|
User Guide
|
||||||
|
==========
|
||||||
|
|
||||||
|
All users of |Flake8| should read this portion of the documentation. This
|
||||||
|
provides examples and documentation around |Flake8|'s assortment of options
|
||||||
|
and how to specify them on the command-line or in configuration files.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
user/index
|
||||||
|
|
||||||
|
Plugin Developer Guide
|
||||||
|
======================
|
||||||
|
|
||||||
|
If you're maintaining a plugin for |Flake8| or creating a new one, you should
|
||||||
|
read this section of the documentation. It explains how you can write your
|
||||||
|
plugins and distribute them to others.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
plugin-development/index
|
||||||
|
|
||||||
|
Contributor Guide
|
||||||
|
=================
|
||||||
|
|
||||||
|
If you are reading |Flake8|'s source code for fun or looking to contribute,
|
||||||
|
you should read this portion of the documentation. This is a mix of documenting
|
||||||
|
the internal-only interfaces |Flake8| and documenting reasoning for Flake8's
|
||||||
|
design.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
internal/index
|
||||||
|
|
||||||
|
Release Notes and History
|
||||||
|
=========================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
release-notes/index
|
||||||
|
|
||||||
|
General Indices
|
||||||
|
===============
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`Index of Documented Public Modules <modindex>`
|
||||||
|
* :ref:`Glossary of terms <glossary>`
|
||||||
0
docs/source/internal/.keep
Normal file
0
docs/source/internal/.keep
Normal file
70
docs/source/internal/checker.rst
Normal file
70
docs/source/internal/checker.rst
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
====================
|
||||||
|
How Checks are Run
|
||||||
|
====================
|
||||||
|
|
||||||
|
In |Flake8| 2.x, |Flake8| delegated check running to pep8. In 3.0 |Flake8|
|
||||||
|
takes on that responsibility. This has allowed for simpler
|
||||||
|
handling of the ``--jobs`` parameter (using :mod:`multiprocessing`) and
|
||||||
|
simplified our fallback if something goes awry with concurency.
|
||||||
|
At the lowest level we have a |FileChecker|. Instances of |FileChecker| are
|
||||||
|
created for *each* file to be analyzed by |Flake8|. Each instance, has a copy
|
||||||
|
of all of the plugins registered with setuptools in the ``flake8.extension``
|
||||||
|
entry-point group.
|
||||||
|
|
||||||
|
The |FileChecker| instances are managed by an instance of |Manager|. The
|
||||||
|
|Manager| instance handles creating sub-processes with
|
||||||
|
:mod:`multiprocessing` module and falling back to running checks in serial if
|
||||||
|
an operating system level error arises. When creating |FileChecker| instances,
|
||||||
|
the |Manager| is responsible for determining if a particular file has been
|
||||||
|
excluded.
|
||||||
|
|
||||||
|
|
||||||
|
Processing Files
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Unfortunately, since |Flake8| took over check running from pep8/pycodestyle,
|
||||||
|
it also had to take over parsing and processing files for the checkers
|
||||||
|
to use. Since it couldn't reuse pycodestyle's functionality (since it did not
|
||||||
|
separate cleanly the processing from check running) that function was isolated
|
||||||
|
into the :class:`~flake8.processor.FileProcessor` class. We moved
|
||||||
|
several helper functions into the :mod:`flake8.processor` module (see also
|
||||||
|
:ref:`Processor Utility Functions <processor_utility_functions>`).
|
||||||
|
|
||||||
|
|
||||||
|
API Reference
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. autoclass:: flake8.checker.FileChecker
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: flake8.checker.Manager
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: flake8.processor.FileProcessor
|
||||||
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
.. _processor_utility_functions:
|
||||||
|
|
||||||
|
Utility Functions
|
||||||
|
`````````````````
|
||||||
|
|
||||||
|
.. autofunction:: flake8.processor.count_parentheses
|
||||||
|
|
||||||
|
.. autofunction:: flake8.processor.expand_indent
|
||||||
|
|
||||||
|
.. autofunction:: flake8.processor.is_eol_token
|
||||||
|
|
||||||
|
.. autofunction:: flake8.processor.is_multiline_string
|
||||||
|
|
||||||
|
.. autofunction:: flake8.processor.log_token
|
||||||
|
|
||||||
|
.. autofunction:: flake8.processor.mutate_string
|
||||||
|
|
||||||
|
.. autofunction:: flake8.processor.token_is_comment
|
||||||
|
|
||||||
|
.. autofunction:: flake8.processor.token_is_newline
|
||||||
|
|
||||||
|
.. Substitutions
|
||||||
|
.. |FileChecker| replace:: :class:`~flake8.checker.FileChecker`
|
||||||
|
.. |Manager| replace:: :class:`~flake8.checker.Manager`
|
||||||
26
docs/source/internal/cli.rst
Normal file
26
docs/source/internal/cli.rst
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
Command Line Interface
|
||||||
|
======================
|
||||||
|
|
||||||
|
The command line interface of |Flake8| is modeled as an application via
|
||||||
|
:class:`~flake8.main.cli.Application`. When a user runs ``flake8`` at their
|
||||||
|
command line, :func:`~flake8.main.cli.main` is run which handles
|
||||||
|
management of the application.
|
||||||
|
|
||||||
|
User input is parsed *twice* to accomodate logging and verbosity options
|
||||||
|
passed by the user as early as possible.
|
||||||
|
This is so as much logging can be produced as possible.
|
||||||
|
|
||||||
|
The default |Flake8| options are registered by
|
||||||
|
:func:`~flake8.main.options.register_default_options`. Trying to register
|
||||||
|
these options in plugins will result in errors.
|
||||||
|
|
||||||
|
|
||||||
|
API Documentation
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
.. autofunction:: flake8.main.cli.main
|
||||||
|
|
||||||
|
.. autoclass:: flake8.main.application.Application
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autofunction:: flake8.main.options.register_default_options
|
||||||
202
docs/source/internal/contributing.rst
Normal file
202
docs/source/internal/contributing.rst
Normal file
|
|
@ -0,0 +1,202 @@
|
||||||
|
========================
|
||||||
|
Contributing to Flake8
|
||||||
|
========================
|
||||||
|
|
||||||
|
There are many ways to contriubte to |Flake8|, and we encourage them all:
|
||||||
|
|
||||||
|
- contributing bug reports and feature requests
|
||||||
|
|
||||||
|
- contributing documenation (and yes that includes this document)
|
||||||
|
|
||||||
|
- reviewing and triaging bugs and merge requests
|
||||||
|
|
||||||
|
Before you go any further, please allow me to reassure you that I do want
|
||||||
|
*your* contribution. If you think your contribution might not be valuable, I
|
||||||
|
reassure you that any help you can provide *is* valuable.
|
||||||
|
|
||||||
|
|
||||||
|
Code of Conduct
|
||||||
|
===============
|
||||||
|
|
||||||
|
|Flake8| adheres to the `Python Code Quality Authority's Code of Conduct`_.
|
||||||
|
Any violations of the Code of Conduct should be reported to Ian Cordasco
|
||||||
|
(graffatcolmingov [at] gmail [dot] com).
|
||||||
|
|
||||||
|
|
||||||
|
Setting Up A Development Environment
|
||||||
|
====================================
|
||||||
|
|
||||||
|
To contribute to |Flake8|'s development, you simply need:
|
||||||
|
|
||||||
|
- Python (one of the versions we support)
|
||||||
|
|
||||||
|
- `tox`_
|
||||||
|
|
||||||
|
We suggest installing this like:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
pip install --user tox
|
||||||
|
|
||||||
|
Or
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
python<version> -m pip install --user tox
|
||||||
|
|
||||||
|
- your favorite editor
|
||||||
|
|
||||||
|
|
||||||
|
Filing a Bug
|
||||||
|
============
|
||||||
|
|
||||||
|
When filing a bug against |Flake8|, please fill out the issue template as it
|
||||||
|
is provided to you by `GitLab`_. If your bug is in reference to one of the
|
||||||
|
checks that |Flake8| reports by default, please do not report them to |Flake8|
|
||||||
|
unless |Flake8| is doing something to prevent the check from running or you
|
||||||
|
have some reason to believe |Flake8| is inhibiting the effectiveness of the
|
||||||
|
check.
|
||||||
|
|
||||||
|
**Please search for closed and open bug reports before opening new ones.**
|
||||||
|
|
||||||
|
All bug reports about checks should go to their respective projects:
|
||||||
|
|
||||||
|
- Error codes starting with ``E`` and ``W`` should be reported to
|
||||||
|
`pycodestyle`_.
|
||||||
|
|
||||||
|
- Error codes starting with ``F`` should be reported to `pyflakes`_
|
||||||
|
|
||||||
|
- Error codes starting with ``C`` should be reported to `mccabe`_
|
||||||
|
|
||||||
|
|
||||||
|
Requesting a New Feature
|
||||||
|
========================
|
||||||
|
|
||||||
|
When requesting a new feature in |Flake8|, please fill out the issue template.
|
||||||
|
Please also note if there are any existing alternatives to your new feature
|
||||||
|
either via plugins, or combining command-line options. Please provide example
|
||||||
|
use cases. For example, do not ask for a feature like this:
|
||||||
|
|
||||||
|
I need feature frobulate for my job.
|
||||||
|
|
||||||
|
Instead ask:
|
||||||
|
|
||||||
|
I need |Flake8| to frobulate these files because my team expects them to
|
||||||
|
frobulated but |Flake8| currently does not frobulate them. We tried using
|
||||||
|
``--filename`` but we could not create a pattern that worked.
|
||||||
|
|
||||||
|
The more you explain about *why* you need a feature, the more likely we are to
|
||||||
|
understand your needs and help you to the best of our ability.
|
||||||
|
|
||||||
|
|
||||||
|
Contributing Documentation
|
||||||
|
==========================
|
||||||
|
|
||||||
|
To contribute to |Flake8|'s documentation, you might want to first read a
|
||||||
|
little about reStructuredText or Sphinx. |Flake8| has a :ref:`guide of best
|
||||||
|
practices <docs-style>` when contributing to our documentation. For the most
|
||||||
|
part, you should be fine following the structure and style of the rest of
|
||||||
|
|Flake8|'s documentation.
|
||||||
|
|
||||||
|
All of |Flake8|'s documentation is written in reStructuredText and rendered by
|
||||||
|
Sphinx. The source (reStructuredText) lives in ``docs/source/``. To build
|
||||||
|
the documentation the way our Continuous Integration does, run:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
tox -e docs
|
||||||
|
|
||||||
|
To view the documentation locally, you can also run:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
tox -e serve-docs
|
||||||
|
|
||||||
|
You can run the latter in a separate terminal and continuously re-run the
|
||||||
|
documentation generation and refresh the documentation you're working on.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
We lint our documentation just like we lint our code.
|
||||||
|
You should also run:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
tox -e linters
|
||||||
|
|
||||||
|
After making changes and before pushing them to ensure that they will
|
||||||
|
pass our CI tests.
|
||||||
|
|
||||||
|
|
||||||
|
Contributing Code
|
||||||
|
=================
|
||||||
|
|
||||||
|
|Flake8| development happens on `GitLab`_. Code contributions should be
|
||||||
|
submitted there.
|
||||||
|
|
||||||
|
Merge requests should:
|
||||||
|
|
||||||
|
- Fix one issue and fix it well
|
||||||
|
|
||||||
|
Fix the issue, but do not include extraneous refactoring or code
|
||||||
|
reformatting. In other words, keep the diff short, but only as short
|
||||||
|
as is necessary to fix the bug appropriately and add sufficient testing
|
||||||
|
around it. Long diffs are fine, so long as everything that it includes
|
||||||
|
is necessary to the purpose of the merge request.
|
||||||
|
|
||||||
|
- Have descriptive titles and descriptions
|
||||||
|
|
||||||
|
Searching old merge requests is made easier when a merge request is well
|
||||||
|
described.
|
||||||
|
|
||||||
|
- Have commits that follow this style:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
Create a short title that is 50 characters long
|
||||||
|
|
||||||
|
Ensure the title and commit message use the imperative voice. The
|
||||||
|
commit and you are doing something. Also, please ensure that the
|
||||||
|
body of the commit message does not exceed 72 characters.
|
||||||
|
|
||||||
|
The body may have multiple paragraphs as necessary.
|
||||||
|
|
||||||
|
The final line of the body references the issue appropriately.
|
||||||
|
|
||||||
|
|
||||||
|
Reviewing and Triaging Issues and Merge Requests
|
||||||
|
================================================
|
||||||
|
|
||||||
|
When reviewing other people's merge requests and issues, please be
|
||||||
|
**especially** mindful of how the words you choose can be read by someone
|
||||||
|
else. We strive for professional code reviews that do not insult the
|
||||||
|
contributor's intelligence or impugn their character. The code review
|
||||||
|
should be focused on the code, it's effectiveness, and whether it is
|
||||||
|
appropriate for |Flake8|.
|
||||||
|
|
||||||
|
If you have the ability to edit an issue or merge request's labels, please do
|
||||||
|
so to make search and prioritization easier.
|
||||||
|
|
||||||
|
|Flake8| uses milestones with both issues and merge requests. This provides
|
||||||
|
direction for other contributors about when an issue or merge request will be
|
||||||
|
delivered.
|
||||||
|
|
||||||
|
|
||||||
|
.. links
|
||||||
|
.. _Python Code Quality Authority's Code of Conduct:
|
||||||
|
http://meta.pycqa.org/en/latest/code-of-conduct.html
|
||||||
|
|
||||||
|
.. _tox:
|
||||||
|
https://tox.readthedocs.io/
|
||||||
|
|
||||||
|
.. _GitLab:
|
||||||
|
https://gitlab.com/pycqa/flake8
|
||||||
|
|
||||||
|
.. _pycodestyle:
|
||||||
|
https://github.com/pycqa/pycodestyle
|
||||||
|
|
||||||
|
.. _pyflakes:
|
||||||
|
https://github.com/pyflakes/pyflakes
|
||||||
|
|
||||||
|
.. _mccabe:
|
||||||
|
https://github.com/pycqa/mccabe
|
||||||
47
docs/source/internal/formatters.rst
Normal file
47
docs/source/internal/formatters.rst
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
=====================
|
||||||
|
Built-in Formatters
|
||||||
|
=====================
|
||||||
|
|
||||||
|
By default |Flake8| has two formatters built-in, ``default`` and ``pylint``.
|
||||||
|
These correspond to two classes |DefaultFormatter| and |PylintFormatter|.
|
||||||
|
|
||||||
|
In |Flake8| 2.0, pep8 handled formatting of errors and also allowed users to
|
||||||
|
specify an arbitrary format string as a parameter to ``--format``. In order
|
||||||
|
to allow for this backwards compatibility, |Flake8| 3.0 made two choices:
|
||||||
|
|
||||||
|
#. To not limit a user's choices for ``--format`` to the format class names
|
||||||
|
|
||||||
|
#. To make the default formatter attempt to use the string provided by the
|
||||||
|
user if it cannot find a formatter with that name.
|
||||||
|
|
||||||
|
Default Formatter
|
||||||
|
=================
|
||||||
|
|
||||||
|
The |DefaultFormatter| continues to use the same default format string as
|
||||||
|
pep8: ``'%(path)s:%(row)d:%(col)d: %(code)s %(text)s'``.
|
||||||
|
|
||||||
|
To provide the default functionality it overrides two methods:
|
||||||
|
|
||||||
|
#. ``after_init``
|
||||||
|
|
||||||
|
#. ``format``
|
||||||
|
|
||||||
|
The former allows us to inspect the value provided to ``--format`` by the
|
||||||
|
user and alter our own format based on that value. The second simply uses
|
||||||
|
that format string to format the error.
|
||||||
|
|
||||||
|
.. autoclass:: flake8.formatting.default.Default
|
||||||
|
:members:
|
||||||
|
|
||||||
|
Pylint Formatter
|
||||||
|
================
|
||||||
|
|
||||||
|
The |PylintFormatter| simply defines the default Pylint format string from
|
||||||
|
pep8: ``'%(path)s:%(row)d: [%(code)s] %(text)s'``.
|
||||||
|
|
||||||
|
.. autoclass:: flake8.formatting.default.Pylint
|
||||||
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
.. |DefaultFormatter| replace:: :class:`~flake8.formatting.default.Default`
|
||||||
|
.. |PylintFormatter| replace:: :class:`~flake8.formatting.default.Pylint`
|
||||||
26
docs/source/internal/index.rst
Normal file
26
docs/source/internal/index.rst
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
==============================
|
||||||
|
Exploring Flake8's Internals
|
||||||
|
==============================
|
||||||
|
|
||||||
|
While writing |Flake8| 3.0, the developers attempted to capture some reasoning
|
||||||
|
and decision information in internal documentation meant for future developers
|
||||||
|
and maintaners. Most of this information is unnecessary for users and plugin
|
||||||
|
developers. Some of it, however, is linked to from the plugin development
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
Keep in mind that not everything will be here and you may need to help pull
|
||||||
|
information out of the developers' heads and into these documents. Please
|
||||||
|
pull gently.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
contributing
|
||||||
|
writing-documentation
|
||||||
|
releases
|
||||||
|
checker
|
||||||
|
cli
|
||||||
|
formatters
|
||||||
|
option_handling
|
||||||
|
plugin_handling
|
||||||
|
utils
|
||||||
234
docs/source/internal/option_handling.rst
Normal file
234
docs/source/internal/option_handling.rst
Normal file
|
|
@ -0,0 +1,234 @@
|
||||||
|
Option and Configuration Handling
|
||||||
|
=================================
|
||||||
|
|
||||||
|
Option Management
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Command-line options are often also set in configuration files for |Flake8|.
|
||||||
|
While not all options are meant to be parsed from configuration files, many
|
||||||
|
default options are also parsed from configuration files as well as
|
||||||
|
most plugin options.
|
||||||
|
|
||||||
|
In |Flake8| 2, plugins received a :class:`optparse.OptionParser` instance and
|
||||||
|
called :meth:`optparse.OptionParser.add_option` to register options. If the
|
||||||
|
plugin author also wanted to have that option parsed from config files they
|
||||||
|
also had to do something like:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
parser.config_options.append('my_config_option')
|
||||||
|
parser.config_options.extend(['config_opt1', 'config_opt2'])
|
||||||
|
|
||||||
|
This was previously undocumented and led to a lot of confusion about why
|
||||||
|
registered options were not automatically parsed from configuration files.
|
||||||
|
|
||||||
|
Since |Flake8| 3 was rewritten from scratch, we decided to take a different
|
||||||
|
approach to configuration file parsing. Instead of needing to know about an
|
||||||
|
undocumented attribute that pep8 looks for, |Flake8| 3 now accepts a parameter
|
||||||
|
to ``add_option``, specifically ``parse_from_config`` which is a boolean
|
||||||
|
value.
|
||||||
|
|
||||||
|
|Flake8| does this by creating its own abstractions on top of :mod:`optparse`.
|
||||||
|
The first abstraction is the :class:`flake8.options.manager.Option` class. The
|
||||||
|
second is the :class:`flake8.options.manager.OptionManager`. In fact, we add
|
||||||
|
three new parameters:
|
||||||
|
|
||||||
|
- ``parse_from_config``
|
||||||
|
|
||||||
|
- ``comma_separated_list``
|
||||||
|
|
||||||
|
- ``normalize_paths``
|
||||||
|
|
||||||
|
The last two are not specifically for configuration file handling, but they
|
||||||
|
do improve that dramatically. We found that there were options that, when
|
||||||
|
specified in a configuration file, often necessitated being spit
|
||||||
|
multiple lines and those options were almost always comma-separated. For
|
||||||
|
example, let's consider a user's list of ignored error codes for a project:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
ignore =
|
||||||
|
# Reasoning
|
||||||
|
E111,
|
||||||
|
# Reasoning
|
||||||
|
E711,
|
||||||
|
# Reasoning
|
||||||
|
E712,
|
||||||
|
# Reasoning
|
||||||
|
E121,
|
||||||
|
# Reasoning
|
||||||
|
E122,
|
||||||
|
# Reasoning
|
||||||
|
E123,
|
||||||
|
# Reasoning
|
||||||
|
E131,
|
||||||
|
# Reasoning
|
||||||
|
E251
|
||||||
|
|
||||||
|
It makes sense here to allow users to specify the value this way, but, the
|
||||||
|
standard libary's :class:`configparser.RawConfigParser` class does returns a
|
||||||
|
string that looks like
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
"\nE111, \nE711, \nE712, \nE121, \nE122, \nE123, \nE131, \nE251 "
|
||||||
|
|
||||||
|
This means that a typical call to :meth:`str.split` with ``','`` will not be
|
||||||
|
sufficient here. Telling |Flake8| that something is a comma-separated list
|
||||||
|
(e.g., ``comma_separated_list=True``) will handle this for you. |Flake8| will
|
||||||
|
return:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
["E111", "E711", "E712", "E121", "E122", "E123", "E131", "E251"]
|
||||||
|
|
||||||
|
Next let's look at how users might like to specify their ``exclude`` list.
|
||||||
|
Presently OpenStack's Nova project has this line in their `tox.ini`_:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
exclude = .venv,.git,.tox,dist,doc,*openstack/common/*,*lib/python*,*egg,build,tools/xenserver*,releasenotes
|
||||||
|
|
||||||
|
We think we can all agree that this would be easier to read like this:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
exclude =
|
||||||
|
.venv,
|
||||||
|
.git,
|
||||||
|
.tox,
|
||||||
|
dist,
|
||||||
|
doc,
|
||||||
|
*openstack/common/*,
|
||||||
|
*lib/python*,
|
||||||
|
*egg,
|
||||||
|
build,
|
||||||
|
tools/xenserver*,
|
||||||
|
releasenotes
|
||||||
|
|
||||||
|
In this case, since these are actually intended to be paths, we would specify
|
||||||
|
both ``comma_separated_list=True`` and ``normalize_paths=True`` because we
|
||||||
|
want the paths to be provided to us with some consistency (either all absolute
|
||||||
|
paths or not).
|
||||||
|
|
||||||
|
Now let's look at how this will actually be used. Most plugin developers
|
||||||
|
will receive an instance of :class:`~flake8.options.manager.OptionManager` so
|
||||||
|
to ease the transition we kept the same API as the
|
||||||
|
:class:`optparse.OptionParser` object. The only difference is that
|
||||||
|
:meth:`~flake8.options.manager.OptionManager.add_option` accepts the three
|
||||||
|
extra arguments we highlighted above.
|
||||||
|
|
||||||
|
.. _tox.ini:
|
||||||
|
https://github.com/openstack/nova/blob/3eb190c4cfc0eefddac6c2cc1b94a699fb1687f8/tox.ini#L155
|
||||||
|
|
||||||
|
Configuration File Management
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
In |Flake8| 2, configuration file discovery and management was handled by
|
||||||
|
pep8. In pep8's 1.6 release series, it drastically broke how discovery and
|
||||||
|
merging worked (as a result of trying to improve it). To avoid a dependency
|
||||||
|
breaking |Flake8| again in the future, we have created our own discovery and
|
||||||
|
management.
|
||||||
|
As part of managing this ourselves, we decided to change management/discovery
|
||||||
|
for 3.0.0. We have done the following:
|
||||||
|
|
||||||
|
- User files (files stored in a user's home directory or in the XDG directory
|
||||||
|
inside their home directory) are the first files read. For example, if the
|
||||||
|
user has a ``~/.flake8`` file, we will read that first.
|
||||||
|
|
||||||
|
- Project files (files stored in the current directory) are read next and
|
||||||
|
merged on top of the user file. In other words, configuration in project
|
||||||
|
files takes precedence over configuration in user files.
|
||||||
|
|
||||||
|
- **New in 3.0.0** The user can specify ``--append-config <path-to-file>``
|
||||||
|
repeatedly to include extra configuration files that should be read and
|
||||||
|
take precedence over user and project files.
|
||||||
|
|
||||||
|
- **New in 3.0.0** The user can specify ``--config <path-to-file>`` to so this
|
||||||
|
file is the only configuration file used. This is a change from |Flake8| 2
|
||||||
|
where pep8 would simply merge this configuration file into the configuration
|
||||||
|
generated by user and project files (where this takes precedence).
|
||||||
|
|
||||||
|
- **New in 3.0.0** The user can specify ``--isolated`` to disable
|
||||||
|
configuration via discovered configuration files.
|
||||||
|
|
||||||
|
To facilitate the configuration file management, we've taken a different
|
||||||
|
approach to discovery and management of files than pep8. In pep8 1.5, 1.6, and
|
||||||
|
1.7 configuration discovery and management was centralized in `66 lines of
|
||||||
|
very terse python`_ which was confusing and not very explicit. The terseness
|
||||||
|
of this function (|Flake8|'s authors believe) caused the confusion and
|
||||||
|
problems with pep8's 1.6 series. As such, |Flake8| has separated out
|
||||||
|
discovery, management, and merging into a module to make reasoning about each
|
||||||
|
of these pieces easier and more explicit (as well as easier to test).
|
||||||
|
|
||||||
|
Configuration file discovery is managed by the
|
||||||
|
:class:`~flake8.options.config.ConfigFileFinder` object. This object needs to
|
||||||
|
know information about the program's name, any extra arguments passed to it,
|
||||||
|
and any configuration files that should be appended to the list of discovered
|
||||||
|
files. It provides methods for finding the files and similiar methods for
|
||||||
|
parsing those fles. For example, it provides
|
||||||
|
:meth:`~flake8.options.config.ConfigFileFinder.local_config_files` to find
|
||||||
|
known local config files (and append the extra configuration files) and it
|
||||||
|
also provides :meth:`~flake8.options.config.ConfigFileFinder.local_configs`
|
||||||
|
to parse those configuration files.
|
||||||
|
|
||||||
|
.. note:: ``local_config_files`` also filters out non-existent files.
|
||||||
|
|
||||||
|
Configuration file merging and managemnt is controlled by the
|
||||||
|
:class:`~flake8.options.config.MergedConfigParser`. This requires the instance
|
||||||
|
of :class:`~flake8.options.manager.OptionManager` that the program is using,
|
||||||
|
the list of appended config files, and the list of extra arguments. This
|
||||||
|
object is currently the sole user of the
|
||||||
|
:class:`~flake8.options.config.ConfigFileFinder` object. It appropriately
|
||||||
|
initializes the object and uses it in each of
|
||||||
|
|
||||||
|
- :meth:`~flake8.options.config.MergedConfigParser.parse_cli_config`
|
||||||
|
- :meth:`~flake8.options.config.MergedConfigParser.parse_local_config`
|
||||||
|
- :meth:`~flake8.options.config.MergedConfigParser.parse_user_config`
|
||||||
|
|
||||||
|
Finally,
|
||||||
|
:meth:`~flake8.options.config.MergedConfigParser.merge_user_and_local_config`
|
||||||
|
takes the user and local configuration files that are parsed by
|
||||||
|
:meth:`~flake8.options.config.MergedConfigParser.parse_local_config` and
|
||||||
|
:meth:`~flake8.options.config.MergedConfigParser.parse_user_config`. The
|
||||||
|
main usage of the ``MergedConfigParser`` is in
|
||||||
|
:func:`~flake8.options.aggregator.aggregate_options`.
|
||||||
|
|
||||||
|
Aggregating Configuration File and Command Line Arguments
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
:func:`~flake8.options.aggregator.aggregate_options` accepts an instance of
|
||||||
|
:class:`~flake8.options.maanger.OptionManager` and does the work to parse the
|
||||||
|
command-line arguments passed by the user necessary for creating an instance
|
||||||
|
of :class:`~flake8.options.config.MergedConfigParser`.
|
||||||
|
|
||||||
|
After parsing the configuration file, we determine the default ignore list. We
|
||||||
|
use the defaults from the OptionManager and update those with the parsed
|
||||||
|
configuration files. Finally we parse the user-provided options one last time
|
||||||
|
using the option defaults and configuration file values as defaults. The
|
||||||
|
parser merges on the command-line specified arguments for us so we have our
|
||||||
|
final, definitive, aggregated options.
|
||||||
|
|
||||||
|
.. _66 lines of very terse python:
|
||||||
|
https://github.com/PyCQA/pep8/blob/b8088a2b6bc5b76bece174efad877f764529bc74/pep8.py#L1981..L2047
|
||||||
|
|
||||||
|
API Documentation
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
.. autofunction:: flake8.options.aggregator.aggregate_options
|
||||||
|
|
||||||
|
.. autoclass:: flake8.options.manager.Option
|
||||||
|
:members: __init__, normalize, to_optparse
|
||||||
|
|
||||||
|
.. autoclass:: flake8.options.manager.OptionManager
|
||||||
|
:members:
|
||||||
|
:special-members:
|
||||||
|
|
||||||
|
.. autoclass:: flake8.options.config.ConfigFileFinder
|
||||||
|
:members:
|
||||||
|
:special-members:
|
||||||
|
|
||||||
|
.. autoclass:: flake8.options.config.MergedConfigParser
|
||||||
|
:members:
|
||||||
|
:special-members:
|
||||||
129
docs/source/internal/plugin_handling.rst
Normal file
129
docs/source/internal/plugin_handling.rst
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
Plugin Handling
|
||||||
|
===============
|
||||||
|
|
||||||
|
Plugin Management
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
|Flake8| 3.0 added support for two other plugins besides those which define
|
||||||
|
new checks. It now supports:
|
||||||
|
|
||||||
|
- extra checks
|
||||||
|
|
||||||
|
- alternative report formatters
|
||||||
|
|
||||||
|
- listeners to auto-correct violations of checks
|
||||||
|
|
||||||
|
To facilitate this, |Flake8| needed a more mature way of managing plugins.
|
||||||
|
Thus, we developed the |PluginManager| which accepts a namespace and will load
|
||||||
|
the plugins for that namespace. A |PluginManager| creates and manages many
|
||||||
|
|Plugin| instances.
|
||||||
|
|
||||||
|
A |Plugin| lazily loads the underlying entry-point provided by setuptools.
|
||||||
|
The entry-point will be loaded either by calling
|
||||||
|
:meth:`~flake8.plugins.manager.Plugin.load_plugin` or accessing the ``plugin``
|
||||||
|
attribute. We also use this abstraction to retrieve options that the plugin
|
||||||
|
wishes to register and parse.
|
||||||
|
|
||||||
|
The only public method the |PluginManager| provides is
|
||||||
|
:meth:`~flake8.plugins.manager.PluginManager.map`. This will accept a function
|
||||||
|
(or other callable) and call it with each plugin as the first parameter.
|
||||||
|
|
||||||
|
We build atop the |PluginManager| with the |PTM|. It is expected that users of
|
||||||
|
the |PTM| will subclass it and specify the ``namespace``, e.g.,
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class ExamplePluginType(flake8.plugin.manager.PluginTypeManager):
|
||||||
|
namespace = 'example-plugins'
|
||||||
|
|
||||||
|
This provides a few extra methods via the |PluginManager|'s ``map`` method.
|
||||||
|
|
||||||
|
Finally, we create three classes of plugins:
|
||||||
|
|
||||||
|
- :class:`~flake8.plugins.manager.Checkers`
|
||||||
|
|
||||||
|
- :class:`~flake8.plugins.manager.Listeners`
|
||||||
|
|
||||||
|
- :class:`~flake8.plugins.manager.ReportFormatters`
|
||||||
|
|
||||||
|
These are used to interact with each of the types of plugins individually.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Our inspiration for our plugin handling comes from the author's extensive
|
||||||
|
experience with ``stevedore``.
|
||||||
|
|
||||||
|
Notifying Listener Plugins
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
One of the interesting challenges with allowing plugins to be notified each
|
||||||
|
time an error or warning is emitted by a checker is finding listeners quickly
|
||||||
|
and efficiently. It makes sense to allow a listener to listen for a certain
|
||||||
|
class of warnings or just a specific warning. Hence, we need to allow all
|
||||||
|
plugins that listen to a specific warning or class to be notified. For
|
||||||
|
example, someone might register a listener for ``E1`` and another for ``E111``
|
||||||
|
if ``E111`` is triggered by the code, both listeners should be notified.
|
||||||
|
If ``E112`` is returned, then only ``E1`` (and any other listeners) would be
|
||||||
|
notified.
|
||||||
|
|
||||||
|
To implement this goal, we needed an object to store listeners in that would
|
||||||
|
allow for efficient look up - a Trie (or Prefix Tree). Given that none of the
|
||||||
|
existing packages on PyPI allowed for storing data on each node of the trie,
|
||||||
|
it was left up to write our own as :class:`~flake8.plugins._trie.Trie`. On
|
||||||
|
top of that we layer our :class:`~flake8.plugins.notifier.Notifier` class.
|
||||||
|
|
||||||
|
Now when |Flake8| receives an error or warning, we can easily call the
|
||||||
|
:meth:`~flake8.plugins.notifier.Notifier.notify` method and let plugins act on
|
||||||
|
that knowledge.
|
||||||
|
|
||||||
|
Default Plugins
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Finally, |Flake8| has always provided its own plugin shim for Pyflakes. As
|
||||||
|
part of that we carry our own shim in-tree and now store that in
|
||||||
|
:mod:`flake8.plugins.pyflakes`.
|
||||||
|
|
||||||
|
|Flake8| also registers plugins for pep8. Each check in pep8 requires
|
||||||
|
different parameters and it cannot easily be shimmed together like Pyflakes
|
||||||
|
was. As such, plugins have a concept of a "group". If you look at our
|
||||||
|
:file:`setup.py` you will see that we register pep8 checks roughly like so:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
pep8.<check-name> = pep8:<check-name>
|
||||||
|
|
||||||
|
We do this to identify that ``<check-name>>`` is part of a group. This also
|
||||||
|
enables us to special-case how we handle reporting those checks. Instead of
|
||||||
|
reporting each check in the ``--version`` output, we report ``pep8`` and check
|
||||||
|
``pep8`` the module for a ``__version__`` attribute. We only report it once
|
||||||
|
to avoid confusing users.
|
||||||
|
|
||||||
|
API Documentation
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
.. autoclass:: flake8.plugins.manager.PluginManager
|
||||||
|
:members:
|
||||||
|
:special-members: __init__, __contains__, __getitem__
|
||||||
|
|
||||||
|
.. autoclass:: flake8.plugins.manager.Plugin
|
||||||
|
:members:
|
||||||
|
:special-members: __init__
|
||||||
|
|
||||||
|
.. autoclass:: flake8.plugins.manager.PluginTypeManager
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: flake8.plugins.manager.Checkers
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: flake8.plugins.manager.Listeners
|
||||||
|
:members: build_notifier
|
||||||
|
|
||||||
|
.. autoclass:: flake8.plugins.manager.ReportFormatters
|
||||||
|
|
||||||
|
.. autoclass:: flake8.plugins.notifier.Notifier
|
||||||
|
|
||||||
|
.. autoclass:: flake8.plugins._trie.Trie
|
||||||
|
|
||||||
|
.. |PluginManager| replace:: :class:`~flake8.plugins.manager.PluginManager`
|
||||||
|
.. |Plugin| replace:: :class:`~flake8.plugins.manager.Plugin`
|
||||||
|
.. |PTM| replace:: :class:`~flake8.plugins.manager.PluginTypeManager`
|
||||||
99
docs/source/internal/releases.rst
Normal file
99
docs/source/internal/releases.rst
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
==================
|
||||||
|
Releasing Flake8
|
||||||
|
==================
|
||||||
|
|
||||||
|
There is not much that is hard to find about how |Flake8| is released.
|
||||||
|
|
||||||
|
- We use **major** releases (e.g., 2.0.0, 3.0.0, etc.) for big, potentially
|
||||||
|
backwards incompatible, releases.
|
||||||
|
|
||||||
|
- We use **minor** releases (e.g., 2.1.0, 2.2.0, 3.1.0, 3.2.0, etc.) for
|
||||||
|
releases that contain features and dependency version changes.
|
||||||
|
|
||||||
|
- We use **patch** releases (e.g., 2.1.1, 2.1.2, 3.0.1, 3.0.10, etc.) for
|
||||||
|
releases that contain *only* bug fixes.
|
||||||
|
|
||||||
|
In this sense we follow semantic versioning. But we follow it as more of a set
|
||||||
|
of guidelines. We're also not perfect, so we may make mistakes, and that's
|
||||||
|
fine.
|
||||||
|
|
||||||
|
|
||||||
|
Major Releases
|
||||||
|
==============
|
||||||
|
|
||||||
|
Major releases are often associated with backwards incompatibility. |Flake8|
|
||||||
|
hopes to avoid those, but will occasionally need them.
|
||||||
|
|
||||||
|
Historically, |Flake8| has generated major releases for:
|
||||||
|
|
||||||
|
- Unvendoring dependencies (2.0)
|
||||||
|
|
||||||
|
- Large scale refactoring (2.0, 3.0)
|
||||||
|
|
||||||
|
- Subtly breaking CLI changes (3.0)
|
||||||
|
|
||||||
|
- Breaking changes to its plugin interface (3.0)
|
||||||
|
|
||||||
|
Major releases can also contain:
|
||||||
|
|
||||||
|
- Bug fixes (which may have backwards incompatible solutions)
|
||||||
|
|
||||||
|
- New features
|
||||||
|
|
||||||
|
- Dependency changes
|
||||||
|
|
||||||
|
|
||||||
|
Minor Releases
|
||||||
|
==============
|
||||||
|
|
||||||
|
Minor releases often have new features in them, which we define roughly as:
|
||||||
|
|
||||||
|
- New command-line flags
|
||||||
|
|
||||||
|
- New behaviour that does not break backwards compatibility
|
||||||
|
|
||||||
|
- New errors detected by dependencies, e.g., by raising the upper limit on
|
||||||
|
PyFlakes we introduce F405
|
||||||
|
|
||||||
|
- Bug fixes
|
||||||
|
|
||||||
|
|
||||||
|
Patch Releases
|
||||||
|
==============
|
||||||
|
|
||||||
|
Patch releases should only ever have bug fixes in them.
|
||||||
|
|
||||||
|
We do not update dependency constraints in patch releases. If you do not
|
||||||
|
install |Flake8| from PyPI, there is a chance that your packager is using
|
||||||
|
different requirements. Some downstream redistributors have been known to
|
||||||
|
force a new version of PyFlakes, pep8/PyCodestyle, or McCabe into place.
|
||||||
|
Occasionally this will cause breakage when using |Flake8|. There is little
|
||||||
|
we can do to help you in those cases.
|
||||||
|
|
||||||
|
|
||||||
|
Process
|
||||||
|
=======
|
||||||
|
|
||||||
|
To prepare a release, we create a file in :file:`docs/source/releases/` named:
|
||||||
|
``{{ release_number }}.rst`` (e.g., ``3.0.0.rst``). We note bug fixes,
|
||||||
|
improvements, and dependency version changes as well as other items of note
|
||||||
|
for users.
|
||||||
|
|
||||||
|
Before releasing, the following tox test environments must pass:
|
||||||
|
|
||||||
|
- Python 2.7 (a.k.a., ``tox -e py27``)
|
||||||
|
|
||||||
|
- Python 3.4 (a.k.a., ``tox -e py34``)
|
||||||
|
|
||||||
|
- Python 3.5 (a.k.a., ``tox -e py35``)
|
||||||
|
|
||||||
|
- PyPy (a.k.a., ``tox -e pypy``)
|
||||||
|
|
||||||
|
- Linters (a.k.a., ``tox -e linters``)
|
||||||
|
|
||||||
|
We tag the most recent commit that passes those items and contains our release
|
||||||
|
notes.
|
||||||
|
|
||||||
|
Finally, we run ``tox -e release`` to build source distributions (e.g.,
|
||||||
|
``flake8-3.0.0.tar.gz``), universal wheels, and upload them to PyPI with
|
||||||
|
Twine.
|
||||||
127
docs/source/internal/utils.rst
Normal file
127
docs/source/internal/utils.rst
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
===================
|
||||||
|
Utility Functions
|
||||||
|
===================
|
||||||
|
|
||||||
|
|Flake8| has a few utility functions that it uses internally.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
As should be implied by where these are documented, these are all
|
||||||
|
**internal** utility functions. Their signatures and return types
|
||||||
|
may change between releases without notice.
|
||||||
|
|
||||||
|
Bugs reported about these **internal** functions will be closed
|
||||||
|
immediately.
|
||||||
|
|
||||||
|
If functions are needed by plugin developers, they may be requested
|
||||||
|
in the bug tracker and after careful consideration they *may* be added
|
||||||
|
to the *documented* stable API.
|
||||||
|
|
||||||
|
.. autofunction:: flake8.utils.parse_comma_separated_list
|
||||||
|
|
||||||
|
:func:`~flake8.utils.parse_comma_separated_list` takes either a string like
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
"E121,W123,F904"
|
||||||
|
"E121,\nW123,\nF804"
|
||||||
|
"E121,\n\tW123,\n\tF804"
|
||||||
|
|
||||||
|
Or it will take a list of strings (potentially with whitespace) such as
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
[" E121\n", "\t\nW123 ", "\n\tF904\n "]
|
||||||
|
|
||||||
|
And converts it to a list that looks as follows
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
["E121", "W123", "F904"]
|
||||||
|
|
||||||
|
This function helps normalize any kind of comma-separated input you or |Flake8|
|
||||||
|
might receive. This is most helpful when taking advantage of |Flake8|'s
|
||||||
|
additional parameters to :class:`~flake8.options.manager.Option`.
|
||||||
|
|
||||||
|
.. autofunction:: flake8.utils.normalize_path
|
||||||
|
|
||||||
|
This utility takes a string that represents a path and returns the absolute
|
||||||
|
path if the string has a ``/`` in it. It also removes trailing ``/``\ s.
|
||||||
|
|
||||||
|
.. autofunction:: flake8.utils.normalize_paths
|
||||||
|
|
||||||
|
This function utilizes :func:`~flake8.utils.parse_comma_separated_list` and
|
||||||
|
:func:`~flake8.utils.normalize_path` to normalize it's input to a list of
|
||||||
|
strings that should be paths.
|
||||||
|
|
||||||
|
.. autofunction:: flake8.utils.stdin_get_value
|
||||||
|
|
||||||
|
This function retrieves and caches the value provided on ``sys.stdin``. This
|
||||||
|
allows plugins to use this to retrieve ``stdin`` if necessary.
|
||||||
|
|
||||||
|
.. autofunction:: flake8.utils.is_windows
|
||||||
|
|
||||||
|
This provides a convenient and explicitly named function that checks if we are
|
||||||
|
currently running on a Windows (or ``nt``) operating system.
|
||||||
|
|
||||||
|
.. autofunction:: flake8.utils.can_run_multiprocessing_on_windows
|
||||||
|
|
||||||
|
This provides a separate and distinct check from
|
||||||
|
:func:`~flake8.utils.is_windows` that allows us to check if the version of
|
||||||
|
Python we're using can actually use multiprocessing on Windows.
|
||||||
|
|
||||||
|
.. autofunction:: flake8.utils.is_using_stdin
|
||||||
|
|
||||||
|
Another helpful function that is named only to be explicit given it is a very
|
||||||
|
trivial check, this checks if the user specified ``-`` in their arguments to
|
||||||
|
|Flake8| to indicate we should read from stdin.
|
||||||
|
|
||||||
|
.. autofunction:: flake8.utils.filenames_from
|
||||||
|
|
||||||
|
When provided an argument to |Flake8|, we need to be able to traverse
|
||||||
|
directories in a convenient manner. For example, if someone runs
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
$ flake8 flake8/
|
||||||
|
|
||||||
|
Then they want us to check all of the files in the directory ``flake8/``. This
|
||||||
|
function will handle that while also handling the case where they specify a
|
||||||
|
file like:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
$ flake8 flake8/__init__.py
|
||||||
|
|
||||||
|
|
||||||
|
.. autofunction:: flake8.utils.fnmatch
|
||||||
|
|
||||||
|
The standard library's :func:`fnmatch.fnmatch` is excellent at deciding if a
|
||||||
|
filename matches a single pattern. In our use case, however, we typically have
|
||||||
|
a list of patterns and want to know if the filename matches any of them. This
|
||||||
|
function abstracts that logic away with a little extra logic.
|
||||||
|
|
||||||
|
.. autofunction:: flake8.utils.parameters_for
|
||||||
|
|
||||||
|
|Flake8| analyzes the parameters to plugins to determine what input they are
|
||||||
|
expecting. Plugins may expect one of the following:
|
||||||
|
|
||||||
|
- ``physical_line`` to receive the line as it appears in the file
|
||||||
|
|
||||||
|
- ``logical_line`` to receive the logical line (not as it appears in the file)
|
||||||
|
|
||||||
|
- ``tree`` to receive the abstract syntax tree (AST) for the file
|
||||||
|
|
||||||
|
We also analyze the rest of the parameters to provide more detail to the
|
||||||
|
plugin. This function will return the parameters in a consistent way across
|
||||||
|
versions of Python and will handle both classes and functions that are used as
|
||||||
|
plugins. Further, if the plugin is a class, it will strip the ``self``
|
||||||
|
argument so we can check the parameters of the plugin consistently.
|
||||||
|
|
||||||
|
.. autofunction:: flake8.utils.parse_unified_diff
|
||||||
|
|
||||||
|
To handle usage of :option:`flake8 --diff`, |Flake8| needs to be able
|
||||||
|
to parse the name of the files in the diff as well as the ranges indicated the
|
||||||
|
sections that have been changed. This function either accepts the diff as an
|
||||||
|
argument or reads the diff from standard-in. It then returns a dictionary with
|
||||||
|
filenames as the keys and sets of line numbers as the value.
|
||||||
183
docs/source/internal/writing-documentation.rst
Normal file
183
docs/source/internal/writing-documentation.rst
Normal file
|
|
@ -0,0 +1,183 @@
|
||||||
|
.. _docs-style:
|
||||||
|
|
||||||
|
==================================
|
||||||
|
Writing Documentation for Flake8
|
||||||
|
==================================
|
||||||
|
|
||||||
|
The maintainers of |Flake8| believe strongly in benefit of style guides.
|
||||||
|
Hence, for all contributors who wish to work on our documentation, we've
|
||||||
|
put together a loose set of guidelines and best practices when adding to
|
||||||
|
our documentation.
|
||||||
|
|
||||||
|
|
||||||
|
View the docs locally before submitting
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
You can and should generate the docs locally before you submit a pull request
|
||||||
|
with your changes. You can build the docs by running:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
tox -e docs
|
||||||
|
|
||||||
|
From the directory containing the ``tox.ini`` file (which also contains the
|
||||||
|
``docs/`` directory that this file lives in).
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If the docs don't build locally, they will not build in our continuous
|
||||||
|
integration system. We will generally not merge any pull request that
|
||||||
|
fails continuous integration.
|
||||||
|
|
||||||
|
|
||||||
|
Run the docs linter tests before submitting
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
You should run the ``doc8`` linter job before you're ready to commit and fix
|
||||||
|
any errors found.
|
||||||
|
|
||||||
|
|
||||||
|
Capitalize Flake8 in prose
|
||||||
|
==========================
|
||||||
|
|
||||||
|
We believe that by capitalizing |Flake8| in prose, we can help reduce
|
||||||
|
confusion between the command-line usage of ``flake8`` and the project.
|
||||||
|
|
||||||
|
We also have defined a global replacement ``|Flake8|`` that should be used
|
||||||
|
and will replace each instance with ``:program:`Flake8```.
|
||||||
|
|
||||||
|
|
||||||
|
Use the prompt directive for command-line examples
|
||||||
|
==================================================
|
||||||
|
|
||||||
|
When documenting something on the command-line, use the ``.. prompt::``
|
||||||
|
directive to make it easier for users to copy and paste into their terminal.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: restructuredtext
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --select E123,W503 dir/
|
||||||
|
flake8 --ignore E24,W504 dir
|
||||||
|
|
||||||
|
|
||||||
|
Wrap lines around 79 characters
|
||||||
|
===============================
|
||||||
|
|
||||||
|
We use a maximum line-length in our documentation that is similar to the
|
||||||
|
default in |Flake8|. Please wrap lines at 79 characters (or less).
|
||||||
|
|
||||||
|
|
||||||
|
Use two new-lines before new sections
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
After the final paragraph of a section and before the next section title,
|
||||||
|
use two new-lines to separate them. This makes reading the plain-text
|
||||||
|
document a little nicer. Sphinx ignores these when rendering so they have
|
||||||
|
no semantic meaning.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: restructuredtext
|
||||||
|
|
||||||
|
Section Header
|
||||||
|
==============
|
||||||
|
|
||||||
|
Paragraph.
|
||||||
|
|
||||||
|
|
||||||
|
Next Section Header
|
||||||
|
===================
|
||||||
|
|
||||||
|
Paragraph.
|
||||||
|
|
||||||
|
|
||||||
|
Surround document titles with equal symbols
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
To indicate the title of a document, we place an equal number of ``=`` symbols
|
||||||
|
on the lines before and after the title. For example:
|
||||||
|
|
||||||
|
.. code-block:: restructuredtext
|
||||||
|
|
||||||
|
==================================
|
||||||
|
Writing Documentation for Flake8
|
||||||
|
==================================
|
||||||
|
|
||||||
|
Note also that we "center" the title by adding a leading space and having
|
||||||
|
extra ``=`` symbols at the end of those lines.
|
||||||
|
|
||||||
|
|
||||||
|
Use the option template for new options
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
All of |Flake8|'s command-line options are documented in the User Guide. Each
|
||||||
|
option is documented individually using the ``.. option::`` directive provided
|
||||||
|
by Sphinx. At the top of the document, in a reStructuredText comment, is a
|
||||||
|
template that should be copied and pasted into place when documening new
|
||||||
|
options.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The ordering of the options page is the order that options are printed
|
||||||
|
in the output of:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --help
|
||||||
|
|
||||||
|
Please insert your option documentation according to that order.
|
||||||
|
|
||||||
|
|
||||||
|
Use anchors for easy reference linking
|
||||||
|
======================================
|
||||||
|
|
||||||
|
Use link anchors to allow for other areas of the documentation to use the
|
||||||
|
``:ref:`` role for intralinking documentation. Example:
|
||||||
|
|
||||||
|
.. code-block:: restructuredtext
|
||||||
|
|
||||||
|
.. _use-anchors:
|
||||||
|
|
||||||
|
Use anchors for easy reference linking
|
||||||
|
======================================
|
||||||
|
|
||||||
|
.. code-block:: restructuredtext
|
||||||
|
|
||||||
|
Somewhere in this paragraph we will :ref:`reference anchors
|
||||||
|
<use-anchors>`.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
You do not need to provide custom text for the ``:ref:`` if the title of
|
||||||
|
the section has a title that is sufficient.
|
||||||
|
|
||||||
|
|
||||||
|
Keep your audience in mind
|
||||||
|
==========================
|
||||||
|
|
||||||
|
|Flake8|'s documentation has three distinct (but not separate) audiences:
|
||||||
|
|
||||||
|
#. Users
|
||||||
|
|
||||||
|
#. Plugin Developers
|
||||||
|
|
||||||
|
#. Flake8 Developers and Contributors
|
||||||
|
|
||||||
|
At the moment, you're one of the third group (because you're contributing
|
||||||
|
or thinking of contributing).
|
||||||
|
|
||||||
|
Consider that most Users aren't very interested in the internal working of
|
||||||
|
|Flake8|. When writing for Users, focus on how to do something or the
|
||||||
|
behaviour of a certain piece of configuration or invocation.
|
||||||
|
|
||||||
|
Plugin developers will only care about the internals of |Flake8| as much as
|
||||||
|
they will have to interact with that. Keep discussions of internal to the
|
||||||
|
mininmum required.
|
||||||
|
|
||||||
|
Finally, Flake8 Developers and Contributors need to know how everything fits
|
||||||
|
together. We don't need detail about every line of code, but cogent
|
||||||
|
explanations and design specifications will help future developers understand
|
||||||
|
the Hows and Whys of |Flake8|'s internal design.
|
||||||
0
docs/source/plugin-development/.keep
Normal file
0
docs/source/plugin-development/.keep
Normal file
150
docs/source/plugin-development/cross-compatibility.rst
Normal file
150
docs/source/plugin-development/cross-compatibility.rst
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
====================================
|
||||||
|
Writing Plugins For Flake8 2 and 3
|
||||||
|
====================================
|
||||||
|
|
||||||
|
Plugins have existed for |Flake8| 2.x for a few years. There are a number of
|
||||||
|
these on PyPI already. While it did not seem reasonable for |Flake8| to attempt
|
||||||
|
to provide a backwards compatible shim for them, we did decide to try to
|
||||||
|
document the easiest way to write a plugin that's compatible across both
|
||||||
|
versions.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If your plugin does not register options, it *should* Just Work.
|
||||||
|
|
||||||
|
The **only** breaking change in |Flake8| 3.0 is the fact that we no longer
|
||||||
|
check the option parser for a list of strings to parse from a config file. On
|
||||||
|
|Flake8| 2.x, to have an option parsed from the configuration files that
|
||||||
|
|Flake8| finds and parses you would have to do something like:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
parser.add_option('-X', '--example-flag', type='string',
|
||||||
|
help='...')
|
||||||
|
parser.config_options.append('example-flag')
|
||||||
|
|
||||||
|
For |Flake8| 3.0, we have added *three* arguments to the
|
||||||
|
:meth:`~flake8.options.manager.OptionManager.add_option` method you will call
|
||||||
|
on the parser you receive:
|
||||||
|
|
||||||
|
- ``parse_from_config`` which expects ``True`` or ``False``
|
||||||
|
|
||||||
|
When ``True``, |Flake8| will parse the option from the config files |Flake8|
|
||||||
|
finds.
|
||||||
|
|
||||||
|
- ``comma_separated_list`` which expects ``True`` or ``False``
|
||||||
|
|
||||||
|
When ``True``, |Flake8| will split the string intelligently and handle
|
||||||
|
extra whitespace. The parsed value will be a list.
|
||||||
|
|
||||||
|
- ``normalize_paths`` which expects ``True`` or ``False``
|
||||||
|
|
||||||
|
When ``True``, |Flake8| will:
|
||||||
|
|
||||||
|
* remove trailing path separators (i.e., ``os.path.sep``)
|
||||||
|
|
||||||
|
* return the absolute path for values that have the separator in them
|
||||||
|
|
||||||
|
All three of these options can be combined or used separately.
|
||||||
|
|
||||||
|
|
||||||
|
Parsing Options from Configuration Files
|
||||||
|
========================================
|
||||||
|
|
||||||
|
The example from |Flake8| 2.x now looks like:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
parser.add_option('-X', '--example-flag', type='string',
|
||||||
|
parse_from_config=True,
|
||||||
|
help='...')
|
||||||
|
|
||||||
|
|
||||||
|
Parsing Comma-Separated Lists
|
||||||
|
=============================
|
||||||
|
|
||||||
|
Now let's imagine that the option we want to add is expecting a comma-separatd
|
||||||
|
list of values from the user (e.g., ``--select E123,W503,F405``). |Flake8| 2.x
|
||||||
|
often forced users to parse these lists themselves since pep8 special-cased
|
||||||
|
certain flags and left others on their own. |Flake8| 3.0 adds
|
||||||
|
``comma_separated_list`` so that the parsed option is already a list for
|
||||||
|
plugin authors. When combined with ``parse_from_config`` this means that users
|
||||||
|
can also do something like:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
example-flag =
|
||||||
|
first,
|
||||||
|
second,
|
||||||
|
third,
|
||||||
|
fourth,
|
||||||
|
fifth
|
||||||
|
|
||||||
|
And |Flake8| will just return the list:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
["first", "second", "third", "fourth", "fifth"]
|
||||||
|
|
||||||
|
|
||||||
|
Normalizing Values that Are Paths
|
||||||
|
=================================
|
||||||
|
|
||||||
|
Finally, let's imagine that our new option wants a path or list of paths. To
|
||||||
|
ensure that these paths are semi-normalized (the way |Flake8| 2.x used to
|
||||||
|
work) we need only pass ``normalize_paths=True``. If you have specified
|
||||||
|
``comma_separated_list=True`` then this will parse the value as a list of
|
||||||
|
paths that have been normalized. Otherwise, this will parse the value
|
||||||
|
as a single path.
|
||||||
|
|
||||||
|
|
||||||
|
Option Handling on Flake8 2 and 3
|
||||||
|
=================================
|
||||||
|
|
||||||
|
So, in conclusion, we can now write our plugin that relies on registering
|
||||||
|
options with |Flake8| and have it work on |Flake8| 2.x and 3.x.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
option_args = ('-X', '--example-flag')
|
||||||
|
option_kwargs = {
|
||||||
|
'type': 'string',
|
||||||
|
'parse_from_config': True,
|
||||||
|
'help': '...',
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
# Flake8 3.x registration
|
||||||
|
parser.add_option(*option_args, **option_kwargs)
|
||||||
|
except TypeError:
|
||||||
|
# Flake8 2.x registration
|
||||||
|
parse_from_config = option_kwargs.pop('parse_from_config', False)
|
||||||
|
parser.add_option(*option_args, **option_kwargs)
|
||||||
|
if parse_from_config:
|
||||||
|
parser.config_options.append(option_args[-1].lstrip('-'))
|
||||||
|
|
||||||
|
|
||||||
|
Or, you can write a tiny helper function:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def register_opt(parser, *args, **kwargs):
|
||||||
|
try:
|
||||||
|
# Flake8 3.x registration
|
||||||
|
parser.add_option(*args, **kwargs)
|
||||||
|
except TypeError:
|
||||||
|
# Flake8 2.x registration
|
||||||
|
parse_from_config = kwargs.pop('parse_from_config', False)
|
||||||
|
parser.add_option(*args, **kwargs)
|
||||||
|
if parse_from_config:
|
||||||
|
parser.config_options.append(args[-1].lstrip('-'))
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def register_options(cls, parser):
|
||||||
|
register_opt(parser, '-X', '--example-flag', type='string',
|
||||||
|
parse_from_config=True, help='...')
|
||||||
|
|
||||||
|
The transition period is admittedly not fantastic, but we believe that this
|
||||||
|
is a worthwhile change for plugin developers going forward. We also hope to
|
||||||
|
help with the transition phase for as many plugins as we can manage.
|
||||||
54
docs/source/plugin-development/formatters.rst
Normal file
54
docs/source/plugin-development/formatters.rst
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
.. _formatting-plugins:
|
||||||
|
|
||||||
|
===========================================
|
||||||
|
Developing a Formatting Plugin for Flake8
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
|Flake8| allowed for custom formatting plugins in version
|
||||||
|
3.0.0. Let's write a plugin together:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from flake8.formatting import base
|
||||||
|
|
||||||
|
|
||||||
|
class Example(base.BaseFormatter):
|
||||||
|
"""Flake8's example formatter."""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
We notice, as soon as we start, that we inherit from |Flake8|'s
|
||||||
|
:class:`~flake8.formatting.base.BaseFormatter` class. If we follow the
|
||||||
|
:ref:`instructions to register a plugin <register-a-plugin>` and try to use
|
||||||
|
our example formatter, e.g., ``flake8 --format=example`` then
|
||||||
|
|Flake8| will fail because we did not implement the ``format`` method.
|
||||||
|
Let's do that next.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class Example(base.BaseFormatter):
|
||||||
|
"""Flake8's example formatter."""
|
||||||
|
|
||||||
|
def format(self, error):
|
||||||
|
return 'Example formatter: {0!r}'.format(error)
|
||||||
|
|
||||||
|
With that we're done. Obviously this isn't a very useful formatter, but it
|
||||||
|
should highlight the simplicitly of creating a formatter with Flake8. If we
|
||||||
|
wanted to instead create a formatter that aggregated the results and returned
|
||||||
|
XML, JSON, or subunit we could also do that. |Flake8| interacts with the
|
||||||
|
formatter in two ways:
|
||||||
|
|
||||||
|
#. It creates the formatter and provides it the options parsed from the
|
||||||
|
configuration files and command-line
|
||||||
|
|
||||||
|
#. It uses the instance of the formatter and calls ``handle`` with the error.
|
||||||
|
|
||||||
|
By default :meth:`flake8.formatting.base.BaseFormatter.handle` simply calls
|
||||||
|
the ``format`` method and then ``write``. Any extra handling you wish to do
|
||||||
|
for formatting purposes should override the ``handle`` method.
|
||||||
|
|
||||||
|
API Documentation
|
||||||
|
=================
|
||||||
|
|
||||||
|
.. autoclass:: flake8.formatting.base.BaseFormatter
|
||||||
|
:members:
|
||||||
56
docs/source/plugin-development/index.rst
Normal file
56
docs/source/plugin-development/index.rst
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
============================
|
||||||
|
Writing Plugins for Flake8
|
||||||
|
============================
|
||||||
|
|
||||||
|
Since |Flake8| 2.0, the |Flake8| tool has allowed for extensions and custom
|
||||||
|
plugins. In |Flake8| 3.0, we're expanding that ability to customize and
|
||||||
|
extend **and** we're attempting to thoroughly document it. Some of the
|
||||||
|
documentation in this section may reference third-party documentation to
|
||||||
|
reduce duplication and to point you, the developer, towards the authoritative
|
||||||
|
documentation for those pieces.
|
||||||
|
|
||||||
|
Getting Started
|
||||||
|
===============
|
||||||
|
|
||||||
|
To get started writing a |Flake8| :term:`plugin` you first need:
|
||||||
|
|
||||||
|
- An idea for a plugin
|
||||||
|
|
||||||
|
- An available package name on PyPI
|
||||||
|
|
||||||
|
- One or more versions of Python installed
|
||||||
|
|
||||||
|
- A text editor or IDE of some kind
|
||||||
|
|
||||||
|
- An idea of what *kind* of plugin you want to build:
|
||||||
|
|
||||||
|
* Formatter
|
||||||
|
|
||||||
|
* Check
|
||||||
|
|
||||||
|
Once you've gathered these things, you can get started.
|
||||||
|
|
||||||
|
All plugins for |Flake8| must be registered via `entry points`_. In this
|
||||||
|
section we cover:
|
||||||
|
|
||||||
|
- How to register your plugin so |Flake8| can find it
|
||||||
|
|
||||||
|
- How to make |Flake8| provide your check plugin with information (via
|
||||||
|
command-line flags, function/class parameters, etc.)
|
||||||
|
|
||||||
|
- How to make a formatter plugin
|
||||||
|
|
||||||
|
- How to write your check plugin so that it works with |Flake8| 2.x and 3.x
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:caption: Plugin Developer Documentation
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
registering-plugins
|
||||||
|
plugin-parameters
|
||||||
|
formatters
|
||||||
|
cross-compatibility
|
||||||
|
|
||||||
|
|
||||||
|
.. _entry points:
|
||||||
|
https://setuptools.readthedocs.io/en/latest/pkg_resources.html#entry-points
|
||||||
163
docs/source/plugin-development/plugin-parameters.rst
Normal file
163
docs/source/plugin-development/plugin-parameters.rst
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
.. _plugin-parameters:
|
||||||
|
|
||||||
|
==========================================
|
||||||
|
Receiving Information For A Check Plugin
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
Plugins to |Flake8| have a great deal of information that they can request
|
||||||
|
from a :class:`~flake8.processor.FileProcessor` instance. Historically,
|
||||||
|
|Flake8| has supported two types of plugins:
|
||||||
|
|
||||||
|
#. classes that accept parsed abstract syntax trees (ASTs)
|
||||||
|
|
||||||
|
#. functions that accept a range of arguments
|
||||||
|
|
||||||
|
|Flake8| now does not distinguish between the two types of plugins. Any plugin
|
||||||
|
can accept either an AST or a range of arguments. Further, any plugin that has
|
||||||
|
certain callable attributes can also register options and receive parsed
|
||||||
|
options.
|
||||||
|
|
||||||
|
|
||||||
|
Indicating Desired Data
|
||||||
|
=======================
|
||||||
|
|
||||||
|
|Flake8| inspects the plugin's signature to determine what parameters it
|
||||||
|
expects using :func:`flake8.utils.parameters_for`.
|
||||||
|
:attr:`flake8.plugins.manager.Plugin.parameters` caches the values so that
|
||||||
|
each plugin makes that fairly expensive call once per plugin. When processing
|
||||||
|
a file, a plugin can ask for any of the following:
|
||||||
|
|
||||||
|
- :attr:`~flake8.processor.FileProcessor.blank_before`
|
||||||
|
- :attr:`~flake8.processor.FileProcessor.blank_lines`
|
||||||
|
- :attr:`~flake8.processor.FileProcessor.checker_state`
|
||||||
|
- :attr:`~flake8.processor.FileProcessor.indect_char`
|
||||||
|
- :attr:`~flake8.processor.FileProcessor.indent_level`
|
||||||
|
- :attr:`~flake8.processor.FileProcessor.line_number`
|
||||||
|
- :attr:`~flake8.processor.FileProcessor.logical_line`
|
||||||
|
- :attr:`~flake8.processor.FileProcessor.max_line_length`
|
||||||
|
- :attr:`~flake8.processor.FileProcessor.multiline`
|
||||||
|
- :attr:`~flake8.processor.FileProcessor.noqa`
|
||||||
|
- :attr:`~flake8.processor.FileProcessor.previous_indent_level`
|
||||||
|
- :attr:`~flake8.processor.FileProcessor.previous_logical`
|
||||||
|
- :attr:`~flake8.processor.FileProcessor.tokens`
|
||||||
|
- :attr:`~flake8.processor.FileProcessor.total_lines`
|
||||||
|
- :attr:`~flake8.processor.FileProcessor.verbose`
|
||||||
|
|
||||||
|
Alternatively, a plugin can accept ``tree`` and ``filename``.
|
||||||
|
``tree`` will be a parsed abstract syntax tree that will be used by plugins
|
||||||
|
like PyFlakes and McCabe.
|
||||||
|
|
||||||
|
|
||||||
|
Registering Options
|
||||||
|
===================
|
||||||
|
|
||||||
|
Any plugin that has callable attributes ``provide_options`` and
|
||||||
|
``register_options`` can parse option information and register new options.
|
||||||
|
|
||||||
|
Your ``register_options`` function should expect to receive an instance of
|
||||||
|
|OptionManager|. An |OptionManager| instance behaves very similarly to
|
||||||
|
:class:`optparse.OptionParser`. It, however, uses the layer that |Flake8| has
|
||||||
|
developed on top of :mod:`optparse` to also handle configuration file parsing.
|
||||||
|
:meth:`~flake8.options.manager.OptionManager.add_option` creates an |Option|
|
||||||
|
which accepts the same parameters as :mod:`optparse` as well as three extra
|
||||||
|
boolean parameters:
|
||||||
|
|
||||||
|
- ``parse_from_config``
|
||||||
|
|
||||||
|
The command-line option should also be parsed from config files discovered
|
||||||
|
by |Flake8|.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This takes the place of appending strings to a list on the
|
||||||
|
:class:`optparse.OptionParser`.
|
||||||
|
|
||||||
|
- ``comma_separated_list``
|
||||||
|
|
||||||
|
The value provided to this option is a comma-separated list. After parsing
|
||||||
|
the value, it should be further broken up into a list. This also allows us
|
||||||
|
to handle values like:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
E123,E124,
|
||||||
|
E125,
|
||||||
|
E126
|
||||||
|
|
||||||
|
- ``normalize_paths``
|
||||||
|
|
||||||
|
The value provided to this option is a path. It should be normalized to be
|
||||||
|
an absolute path. This can be combined with ``comma_separated_list`` to
|
||||||
|
allow a comma-separated list of paths.
|
||||||
|
|
||||||
|
Each of these options works individually or can be combined. Let's look at a
|
||||||
|
couple examples from |Flake8|. In each example, we will have
|
||||||
|
``option_manager`` which is an instance of |OptionManager|.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
option_manager.add_option(
|
||||||
|
'--max-line-length', type='int', metavar='n',
|
||||||
|
default=defaults.MAX_LINE_LENGTH, parse_from_config=True,
|
||||||
|
help='Maximum allowed line length for the entirety of this run. '
|
||||||
|
'(Default: %default)',
|
||||||
|
)
|
||||||
|
|
||||||
|
Here we are adding the ``--max-line-length`` command-line option which is
|
||||||
|
always an integer and will be parsed from the configuration file. Since we
|
||||||
|
provide a default, we take advantage of :mod:`optparse`\ 's willingness to
|
||||||
|
display that in the help text with ``%default``.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
option_manager.add_option(
|
||||||
|
'--select', metavar='errors', default='',
|
||||||
|
parse_from_config=True, comma_separated_list=True,
|
||||||
|
help='Comma-separated list of errors and warnings to enable.'
|
||||||
|
' For example, ``--select=E4,E51,W234``. (Default: %default)',
|
||||||
|
)
|
||||||
|
|
||||||
|
In adding the ``--select`` command-line option, we're also indicating to the
|
||||||
|
|OptionManager| that we want the value parsed from the config files and parsed
|
||||||
|
as a comma-separated list.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
option_manager.add_option(
|
||||||
|
'--exclude', metavar='patterns', default=defaults.EXCLUDE,
|
||||||
|
comma_separated_list=True, parse_from_config=True,
|
||||||
|
normalize_paths=True,
|
||||||
|
help='Comma-separated list of files or directories to exclude.'
|
||||||
|
'(Default: %default)',
|
||||||
|
)
|
||||||
|
|
||||||
|
Finally, we show an option that uses all three extra flags. Values from
|
||||||
|
``--exclude`` will be parsed from the config, converted from a comma-separated
|
||||||
|
list, and then each item will be normalized.
|
||||||
|
|
||||||
|
For information about other parameters to
|
||||||
|
:meth:`~flake8.options.manager.OptionManager.add_option` refer to the
|
||||||
|
documentation of :mod:`optparse`.
|
||||||
|
|
||||||
|
|
||||||
|
Accessing Parsed Options
|
||||||
|
========================
|
||||||
|
|
||||||
|
When a plugin has a callable ``provide_options`` attribute, |Flake8| will call
|
||||||
|
it and attempt to provide the |OptionManager| instance, the parsed options
|
||||||
|
which will be an instance of :class:`optparse.Values`, and the extra arguments
|
||||||
|
that were not parsed by the |OptionManager|. If that fails, we will just pass
|
||||||
|
the :class:`optparse.Values`. In other words, your ``provide_options``
|
||||||
|
callable will have one of the following signatures:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def provide_options(option_manager, options, args):
|
||||||
|
pass
|
||||||
|
# or
|
||||||
|
def provide_options(options):
|
||||||
|
pass
|
||||||
|
|
||||||
|
.. substitutions
|
||||||
|
.. |OptionManager| replace:: :class:`~flake8.options.manager.OptionManager`
|
||||||
|
.. |Option| replace:: :class:`~flake8.options.manager.Option`
|
||||||
115
docs/source/plugin-development/registering-plugins.rst
Normal file
115
docs/source/plugin-development/registering-plugins.rst
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
.. _register-a-plugin:
|
||||||
|
|
||||||
|
==================================
|
||||||
|
Registering a Plugin with Flake8
|
||||||
|
==================================
|
||||||
|
|
||||||
|
To register any kind of plugin with |Flake8|, you need:
|
||||||
|
|
||||||
|
#. A way to install the plugin (whether it is packaged on its own or
|
||||||
|
as part of something else). In this section, we will use a ``setup.py``
|
||||||
|
written for an example plugin.
|
||||||
|
|
||||||
|
#. A name for your plugin that will (ideally) be unique.
|
||||||
|
|
||||||
|
#. A somewhat recent version of setuptools (newer than 0.7.0 but preferably as
|
||||||
|
recent as you can attain).
|
||||||
|
|
||||||
|
|Flake8| relies on functionality provided by setuptools called
|
||||||
|
`Entry Points`_. These allow any package to register a plugin with |Flake8|
|
||||||
|
via that package's ``setup.py`` file.
|
||||||
|
|
||||||
|
Let's presume that we already have our plugin written and it's in a module
|
||||||
|
called ``flake8_example``. We might have a ``setup.py`` that looks something
|
||||||
|
like:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from __future__ import with_statement
|
||||||
|
import setuptools
|
||||||
|
|
||||||
|
requires = [
|
||||||
|
"flake8 > 3.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
flake8_entry_point = # ...
|
||||||
|
|
||||||
|
setuptools.setup(
|
||||||
|
name="flake8_example",
|
||||||
|
license="MIT",
|
||||||
|
version="0.1.0",
|
||||||
|
description="our extension to flake8",
|
||||||
|
author="Me",
|
||||||
|
author_email="example@example.com",
|
||||||
|
url="https://gitlab.com/me/flake8_example",
|
||||||
|
packages=[
|
||||||
|
"flake8_example",
|
||||||
|
],
|
||||||
|
install_requires=requires,
|
||||||
|
entry_points={
|
||||||
|
flake8_entry_point: [
|
||||||
|
'X = flake8_example:ExamplePlugin',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
classifiers=[
|
||||||
|
"Environment :: Console",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"License :: OSI Approved :: MIT License",
|
||||||
|
"Programming Language :: Python",
|
||||||
|
"Programming Language :: Python :: 2",
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||||
|
"Topic :: Software Development :: Quality Assurance",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
Note specifically these lines:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
flake8_entry_point = # ...
|
||||||
|
|
||||||
|
setuptools.setup(
|
||||||
|
# snip ...
|
||||||
|
entry_points={
|
||||||
|
flake8_entry_point: [
|
||||||
|
'X = flake8_example:ExamplePlugin',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
# snip ...
|
||||||
|
)
|
||||||
|
|
||||||
|
We tell setuptools to register our entry point "X" inside the specific
|
||||||
|
grouping of entry-points that flake8 should look in.
|
||||||
|
|
||||||
|
|Flake8| presently looks at three groups:
|
||||||
|
|
||||||
|
- ``flake8.extension``
|
||||||
|
|
||||||
|
- ``flake8.listen``
|
||||||
|
|
||||||
|
- ``flake8.report``
|
||||||
|
|
||||||
|
If your plugin is one that adds checks to |Flake8|, you will use
|
||||||
|
``flake8.extension``. If your plugin automatically fixes errors in code, you
|
||||||
|
will use ``flake8.listen``. Finally, if your plugin performs extra report
|
||||||
|
handling (formatting, filtering, etc.) it will use ``flake8.report``.
|
||||||
|
|
||||||
|
If our ``ExamplePlugin`` is something that adds checks, our code would look
|
||||||
|
like:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
setuptools.setup(
|
||||||
|
# snip ...
|
||||||
|
entry_points={
|
||||||
|
'flake8.extension': [
|
||||||
|
'X = flake8_example:ExamplePlugin',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
# snip ...
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
.. _Entry Points:
|
||||||
|
https://pythonhosted.org/setuptools/pkg_resources.html#entry-points
|
||||||
4
docs/source/release-notes/0.6.0.rst
Normal file
4
docs/source/release-notes/0.6.0.rst
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
0.6 - 2010-02-15
|
||||||
|
----------------
|
||||||
|
|
||||||
|
- Fix the McCabe metric on some loops
|
||||||
6
docs/source/release-notes/0.7.0.rst
Normal file
6
docs/source/release-notes/0.7.0.rst
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
0.7 - 2010-02-18
|
||||||
|
----------------
|
||||||
|
|
||||||
|
- Fix pep8 initialization when run through Hg
|
||||||
|
- Make pep8 short options work when run through the command line
|
||||||
|
- Skip duplicates when controlling files via Hg
|
||||||
5
docs/source/release-notes/0.8.0.rst
Normal file
5
docs/source/release-notes/0.8.0.rst
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
0.8 - 2011-02-27
|
||||||
|
----------------
|
||||||
|
|
||||||
|
- fixed hg hook
|
||||||
|
- discard unexisting files on hook check
|
||||||
5
docs/source/release-notes/0.9.0.rst
Normal file
5
docs/source/release-notes/0.9.0.rst
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
0.9 - 2011-11-09
|
||||||
|
----------------
|
||||||
|
|
||||||
|
- update pep8 version to 0.6.1
|
||||||
|
- mccabe check: gracefully handle compile failure
|
||||||
5
docs/source/release-notes/1.0.0.rst
Normal file
5
docs/source/release-notes/1.0.0.rst
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
1.0 - 2011-11-29
|
||||||
|
----------------
|
||||||
|
|
||||||
|
- Deactivates by default the complexity checker
|
||||||
|
- Introduces the complexity option in the HG hook and the command line.
|
||||||
8
docs/source/release-notes/1.1.0.rst
Normal file
8
docs/source/release-notes/1.1.0.rst
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
1.1 - 2012-02-14
|
||||||
|
----------------
|
||||||
|
|
||||||
|
- fixed the value returned by --version
|
||||||
|
- allow the flake8: header to be more generic
|
||||||
|
- fixed the "hg hook raises 'physical lines'" bug
|
||||||
|
- allow three argument form of raise
|
||||||
|
- now uses setuptools if available, for 'develop' command
|
||||||
6
docs/source/release-notes/1.2.0.rst
Normal file
6
docs/source/release-notes/1.2.0.rst
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
1.2 - 2012-02-12
|
||||||
|
----------------
|
||||||
|
|
||||||
|
- added a git hook
|
||||||
|
- now Python 3 compatible
|
||||||
|
- mccabe and pyflakes have warning codes like pep8 now
|
||||||
4
docs/source/release-notes/1.3.0.rst
Normal file
4
docs/source/release-notes/1.3.0.rst
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
1.3 - 2012-03-12
|
||||||
|
----------------
|
||||||
|
|
||||||
|
- fixed false W402 warning on exception blocks.
|
||||||
4
docs/source/release-notes/1.3.1.rst
Normal file
4
docs/source/release-notes/1.3.1.rst
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
1.3.1 - 2012-05-19
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- fixed support for Python 2.5
|
||||||
5
docs/source/release-notes/1.4.0.rst
Normal file
5
docs/source/release-notes/1.4.0.rst
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
1.4 - 2012-07-12
|
||||||
|
----------------
|
||||||
|
|
||||||
|
- git_hook: Only check staged changes for compliance
|
||||||
|
- use pep8 1.2
|
||||||
9
docs/source/release-notes/1.5.0.rst
Normal file
9
docs/source/release-notes/1.5.0.rst
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
1.5 - 2012-10-13
|
||||||
|
----------------
|
||||||
|
|
||||||
|
- fixed the stdin
|
||||||
|
- make sure mccabe catches the syntax errors as warnings
|
||||||
|
- pep8 upgrade
|
||||||
|
- added max_line_length default value
|
||||||
|
- added Flake8Command and entry points if setuptools is around
|
||||||
|
- using the setuptools console wrapper when available
|
||||||
14
docs/source/release-notes/1.6.0.rst
Normal file
14
docs/source/release-notes/1.6.0.rst
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
1.6 - 2012-11-16
|
||||||
|
----------------
|
||||||
|
|
||||||
|
- changed the signatures of the ``check_file`` function in flake8/run.py,
|
||||||
|
``skip_warning`` in flake8/util.py and the ``check``, ``checkPath``
|
||||||
|
functions in flake8/pyflakes.py.
|
||||||
|
- fix ``--exclude`` and ``--ignore`` command flags (#14, #19)
|
||||||
|
- fix the git hook that wasn't catching files not already added to the index
|
||||||
|
(#29)
|
||||||
|
- pre-emptively includes the addition to pep8 to ignore certain lines.
|
||||||
|
Add ``# nopep8`` to the end of a line to ignore it. (#37)
|
||||||
|
- ``check_file`` can now be used without any special prior setup (#21)
|
||||||
|
- unpacking exceptions will no longer cause an exception (#20)
|
||||||
|
- fixed crash on non-existent file (#38)
|
||||||
7
docs/source/release-notes/1.6.1.rst
Normal file
7
docs/source/release-notes/1.6.1.rst
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
1.6.1 - 2012-11-24
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- fixed the mercurial hook, a change from a previous patch was not properly
|
||||||
|
applied
|
||||||
|
- fixed an assumption about warnings/error messages that caused an exception
|
||||||
|
to be thrown when McCabe is used
|
||||||
4
docs/source/release-notes/1.6.2.rst
Normal file
4
docs/source/release-notes/1.6.2.rst
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
1.6.2 - 2012-11-25
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- fixed the NameError: global name 'message' is not defined (#46)
|
||||||
9
docs/source/release-notes/1.7.0.rst
Normal file
9
docs/source/release-notes/1.7.0.rst
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
1.7.0 - 2012-12-21
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Fixes part of #35: Exception for no WITHITEM being an attribute of Checker
|
||||||
|
for Python 3.3
|
||||||
|
- Support stdin
|
||||||
|
- Incorporate @phd's builtins pull request
|
||||||
|
- Fix the git hook
|
||||||
|
- Update pep8.py to the latest version
|
||||||
13
docs/source/release-notes/2.0.0.rst
Normal file
13
docs/source/release-notes/2.0.0.rst
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
2.0.0 - 2013-02-23
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Pyflakes errors are prefixed by an ``F`` instead of an ``E``
|
||||||
|
- McCabe complexity warnings are prefixed by a ``C`` instead of a ``W``
|
||||||
|
- Flake8 supports extensions through entry points
|
||||||
|
- Due to the above support, we **require** setuptools
|
||||||
|
- We publish the `documentation <https://flake8.readthedocs.org/>`_
|
||||||
|
- Fixes #13: pep8, pyflakes and mccabe become external dependencies
|
||||||
|
- Split run.py into main.py, engine.py and hooks.py for better logic
|
||||||
|
- Expose our parser for our users
|
||||||
|
- New feature: Install git and hg hooks automagically
|
||||||
|
- By relying on pyflakes (0.6.1), we also fixed #45 and #35
|
||||||
12
docs/source/release-notes/2.1.0.rst
Normal file
12
docs/source/release-notes/2.1.0.rst
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
2.1.0 - 2013-10-26
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Add FLAKE8_LAZY and FLAKE8_IGNORE environment variable support to git and
|
||||||
|
mercurial hooks
|
||||||
|
- Force git and mercurial hooks to repsect configuration in setup.cfg
|
||||||
|
- Only check staged files if that is specified
|
||||||
|
- Fix hook file permissions
|
||||||
|
- Fix the git hook on python 3
|
||||||
|
- Ignore non-python files when running the git hook
|
||||||
|
- Ignore .tox directories by default
|
||||||
|
- Flake8 now reports the column number for PyFlakes messages
|
||||||
12
docs/source/release-notes/2.2.0.rst
Normal file
12
docs/source/release-notes/2.2.0.rst
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
2.2.0 - 2014-06-22
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- New option ``doctests`` to run Pyflakes checks on doctests too
|
||||||
|
- New option ``jobs`` to launch multiple jobs in parallel
|
||||||
|
- Turn on using multiple jobs by default using the CPU count
|
||||||
|
- Add support for ``python -m flake8`` on Python 2.7 and Python 3
|
||||||
|
- Fix Git and Mercurial hooks: issues #88, #133, #148 and #149
|
||||||
|
- Fix crashes with Python 3.4 by upgrading dependencies
|
||||||
|
- Fix traceback when running tests with Python 2.6
|
||||||
|
- Fix the setuptools command ``python setup.py flake8`` to read
|
||||||
|
the project configuration
|
||||||
5
docs/source/release-notes/2.2.1.rst
Normal file
5
docs/source/release-notes/2.2.1.rst
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
2.2.1 - 2014-06-30
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Turn off multiple jobs by default. To enable automatic use of all CPUs, use
|
||||||
|
``--jobs=auto``. Fixes #155 and #154.
|
||||||
5
docs/source/release-notes/2.2.2.rst
Normal file
5
docs/source/release-notes/2.2.2.rst
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
2.2.2 - 2014-07-04
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Re-enable multiprocessing by default while fixing the issue Windows users
|
||||||
|
were seeing.
|
||||||
4
docs/source/release-notes/2.2.3.rst
Normal file
4
docs/source/release-notes/2.2.3.rst
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
2.2.3 - 2014-08-25
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Actually turn multiprocessing on by default
|
||||||
20
docs/source/release-notes/2.2.4.rst
Normal file
20
docs/source/release-notes/2.2.4.rst
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
2.2.4 - 2014-10-09
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Fix bugs triggered by turning multiprocessing on by default (again)
|
||||||
|
|
||||||
|
Multiprocessing is forcibly disabled in the following cases:
|
||||||
|
|
||||||
|
- Passing something in via stdin
|
||||||
|
|
||||||
|
- Analyzing a diff
|
||||||
|
|
||||||
|
- Using windows
|
||||||
|
|
||||||
|
- Fix --install-hook when there are no config files present for pep8 or
|
||||||
|
flake8.
|
||||||
|
|
||||||
|
- Fix how the setuptools command parses excludes in config files
|
||||||
|
|
||||||
|
- Fix how the git hook determines which files to analyze (Thanks Chris
|
||||||
|
Buccella!)
|
||||||
6
docs/source/release-notes/2.2.5.rst
Normal file
6
docs/source/release-notes/2.2.5.rst
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
2.2.5 - 2014-10-19
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Flush standard out when using multiprocessing
|
||||||
|
|
||||||
|
- Make the check for "# flake8: noqa" more strict
|
||||||
10
docs/source/release-notes/2.3.0.rst
Normal file
10
docs/source/release-notes/2.3.0.rst
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
2.3.0 - 2015-01-04
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- **Feature**: Add ``--output-file`` option to specify a file to write to
|
||||||
|
instead of ``stdout``.
|
||||||
|
|
||||||
|
- **Bug** Fix interleaving of output while using multiprocessing
|
||||||
|
(`GitLab#17`_)
|
||||||
|
|
||||||
|
.. _GitLab#17: https://gitlab.com/pycqa/flake8/issues/17
|
||||||
33
docs/source/release-notes/2.4.0.rst
Normal file
33
docs/source/release-notes/2.4.0.rst
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
2.4.0 - 2015-03-07
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- **Bug** Print filenames when using multiprocessing and ``-q`` option.
|
||||||
|
(`GitLab#31`_)
|
||||||
|
|
||||||
|
- **Bug** Put upper cap on dependencies. The caps for 2.4.0 are:
|
||||||
|
|
||||||
|
- ``pep8 < 1.6`` (Related to `GitLab#35`_)
|
||||||
|
|
||||||
|
- ``mccabe < 0.4``
|
||||||
|
|
||||||
|
- ``pyflakes < 0.9``
|
||||||
|
|
||||||
|
See also `GitLab#32`_
|
||||||
|
|
||||||
|
- **Bug** Files excluded in a config file were not being excluded when flake8
|
||||||
|
was run from a git hook. (`GitHub#2`_)
|
||||||
|
|
||||||
|
- **Improvement** Print warnings for users who are providing mutually
|
||||||
|
exclusive options to flake8. (`GitLab#8`_, `GitLab!18`_)
|
||||||
|
|
||||||
|
- **Feature** Allow git hook configuration to live in ``.git/config``.
|
||||||
|
See the updated `VCS hooks docs`_ for more details. (`GitLab!20`_)
|
||||||
|
|
||||||
|
.. _GitHub#2: https://github.com/pycqa/flake8/pull/2
|
||||||
|
.. _GitLab#8: https://gitlab.com/pycqa/flake8/issues/8
|
||||||
|
.. _GitLab#31: https://gitlab.com/pycqa/flake8/issues/31
|
||||||
|
.. _GitLab#32: https://gitlab.com/pycqa/flake8/issues/32
|
||||||
|
.. _GitLab#35: https://gitlab.com/pycqa/flake8/issues/35
|
||||||
|
.. _GitLab!18: https://gitlab.com/pycqa/flake8/merge_requests/18
|
||||||
|
.. _GitLab!20: https://gitlab.com/pycqa/flake8/merge_requests/20
|
||||||
|
.. _VCS hooks docs: https://flake8.readthedocs.org/en/latest/vcs.html
|
||||||
12
docs/source/release-notes/2.4.1.rst
Normal file
12
docs/source/release-notes/2.4.1.rst
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
2.4.1 - 2015-05-18
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- **Bug** Do not raise a ``SystemError`` unless there were errors in the
|
||||||
|
setuptools command. (`GitLab#39`_, `GitLab!23`_)
|
||||||
|
|
||||||
|
- **Bug** Do not verify dependencies of extensions loaded via entry-points.
|
||||||
|
|
||||||
|
- **Improvement** Blacklist versions of pep8 we know are broken
|
||||||
|
|
||||||
|
.. _GitLab#39: https://gitlab.com/pycqa/flake8/issues/39
|
||||||
|
.. _GitLab!23: https://gitlab.com/pycqa/flake8/merge_requests/23
|
||||||
25
docs/source/release-notes/2.5.0.rst
Normal file
25
docs/source/release-notes/2.5.0.rst
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
2.5.0 - 2015-10-26
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- **Improvement** Raise cap on PyFlakes for Python 3.5 support
|
||||||
|
|
||||||
|
- **Improvement** Avoid deprecation warnings when loading extensions
|
||||||
|
(`GitLab#59`_, `GitLab#90`_)
|
||||||
|
|
||||||
|
- **Improvement** Separate logic to enable "off-by-default" extensions
|
||||||
|
(`GitLab#67`_)
|
||||||
|
|
||||||
|
- **Bug** Properly parse options to setuptools Flake8 command (`GitLab!41`_)
|
||||||
|
|
||||||
|
- **Bug** Fix exceptions when output on stdout is truncated before Flake8
|
||||||
|
finishes writing the output (`GitLab#69`_)
|
||||||
|
|
||||||
|
- **Bug** Fix error on OS X where Flake8 can no longer acquire or create new
|
||||||
|
semaphores (`GitLab#74`_)
|
||||||
|
|
||||||
|
.. _GitLab!41: https://gitlab.com/pycqa/flake8/merge_requests/41
|
||||||
|
.. _GitLab#59: https://gitlab.com/pycqa/flake8/issues/59
|
||||||
|
.. _GitLab#67: https://gitlab.com/pycqa/flake8/issues/67
|
||||||
|
.. _GitLab#69: https://gitlab.com/pycqa/flake8/issues/69
|
||||||
|
.. _GitLab#74: https://gitlab.com/pycqa/flake8/issues/74
|
||||||
|
.. _GitLab#90: https://gitlab.com/pycqa/flake8/issues/90
|
||||||
13
docs/source/release-notes/2.5.1.rst
Normal file
13
docs/source/release-notes/2.5.1.rst
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
2.5.1 - 2015-12-08
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- **Bug** Properly look for ``.flake8`` in current working directory
|
||||||
|
(`GitLab#103`_)
|
||||||
|
|
||||||
|
- **Bug** Monkey-patch ``pep8.stdin_get_value`` to cache the actual value in
|
||||||
|
stdin. This helps plugins relying on the function when run with
|
||||||
|
multiprocessing. (`GitLab#105`_, `GitLab#107`_)
|
||||||
|
|
||||||
|
.. _GitLab#103: https://gitlab.com/pycqa/flake8/issues/103
|
||||||
|
.. _GitLab#105: https://gitlab.com/pycqa/flake8/issues/105
|
||||||
|
.. _GitLab#107: https://gitlab.com/pycqa/flake8/issues/107
|
||||||
7
docs/source/release-notes/2.5.2.rst
Normal file
7
docs/source/release-notes/2.5.2.rst
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
2.5.2 - 2016-01-30
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- **Bug** Parse ``output_file`` and ``enable_extensions`` from config files
|
||||||
|
|
||||||
|
- **Improvement** Raise upper bound on mccabe plugin to allow for version
|
||||||
|
0.4.0
|
||||||
5
docs/source/release-notes/2.5.3.rst
Normal file
5
docs/source/release-notes/2.5.3.rst
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
2.5.3 - 2016-02-11
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- **Bug** Actually parse ``output_file`` and ``enable_extensions`` from config
|
||||||
|
files
|
||||||
4
docs/source/release-notes/2.5.4.rst
Normal file
4
docs/source/release-notes/2.5.4.rst
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
2.5.4 - 2016-02-11
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- **Bug** Missed an attribute rename during the v2.5.3 release.
|
||||||
7
docs/source/release-notes/2.5.5.rst
Normal file
7
docs/source/release-notes/2.5.5.rst
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
2.5.5 - 2016-06-14
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- **Bug** Fix setuptools integration when parsing config files
|
||||||
|
|
||||||
|
- **Bug** Don't pass the user's config path as the config_file when creating a
|
||||||
|
StyleGuide
|
||||||
6
docs/source/release-notes/2.6.1.rst
Normal file
6
docs/source/release-notes/2.6.1.rst
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
2.6.1 - 2016-06-25
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- **Bug** Update the config files to search for to include ``setup.cfg`` and
|
||||||
|
``tox.ini``. This was broken in 2.5.5 when we stopped passing
|
||||||
|
``config_file`` to our Style Guide
|
||||||
42
docs/source/release-notes/3.0.0.rst
Normal file
42
docs/source/release-notes/3.0.0.rst
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
3.0.0b1 -- 2016-06-25
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
- Rewrite our documentation from scratch! (http://flake8.pycqa.org)
|
||||||
|
|
||||||
|
- Drop explicit support for Pythons 2.6, 3.2, and 3.3.
|
||||||
|
|
||||||
|
- Remove dependence on pep8/pycodestyle for file processing, plugin
|
||||||
|
dispatching, and more. We now control all of this while keeping backwards
|
||||||
|
compatibility.
|
||||||
|
|
||||||
|
- ``--select`` and ``--ignore`` can now both be specified and try to find the
|
||||||
|
most specific rule from each. For example, if you do ``--select E --ignore
|
||||||
|
E123`` then we will report everything that starts with ``E`` except for
|
||||||
|
``E123``. Previously, you would have had to do ``--ignore E123,F,W`` which
|
||||||
|
will also still work, but the former should be far more intuitive.
|
||||||
|
|
||||||
|
- Add support for in-line ``# noqa`` comments to specify **only** the error
|
||||||
|
codes to be ignored, e.g., ``# noqa: E123,W503``
|
||||||
|
|
||||||
|
- Add entry-point for formatters as well as a base class that new formatters
|
||||||
|
can inherit from. See the documentation for more details.
|
||||||
|
|
||||||
|
- Add detailed verbose output using the standard library logging module.
|
||||||
|
|
||||||
|
- Enhance our usage of optparse for plugin developers by adding new parameters
|
||||||
|
to the ``add_option`` that plugins use to register new options.
|
||||||
|
|
||||||
|
- Update ``--install-hook`` to require the name of version control system hook
|
||||||
|
you wish to install a Flake8.
|
||||||
|
|
||||||
|
- Stop checking sub-directories more than once via the setuptools command
|
||||||
|
|
||||||
|
- When passing a file on standard-in, allow the caller to specify
|
||||||
|
``--stdin-display-name`` so the output is properly formatted
|
||||||
|
|
||||||
|
- The Git hook now uses ``sys.executable`` to format the shebang line.
|
||||||
|
This allows Flake8 to install a hook script from a virtualenv that points to
|
||||||
|
that virtualenv's Flake8 as opposed to a global one (without the virtualenv
|
||||||
|
being sourced).
|
||||||
|
|
||||||
|
- When using ``--count``, the output is no longer written to stderr.
|
||||||
41
docs/source/release-notes/index.rst
Normal file
41
docs/source/release-notes/index.rst
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
===========================
|
||||||
|
Release Notes and History
|
||||||
|
===========================
|
||||||
|
|
||||||
|
All of the release notes that have been recorded for Flake8 are organized here
|
||||||
|
with the newest releases first.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
3.0.0
|
||||||
|
2.5.5
|
||||||
|
2.5.4
|
||||||
|
2.5.3
|
||||||
|
2.5.2
|
||||||
|
2.5.1
|
||||||
|
2.5.0
|
||||||
|
2.4.1
|
||||||
|
2.4.0
|
||||||
|
2.3.0
|
||||||
|
2.2.5
|
||||||
|
2.2.4
|
||||||
|
2.2.3
|
||||||
|
2.2.2
|
||||||
|
2.2.1
|
||||||
|
2.2.0
|
||||||
|
2.1.0
|
||||||
|
2.0.0
|
||||||
|
1.7.0
|
||||||
|
1.6.2
|
||||||
|
1.6.1
|
||||||
|
1.6.0
|
||||||
|
1.5.0
|
||||||
|
1.4.0
|
||||||
|
1.3.1
|
||||||
|
1.3.0
|
||||||
|
1.2.0
|
||||||
|
1.1.0
|
||||||
|
1.0.0
|
||||||
|
0.9.0
|
||||||
|
0.8.0
|
||||||
|
0.7.0
|
||||||
|
0.6.0
|
||||||
4
docs/source/requirements.txt
Normal file
4
docs/source/requirements.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
sphinx>=1.3.0
|
||||||
|
sphinx_rtd_theme
|
||||||
|
sphinx-prompt
|
||||||
|
configparser
|
||||||
0
docs/source/user/.keep
Normal file
0
docs/source/user/.keep
Normal file
227
docs/source/user/configuration.rst
Normal file
227
docs/source/user/configuration.rst
Normal file
|
|
@ -0,0 +1,227 @@
|
||||||
|
.. _configuration:
|
||||||
|
|
||||||
|
====================
|
||||||
|
Configuring Flake8
|
||||||
|
====================
|
||||||
|
|
||||||
|
Once you have learned how to :ref:`invoke <invocation>` |Flake8|, you will soon
|
||||||
|
want to learn how to configure it so you do not have to specify the same
|
||||||
|
options every time you use it.
|
||||||
|
|
||||||
|
This section will show you how to make
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8
|
||||||
|
|
||||||
|
Remember that you want to specify certain options without writing
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --select E123,W456 --enable-extensions H111
|
||||||
|
|
||||||
|
|
||||||
|
Configuration Locations
|
||||||
|
=======================
|
||||||
|
|
||||||
|
|Flake8| supports storing its configuration in the following places:
|
||||||
|
|
||||||
|
- Your top-level user directory
|
||||||
|
|
||||||
|
- In your project in one of ``setup.cfg``, ``tox.ini``, or ``.flake8``.
|
||||||
|
|
||||||
|
|
||||||
|
"User" Configuration
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
|Flake8| allows a user to use "global" configuration file to store preferences.
|
||||||
|
The user configuration file is expected to be stored somewhere in the user's
|
||||||
|
"home" directory.
|
||||||
|
|
||||||
|
- On Windows the "home" directory will be something like
|
||||||
|
``C:\\Users\sigmavirus24``, a.k.a, ``~\``.
|
||||||
|
|
||||||
|
- On Linux and other Unix like systems (including OS X) we will look in
|
||||||
|
``~/``.
|
||||||
|
|
||||||
|
Note that |Flake8| looks for ``~\.flake8`` on Windows and ``~/.config/flake8``
|
||||||
|
on Linux and other Unix systems.
|
||||||
|
|
||||||
|
User configuration files use the same syntax as Project Configuration files.
|
||||||
|
Keep reading to see that syntax.
|
||||||
|
|
||||||
|
|
||||||
|
Project Configuration
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
|Flake8| is written with the understanding that people organize projects into
|
||||||
|
sub-directories. Let's take for example |Flake8|'s own project structure
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
flake8
|
||||||
|
├── docs
|
||||||
|
│ ├── build
|
||||||
|
│ └── source
|
||||||
|
│ ├── _static
|
||||||
|
│ ├── _templates
|
||||||
|
│ ├── dev
|
||||||
|
│ ├── internal
|
||||||
|
│ └── user
|
||||||
|
├── flake8
|
||||||
|
│ ├── formatting
|
||||||
|
│ ├── main
|
||||||
|
│ ├── options
|
||||||
|
│ └── plugins
|
||||||
|
└── tests
|
||||||
|
├── fixtures
|
||||||
|
│ └── config_files
|
||||||
|
├── integration
|
||||||
|
└── unit
|
||||||
|
|
||||||
|
In the top-level ``flake8`` directory (which contains ``docs``, ``flake8``,
|
||||||
|
and ``tests``) there's also ``tox.ini`` and ``setup.cfg`` files. In our case,
|
||||||
|
we keep our |Flake8| configuration in ``tox.ini``. Regardless of whether you
|
||||||
|
keep your config in ``.flake8``, ``setup.cfg``, or ``tox.ini`` we expect you
|
||||||
|
to use INI to configure |Flake8| (since each of these files already uses INI
|
||||||
|
as a format). This means that any |Flake8| configuration you wish to set needs
|
||||||
|
to be in the ``flake8`` section, which means it needs to start like so:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
|
||||||
|
Each command-line option that you want to specify in your config file can
|
||||||
|
be named in either of two ways:
|
||||||
|
|
||||||
|
#. Using underscores (``_``) instead of hyphens (``-``)
|
||||||
|
|
||||||
|
#. Simply using hyphens (without the leading hyphens)
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Not every |Flake8| command-line option can be specified in the
|
||||||
|
configuration file. See :ref:`our list of options <options-list>` to
|
||||||
|
determine which options will be parsed from the configuration files.
|
||||||
|
|
||||||
|
Let's actually look at |Flake8|'s own configuration section:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
ignore = D203
|
||||||
|
exclude = .git,__pycache__,docs/source/conf.py,old,build,dist
|
||||||
|
max-complexity = 10
|
||||||
|
|
||||||
|
This is equivalent to:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --ignore D203 \
|
||||||
|
--exclude .git,__pycache__,docs/source/conf.py,old,build,dist \
|
||||||
|
--max-complexity 10
|
||||||
|
|
||||||
|
In our case, if we wanted to, we could also do
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
ignore = D203
|
||||||
|
exclude =
|
||||||
|
.git,
|
||||||
|
__pycache__,
|
||||||
|
docs/source/conf.py,
|
||||||
|
old,
|
||||||
|
build,
|
||||||
|
dist
|
||||||
|
max-complexity = 10
|
||||||
|
|
||||||
|
This would allow us to add comments for why we're excluding items, e.g.,
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
ignore = D203
|
||||||
|
exclude =
|
||||||
|
# No need to traverse our git directory
|
||||||
|
.git,
|
||||||
|
# There's no value in checking cache directories
|
||||||
|
__pycache__,
|
||||||
|
# The conf file is mostly autogenerated, ignore it
|
||||||
|
docs/source/conf.py,
|
||||||
|
# The old directory contains Flake8 2.0
|
||||||
|
old,
|
||||||
|
# This contains our built documentation
|
||||||
|
build,
|
||||||
|
# This contains builds of flake8 that we don't want to check
|
||||||
|
dist
|
||||||
|
max-complexity = 10
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If you're using Python 2, you will notice that we download the
|
||||||
|
:mod:`configparser` backport from PyPI. That backport enables us to
|
||||||
|
support this behaviour on all supported versions of Python.
|
||||||
|
|
||||||
|
Please do **not** open issues about this dependency to |Flake8|.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
You can also specify ``--max-complexity`` as ``max_complexity = 10``.
|
||||||
|
|
||||||
|
This is also useful if you have a long list of error codes to ignore. Let's
|
||||||
|
look at a portion of OpenStack's Swift `project configuration`_:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
# it's not a bug that we aren't using all of hacking, ignore:
|
||||||
|
# F812: list comprehension redefines ...
|
||||||
|
# H101: Use TODO(NAME)
|
||||||
|
# H202: assertRaises Exception too broad
|
||||||
|
# H233: Python 3.x incompatible use of print operator
|
||||||
|
# H301: one import per line
|
||||||
|
# H306: imports not in alphabetical order (time, os)
|
||||||
|
# H401: docstring should not start with a space
|
||||||
|
# H403: multi line docstrings should end on a new line
|
||||||
|
# H404: multi line docstring should start without a leading new line
|
||||||
|
# H405: multi line docstring summary not separated with an empty line
|
||||||
|
# H501: Do not use self.__dict__ for string formatting
|
||||||
|
ignore = F812,H101,H202,H233,H301,H306,H401,H403,H404,H405,H501
|
||||||
|
|
||||||
|
They use the comments to describe the check but they could also write this as:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
# it's not a bug that we aren't using all of hacking
|
||||||
|
ignore =
|
||||||
|
# F812: list comprehension redefines ...
|
||||||
|
F812,
|
||||||
|
# H101: Use TODO(NAME)
|
||||||
|
H101,
|
||||||
|
# H202: assertRaises Exception too broad
|
||||||
|
H202,
|
||||||
|
# H233: Python 3.x incompatible use of print operator
|
||||||
|
H233,
|
||||||
|
# H301: one import per line
|
||||||
|
H301,
|
||||||
|
# H306: imports not in alphabetical order (time, os)
|
||||||
|
H306,
|
||||||
|
# H401: docstring should not start with a space
|
||||||
|
H401,
|
||||||
|
# H403: multi line docstrings should end on a new line
|
||||||
|
H403,
|
||||||
|
# H404: multi line docstring should start without a leading new line
|
||||||
|
H404,
|
||||||
|
# H405: multi line docstring summary not separated with an empty line
|
||||||
|
H405,
|
||||||
|
# H501: Do not use self.__dict__ for string formatting
|
||||||
|
H501
|
||||||
|
|
||||||
|
Or they could use each comment to describe **why** they've ignored the check.
|
||||||
|
|Flake8| knows how to parse these lists and will appropriatey handle
|
||||||
|
these situations.
|
||||||
|
|
||||||
|
.. _project configuration:
|
||||||
|
https://github.com/openstack/swift/blob/3944d820387f08372c1a29444f4af7d8e6090ae9/tox.ini#L66..L81
|
||||||
90
docs/source/user/ignoring-errors.rst
Normal file
90
docs/source/user/ignoring-errors.rst
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
=============================
|
||||||
|
Ignoring Errors with Flake8
|
||||||
|
=============================
|
||||||
|
|
||||||
|
By default, |Flake8| has a list of error codes that it ignores. The list used
|
||||||
|
by a version of |Flake8| may be different than the list used by a different
|
||||||
|
version. To see the default list, :option:`flake8 --help` will
|
||||||
|
show the output with the current default list.
|
||||||
|
|
||||||
|
|
||||||
|
Changing the Ignore List
|
||||||
|
========================
|
||||||
|
|
||||||
|
If we want to change the list of ignored codes for a single run, we can use
|
||||||
|
:option:`flake8 --ignore` to specify a comma-separated list of codes for a
|
||||||
|
specific run on the command-line, e.g.,
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --ignore=E1,E23,W503 path/to/files/ path/to/more/files/
|
||||||
|
|
||||||
|
This tells |Flake8| to ignore any error codes starting with ``E1``, ``E23``,
|
||||||
|
or ``W503`` while it is running.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The documentation for :option:`flake8 --ignore` shows examples for how
|
||||||
|
to change the ignore list in the configuration file. See also
|
||||||
|
:ref:`configuration` as well for details about how to use configuration
|
||||||
|
files.
|
||||||
|
|
||||||
|
|
||||||
|
In-line Ignoring Errors
|
||||||
|
=======================
|
||||||
|
|
||||||
|
In some cases, we might not want to ignore an error code (or class of error
|
||||||
|
codes) for the entirety of our project. Instead, we might want to ignore the
|
||||||
|
specific error code on a specific line. Let's take for example a line like
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
example = lambda: 'example'
|
||||||
|
|
||||||
|
Sometimes we genuinely need something this simple. We could instead define
|
||||||
|
a function like we normally would. Note, in some contexts this distracts from
|
||||||
|
what is actually happening. In those cases, we can also do:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
example = lambda: 'example' # noqa: E731
|
||||||
|
|
||||||
|
This will only ignore the error from pycodestyle that checks for lambda
|
||||||
|
assignments and generates an ``E731``. If there are other errors on the line
|
||||||
|
then those will be reported.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If we ever want to disable |Flake8| respecting ``# noqa`` comments, we can
|
||||||
|
can refer to :option:`flake8 --disable-noqa`.
|
||||||
|
|
||||||
|
If we instead had more than one error that we wished to ignore, we could
|
||||||
|
list all of the errors with commas separating them:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# noqa: E731,E123
|
||||||
|
|
||||||
|
Finally, if we have a particularly bad line of code, we can ignore every error
|
||||||
|
using simply ``# noqa`` with nothing after it.
|
||||||
|
|
||||||
|
|
||||||
|
Ignoring Entire Files
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Imagine a situation where we are adding |Flake8| to a codebase. Let's further
|
||||||
|
imagine that with the exception of a few particularly bad files, we can add
|
||||||
|
|Flake8| easily and move on with our lives. There are two ways to ignore the
|
||||||
|
file:
|
||||||
|
|
||||||
|
#. By explicitly adding it to our list of excluded paths (see: :option:`flake8
|
||||||
|
--exclude`)
|
||||||
|
|
||||||
|
#. By adding ``# flake8: noqa`` to the file
|
||||||
|
|
||||||
|
The former is the **recommended** way of ignoring entire files. By using our
|
||||||
|
exclude list, we can include it in our configuration file and have one central
|
||||||
|
place to find what files aren't included in |Flake8| checks. The latter has the
|
||||||
|
benefit that when we run |Flake8| with :option:`flake8 --disable-noqa` all of
|
||||||
|
the errors in that file will show up without having to modify our
|
||||||
|
configuration. Both exist so we can choose which is better for us.
|
||||||
33
docs/source/user/index.rst
Normal file
33
docs/source/user/index.rst
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
==============
|
||||||
|
Using Flake8
|
||||||
|
==============
|
||||||
|
|
||||||
|
|Flake8| can be used in many ways. A few:
|
||||||
|
|
||||||
|
- invoked on the command-line
|
||||||
|
|
||||||
|
- invoked via Python
|
||||||
|
|
||||||
|
- called by Git or Mercurial on or around committing
|
||||||
|
|
||||||
|
This guide will cover all of these and the nuances for using |Flake8|.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This portion of |Flake8|'s documentation does not cover installation. See
|
||||||
|
the :ref:`installation-guide` section for how to install |Flake8|.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
invocation
|
||||||
|
configuration
|
||||||
|
options
|
||||||
|
ignoring-errors
|
||||||
|
using-plugins
|
||||||
|
python-api
|
||||||
|
|
||||||
|
.. config files
|
||||||
|
.. command-line tutorial
|
||||||
|
.. VCS usage
|
||||||
|
.. installing and using plugins
|
||||||
144
docs/source/user/invocation.rst
Normal file
144
docs/source/user/invocation.rst
Normal file
|
|
@ -0,0 +1,144 @@
|
||||||
|
.. _invocation:
|
||||||
|
|
||||||
|
=================
|
||||||
|
Invoking Flake8
|
||||||
|
=================
|
||||||
|
|
||||||
|
Once you have :ref:`installed <installation-guide>` |Flake8|, you can begin
|
||||||
|
using it. Most of the time, you will be able to generically invoke |Flake8|
|
||||||
|
like so:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 ...
|
||||||
|
|
||||||
|
Where you simply allow the shell running in your terminal to locate |Flake8|.
|
||||||
|
In some cases, though, you may have installed |Flake8| for multiple versions
|
||||||
|
of Python (e.g., Python 2.7 and Python 3.5) and you need to call a specific
|
||||||
|
version. In that case, you will have much better results using:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
python2.7 -m flake8
|
||||||
|
|
||||||
|
Or
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
python3.5 -m flake8
|
||||||
|
|
||||||
|
Since that will tell the correct version of Python to run |Flake8|.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Installing |Flake8| once will not install it on both Python 2.7 and
|
||||||
|
Python 3.5. It will only install it for the version of Python that
|
||||||
|
is running pip.
|
||||||
|
|
||||||
|
It is also possible to specify command-line options directly to |Flake8|:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --select E123
|
||||||
|
|
||||||
|
Or
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
python<version> -m flake8 --select E123
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This is the last time we will show both versions of an invocation.
|
||||||
|
From now on, we'll simply use ``flake8`` and assume that the user
|
||||||
|
knows they can instead use ``python<version> -m flake8`` instead.
|
||||||
|
|
||||||
|
It's also possible to narrow what |Flake8| will try to check by specifying
|
||||||
|
exactly the paths and directories you want it to check. Let's assume that
|
||||||
|
we have a directory with python files and sub-directories which have python
|
||||||
|
files (and may have more sub-directories) called ``my_project``. Then if
|
||||||
|
we only want errors from files found inside ``my_project`` we can do:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 my_project
|
||||||
|
|
||||||
|
And if we only want certain errors (e.g., ``E123``) from files in that
|
||||||
|
directory we can also do:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --select E123 my_project
|
||||||
|
|
||||||
|
If you want to explore more options that can be passed on the command-line,
|
||||||
|
you can use the ``--help`` option:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --help
|
||||||
|
|
||||||
|
And you should see something like:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
Usage: flake8 [options] file file ...
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--version show program's version number and exit
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
-v, --verbose Print more information about what is happening in
|
||||||
|
flake8. This option is repeatable and will increase
|
||||||
|
verbosity each time it is repeated.
|
||||||
|
-q, --quiet Report only file names, or nothing. This option is
|
||||||
|
repeatable.
|
||||||
|
--count Print total number of errors and warnings to standard
|
||||||
|
error and set the exit code to 1 if total is not
|
||||||
|
empty.
|
||||||
|
--diff Report changes only within line number ranges in the
|
||||||
|
unified diff provided on standard in by the user.
|
||||||
|
--exclude=patterns Comma-separated list of files or directories to
|
||||||
|
exclude.(Default:
|
||||||
|
.svn,CVS,.bzr,.hg,.git,__pycache__,.tox)
|
||||||
|
--filename=patterns Only check for filenames matching the patterns in this
|
||||||
|
comma-separated list. (Default: *.py)
|
||||||
|
--format=format Format errors according to the chosen formatter.
|
||||||
|
--hang-closing Hang closing bracket instead of matching indentation
|
||||||
|
of opening bracket's line.
|
||||||
|
--ignore=errors Comma-separated list of errors and warnings to ignore
|
||||||
|
(or skip). For example, ``--ignore=E4,E51,W234``.
|
||||||
|
(Default: E121,E123,E126,E226,E24,E704)
|
||||||
|
--max-line-length=n Maximum allowed line length for the entirety of this
|
||||||
|
run. (Default: 79)
|
||||||
|
--select=errors Comma-separated list of errors and warnings to enable.
|
||||||
|
For example, ``--select=E4,E51,W234``. (Default: )
|
||||||
|
--disable-noqa Disable the effect of "# noqa". This will report
|
||||||
|
errors on lines with "# noqa" at the end.
|
||||||
|
--show-source Show the source generate each error or warning.
|
||||||
|
--statistics Count errors and warnings.
|
||||||
|
--enabled-extensions=ENABLED_EXTENSIONS
|
||||||
|
Enable plugins and extensions that are otherwise
|
||||||
|
disabled by default
|
||||||
|
--exit-zero Exit with status code "0" even if there are errors.
|
||||||
|
-j JOBS, --jobs=JOBS Number of subprocesses to use to run checks in
|
||||||
|
parallel. This is ignored on Windows. The default,
|
||||||
|
"auto", will auto-detect the number of processors
|
||||||
|
available to use. (Default: auto)
|
||||||
|
--output-file=OUTPUT_FILE
|
||||||
|
Redirect report to a file.
|
||||||
|
--append-config=APPEND_CONFIG
|
||||||
|
Provide extra config files to parse in addition to the
|
||||||
|
files found by Flake8 by default. These files are the
|
||||||
|
last ones read and so they take the highest precedence
|
||||||
|
when multiple files provide the same option.
|
||||||
|
--config=CONFIG Path to the config file that will be the authoritative
|
||||||
|
config source. This will cause Flake8 to ignore all
|
||||||
|
other configuration files.
|
||||||
|
--isolated Ignore all found configuration files.
|
||||||
|
--builtins=BUILTINS define more built-ins, comma separated
|
||||||
|
--doctests check syntax of the doctests
|
||||||
|
--include-in-doctest=INCLUDE_IN_DOCTEST
|
||||||
|
Run doctests only on these files
|
||||||
|
--exclude-from-doctest=EXCLUDE_FROM_DOCTEST
|
||||||
|
Skip these files when running doctests
|
||||||
|
|
||||||
|
Installed plugins: pyflakes: 1.0.0, pep8: 1.7.0
|
||||||
730
docs/source/user/options.rst
Normal file
730
docs/source/user/options.rst
Normal file
|
|
@ -0,0 +1,730 @@
|
||||||
|
.. _options-list:
|
||||||
|
|
||||||
|
================================================
|
||||||
|
Full Listing of Options and Their Descriptions
|
||||||
|
================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
NOTE(sigmavirus24): When adding new options here, please follow the
|
||||||
|
following _rough_ template:
|
||||||
|
|
||||||
|
.. option:: --<opt-name>[=<descriptive-name-of-parameter>]
|
||||||
|
|
||||||
|
Active description of option's purpose (note that each description
|
||||||
|
starts with an active verb)
|
||||||
|
|
||||||
|
Command-line usage:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --<opt-name>[=<example-parameter(s)>] [positional params]
|
||||||
|
|
||||||
|
This **can[ not]** be specified in config files.
|
||||||
|
|
||||||
|
(If it can be, an example using .. code-block:: ini)
|
||||||
|
|
||||||
|
Thank you for your contribution to Flake8's documentation.
|
||||||
|
|
||||||
|
.. program:: flake8
|
||||||
|
|
||||||
|
.. option:: --version
|
||||||
|
|
||||||
|
Show |Flake8|'s version as well as the versions of all plugins
|
||||||
|
installed.
|
||||||
|
|
||||||
|
Command-line usage:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --version
|
||||||
|
|
||||||
|
This **can not** be specified in config files.
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: -h, --help
|
||||||
|
|
||||||
|
Show a description of how to use |Flake8| and its options.
|
||||||
|
|
||||||
|
Command-line usage:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --help
|
||||||
|
flake8 -h
|
||||||
|
|
||||||
|
This **can not** be specified in config files.
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: -v, --verbose
|
||||||
|
|
||||||
|
Increase the verbosity of |Flake8|'s output. Each time you specify
|
||||||
|
it, it will print more and more information.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 -vv
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
verbose = 2
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: -q, --quiet
|
||||||
|
|
||||||
|
Decrease the verbosity of |Flake8|'s output. Each time you specify it,
|
||||||
|
it will print less and less information.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 -q
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
quiet = 1
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --count
|
||||||
|
|
||||||
|
Print the total number of errors.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --count dir/
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
count = True
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --diff
|
||||||
|
|
||||||
|
Use the unified diff provided on standard in to only check the modified
|
||||||
|
files and report errors included in the diff.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
git diff -u | flake8 --diff
|
||||||
|
|
||||||
|
This **can not** be specified in config files.
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --exclude=<patterns>
|
||||||
|
|
||||||
|
Provide a comma-separated list of glob patterns to exclude from checks.
|
||||||
|
|
||||||
|
This defaults to: ``.svn,CVS,.bzr,.hg,.git,__pycache__,.tox``
|
||||||
|
|
||||||
|
Example patterns:
|
||||||
|
|
||||||
|
- ``*.pyc`` will match any file that ends with ``.pyc``
|
||||||
|
|
||||||
|
- ``__pycache__`` will match any path that has ``__pycache__`` in it
|
||||||
|
|
||||||
|
- ``lib/python`` will look expand that using :func:`os.path.abspath` and
|
||||||
|
look for matching paths
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --exclude=*.pyc dir/
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
exclude =
|
||||||
|
.tox,
|
||||||
|
__pycache__
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --filename=<patterns>
|
||||||
|
|
||||||
|
Provide a comma-separate list of glob patterns to include for checks.
|
||||||
|
|
||||||
|
This defaults to: ``*.py``
|
||||||
|
|
||||||
|
Example patterns:
|
||||||
|
|
||||||
|
- ``*.py`` will match any file that ends with ``.py``
|
||||||
|
|
||||||
|
- ``__pycache__`` will match any path that has ``__pycache__`` in it
|
||||||
|
|
||||||
|
- ``lib/python`` will look expand that using :func:`os.path.abspath` and
|
||||||
|
look for matching paths
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --filename=*.py dir/
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
filename =
|
||||||
|
example.py,
|
||||||
|
another-example*.py
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --stdin-display-name=<display_name>
|
||||||
|
|
||||||
|
Provide the name to use to report warnings and errors from code on stdin.
|
||||||
|
|
||||||
|
Instead of reporting an error as something like:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
stdin:82:73 E501 line too long
|
||||||
|
|
||||||
|
You can specify this option to have it report whatever value you want
|
||||||
|
instead of stdin.
|
||||||
|
|
||||||
|
This defaults to: ``stdin``
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
cat file.py | flake8 --stdin-display-name=file.py -
|
||||||
|
|
||||||
|
This **can not** be specified in config files.
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --format=<format>
|
||||||
|
|
||||||
|
Select the formatter used to display errors to the user.
|
||||||
|
|
||||||
|
This defaults to: ``default``
|
||||||
|
|
||||||
|
By default, there are two formatters available:
|
||||||
|
|
||||||
|
- default
|
||||||
|
- pylint
|
||||||
|
|
||||||
|
Other formatters can be installed. Refer to their documentation for the
|
||||||
|
name to use to select them. Further, users can specify their own format
|
||||||
|
string. The variables available are:
|
||||||
|
|
||||||
|
- code
|
||||||
|
- col
|
||||||
|
- path
|
||||||
|
- row
|
||||||
|
- text
|
||||||
|
|
||||||
|
The default formatter has a format string of:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
'%(path)s:%(row)d:%(col)d: %(code)s %(text)s'
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --format=pylint dir/
|
||||||
|
flake8 --format='%(path)s::%(row)d,%(col)d::%(code)s::%(text)s' dir/
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
format=pylint
|
||||||
|
format=%(path)s::%(row)d,%(col)d::%(code)s::%(text)s
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --hang-closing
|
||||||
|
|
||||||
|
Toggle whether pycodestyle should enforce matching the indentation of the
|
||||||
|
opening bracket's line. When you specify this, it will prefer that you
|
||||||
|
hang the closing bracket rather than match the indentation.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --hang-closing dir/
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
hang_closing = True
|
||||||
|
hang-closing = True
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --ignore=<errors>
|
||||||
|
|
||||||
|
Specify a list of codes to ignore. The list is expected to be
|
||||||
|
comma-separated, and does not need to specify an error code exactly.
|
||||||
|
Since |Flake8| 3.0, this **can** be combined with :option:`--select`. See
|
||||||
|
:option:`--select` for more information.
|
||||||
|
|
||||||
|
For example, if you wish to only ignore ``W234``, then you can specify
|
||||||
|
that. But if you want to ignore all codes that start with ``W23`` you
|
||||||
|
need only specify ``W23`` to ignore them. This also works for ``W2`` and
|
||||||
|
``W`` (for example).
|
||||||
|
|
||||||
|
This defaults to: ``E121,E123,E126,E226,E24,E704``
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --ignore=E121,E123 dir/
|
||||||
|
flake8 --ignore=E24,E704 dir/
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
ignore =
|
||||||
|
E121,
|
||||||
|
E123
|
||||||
|
ignore = E121,E123
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --max-line-length=<n>
|
||||||
|
|
||||||
|
Set the maximum length that any line (with some exceptions) may be.
|
||||||
|
|
||||||
|
Exceptions include lines that are either strings or comments which are
|
||||||
|
entirely URLs. For example:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# https://some-super-long-domain-name.com/with/some/very/long/path
|
||||||
|
|
||||||
|
url = (
|
||||||
|
'http://...'
|
||||||
|
)
|
||||||
|
|
||||||
|
This defaults to: 79
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --max-line-length 99 dir/
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
max-line-length = 79
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --select=<errors>
|
||||||
|
|
||||||
|
Specify the list of error codes you wish |Flake8| to report. Similarly to
|
||||||
|
:option:`--ignore`. You can specify a portion of an error code to get all
|
||||||
|
that start with that string. For example, you can use ``E``, ``E4``,
|
||||||
|
``E43``, and ``E431``.
|
||||||
|
|
||||||
|
This defaults to: E,F,W,C
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --select=E431,E5,W,F dir/
|
||||||
|
flake8 --select=E,W dir/
|
||||||
|
|
||||||
|
This can also be combined with :option:`--ignore`:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --select=E --ignore=E432 dir/
|
||||||
|
|
||||||
|
This will report all codes that start with ``E``, but ignore ``E432``
|
||||||
|
specifically. This is more flexibly than the |Flake8| 2.x and 1.x used
|
||||||
|
to be.
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
select =
|
||||||
|
E431,
|
||||||
|
W,
|
||||||
|
F
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --disable-noqa
|
||||||
|
|
||||||
|
Report all errors, even if it is on the same line as a ``# NOQA`` comment.
|
||||||
|
``# NOQA`` can be used to silence messages on specific lines. Sometimes,
|
||||||
|
users will want to see what errors are being silenced without editing the
|
||||||
|
file. This option allows you to see all the warnings, errors, etc.
|
||||||
|
reported.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --disable-noqa dir/
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
disable_noqa = True
|
||||||
|
disable-noqa = True
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --show-source
|
||||||
|
|
||||||
|
Print the source code generating the error/warning in question.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --show-source dir/
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
show_source = True
|
||||||
|
show-source = True
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --statistics
|
||||||
|
|
||||||
|
Count the number of occurrences of each error/warning code and
|
||||||
|
print a report.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --statistics
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
statistics = True
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --enable-extensions=<errors>
|
||||||
|
|
||||||
|
Enable off-by-default extensions.
|
||||||
|
|
||||||
|
Plugins to |Flake8| have the option of registering themselves as
|
||||||
|
off-by-default. These plugins effectively add themselves to the
|
||||||
|
default ignore list.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --enable-extensions=H111 dir/
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
enable-extensions =
|
||||||
|
H111,
|
||||||
|
G123
|
||||||
|
enable_extensions =
|
||||||
|
H111,
|
||||||
|
G123
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --exit-zero
|
||||||
|
|
||||||
|
Force |Flake8| to use the exit status code 0 even if there are errors.
|
||||||
|
|
||||||
|
By default |Flake8| will exit with a non-zero integer if there are errors.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --exit-zero dir/
|
||||||
|
|
||||||
|
This **can not** be specified in config files.
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --install-hook=VERSION_CONTROL_SYSTEM
|
||||||
|
|
||||||
|
Install a hook for your version control system that is executed before
|
||||||
|
or during commit.
|
||||||
|
|
||||||
|
The available options are:
|
||||||
|
|
||||||
|
- git
|
||||||
|
- mercurial
|
||||||
|
|
||||||
|
Command-line usage:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --install-hook=git
|
||||||
|
flake8 --install-hook=mercurial
|
||||||
|
|
||||||
|
This **can not** be specified in config files.
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --jobs=<n>
|
||||||
|
|
||||||
|
Specify the number of subprocesses that |Flake8| will use to run checks in
|
||||||
|
parallel.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This option is ignored on Windows because :mod:`multiprocessing` does
|
||||||
|
not support Windows across all supported versions of Python.
|
||||||
|
|
||||||
|
This defaults to: ``auto``
|
||||||
|
|
||||||
|
The default behaviour will use the number of CPUs on your machine as
|
||||||
|
reported by :func:`multiprocessing.cpu_count`.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --jobs=8 dir/
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
jobs = 8
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --output-file=<path>
|
||||||
|
|
||||||
|
Redirect all output to the specified file.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --output-file=output.txt dir/
|
||||||
|
flake8 -vv --output-file=output.txt dir/
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
output-file = output.txt
|
||||||
|
output_file = output.txt
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --append-config=<config>
|
||||||
|
|
||||||
|
Provide extra config files to parse in after and in addition to the files
|
||||||
|
that |Flake8| found on its own. Since these files are the last ones read
|
||||||
|
into the Configuration Parser, so it has the highest precedence if it
|
||||||
|
provides an option specified in another config file.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --append-config=my-extra-config.ini dir/
|
||||||
|
|
||||||
|
This **can not** be specified in config files.
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --config=<config>
|
||||||
|
|
||||||
|
Provide a path to a config file that will be the only config file read and
|
||||||
|
used. This will cause |Flake8| to ignore all other config files that
|
||||||
|
exist.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --config=my-only-config.ini dir/
|
||||||
|
|
||||||
|
This **can not** be specified in config files.
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --isolated
|
||||||
|
|
||||||
|
Ignore any config files and use |Flake8| as if there were no config files
|
||||||
|
found.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --isolated dir/
|
||||||
|
|
||||||
|
This **can not** be specified in config files.
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --builtins=<builtins>
|
||||||
|
|
||||||
|
Provide a custom list of builtin functions, objects, names, etc.
|
||||||
|
|
||||||
|
This allows you to let pyflakes know about builtins that it may
|
||||||
|
not immediately recognize so it does not report warnings for using
|
||||||
|
an undefined name.
|
||||||
|
|
||||||
|
This is registered by the default PyFlakes plugin.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --builtins=_,_LE,_LW dir/
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
builtins =
|
||||||
|
_,
|
||||||
|
_LE,
|
||||||
|
_LW
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --doctests
|
||||||
|
|
||||||
|
Enable PyFlakes syntax checking of doctests in docstrings.
|
||||||
|
|
||||||
|
This is registered by the default PyFlakes plugin.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --doctests dir/
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
doctests = True
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --include-in-doctest=<paths>
|
||||||
|
|
||||||
|
Specify which files are checked by PyFlakes for doctest syntax.
|
||||||
|
|
||||||
|
This is registered by the default PyFlakes plugin.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --include-in-doctest=dir/subdir/file.py,dir/other/file.py dir/
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
include-in-doctest =
|
||||||
|
dir/subdir/file.py,
|
||||||
|
dir/other/file.py
|
||||||
|
include_in_doctest =
|
||||||
|
dir/subdir/file.py,
|
||||||
|
dir/other/file.py
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --exclude-from-doctest=<paths>
|
||||||
|
|
||||||
|
Specify which files are not to be checked by PyFlakes for doctest syntax.
|
||||||
|
|
||||||
|
This is registered by the default PyFlakes plugin.
|
||||||
|
|
||||||
|
Command-line example:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --exclude-in-doctest=dir/subdir/file.py,dir/other/file.py dir/
|
||||||
|
|
||||||
|
This **can** be specified in config files.
|
||||||
|
|
||||||
|
Example config file usage:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
exclude-in-doctest =
|
||||||
|
dir/subdir/file.py,
|
||||||
|
dir/other/file.py
|
||||||
|
exclude_in_doctest =
|
||||||
|
dir/subdir/file.py,
|
||||||
|
dir/other/file.py
|
||||||
|
|
||||||
|
|
||||||
|
.. option:: --benchmark
|
||||||
|
|
||||||
|
Collect and print benchmarks for this run of |Flake8|. This aggregates the
|
||||||
|
total number of:
|
||||||
|
|
||||||
|
- tokens
|
||||||
|
- physical lines
|
||||||
|
- logical lines
|
||||||
|
- files
|
||||||
|
|
||||||
|
and the number of elapsed seconds.
|
||||||
|
|
||||||
|
Command-line usage:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --benchmark dir/
|
||||||
|
|
||||||
|
This **can not** be specified in config files.
|
||||||
11
docs/source/user/python-api.rst
Normal file
11
docs/source/user/python-api.rst
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
===================
|
||||||
|
Public Python API
|
||||||
|
===================
|
||||||
|
|
||||||
|
|Flake8| 3.0.0 presently does not have a public, stable Python API.
|
||||||
|
|
||||||
|
When it does it will be located in :mod:`flake8.api` and that will
|
||||||
|
be documented here.
|
||||||
|
|
||||||
|
.. automodule:: flake8.api
|
||||||
|
:members:
|
||||||
66
docs/source/user/using-plugins.rst
Normal file
66
docs/source/user/using-plugins.rst
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
==================================
|
||||||
|
Using Plugins For Fun and Profit
|
||||||
|
==================================
|
||||||
|
|
||||||
|
|Flake8| is useful on its own but a lot of |Flake8|'s popularity is due to
|
||||||
|
its extensibility. Our community has developed :term:`plugin`\ s that augment
|
||||||
|
|Flake8|'s behaviour. Most of these plugins are uploaded to PyPI_. The
|
||||||
|
developers of these plugins often have some style they wish to enforce.
|
||||||
|
|
||||||
|
For example, `flake8-docstrings`_ adds a check for :pep:`257` style
|
||||||
|
conformance. Others attempt to enforce consistency, like `flake8-future`_.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The accuracy or reliability of these plugins may vary wildly from plugin
|
||||||
|
to plugin and not all plugins are guaranteed to work with |Flake8| 3.0.
|
||||||
|
|
||||||
|
To install a third-party plugin, make sure that you know which version of
|
||||||
|
Python (or pip) you used to install |Flake8|. You can then use the most
|
||||||
|
appropriate of:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
pip install <plugin-name>
|
||||||
|
pip3 install <plugin-name>
|
||||||
|
python -m pip install <plugin-name>
|
||||||
|
python2.7 -m pip install <plugin-name>
|
||||||
|
python3 -m pip install <plugin-name>
|
||||||
|
python3.4 -m pip install <plugin-name>
|
||||||
|
python3.5 -m pip install <plugin-name>
|
||||||
|
|
||||||
|
To install the plugin, where ``<plugin-name>`` is the package name on PyPI_.
|
||||||
|
To verify installation use:
|
||||||
|
|
||||||
|
.. prompt:: bash
|
||||||
|
|
||||||
|
flake8 --version
|
||||||
|
python<version> -m flake8 --version
|
||||||
|
|
||||||
|
To see the plugin's name and version in the output.
|
||||||
|
|
||||||
|
.. seealso:: :ref:`How to Invoke Flake8 <invocation>`
|
||||||
|
|
||||||
|
After installation, most plugins immediately start reporting :term:`error`\ s.
|
||||||
|
Check the plugin's documentation for which error codes it returns and if it
|
||||||
|
disables any by default.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
You can use both :option:`flake8 --select` and :option:`flake8 --ignore`
|
||||||
|
with plugins.
|
||||||
|
|
||||||
|
Some plugins register new options, so be sure to check :option:`flake8 --help`
|
||||||
|
for new flags and documentation. These plugins may also allow these flags to
|
||||||
|
be specified in your configuration file. Hopefully, the plugin authors have
|
||||||
|
documented this for you.
|
||||||
|
|
||||||
|
.. seealso:: :ref:`Configuring Flake8 <configuration>`
|
||||||
|
|
||||||
|
|
||||||
|
.. _PyPI:
|
||||||
|
https://pypi.io/
|
||||||
|
.. _flake8-docstrings:
|
||||||
|
https://pypi.io/project/flake8-docstrings/
|
||||||
|
.. _flake8-future:
|
||||||
|
https://pypi.io/project/flake8-future/
|
||||||
50
docs/vcs.rst
50
docs/vcs.rst
|
|
@ -1,50 +0,0 @@
|
||||||
VCS Hooks
|
|
||||||
=========
|
|
||||||
|
|
||||||
flake8 can install hooks for Mercurial and Git so that flake8 is run
|
|
||||||
automatically before commits. The commit will fail if there are any
|
|
||||||
flake8 issues.
|
|
||||||
|
|
||||||
You can install the hook by issuing this command in the root of your
|
|
||||||
project::
|
|
||||||
|
|
||||||
$ flake8 --install-hook
|
|
||||||
|
|
||||||
In the case of Git, the hook won't be installed if a custom
|
|
||||||
``pre-commit`` hook file is already present in
|
|
||||||
the ``.git/hooks`` directory.
|
|
||||||
|
|
||||||
You can control the behavior of the pre-commit hook using configuration file
|
|
||||||
settings or environment variables:
|
|
||||||
|
|
||||||
``flake8.complexity`` or ``FLAKE8_COMPLEXITY``
|
|
||||||
Any value > 0 enables complexity checking with McCabe. (defaults
|
|
||||||
to 10)
|
|
||||||
|
|
||||||
``flake8.strict`` or ``FLAKE8_STRICT``
|
|
||||||
If True, this causes the commit to fail in case of any errors at
|
|
||||||
all. (defaults to False)
|
|
||||||
|
|
||||||
``flake8.ignore`` or ``FLAKE8_IGNORE``
|
|
||||||
Comma-separated list of errors and warnings to ignore. (defaults to
|
|
||||||
empty)
|
|
||||||
|
|
||||||
``flake8.lazy`` or ``FLAKE8_LAZY``
|
|
||||||
If True, also scans those files not added to the index before
|
|
||||||
commit. (defaults to False)
|
|
||||||
|
|
||||||
You can set these either through the git command line
|
|
||||||
|
|
||||||
.. code-block:: bash-session
|
|
||||||
|
|
||||||
$ git config flake8.complexity 10
|
|
||||||
$ git config flake8.strict true
|
|
||||||
|
|
||||||
Or by directly editing ``.git/config`` and adding a section like
|
|
||||||
|
|
||||||
.. code-block:: ini
|
|
||||||
|
|
||||||
[flake8]
|
|
||||||
complexity = 10
|
|
||||||
strict = true
|
|
||||||
lazy = false
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
.. _error-codes:
|
|
||||||
|
|
||||||
Warning / Error codes
|
|
||||||
=====================
|
|
||||||
|
|
||||||
The convention of Flake8 is to assign a code to each error or warning, like
|
|
||||||
the ``pycodestyle`` tool. These codes are used to configure the list of errors
|
|
||||||
which are selected or ignored.
|
|
||||||
|
|
||||||
Each code consists of an upper case ASCII letter followed by three digits.
|
|
||||||
The recommendation is to use a different prefix for each plugin. A list of the
|
|
||||||
known prefixes is published below:
|
|
||||||
|
|
||||||
- ``E***``/``W***``: `pycodestyle errors and warnings
|
|
||||||
<https://pycodestyle.readthedocs.io/en/latest/intro.html#error-codes>`_
|
|
||||||
- ``F***``: PyFlakes codes (see below)
|
|
||||||
- ``C9**``: McCabe complexity plugin `mccabe
|
|
||||||
<https://github.com/flintwork/mccabe>`_
|
|
||||||
- ``N8**``: Naming Conventions plugin `pep8-naming
|
|
||||||
<https://github.com/flintwork/pep8-naming>`_
|
|
||||||
|
|
||||||
|
|
||||||
The original PyFlakes does not provide error codes. Flake8 patches the
|
|
||||||
PyFlakes messages to add the following codes:
|
|
||||||
|
|
||||||
+------+--------------------------------------------------------------------+
|
|
||||||
| code | sample message |
|
|
||||||
+======+====================================================================+
|
|
||||||
| F401 | ``module`` imported but unused |
|
|
||||||
+------+--------------------------------------------------------------------+
|
|
||||||
| F402 | import ``module`` from line ``N`` shadowed by loop variable |
|
|
||||||
+------+--------------------------------------------------------------------+
|
|
||||||
| F403 | 'from ``module`` import \*' used; unable to detect undefined names |
|
|
||||||
+------+--------------------------------------------------------------------+
|
|
||||||
| F404 | future import(s) ``name`` after other statements |
|
|
||||||
+------+--------------------------------------------------------------------+
|
|
||||||
| F405 | ``name`` may be undefined, or defined from star imports: ``module``|
|
|
||||||
+------+--------------------------------------------------------------------+
|
|
||||||
+------+--------------------------------------------------------------------+
|
|
||||||
| F811 | redefinition of unused ``name`` from line ``N`` |
|
|
||||||
+------+--------------------------------------------------------------------+
|
|
||||||
| F812 | list comprehension redefines ``name`` from line ``N`` |
|
|
||||||
+------+--------------------------------------------------------------------+
|
|
||||||
| F821 | undefined name ``name`` |
|
|
||||||
+------+--------------------------------------------------------------------+
|
|
||||||
| F822 | undefined name ``name`` in __all__ |
|
|
||||||
+------+--------------------------------------------------------------------+
|
|
||||||
| F823 | local variable ``name`` ... referenced before assignment |
|
|
||||||
+------+--------------------------------------------------------------------+
|
|
||||||
| F831 | duplicate argument ``name`` in function definition |
|
|
||||||
+------+--------------------------------------------------------------------+
|
|
||||||
| F841 | local variable ``name`` is assigned to but never used |
|
|
||||||
+------+--------------------------------------------------------------------+
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
__version__ = '2.6.1'
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
from flake8.main import main
|
|
||||||
|
|
||||||
# python -m flake8 (with Python >= 2.7)
|
|
||||||
main()
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
import atexit
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def install_vcs_hook(option, option_str, value, parser):
|
|
||||||
# For now, there's no way to affect a change in how pep8 processes
|
|
||||||
# options. If no args are provided and there's no config file present,
|
|
||||||
# it will error out because no input was provided. To get around this,
|
|
||||||
# when we're using --install-hook, we'll say that there were arguments so
|
|
||||||
# we can actually attempt to install the hook.
|
|
||||||
# See: https://gitlab.com/pycqa/flake8/issues/2 and
|
|
||||||
# https://github.com/jcrocholl/pep8/blob/4c5bf00cb613be617c7f48d3b2b82a1c7b895ac1/pep8.py#L1912
|
|
||||||
# for more context.
|
|
||||||
parser.values.install_hook = True
|
|
||||||
parser.rargs.append('.')
|
|
||||||
|
|
||||||
|
|
||||||
def restore_stdout(old_stdout):
|
|
||||||
sys.stdout.close()
|
|
||||||
sys.stdout = old_stdout
|
|
||||||
|
|
||||||
|
|
||||||
def redirect_stdout(option, option_str, value, parser):
|
|
||||||
fd = open(value, 'w')
|
|
||||||
old_stdout, sys.stdout = sys.stdout, fd
|
|
||||||
|
|
||||||
atexit.register(restore_stdout, old_stdout)
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""Compatibility shims for Flake8."""
|
|
||||||
import os.path
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def relpath(path, start='.'):
|
|
||||||
"""Wallpaper over the differences between 2.6 and newer versions."""
|
|
||||||
if sys.version_info < (2, 7) and path.startswith(start):
|
|
||||||
return path[len(start):]
|
|
||||||
else:
|
|
||||||
return os.path.relpath(path, start=start)
|
|
||||||
316
flake8/engine.py
316
flake8/engine.py
|
|
@ -1,316 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
import errno
|
|
||||||
import io
|
|
||||||
import platform
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
import pycodestyle as pep8
|
|
||||||
|
|
||||||
from flake8 import __version__
|
|
||||||
from flake8 import callbacks
|
|
||||||
from flake8.reporter import (multiprocessing, BaseQReport, FileQReport,
|
|
||||||
QueueReport)
|
|
||||||
from flake8 import util
|
|
||||||
|
|
||||||
_flake8_noqa = re.compile(r'\s*# flake8[:=]\s*noqa', re.I).search
|
|
||||||
|
|
||||||
EXTRA_EXCLUDE = ['.tox', '.eggs', '*.egg']
|
|
||||||
|
|
||||||
pep8.PROJECT_CONFIG = ('.flake8',) + pep8.PROJECT_CONFIG
|
|
||||||
|
|
||||||
|
|
||||||
def _load_entry_point(entry_point, verify_requirements):
|
|
||||||
"""Based on the version of setuptools load an entry-point correctly.
|
|
||||||
|
|
||||||
setuptools 11.3 deprecated `require=False` in the call to EntryPoint.load.
|
|
||||||
To load entry points correctly after that without requiring all
|
|
||||||
dependencies be present, the proper way is to call EntryPoint.resolve.
|
|
||||||
|
|
||||||
This function will provide backwards compatibility for older versions of
|
|
||||||
setuptools while also ensuring we do the right thing for the future.
|
|
||||||
"""
|
|
||||||
if hasattr(entry_point, 'resolve') and hasattr(entry_point, 'require'):
|
|
||||||
if verify_requirements:
|
|
||||||
entry_point.require()
|
|
||||||
plugin = entry_point.resolve()
|
|
||||||
else:
|
|
||||||
plugin = entry_point.load(require=verify_requirements)
|
|
||||||
|
|
||||||
return plugin
|
|
||||||
|
|
||||||
|
|
||||||
def _register_extensions():
|
|
||||||
"""Register all the extensions."""
|
|
||||||
extensions = util.OrderedSet()
|
|
||||||
extensions.add(('pycodestyle', pep8.__version__))
|
|
||||||
parser_hooks = []
|
|
||||||
options_hooks = []
|
|
||||||
ignored_hooks = []
|
|
||||||
try:
|
|
||||||
from pkg_resources import iter_entry_points
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
for entry in iter_entry_points('flake8.extension'):
|
|
||||||
# Do not verify that the requirements versions are valid
|
|
||||||
checker = _load_entry_point(entry, verify_requirements=False)
|
|
||||||
pep8.register_check(checker, codes=[entry.name])
|
|
||||||
extensions.add((checker.name, checker.version))
|
|
||||||
if hasattr(checker, 'add_options'):
|
|
||||||
parser_hooks.append(checker.add_options)
|
|
||||||
if hasattr(checker, 'parse_options'):
|
|
||||||
options_hooks.append(checker.parse_options)
|
|
||||||
if getattr(checker, 'off_by_default', False) is True:
|
|
||||||
ignored_hooks.append(entry.name)
|
|
||||||
return extensions, parser_hooks, options_hooks, ignored_hooks
|
|
||||||
|
|
||||||
|
|
||||||
def get_parser():
|
|
||||||
"""This returns an instance of optparse.OptionParser with all the
|
|
||||||
extensions registered and options set. This wraps ``pep8.get_parser``.
|
|
||||||
"""
|
|
||||||
(extensions, parser_hooks, options_hooks, ignored) = _register_extensions()
|
|
||||||
details = ', '.join('%s: %s' % ext for ext in extensions)
|
|
||||||
python_version = get_python_version()
|
|
||||||
parser = pep8.get_parser('flake8', '%s (%s) %s' % (
|
|
||||||
__version__, details, python_version
|
|
||||||
))
|
|
||||||
for opt in ('--repeat', '--testsuite', '--doctest'):
|
|
||||||
try:
|
|
||||||
parser.remove_option(opt)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if multiprocessing:
|
|
||||||
parser.config_options.append('jobs')
|
|
||||||
parser.add_option('-j', '--jobs', type='string', default='auto',
|
|
||||||
help="number of jobs to run simultaneously, "
|
|
||||||
"or 'auto'. This is ignored on Windows.")
|
|
||||||
|
|
||||||
parser.add_option('--exit-zero', action='store_true',
|
|
||||||
help="exit with code 0 even if there are errors")
|
|
||||||
for parser_hook in parser_hooks:
|
|
||||||
parser_hook(parser)
|
|
||||||
# See comment above regarding why this has to be a callback.
|
|
||||||
parser.add_option('--install-hook', default=False, dest='install_hook',
|
|
||||||
help='Install the appropriate hook for this '
|
|
||||||
'repository.', action='callback',
|
|
||||||
callback=callbacks.install_vcs_hook)
|
|
||||||
parser.add_option('--output-file', default=None,
|
|
||||||
help='Redirect report to a file.',
|
|
||||||
type='string', nargs=1, action='callback',
|
|
||||||
callback=callbacks.redirect_stdout)
|
|
||||||
parser.add_option('--enable-extensions', default='',
|
|
||||||
dest='enable_extensions',
|
|
||||||
help='Enable plugins and extensions that are disabled '
|
|
||||||
'by default',
|
|
||||||
type='string')
|
|
||||||
parser.config_options.extend(['output-file', 'enable-extensions'])
|
|
||||||
parser.ignored_extensions = ignored
|
|
||||||
return parser, options_hooks
|
|
||||||
|
|
||||||
|
|
||||||
class NoQAStyleGuide(pep8.StyleGuide):
|
|
||||||
|
|
||||||
def input_file(self, filename, lines=None, expected=None, line_offset=0):
|
|
||||||
"""Run all checks on a Python source file."""
|
|
||||||
if self.options.verbose:
|
|
||||||
print('checking %s' % filename)
|
|
||||||
fchecker = self.checker_class(
|
|
||||||
filename, lines=lines, options=self.options)
|
|
||||||
# Any "flake8: noqa" comments to ignore the entire file?
|
|
||||||
if any(_flake8_noqa(line) for line in fchecker.lines):
|
|
||||||
return 0
|
|
||||||
return fchecker.check_all(expected=expected, line_offset=line_offset)
|
|
||||||
|
|
||||||
|
|
||||||
class StyleGuide(object):
|
|
||||||
"""A wrapper StyleGuide object for Flake8 usage.
|
|
||||||
|
|
||||||
This allows for OSErrors to be caught in the styleguide and special logic
|
|
||||||
to be used to handle those errors.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Reasoning for error numbers is in-line below
|
|
||||||
serial_retry_errors = set([
|
|
||||||
# ENOSPC: Added by sigmavirus24
|
|
||||||
# > On some operating systems (OSX), multiprocessing may cause an
|
|
||||||
# > ENOSPC error while trying to trying to create a Semaphore.
|
|
||||||
# > In those cases, we should replace the customized Queue Report
|
|
||||||
# > class with pep8's StandardReport class to ensure users don't run
|
|
||||||
# > into this problem.
|
|
||||||
# > (See also: https://gitlab.com/pycqa/flake8/issues/74)
|
|
||||||
errno.ENOSPC,
|
|
||||||
# NOTE(sigmavirus24): When adding to this list, include the reasoning
|
|
||||||
# on the lines before the error code and always append your error
|
|
||||||
# code. Further, please always add a trailing `,` to reduce the visual
|
|
||||||
# noise in diffs.
|
|
||||||
])
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
# This allows us to inject a mocked StyleGuide in the tests.
|
|
||||||
self._styleguide = kwargs.pop('styleguide', NoQAStyleGuide(**kwargs))
|
|
||||||
|
|
||||||
@property
|
|
||||||
def options(self):
|
|
||||||
return self._styleguide.options
|
|
||||||
|
|
||||||
@property
|
|
||||||
def paths(self):
|
|
||||||
return self._styleguide.paths
|
|
||||||
|
|
||||||
def _retry_serial(self, func, *args, **kwargs):
|
|
||||||
"""This will retry the passed function in serial if necessary.
|
|
||||||
|
|
||||||
In the event that we encounter an OSError with an errno in
|
|
||||||
:attr:`serial_retry_errors`, this function will retry this function
|
|
||||||
using pep8's default Report class which operates in serial.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return func(*args, **kwargs)
|
|
||||||
except OSError as oserr:
|
|
||||||
if oserr.errno in self.serial_retry_errors:
|
|
||||||
self.init_report(pep8.StandardReport)
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
return func(*args, **kwargs)
|
|
||||||
|
|
||||||
def check_files(self, paths=None):
|
|
||||||
return self._retry_serial(self._styleguide.check_files, paths=paths)
|
|
||||||
|
|
||||||
def excluded(self, filename, parent=None):
|
|
||||||
return self._styleguide.excluded(filename, parent=parent)
|
|
||||||
|
|
||||||
def init_report(self, reporter=None):
|
|
||||||
return self._styleguide.init_report(reporter)
|
|
||||||
|
|
||||||
def input_file(self, filename, lines=None, expected=None, line_offset=0):
|
|
||||||
return self._retry_serial(
|
|
||||||
self._styleguide.input_file,
|
|
||||||
filename=filename,
|
|
||||||
lines=lines,
|
|
||||||
expected=expected,
|
|
||||||
line_offset=line_offset,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _parse_multi_options(options, split_token=','):
|
|
||||||
r"""Split and strip and discard empties.
|
|
||||||
|
|
||||||
Turns the following:
|
|
||||||
|
|
||||||
A,
|
|
||||||
B,
|
|
||||||
|
|
||||||
into ["A", "B"].
|
|
||||||
|
|
||||||
Credit: Kristian Glass as contributed to pep8
|
|
||||||
"""
|
|
||||||
if options:
|
|
||||||
return [o.strip() for o in options.split(split_token) if o.strip()]
|
|
||||||
else:
|
|
||||||
return options
|
|
||||||
|
|
||||||
|
|
||||||
def _disable_extensions(parser, options):
|
|
||||||
ignored_extensions = set(getattr(parser, 'ignored_extensions', []))
|
|
||||||
enabled = set(_parse_multi_options(options.enable_extensions))
|
|
||||||
|
|
||||||
# Remove any of the selected extensions from the extensions ignored by
|
|
||||||
# default.
|
|
||||||
ignored_extensions -= enabled
|
|
||||||
|
|
||||||
# Whatever is left afterwards should be unioned with options.ignore and
|
|
||||||
# options.ignore should be updated with that.
|
|
||||||
options.ignore = tuple(ignored_extensions.union(options.ignore))
|
|
||||||
|
|
||||||
|
|
||||||
def get_style_guide(**kwargs):
|
|
||||||
"""Parse the options and configure the checker. This returns a sub-class
|
|
||||||
of ``pep8.StyleGuide``."""
|
|
||||||
kwargs['parser'], options_hooks = get_parser()
|
|
||||||
styleguide = StyleGuide(**kwargs)
|
|
||||||
options = styleguide.options
|
|
||||||
_disable_extensions(kwargs['parser'], options)
|
|
||||||
|
|
||||||
if options.exclude and not isinstance(options.exclude, list):
|
|
||||||
options.exclude = pep8.normalize_paths(options.exclude)
|
|
||||||
elif not options.exclude:
|
|
||||||
options.exclude = []
|
|
||||||
|
|
||||||
# Add patterns in EXTRA_EXCLUDE to the list of excluded patterns
|
|
||||||
options.exclude.extend(pep8.normalize_paths(EXTRA_EXCLUDE))
|
|
||||||
|
|
||||||
for options_hook in options_hooks:
|
|
||||||
options_hook(options)
|
|
||||||
|
|
||||||
if util.warn_when_using_jobs(options):
|
|
||||||
if not multiprocessing:
|
|
||||||
warnings.warn("The multiprocessing module is not available. "
|
|
||||||
"Ignoring --jobs arguments.")
|
|
||||||
if util.is_windows():
|
|
||||||
warnings.warn("The --jobs option is not available on Windows. "
|
|
||||||
"Ignoring --jobs arguments.")
|
|
||||||
if util.is_using_stdin(styleguide.paths):
|
|
||||||
warnings.warn("The --jobs option is not compatible with supplying "
|
|
||||||
"input using - . Ignoring --jobs arguments.")
|
|
||||||
if options.diff:
|
|
||||||
warnings.warn("The --diff option was specified with --jobs but "
|
|
||||||
"they are not compatible. Ignoring --jobs arguments."
|
|
||||||
)
|
|
||||||
|
|
||||||
if options.diff:
|
|
||||||
options.jobs = None
|
|
||||||
|
|
||||||
force_disable_jobs = util.force_disable_jobs(styleguide)
|
|
||||||
|
|
||||||
if multiprocessing and options.jobs and not force_disable_jobs:
|
|
||||||
if options.jobs.isdigit():
|
|
||||||
n_jobs = int(options.jobs)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
n_jobs = multiprocessing.cpu_count()
|
|
||||||
except NotImplementedError:
|
|
||||||
n_jobs = 1
|
|
||||||
if n_jobs > 1:
|
|
||||||
options.jobs = n_jobs
|
|
||||||
reporter = QueueReport
|
|
||||||
if options.quiet:
|
|
||||||
reporter = BaseQReport
|
|
||||||
if options.quiet == 1:
|
|
||||||
reporter = FileQReport
|
|
||||||
report = styleguide.init_report(reporter)
|
|
||||||
report.input_file = styleguide.input_file
|
|
||||||
styleguide.runner = report.task_queue.put
|
|
||||||
|
|
||||||
return styleguide
|
|
||||||
|
|
||||||
|
|
||||||
def get_python_version():
|
|
||||||
# The implementation isn't all that important.
|
|
||||||
try:
|
|
||||||
impl = platform.python_implementation() + " "
|
|
||||||
except AttributeError: # Python 2.5
|
|
||||||
impl = ''
|
|
||||||
return '%s%s on %s' % (impl, platform.python_version(), platform.system())
|
|
||||||
|
|
||||||
|
|
||||||
def make_stdin_get_value(original):
|
|
||||||
def stdin_get_value():
|
|
||||||
if not hasattr(stdin_get_value, 'cached_stdin'):
|
|
||||||
value = original()
|
|
||||||
if sys.version_info < (3, 0):
|
|
||||||
stdin = io.BytesIO(value)
|
|
||||||
else:
|
|
||||||
stdin = io.StringIO(value)
|
|
||||||
stdin_get_value.cached_stdin = stdin
|
|
||||||
else:
|
|
||||||
stdin = stdin_get_value.cached_stdin
|
|
||||||
return stdin.getvalue()
|
|
||||||
|
|
||||||
return stdin_get_value
|
|
||||||
|
|
||||||
|
|
||||||
pep8.stdin_get_value = make_stdin_get_value(pep8.stdin_get_value)
|
|
||||||
295
flake8/hooks.py
295
flake8/hooks.py
|
|
@ -1,295 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import with_statement
|
|
||||||
import os
|
|
||||||
import pycodestyle as pep8
|
|
||||||
import sys
|
|
||||||
import stat
|
|
||||||
from subprocess import Popen, PIPE
|
|
||||||
import shutil
|
|
||||||
import tempfile
|
|
||||||
try:
|
|
||||||
from configparser import ConfigParser
|
|
||||||
except ImportError: # Python 2
|
|
||||||
from ConfigParser import ConfigParser
|
|
||||||
|
|
||||||
from flake8 import compat
|
|
||||||
from flake8.engine import get_parser, get_style_guide
|
|
||||||
|
|
||||||
|
|
||||||
def git_hook(complexity=-1, strict=False, ignore=None, lazy=False):
|
|
||||||
"""This is the function used by the git hook.
|
|
||||||
|
|
||||||
:param int complexity: (optional), any value > 0 enables complexity
|
|
||||||
checking with mccabe
|
|
||||||
:param bool strict: (optional), if True, this returns the total number of
|
|
||||||
errors which will cause the hook to fail
|
|
||||||
:param str ignore: (optional), a comma-separated list of errors and
|
|
||||||
warnings to ignore
|
|
||||||
:param bool lazy: (optional), allows for the instances where you don't add
|
|
||||||
the files to the index before running a commit, e.g., git commit -a
|
|
||||||
:returns: total number of errors if strict is True, otherwise 0
|
|
||||||
"""
|
|
||||||
gitcmd = "git diff-index --cached --name-only --diff-filter=ACMRTUXB HEAD"
|
|
||||||
if lazy:
|
|
||||||
# Catch all files, including those not added to the index
|
|
||||||
gitcmd = gitcmd.replace('--cached ', '')
|
|
||||||
|
|
||||||
if hasattr(ignore, 'split'):
|
|
||||||
ignore = ignore.split(',')
|
|
||||||
|
|
||||||
# Returns the exit code, list of files modified, list of error messages
|
|
||||||
_, files_modified, _ = run(gitcmd)
|
|
||||||
|
|
||||||
# We only want to pass ignore and max_complexity if they differ from the
|
|
||||||
# defaults so that we don't override a local configuration file
|
|
||||||
options = {}
|
|
||||||
if ignore:
|
|
||||||
options['ignore'] = ignore
|
|
||||||
if complexity > -1:
|
|
||||||
options['max_complexity'] = complexity
|
|
||||||
|
|
||||||
tmpdir = tempfile.mkdtemp()
|
|
||||||
|
|
||||||
flake8_style = get_style_guide(paths=['.'], **options)
|
|
||||||
filepatterns = flake8_style.options.filename
|
|
||||||
|
|
||||||
# Copy staged versions to temporary directory
|
|
||||||
files_to_check = []
|
|
||||||
try:
|
|
||||||
for file_ in files_modified:
|
|
||||||
# get the staged version of the file
|
|
||||||
gitcmd_getstaged = "git show :%s" % file_
|
|
||||||
_, out, _ = run(gitcmd_getstaged, raw_output=True, decode=False)
|
|
||||||
# write the staged version to temp dir with its full path to
|
|
||||||
# avoid overwriting files with the same name
|
|
||||||
dirname, filename = os.path.split(os.path.abspath(file_))
|
|
||||||
prefix = os.path.commonprefix([dirname, tmpdir])
|
|
||||||
dirname = compat.relpath(dirname, start=prefix)
|
|
||||||
dirname = os.path.join(tmpdir, dirname)
|
|
||||||
if not os.path.isdir(dirname):
|
|
||||||
os.makedirs(dirname)
|
|
||||||
|
|
||||||
# check_files() only does this check if passed a dir; so we do it
|
|
||||||
if ((pep8.filename_match(file_, filepatterns) and
|
|
||||||
not flake8_style.excluded(file_))):
|
|
||||||
|
|
||||||
filename = os.path.join(dirname, filename)
|
|
||||||
files_to_check.append(filename)
|
|
||||||
# write staged version of file to temporary directory
|
|
||||||
with open(filename, "wb") as fh:
|
|
||||||
fh.write(out)
|
|
||||||
|
|
||||||
# Run the checks
|
|
||||||
report = flake8_style.check_files(files_to_check)
|
|
||||||
# remove temporary directory
|
|
||||||
finally:
|
|
||||||
shutil.rmtree(tmpdir, ignore_errors=True)
|
|
||||||
|
|
||||||
if strict:
|
|
||||||
return report.total_errors
|
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def hg_hook(ui, repo, **kwargs):
|
|
||||||
"""This is the function executed directly by Mercurial as part of the
|
|
||||||
hook. This is never called directly by the user, so the parameters are
|
|
||||||
undocumented. If you would like to learn more about them, please feel free
|
|
||||||
to read the official Mercurial documentation.
|
|
||||||
"""
|
|
||||||
complexity = ui.config('flake8', 'complexity', default=-1)
|
|
||||||
strict = ui.configbool('flake8', 'strict', default=True)
|
|
||||||
ignore = ui.config('flake8', 'ignore', default=None)
|
|
||||||
config = ui.config('flake8', 'config', default=None)
|
|
||||||
|
|
||||||
paths = _get_files(repo, **kwargs)
|
|
||||||
|
|
||||||
# We only want to pass ignore and max_complexity if they differ from the
|
|
||||||
# defaults so that we don't override a local configuration file
|
|
||||||
options = {}
|
|
||||||
if ignore:
|
|
||||||
options['ignore'] = ignore
|
|
||||||
if complexity > -1:
|
|
||||||
options['max_complexity'] = complexity
|
|
||||||
|
|
||||||
flake8_style = get_style_guide(config_file=config, paths=['.'],
|
|
||||||
**options)
|
|
||||||
report = flake8_style.check_files(paths)
|
|
||||||
|
|
||||||
if strict:
|
|
||||||
return report.total_errors
|
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def run(command, raw_output=False, decode=True):
|
|
||||||
p = Popen(command.split(), stdout=PIPE, stderr=PIPE)
|
|
||||||
(stdout, stderr) = p.communicate()
|
|
||||||
# On python 3, subprocess.Popen returns bytes objects which expect
|
|
||||||
# endswith to be given a bytes object or a tuple of bytes but not native
|
|
||||||
# string objects. This is simply less mysterious than using b'.py' in the
|
|
||||||
# endswith method. That should work but might still fail horribly.
|
|
||||||
if decode:
|
|
||||||
if hasattr(stdout, 'decode'):
|
|
||||||
stdout = stdout.decode('utf-8')
|
|
||||||
if hasattr(stderr, 'decode'):
|
|
||||||
stderr = stderr.decode('utf-8')
|
|
||||||
if not raw_output:
|
|
||||||
stdout = [line.strip() for line in stdout.splitlines()]
|
|
||||||
stderr = [line.strip() for line in stderr.splitlines()]
|
|
||||||
return (p.returncode, stdout, stderr)
|
|
||||||
|
|
||||||
|
|
||||||
def _get_files(repo, **kwargs):
|
|
||||||
seen = set()
|
|
||||||
for rev in range(repo[kwargs['node']], len(repo)):
|
|
||||||
for file_ in repo[rev].files():
|
|
||||||
file_ = os.path.join(repo.root, file_)
|
|
||||||
if file_ in seen or not os.path.exists(file_):
|
|
||||||
continue
|
|
||||||
seen.add(file_)
|
|
||||||
if file_.endswith('.py'):
|
|
||||||
yield file_
|
|
||||||
|
|
||||||
|
|
||||||
def find_vcs():
|
|
||||||
try:
|
|
||||||
_, git_dir, _ = run('git rev-parse --git-dir')
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if git_dir and os.path.isdir(git_dir[0]):
|
|
||||||
if not os.path.isdir(os.path.join(git_dir[0], 'hooks')):
|
|
||||||
os.mkdir(os.path.join(git_dir[0], 'hooks'))
|
|
||||||
return os.path.join(git_dir[0], 'hooks', 'pre-commit')
|
|
||||||
try:
|
|
||||||
_, hg_dir, _ = run('hg root')
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if hg_dir and os.path.isdir(hg_dir[0]):
|
|
||||||
return os.path.join(hg_dir[0], '.hg', 'hgrc')
|
|
||||||
return ''
|
|
||||||
|
|
||||||
|
|
||||||
def get_git_config(option, opt_type='', convert_type=True):
|
|
||||||
# type can be --bool, --int or an empty string
|
|
||||||
_, git_cfg_value, _ = run('git config --get %s %s' % (opt_type, option),
|
|
||||||
raw_output=True)
|
|
||||||
git_cfg_value = git_cfg_value.strip()
|
|
||||||
if not convert_type:
|
|
||||||
return git_cfg_value
|
|
||||||
if opt_type == '--bool':
|
|
||||||
git_cfg_value = git_cfg_value.lower() == 'true'
|
|
||||||
elif git_cfg_value and opt_type == '--int':
|
|
||||||
git_cfg_value = int(git_cfg_value)
|
|
||||||
return git_cfg_value
|
|
||||||
|
|
||||||
|
|
||||||
_params = {
|
|
||||||
'FLAKE8_COMPLEXITY': '--int',
|
|
||||||
'FLAKE8_STRICT': '--bool',
|
|
||||||
'FLAKE8_IGNORE': '',
|
|
||||||
'FLAKE8_LAZY': '--bool',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def get_git_param(option, default=''):
|
|
||||||
global _params
|
|
||||||
opt_type = _params[option]
|
|
||||||
param_value = get_git_config(option.lower().replace('_', '.'),
|
|
||||||
opt_type=opt_type, convert_type=False)
|
|
||||||
if param_value == '':
|
|
||||||
param_value = os.environ.get(option, default)
|
|
||||||
if opt_type == '--bool' and not isinstance(param_value, bool):
|
|
||||||
param_value = param_value.lower() == 'true'
|
|
||||||
elif param_value and opt_type == '--int':
|
|
||||||
param_value = int(param_value)
|
|
||||||
return param_value
|
|
||||||
|
|
||||||
|
|
||||||
git_hook_file = """#!/usr/bin/env python
|
|
||||||
import sys
|
|
||||||
from flake8.hooks import git_hook, get_git_param
|
|
||||||
|
|
||||||
# `get_git_param` will retrieve configuration from your local git config and
|
|
||||||
# then fall back to using the environment variables that the hook has always
|
|
||||||
# supported.
|
|
||||||
# For example, to set the complexity, you'll need to do:
|
|
||||||
# git config flake8.complexity 10
|
|
||||||
COMPLEXITY = get_git_param('FLAKE8_COMPLEXITY', 10)
|
|
||||||
STRICT = get_git_param('FLAKE8_STRICT', False)
|
|
||||||
IGNORE = get_git_param('FLAKE8_IGNORE', None)
|
|
||||||
LAZY = get_git_param('FLAKE8_LAZY', False)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(git_hook(
|
|
||||||
complexity=COMPLEXITY,
|
|
||||||
strict=STRICT,
|
|
||||||
ignore=IGNORE,
|
|
||||||
lazy=LAZY,
|
|
||||||
))
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def _install_hg_hook(path):
|
|
||||||
getenv = os.environ.get
|
|
||||||
if not os.path.isfile(path):
|
|
||||||
# Make the file so we can avoid IOError's
|
|
||||||
open(path, 'w').close()
|
|
||||||
|
|
||||||
c = ConfigParser()
|
|
||||||
c.readfp(open(path, 'r'))
|
|
||||||
if not c.has_section('hooks'):
|
|
||||||
c.add_section('hooks')
|
|
||||||
|
|
||||||
if not c.has_option('hooks', 'commit'):
|
|
||||||
c.set('hooks', 'commit', 'python:flake8.hooks.hg_hook')
|
|
||||||
|
|
||||||
if not c.has_option('hooks', 'qrefresh'):
|
|
||||||
c.set('hooks', 'qrefresh', 'python:flake8.hooks.hg_hook')
|
|
||||||
|
|
||||||
if not c.has_section('flake8'):
|
|
||||||
c.add_section('flake8')
|
|
||||||
|
|
||||||
if not c.has_option('flake8', 'complexity'):
|
|
||||||
c.set('flake8', 'complexity', str(getenv('FLAKE8_COMPLEXITY', 10)))
|
|
||||||
|
|
||||||
if not c.has_option('flake8', 'strict'):
|
|
||||||
c.set('flake8', 'strict', getenv('FLAKE8_STRICT', False))
|
|
||||||
|
|
||||||
if not c.has_option('flake8', 'ignore'):
|
|
||||||
c.set('flake8', 'ignore', getenv('FLAKE8_IGNORE', ''))
|
|
||||||
|
|
||||||
if not c.has_option('flake8', 'lazy'):
|
|
||||||
c.set('flake8', 'lazy', getenv('FLAKE8_LAZY', False))
|
|
||||||
|
|
||||||
with open(path, 'w') as fd:
|
|
||||||
c.write(fd)
|
|
||||||
|
|
||||||
|
|
||||||
def install_hook():
|
|
||||||
vcs = find_vcs()
|
|
||||||
|
|
||||||
if not vcs:
|
|
||||||
p = get_parser()[0]
|
|
||||||
sys.stderr.write('Error: could not find either a git or mercurial '
|
|
||||||
'directory. Please re-run this in a proper '
|
|
||||||
'repository.\n')
|
|
||||||
p.print_help()
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
status = 0
|
|
||||||
if 'git' in vcs:
|
|
||||||
if os.path.exists(vcs):
|
|
||||||
sys.exit('Error: hook already exists (%s)' % vcs)
|
|
||||||
with open(vcs, 'w') as fd:
|
|
||||||
fd.write(git_hook_file)
|
|
||||||
# rwxr--r--
|
|
||||||
os.chmod(vcs, stat.S_IRWXU | stat.S_IRGRP | stat.S_IROTH)
|
|
||||||
elif 'hg' in vcs:
|
|
||||||
_install_hg_hook(vcs)
|
|
||||||
else:
|
|
||||||
status = 1
|
|
||||||
|
|
||||||
sys.exit(status)
|
|
||||||
141
flake8/main.py
141
flake8/main.py
|
|
@ -1,141 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import pycodestyle as pep8
|
|
||||||
import setuptools
|
|
||||||
|
|
||||||
from flake8.engine import get_parser, get_style_guide
|
|
||||||
from flake8.util import option_normalizer
|
|
||||||
|
|
||||||
if sys.platform.startswith('win'):
|
|
||||||
USER_CONFIG = os.path.expanduser(r'~\.flake8')
|
|
||||||
else:
|
|
||||||
USER_CONFIG = os.path.join(
|
|
||||||
os.getenv('XDG_CONFIG_HOME') or os.path.expanduser('~/.config'),
|
|
||||||
'flake8'
|
|
||||||
)
|
|
||||||
|
|
||||||
pep8.USER_CONFIG = USER_CONFIG
|
|
||||||
|
|
||||||
EXTRA_IGNORE = []
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Parse options and run checks on Python source."""
|
|
||||||
# Prepare
|
|
||||||
flake8_style = get_style_guide(parse_argv=True)
|
|
||||||
options = flake8_style.options
|
|
||||||
|
|
||||||
if options.install_hook:
|
|
||||||
from flake8.hooks import install_hook
|
|
||||||
install_hook()
|
|
||||||
|
|
||||||
# Run the checkers
|
|
||||||
report = flake8_style.check_files()
|
|
||||||
|
|
||||||
exit_code = print_report(report, flake8_style)
|
|
||||||
if exit_code > 0:
|
|
||||||
raise SystemExit(exit_code > 0)
|
|
||||||
|
|
||||||
|
|
||||||
def print_report(report, flake8_style):
|
|
||||||
# Print the final report
|
|
||||||
options = flake8_style.options
|
|
||||||
if options.statistics:
|
|
||||||
report.print_statistics()
|
|
||||||
if options.benchmark:
|
|
||||||
report.print_benchmark()
|
|
||||||
if report.total_errors:
|
|
||||||
if options.count:
|
|
||||||
sys.stderr.write(str(report.total_errors) + '\n')
|
|
||||||
if not options.exit_zero:
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def check_file(path, ignore=(), complexity=-1):
|
|
||||||
"""Checks a file using pep8 and pyflakes by default and mccabe
|
|
||||||
optionally.
|
|
||||||
|
|
||||||
:param str path: path to the file to be checked
|
|
||||||
:param tuple ignore: (optional), error and warning codes to be ignored
|
|
||||||
:param int complexity: (optional), enables the mccabe check for values > 0
|
|
||||||
"""
|
|
||||||
ignore = set(ignore).union(EXTRA_IGNORE)
|
|
||||||
flake8_style = get_style_guide(ignore=ignore, max_complexity=complexity)
|
|
||||||
return flake8_style.input_file(path)
|
|
||||||
|
|
||||||
|
|
||||||
def check_code(code, ignore=(), complexity=-1):
|
|
||||||
"""Checks code using pep8 and pyflakes by default and mccabe optionally.
|
|
||||||
|
|
||||||
:param str code: code to be checked
|
|
||||||
:param tuple ignore: (optional), error and warning codes to be ignored
|
|
||||||
:param int complexity: (optional), enables the mccabe check for values > 0
|
|
||||||
"""
|
|
||||||
ignore = set(ignore).union(EXTRA_IGNORE)
|
|
||||||
flake8_style = get_style_guide(ignore=ignore, max_complexity=complexity)
|
|
||||||
return flake8_style.input_file(None, lines=code.splitlines(True))
|
|
||||||
|
|
||||||
|
|
||||||
class Flake8Command(setuptools.Command):
|
|
||||||
"""The :class:`Flake8Command` class is used by setuptools to perform
|
|
||||||
checks on registered modules.
|
|
||||||
"""
|
|
||||||
|
|
||||||
description = "Run flake8 on modules registered in setuptools"
|
|
||||||
user_options = []
|
|
||||||
|
|
||||||
def initialize_options(self):
|
|
||||||
self.option_to_cmds = {}
|
|
||||||
parser = get_parser()[0]
|
|
||||||
for opt in parser.option_list:
|
|
||||||
cmd_name = opt._long_opts[0][2:]
|
|
||||||
option_name = cmd_name.replace('-', '_')
|
|
||||||
self.option_to_cmds[option_name] = opt
|
|
||||||
setattr(self, option_name, None)
|
|
||||||
|
|
||||||
def finalize_options(self):
|
|
||||||
self.options_dict = {}
|
|
||||||
for (option_name, opt) in self.option_to_cmds.items():
|
|
||||||
if option_name in ['help', 'verbose']:
|
|
||||||
continue
|
|
||||||
value = getattr(self, option_name)
|
|
||||||
if value is None:
|
|
||||||
continue
|
|
||||||
value = option_normalizer(value, opt, option_name)
|
|
||||||
# Check if there's any values that need to be fixed.
|
|
||||||
if option_name == "include" and isinstance(value, str):
|
|
||||||
value = re.findall('[^,;\s]+', value)
|
|
||||||
|
|
||||||
self.options_dict[option_name] = value
|
|
||||||
|
|
||||||
def distribution_files(self):
|
|
||||||
if self.distribution.packages:
|
|
||||||
package_dirs = self.distribution.package_dir or {}
|
|
||||||
for package in self.distribution.packages:
|
|
||||||
pkg_dir = package
|
|
||||||
if package in package_dirs:
|
|
||||||
pkg_dir = package_dirs[package]
|
|
||||||
elif '' in package_dirs:
|
|
||||||
pkg_dir = package_dirs[''] + os.path.sep + pkg_dir
|
|
||||||
yield pkg_dir.replace('.', os.path.sep)
|
|
||||||
|
|
||||||
if self.distribution.py_modules:
|
|
||||||
for filename in self.distribution.py_modules:
|
|
||||||
yield "%s.py" % filename
|
|
||||||
# Don't miss the setup.py file itself
|
|
||||||
yield "setup.py"
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
# Prepare
|
|
||||||
paths = list(self.distribution_files())
|
|
||||||
flake8_style = get_style_guide(paths=paths, **self.options_dict)
|
|
||||||
|
|
||||||
# Run the checkers
|
|
||||||
report = flake8_style.check_files()
|
|
||||||
exit_code = print_report(report, flake8_style)
|
|
||||||
if exit_code > 0:
|
|
||||||
raise SystemExit(exit_code > 0)
|
|
||||||
|
|
@ -1,152 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Adapted from a contribution of Johan Dahlin
|
|
||||||
|
|
||||||
import collections
|
|
||||||
import errno
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
try:
|
|
||||||
import multiprocessing
|
|
||||||
except ImportError: # Python 2.5
|
|
||||||
multiprocessing = None
|
|
||||||
|
|
||||||
import pycodestyle as pep8
|
|
||||||
|
|
||||||
__all__ = ['multiprocessing', 'BaseQReport', 'QueueReport']
|
|
||||||
|
|
||||||
|
|
||||||
class BaseQReport(pep8.BaseReport):
|
|
||||||
"""Base Queue Report."""
|
|
||||||
_loaded = False # Windows support
|
|
||||||
|
|
||||||
# Reasoning for ignored error numbers is in-line below
|
|
||||||
ignored_errors = set([
|
|
||||||
# EPIPE: Added by sigmavirus24
|
|
||||||
# > If output during processing is piped to something that may close
|
|
||||||
# > its own stdin before we've finished printing results, we need to
|
|
||||||
# > catch a Broken pipe error and continue on.
|
|
||||||
# > (See also: https://gitlab.com/pycqa/flake8/issues/69)
|
|
||||||
errno.EPIPE,
|
|
||||||
# NOTE(sigmavirus24): When adding to this list, include the reasoning
|
|
||||||
# on the lines before the error code and always append your error
|
|
||||||
# code. Further, please always add a trailing `,` to reduce the visual
|
|
||||||
# noise in diffs.
|
|
||||||
])
|
|
||||||
|
|
||||||
def __init__(self, options):
|
|
||||||
assert options.jobs > 0
|
|
||||||
super(BaseQReport, self).__init__(options)
|
|
||||||
self.counters = collections.defaultdict(int)
|
|
||||||
self.n_jobs = options.jobs
|
|
||||||
|
|
||||||
# init queues
|
|
||||||
self.task_queue = multiprocessing.Queue()
|
|
||||||
self.result_queue = multiprocessing.Queue()
|
|
||||||
if sys.platform == 'win32':
|
|
||||||
# Work around http://bugs.python.org/issue10845
|
|
||||||
sys.modules['__main__'].__file__ = __file__
|
|
||||||
|
|
||||||
def _cleanup_queue(self, queue):
|
|
||||||
while not queue.empty():
|
|
||||||
queue.get_nowait()
|
|
||||||
|
|
||||||
def _put_done(self):
|
|
||||||
# collect queues
|
|
||||||
for i in range(self.n_jobs):
|
|
||||||
self.task_queue.put('DONE')
|
|
||||||
self.update_state(self.result_queue.get())
|
|
||||||
|
|
||||||
def _process_main(self):
|
|
||||||
if not self._loaded:
|
|
||||||
# Windows needs to parse again the configuration
|
|
||||||
from flake8.main import get_style_guide
|
|
||||||
get_style_guide(parse_argv=True)
|
|
||||||
for filename in iter(self.task_queue.get, 'DONE'):
|
|
||||||
self.input_file(filename)
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
super(BaseQReport, self).start()
|
|
||||||
self.__class__._loaded = True
|
|
||||||
# spawn processes
|
|
||||||
for i in range(self.n_jobs):
|
|
||||||
p = multiprocessing.Process(target=self.process_main)
|
|
||||||
p.daemon = True
|
|
||||||
p.start()
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
try:
|
|
||||||
self._put_done()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
# cleanup queues to unlock threads
|
|
||||||
self._cleanup_queue(self.result_queue)
|
|
||||||
self._cleanup_queue(self.task_queue)
|
|
||||||
super(BaseQReport, self).stop()
|
|
||||||
|
|
||||||
def process_main(self):
|
|
||||||
try:
|
|
||||||
self._process_main()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
pass
|
|
||||||
except IOError as ioerr:
|
|
||||||
# If we happen across an IOError that we aren't certain can/should
|
|
||||||
# be ignored, we should re-raise the exception.
|
|
||||||
if ioerr.errno not in self.ignored_errors:
|
|
||||||
raise
|
|
||||||
finally:
|
|
||||||
# ensure all output is flushed before main process continues
|
|
||||||
sys.stdout.flush()
|
|
||||||
sys.stderr.flush()
|
|
||||||
self.result_queue.put(self.get_state())
|
|
||||||
|
|
||||||
def get_state(self):
|
|
||||||
return {'total_errors': self.total_errors,
|
|
||||||
'counters': self.counters,
|
|
||||||
'messages': self.messages}
|
|
||||||
|
|
||||||
def update_state(self, state):
|
|
||||||
self.total_errors += state['total_errors']
|
|
||||||
for key, value in state['counters'].items():
|
|
||||||
self.counters[key] += value
|
|
||||||
self.messages.update(state['messages'])
|
|
||||||
|
|
||||||
|
|
||||||
class FileQReport(BaseQReport):
|
|
||||||
"""File Queue Report."""
|
|
||||||
print_filename = True
|
|
||||||
|
|
||||||
|
|
||||||
class QueueReport(pep8.StandardReport, BaseQReport):
|
|
||||||
"""Standard Queue Report."""
|
|
||||||
|
|
||||||
def get_file_results(self):
|
|
||||||
"""Print the result and return the overall count for this file."""
|
|
||||||
self._deferred_print.sort()
|
|
||||||
|
|
||||||
for line_number, offset, code, text, doc in self._deferred_print:
|
|
||||||
print(self._fmt % {
|
|
||||||
'path': self.filename,
|
|
||||||
'row': self.line_offset + line_number, 'col': offset + 1,
|
|
||||||
'code': code, 'text': text,
|
|
||||||
})
|
|
||||||
# stdout is block buffered when not stdout.isatty().
|
|
||||||
# line can be broken where buffer boundary since other processes
|
|
||||||
# write to same file.
|
|
||||||
# flush() after print() to avoid buffer boundary.
|
|
||||||
# Typical buffer size is 8192. line written safely when
|
|
||||||
# len(line) < 8192.
|
|
||||||
sys.stdout.flush()
|
|
||||||
if self._show_source:
|
|
||||||
if line_number > len(self.lines):
|
|
||||||
line = ''
|
|
||||||
else:
|
|
||||||
line = self.lines[line_number - 1]
|
|
||||||
print(line.rstrip())
|
|
||||||
sys.stdout.flush()
|
|
||||||
print(re.sub(r'\S', ' ', line[:offset]) + '^')
|
|
||||||
sys.stdout.flush()
|
|
||||||
if self._show_pep8 and doc:
|
|
||||||
print(' ' + doc.strip())
|
|
||||||
sys.stdout.flush()
|
|
||||||
return self.file_errors
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
"""
|
|
||||||
Implementation of the command-line I{flake8} tool.
|
|
||||||
"""
|
|
||||||
from flake8.hooks import git_hook, hg_hook # noqa
|
|
||||||
from flake8.main import check_code, check_file, Flake8Command # noqa
|
|
||||||
from flake8.main import main
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
#
|
|
||||||
|
|
@ -1,309 +0,0 @@
|
||||||
"""
|
|
||||||
_test_warnings.py
|
|
||||||
|
|
||||||
Tests for the warnings that are emitted by flake8.
|
|
||||||
|
|
||||||
This module is named _test_warnings instead of test_warnings so that a
|
|
||||||
normal nosetests run does not collect it. The tests in this module pass
|
|
||||||
when they are run alone, but they fail when they are run along with other
|
|
||||||
tests (nosetests --with-isolation doesn't help).
|
|
||||||
|
|
||||||
In tox.ini, these tests are run separately.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import with_statement
|
|
||||||
|
|
||||||
import os
|
|
||||||
import warnings
|
|
||||||
import unittest
|
|
||||||
try:
|
|
||||||
from unittest import mock
|
|
||||||
except ImportError:
|
|
||||||
import mock # < PY33
|
|
||||||
|
|
||||||
from flake8 import engine
|
|
||||||
from flake8.util import is_windows
|
|
||||||
|
|
||||||
# The Problem
|
|
||||||
# ------------
|
|
||||||
#
|
|
||||||
# Some of the tests in this module pass when this module is run on its own, but
|
|
||||||
# they fail when this module is run as part of the whole test suite. These are
|
|
||||||
# the problematic tests:
|
|
||||||
#
|
|
||||||
# test_jobs_verbose
|
|
||||||
# test_stdin_jobs_warning
|
|
||||||
#
|
|
||||||
# On some platforms, the warnings.capture_warnings function doesn't work
|
|
||||||
# properly when run with the other flake8 tests. It drops some warnings, even
|
|
||||||
# though the warnings filter is set to 'always'. However, when run separately,
|
|
||||||
# these tests pass.
|
|
||||||
#
|
|
||||||
# This problem only occurs on Windows, with Python 3.3 and older. Maybe it's
|
|
||||||
# related to PEP 446 - Inheritable file descriptors?
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# Things that didn't work
|
|
||||||
# ------------
|
|
||||||
#
|
|
||||||
# Nose --attr
|
|
||||||
# I tried using the nosetests --attr feature to run the tests separately. I
|
|
||||||
# put the following in setup.cfg
|
|
||||||
#
|
|
||||||
# [nosetests]
|
|
||||||
# atttr=!run_alone
|
|
||||||
#
|
|
||||||
# Then I added a tox section thst did this
|
|
||||||
#
|
|
||||||
# nosetests --attr=run_alone
|
|
||||||
#
|
|
||||||
# However, the command line --attr would not override the config file --attr,
|
|
||||||
# so the special tox section wound up runing all the tests, and failing.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# Nose --with-isolation
|
|
||||||
# The nosetests --with-isolation flag did not help.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# unittest.skipIf
|
|
||||||
# I tried decorating the problematic tests with the unittest.skipIf
|
|
||||||
# decorator.
|
|
||||||
#
|
|
||||||
# @unittest.skipIf(is_windows() and sys.version_info < (3, 4),
|
|
||||||
# "Fails on Windows with Python < 3.4 when run with other"
|
|
||||||
# " tests.")
|
|
||||||
#
|
|
||||||
# The idea is, skip the tests in the main test run, on affected platforms.
|
|
||||||
# Then, only on those platforms, come back in later and run the tests
|
|
||||||
# separately.
|
|
||||||
#
|
|
||||||
# I added a new stanza to tox.ini, to run the tests separately on the
|
|
||||||
# affected platforms.
|
|
||||||
#
|
|
||||||
# nosetests --no-skip
|
|
||||||
#
|
|
||||||
# I ran in to a bug in the nosetests skip plugin. It would report the test as
|
|
||||||
# having been run, but it would not actually run the test. So, when run with
|
|
||||||
# --no-skip, the following test would be reported as having run and passed!
|
|
||||||
#
|
|
||||||
# @unittest.skip("This passes o_o")
|
|
||||||
# def test_should_fail(self):
|
|
||||||
# assert 0
|
|
||||||
#
|
|
||||||
# This bug has been reported here:
|
|
||||||
# "--no-skip broken with Python 2.7"
|
|
||||||
# https://github.com/nose-devs/nose/issues/512
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# py.test
|
|
||||||
#
|
|
||||||
# I tried using py.test, and its @pytest.mark.xfail decorator. I added some
|
|
||||||
# separate stanzas in tox, and useing the pytest --runxfail option to run the
|
|
||||||
# tests separately. This allows us to run all the tests together, on
|
|
||||||
# platforms that allow it. On platforms that don't allow us to run the tests
|
|
||||||
# all together, this still runs all the tests, but in two separate steps.
|
|
||||||
#
|
|
||||||
# This is the same solution as the nosetests --no-skip solution I described
|
|
||||||
# above, but --runxfail does not have the same bug as --no-skip.
|
|
||||||
#
|
|
||||||
# This has the advantage that all tests are discoverable by default, outside
|
|
||||||
# of tox. However, nose does not recognize the pytest.mark.xfail decorator.
|
|
||||||
# So, if a user runs nosetests, it still tries to run the problematic tests
|
|
||||||
# together with the rest of the test suite, causing them to fail.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# Solution
|
|
||||||
# ------------
|
|
||||||
# Move the problematic tests to _test_warnings.py, so nose.collector will not
|
|
||||||
# find them. Set up a separate section in tox.ini that runs this:
|
|
||||||
#
|
|
||||||
# nosetests flake8.tests._test_warnings
|
|
||||||
#
|
|
||||||
# This allows all tests to pass on all platforms, when run through tox.
|
|
||||||
# However, it means that, even on unaffected platforms, the problematic tests
|
|
||||||
# are not discovered and run outside of tox (if the user just runs nosetests
|
|
||||||
# manually, for example).
|
|
||||||
|
|
||||||
|
|
||||||
class IntegrationTestCaseWarnings(unittest.TestCase):
|
|
||||||
"""Integration style tests to check that warnings are issued properly for
|
|
||||||
different command line options."""
|
|
||||||
|
|
||||||
windows_warning_text = ("The --jobs option is not available on Windows."
|
|
||||||
" Ignoring --jobs arguments.")
|
|
||||||
stdin_warning_text = ("The --jobs option is not compatible with"
|
|
||||||
" supplying input using - . Ignoring --jobs"
|
|
||||||
" arguments.")
|
|
||||||
|
|
||||||
def this_file(self):
|
|
||||||
"""Return the real path of this file."""
|
|
||||||
this_file = os.path.realpath(__file__)
|
|
||||||
if this_file.endswith("pyc"):
|
|
||||||
this_file = this_file[:-1]
|
|
||||||
return this_file
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_style_guide_with_warnings(engine, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
Return a style guide object (obtained by calling
|
|
||||||
engine.get_style_guide) and a list of the warnings that were raised in
|
|
||||||
the process.
|
|
||||||
|
|
||||||
Note: not threadsafe
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Note
|
|
||||||
# https://docs.python.org/2/library/warnings.html
|
|
||||||
#
|
|
||||||
# The catch_warnings manager works by replacing and then later
|
|
||||||
# restoring the module's showwarning() function and internal list of
|
|
||||||
# filter specifications. This means the context manager is modifying
|
|
||||||
# global state and therefore is not thread-safe
|
|
||||||
|
|
||||||
with warnings.catch_warnings(record=True) as collected_warnings:
|
|
||||||
# Cause all warnings to always be triggered.
|
|
||||||
warnings.simplefilter("always")
|
|
||||||
|
|
||||||
# Get the style guide
|
|
||||||
style_guide = engine.get_style_guide(*args, **kwargs)
|
|
||||||
|
|
||||||
# Now that the warnings have been collected, return the style guide and
|
|
||||||
# the warnings.
|
|
||||||
return (style_guide, collected_warnings)
|
|
||||||
|
|
||||||
def verify_warnings(self, collected_warnings, expected_warnings):
|
|
||||||
"""
|
|
||||||
Verifies that collected_warnings is a sequence that contains user
|
|
||||||
warnings that match the sequence of string values passed in as
|
|
||||||
expected_warnings.
|
|
||||||
"""
|
|
||||||
if expected_warnings is None:
|
|
||||||
expected_warnings = []
|
|
||||||
|
|
||||||
collected_user_warnings = [w for w in collected_warnings
|
|
||||||
if issubclass(w.category, UserWarning)]
|
|
||||||
|
|
||||||
self.assertEqual(len(collected_user_warnings),
|
|
||||||
len(expected_warnings))
|
|
||||||
|
|
||||||
collected_warnings_set = set(str(warning.message)
|
|
||||||
for warning
|
|
||||||
in collected_user_warnings)
|
|
||||||
expected_warnings_set = set(expected_warnings)
|
|
||||||
self.assertEqual(collected_warnings_set, expected_warnings_set)
|
|
||||||
|
|
||||||
def check_files_collect_warnings(self,
|
|
||||||
arglist=[],
|
|
||||||
explicit_stdin=False,
|
|
||||||
count=0,
|
|
||||||
verbose=False):
|
|
||||||
"""Call check_files and collect any warnings that are issued."""
|
|
||||||
if verbose:
|
|
||||||
arglist.append('--verbose')
|
|
||||||
if explicit_stdin:
|
|
||||||
target_file = "-"
|
|
||||||
else:
|
|
||||||
target_file = self.this_file()
|
|
||||||
argv = ['flake8'] + arglist + [target_file]
|
|
||||||
with mock.patch("sys.argv", argv):
|
|
||||||
(style_guide,
|
|
||||||
collected_warnings,
|
|
||||||
) = self.get_style_guide_with_warnings(engine,
|
|
||||||
parse_argv=True)
|
|
||||||
report = style_guide.check_files()
|
|
||||||
self.assertEqual(report.total_errors, count)
|
|
||||||
return style_guide, report, collected_warnings
|
|
||||||
|
|
||||||
def check_files_no_warnings_allowed(self,
|
|
||||||
arglist=[],
|
|
||||||
explicit_stdin=False,
|
|
||||||
count=0,
|
|
||||||
verbose=False):
|
|
||||||
"""Call check_files, and assert that there were no warnings issued."""
|
|
||||||
(style_guide,
|
|
||||||
report,
|
|
||||||
collected_warnings,
|
|
||||||
) = self.check_files_collect_warnings(arglist=arglist,
|
|
||||||
explicit_stdin=explicit_stdin,
|
|
||||||
count=count,
|
|
||||||
verbose=verbose)
|
|
||||||
self.verify_warnings(collected_warnings, expected_warnings=None)
|
|
||||||
return style_guide, report
|
|
||||||
|
|
||||||
def _job_tester(self, jobs, verbose=False):
|
|
||||||
# mock stdout.flush so we can count the number of jobs created
|
|
||||||
with mock.patch('sys.stdout.flush') as mocked:
|
|
||||||
(guide,
|
|
||||||
report,
|
|
||||||
collected_warnings,
|
|
||||||
) = self.check_files_collect_warnings(
|
|
||||||
arglist=['--jobs=%s' % jobs],
|
|
||||||
verbose=verbose)
|
|
||||||
|
|
||||||
if is_windows():
|
|
||||||
# The code path where guide.options.jobs gets converted to an
|
|
||||||
# int is not run on windows. So, do the int conversion here.
|
|
||||||
self.assertEqual(int(guide.options.jobs), jobs)
|
|
||||||
# On windows, call count is always zero.
|
|
||||||
self.assertEqual(mocked.call_count, 0)
|
|
||||||
else:
|
|
||||||
self.assertEqual(guide.options.jobs, jobs)
|
|
||||||
self.assertEqual(mocked.call_count, jobs)
|
|
||||||
|
|
||||||
expected_warings = []
|
|
||||||
if verbose and is_windows():
|
|
||||||
expected_warings.append(self.windows_warning_text)
|
|
||||||
self.verify_warnings(collected_warnings, expected_warings)
|
|
||||||
|
|
||||||
def test_jobs(self, verbose=False):
|
|
||||||
self._job_tester(2, verbose=verbose)
|
|
||||||
self._job_tester(10, verbose=verbose)
|
|
||||||
|
|
||||||
def test_no_args_no_warnings(self, verbose=False):
|
|
||||||
self.check_files_no_warnings_allowed(verbose=verbose)
|
|
||||||
|
|
||||||
def test_stdin_jobs_warning(self, verbose=False):
|
|
||||||
self.count = 0
|
|
||||||
|
|
||||||
def fake_stdin():
|
|
||||||
self.count += 1
|
|
||||||
with open(self.this_file(), "r") as f:
|
|
||||||
return f.read()
|
|
||||||
|
|
||||||
with mock.patch("pycodestyle.stdin_get_value", fake_stdin):
|
|
||||||
(style_guide,
|
|
||||||
report,
|
|
||||||
collected_warnings,
|
|
||||||
) = self.check_files_collect_warnings(arglist=['--jobs=4'],
|
|
||||||
explicit_stdin=True,
|
|
||||||
verbose=verbose)
|
|
||||||
expected_warings = []
|
|
||||||
if verbose:
|
|
||||||
expected_warings.append(self.stdin_warning_text)
|
|
||||||
if is_windows():
|
|
||||||
expected_warings.append(self.windows_warning_text)
|
|
||||||
self.verify_warnings(collected_warnings, expected_warings)
|
|
||||||
self.assertEqual(self.count, 1)
|
|
||||||
|
|
||||||
def test_jobs_verbose(self):
|
|
||||||
self.test_jobs(verbose=True)
|
|
||||||
|
|
||||||
def test_no_args_no_warnings_verbose(self):
|
|
||||||
self.test_no_args_no_warnings(verbose=True)
|
|
||||||
|
|
||||||
def test_stdin_jobs_warning_verbose(self):
|
|
||||||
self.test_stdin_jobs_warning(verbose=True)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
||||||
|
|
@ -1,236 +0,0 @@
|
||||||
from __future__ import with_statement
|
|
||||||
|
|
||||||
import errno
|
|
||||||
import unittest
|
|
||||||
try:
|
|
||||||
from unittest import mock
|
|
||||||
except ImportError:
|
|
||||||
import mock # < PY33
|
|
||||||
|
|
||||||
from flake8 import engine, util, __version__, reporter
|
|
||||||
import pycodestyle as pep8
|
|
||||||
|
|
||||||
|
|
||||||
class TestEngine(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.patches = {}
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
assert len(self.patches.items()) == 0
|
|
||||||
|
|
||||||
def start_patch(self, patch):
|
|
||||||
self.patches[patch] = mock.patch(patch)
|
|
||||||
return self.patches[patch].start()
|
|
||||||
|
|
||||||
def stop_patches(self):
|
|
||||||
patches = self.patches.copy()
|
|
||||||
for k, v in patches.items():
|
|
||||||
v.stop()
|
|
||||||
del(self.patches[k])
|
|
||||||
|
|
||||||
def test_get_style_guide(self):
|
|
||||||
with mock.patch('flake8.engine._register_extensions') as reg_ext:
|
|
||||||
reg_ext.return_value = ([], [], [], [])
|
|
||||||
g = engine.get_style_guide()
|
|
||||||
self.assertTrue(isinstance(g, engine.StyleGuide))
|
|
||||||
reg_ext.assert_called_once_with()
|
|
||||||
|
|
||||||
def test_get_style_guide_kwargs(self):
|
|
||||||
m = mock.Mock()
|
|
||||||
with mock.patch('flake8.engine.StyleGuide') as StyleGuide:
|
|
||||||
with mock.patch('flake8.engine.get_parser') as get_parser:
|
|
||||||
m.ignored_extensions = []
|
|
||||||
StyleGuide.return_value.options.jobs = '42'
|
|
||||||
StyleGuide.return_value.options.diff = False
|
|
||||||
get_parser.return_value = (m, [])
|
|
||||||
engine.get_style_guide(foo='bar')
|
|
||||||
get_parser.assert_called_once_with()
|
|
||||||
StyleGuide.assert_called_once_with(**{'parser': m, 'foo': 'bar'})
|
|
||||||
|
|
||||||
def test_register_extensions(self):
|
|
||||||
with mock.patch('pycodestyle.register_check') as register_check:
|
|
||||||
registered_exts = engine._register_extensions()
|
|
||||||
self.assertTrue(isinstance(registered_exts[0], util.OrderedSet))
|
|
||||||
self.assertTrue(len(registered_exts[0]) > 0)
|
|
||||||
for i in registered_exts[1:]:
|
|
||||||
self.assertTrue(isinstance(i, list))
|
|
||||||
self.assertTrue(register_check.called)
|
|
||||||
|
|
||||||
def test_disable_extensions(self):
|
|
||||||
parser = mock.MagicMock()
|
|
||||||
options = mock.MagicMock()
|
|
||||||
|
|
||||||
parser.ignored_extensions = ['I123', 'I345', 'I678', 'I910']
|
|
||||||
|
|
||||||
options.enable_extensions = 'I345,\nI678,I910'
|
|
||||||
options.ignore = ('E121', 'E123')
|
|
||||||
|
|
||||||
engine._disable_extensions(parser, options)
|
|
||||||
self.assertEqual(set(options.ignore), set(['E121', 'E123', 'I123']))
|
|
||||||
|
|
||||||
def test_get_parser(self):
|
|
||||||
# setup
|
|
||||||
re = self.start_patch('flake8.engine._register_extensions')
|
|
||||||
gpv = self.start_patch('flake8.engine.get_python_version')
|
|
||||||
pgp = self.start_patch('pycodestyle.get_parser')
|
|
||||||
m = mock.Mock()
|
|
||||||
re.return_value = ([('pyflakes', '0.7'), ('mccabe', '0.2')], [], [],
|
|
||||||
[])
|
|
||||||
gpv.return_value = 'Python Version'
|
|
||||||
pgp.return_value = m
|
|
||||||
# actual call we're testing
|
|
||||||
parser, hooks = engine.get_parser()
|
|
||||||
# assertions
|
|
||||||
self.assertTrue(re.called)
|
|
||||||
self.assertTrue(gpv.called)
|
|
||||||
pgp.assert_called_once_with(
|
|
||||||
'flake8',
|
|
||||||
'%s (pyflakes: 0.7, mccabe: 0.2) Python Version' % __version__)
|
|
||||||
self.assertTrue(m.remove_option.called)
|
|
||||||
self.assertTrue(m.add_option.called)
|
|
||||||
self.assertEqual(parser, m)
|
|
||||||
self.assertEqual(hooks, [])
|
|
||||||
# clean-up
|
|
||||||
self.stop_patches()
|
|
||||||
|
|
||||||
def test_get_python_version(self):
|
|
||||||
self.assertTrue('on' in engine.get_python_version())
|
|
||||||
# Silly test but it will provide 100% test coverage
|
|
||||||
# Also we can never be sure (without reconstructing the string
|
|
||||||
# ourselves) what system we may be testing on.
|
|
||||||
|
|
||||||
def test_windows_disables_jobs(self):
|
|
||||||
with mock.patch('flake8.util.is_windows') as is_windows:
|
|
||||||
is_windows.return_value = True
|
|
||||||
guide = engine.get_style_guide()
|
|
||||||
assert isinstance(guide, reporter.BaseQReport) is False
|
|
||||||
|
|
||||||
def test_stdin_disables_jobs(self):
|
|
||||||
with mock.patch('flake8.util.is_using_stdin') as is_using_stdin:
|
|
||||||
is_using_stdin.return_value = True
|
|
||||||
guide = engine.get_style_guide()
|
|
||||||
assert isinstance(guide, reporter.BaseQReport) is False
|
|
||||||
|
|
||||||
def test_disables_extensions_that_are_not_selected(self):
|
|
||||||
with mock.patch('flake8.engine._register_extensions') as re:
|
|
||||||
re.return_value = ([('fake_ext', '0.1a1')], [], [], ['X'])
|
|
||||||
sg = engine.get_style_guide()
|
|
||||||
assert 'X' in sg.options.ignore
|
|
||||||
|
|
||||||
def test_enables_off_by_default_extensions(self):
|
|
||||||
with mock.patch('flake8.engine._register_extensions') as re:
|
|
||||||
re.return_value = ([('fake_ext', '0.1a1')], [], [], ['X'])
|
|
||||||
parser, options = engine.get_parser()
|
|
||||||
parser.parse_args(['--select=X'])
|
|
||||||
sg = engine.StyleGuide(parser=parser)
|
|
||||||
assert 'X' not in sg.options.ignore
|
|
||||||
|
|
||||||
def test_load_entry_point_verifies_requirements(self):
|
|
||||||
entry_point = mock.Mock(spec=['require', 'resolve', 'load'])
|
|
||||||
|
|
||||||
engine._load_entry_point(entry_point, verify_requirements=True)
|
|
||||||
entry_point.require.assert_called_once_with()
|
|
||||||
entry_point.resolve.assert_called_once_with()
|
|
||||||
|
|
||||||
def test_load_entry_point_does_not_verify_requirements(self):
|
|
||||||
entry_point = mock.Mock(spec=['require', 'resolve', 'load'])
|
|
||||||
|
|
||||||
engine._load_entry_point(entry_point, verify_requirements=False)
|
|
||||||
self.assertFalse(entry_point.require.called)
|
|
||||||
entry_point.resolve.assert_called_once_with()
|
|
||||||
|
|
||||||
def test_load_entry_point_passes_require_argument_to_load(self):
|
|
||||||
entry_point = mock.Mock(spec=['load'])
|
|
||||||
|
|
||||||
engine._load_entry_point(entry_point, verify_requirements=True)
|
|
||||||
entry_point.load.assert_called_once_with(require=True)
|
|
||||||
entry_point.reset_mock()
|
|
||||||
|
|
||||||
engine._load_entry_point(entry_point, verify_requirements=False)
|
|
||||||
entry_point.load.assert_called_once_with(require=False)
|
|
||||||
|
|
||||||
|
|
||||||
def oserror_generator(error_number, message='Ominous OSError message'):
|
|
||||||
def oserror_side_effect(*args, **kwargs):
|
|
||||||
if hasattr(oserror_side_effect, 'used'):
|
|
||||||
return
|
|
||||||
|
|
||||||
oserror_side_effect.used = True
|
|
||||||
raise OSError(error_number, message)
|
|
||||||
|
|
||||||
return oserror_side_effect
|
|
||||||
|
|
||||||
|
|
||||||
class TestStyleGuide(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
mocked_styleguide = mock.Mock(spec=engine.NoQAStyleGuide)
|
|
||||||
self.styleguide = engine.StyleGuide(styleguide=mocked_styleguide)
|
|
||||||
self.mocked_sg = mocked_styleguide
|
|
||||||
|
|
||||||
def test_proxies_excluded(self):
|
|
||||||
self.styleguide.excluded('file.py', parent='.')
|
|
||||||
|
|
||||||
self.mocked_sg.excluded.assert_called_once_with('file.py', parent='.')
|
|
||||||
|
|
||||||
def test_proxies_init_report(self):
|
|
||||||
reporter = object()
|
|
||||||
self.styleguide.init_report(reporter)
|
|
||||||
|
|
||||||
self.mocked_sg.init_report.assert_called_once_with(reporter)
|
|
||||||
|
|
||||||
def test_proxies_check_files(self):
|
|
||||||
self.styleguide.check_files(['foo', 'bar'])
|
|
||||||
|
|
||||||
self.mocked_sg.check_files.assert_called_once_with(
|
|
||||||
paths=['foo', 'bar']
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_proxies_input_file(self):
|
|
||||||
self.styleguide.input_file('file.py',
|
|
||||||
lines=[9, 10],
|
|
||||||
expected='foo',
|
|
||||||
line_offset=20)
|
|
||||||
|
|
||||||
self.mocked_sg.input_file.assert_called_once_with(filename='file.py',
|
|
||||||
lines=[9, 10],
|
|
||||||
expected='foo',
|
|
||||||
line_offset=20)
|
|
||||||
|
|
||||||
def test_check_files_retries_on_specific_OSErrors(self):
|
|
||||||
self.mocked_sg.check_files.side_effect = oserror_generator(
|
|
||||||
errno.ENOSPC, 'No space left on device'
|
|
||||||
)
|
|
||||||
|
|
||||||
self.styleguide.check_files(['foo', 'bar'])
|
|
||||||
|
|
||||||
self.mocked_sg.init_report.assert_called_once_with(pep8.StandardReport)
|
|
||||||
|
|
||||||
def test_input_file_retries_on_specific_OSErrors(self):
|
|
||||||
self.mocked_sg.input_file.side_effect = oserror_generator(
|
|
||||||
errno.ENOSPC, 'No space left on device'
|
|
||||||
)
|
|
||||||
|
|
||||||
self.styleguide.input_file('file.py')
|
|
||||||
|
|
||||||
self.mocked_sg.init_report.assert_called_once_with(pep8.StandardReport)
|
|
||||||
|
|
||||||
def test_check_files_reraises_unknown_OSErrors(self):
|
|
||||||
self.mocked_sg.check_files.side_effect = oserror_generator(
|
|
||||||
errno.EADDRINUSE,
|
|
||||||
'lol why are we talking about binding to sockets'
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertRaises(OSError, self.styleguide.check_files,
|
|
||||||
['foo', 'bar'])
|
|
||||||
|
|
||||||
def test_input_file_reraises_unknown_OSErrors(self):
|
|
||||||
self.mocked_sg.input_file.side_effect = oserror_generator(
|
|
||||||
errno.EADDRINUSE,
|
|
||||||
'lol why are we talking about binding to sockets'
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertRaises(OSError, self.styleguide.input_file,
|
|
||||||
['foo', 'bar'])
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
"""Module containing the tests for flake8.hooks."""
|
|
||||||
import os
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
try:
|
|
||||||
from unittest import mock
|
|
||||||
except ImportError:
|
|
||||||
import mock
|
|
||||||
|
|
||||||
import flake8.hooks
|
|
||||||
from flake8.util import is_windows
|
|
||||||
|
|
||||||
|
|
||||||
def excluded(filename):
|
|
||||||
return filename.endswith('afile.py')
|
|
||||||
|
|
||||||
|
|
||||||
class TestGitHook(unittest.TestCase):
|
|
||||||
if is_windows:
|
|
||||||
# On Windows, absolute paths start with a drive letter, for example C:
|
|
||||||
# Here we build a fake absolute path starting with the current drive
|
|
||||||
# letter, for example C:\fake\temp
|
|
||||||
current_drive, ignore_tail = os.path.splitdrive(os.getcwd())
|
|
||||||
fake_abs_path = os.path.join(current_drive, os.path.sep, 'fake', 'tmp')
|
|
||||||
else:
|
|
||||||
fake_abs_path = os.path.join(os.path.sep, 'fake', 'tmp')
|
|
||||||
|
|
||||||
@mock.patch('os.makedirs')
|
|
||||||
@mock.patch('flake8.hooks.open', create=True)
|
|
||||||
@mock.patch('shutil.rmtree')
|
|
||||||
@mock.patch('tempfile.mkdtemp', return_value=fake_abs_path)
|
|
||||||
@mock.patch('flake8.hooks.run',
|
|
||||||
return_value=(None,
|
|
||||||
[os.path.join('foo', 'afile.py'),
|
|
||||||
os.path.join('foo', 'bfile.py')],
|
|
||||||
None))
|
|
||||||
@mock.patch('flake8.hooks.get_style_guide')
|
|
||||||
def test_prepends_tmp_directory_to_exclude(self, get_style_guide, run,
|
|
||||||
*args):
|
|
||||||
style_guide = get_style_guide.return_value = mock.Mock()
|
|
||||||
style_guide.options.exclude = [os.path.join('foo', 'afile.py')]
|
|
||||||
style_guide.options.filename = [os.path.join('foo', '*')]
|
|
||||||
style_guide.excluded = excluded
|
|
||||||
|
|
||||||
flake8.hooks.git_hook()
|
|
||||||
|
|
||||||
dirname, filename = os.path.split(
|
|
||||||
os.path.abspath(os.path.join('foo', 'bfile.py')))
|
|
||||||
if is_windows:
|
|
||||||
# In Windows, the absolute path in dirname will start with a drive
|
|
||||||
# letter. Here, we discad the drive letter.
|
|
||||||
ignore_drive, dirname = os.path.splitdrive(dirname)
|
|
||||||
tmpdir = os.path.join(self.fake_abs_path, dirname[1:])
|
|
||||||
tmpfile = os.path.join(tmpdir, 'bfile.py')
|
|
||||||
style_guide.check_files.assert_called_once_with([tmpfile])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
from __future__ import with_statement
|
|
||||||
|
|
||||||
import os
|
|
||||||
import unittest
|
|
||||||
try:
|
|
||||||
from unittest import mock
|
|
||||||
except ImportError:
|
|
||||||
import mock # < PY33
|
|
||||||
|
|
||||||
from flake8 import engine
|
|
||||||
from flake8.util import is_windows
|
|
||||||
|
|
||||||
|
|
||||||
class IntegrationTestCase(unittest.TestCase):
|
|
||||||
"""Integration style tests to exercise different command line options."""
|
|
||||||
|
|
||||||
def this_file(self):
|
|
||||||
"""Return the real path of this file."""
|
|
||||||
this_file = os.path.realpath(__file__)
|
|
||||||
if this_file.endswith("pyc"):
|
|
||||||
this_file = this_file[:-1]
|
|
||||||
return this_file
|
|
||||||
|
|
||||||
def check_files(self, arglist=[], explicit_stdin=False, count=0):
|
|
||||||
"""Call check_files."""
|
|
||||||
if explicit_stdin:
|
|
||||||
target_file = "-"
|
|
||||||
else:
|
|
||||||
target_file = self.this_file()
|
|
||||||
argv = ['flake8'] + arglist + [target_file]
|
|
||||||
with mock.patch("sys.argv", argv):
|
|
||||||
style_guide = engine.get_style_guide(parse_argv=True)
|
|
||||||
report = style_guide.check_files()
|
|
||||||
self.assertEqual(report.total_errors, count)
|
|
||||||
return style_guide, report
|
|
||||||
|
|
||||||
def test_no_args(self):
|
|
||||||
# assert there are no reported errors
|
|
||||||
self.check_files()
|
|
||||||
|
|
||||||
def _job_tester(self, jobs):
|
|
||||||
# mock stdout.flush so we can count the number of jobs created
|
|
||||||
with mock.patch('sys.stdout.flush') as mocked:
|
|
||||||
guide, report = self.check_files(arglist=['--jobs=%s' % jobs])
|
|
||||||
if is_windows():
|
|
||||||
# The code path where guide.options.jobs gets converted to an
|
|
||||||
# int is not run on windows. So, do the int conversion here.
|
|
||||||
self.assertEqual(int(guide.options.jobs), jobs)
|
|
||||||
# On windows, call count is always zero.
|
|
||||||
self.assertEqual(mocked.call_count, 0)
|
|
||||||
else:
|
|
||||||
self.assertEqual(guide.options.jobs, jobs)
|
|
||||||
self.assertEqual(mocked.call_count, jobs)
|
|
||||||
|
|
||||||
def test_jobs(self):
|
|
||||||
self._job_tester(2)
|
|
||||||
self._job_tester(10)
|
|
||||||
|
|
||||||
def test_stdin(self):
|
|
||||||
self.count = 0
|
|
||||||
|
|
||||||
def fake_stdin():
|
|
||||||
self.count += 1
|
|
||||||
with open(self.this_file(), "r") as f:
|
|
||||||
return f.read()
|
|
||||||
|
|
||||||
with mock.patch("pycodestyle.stdin_get_value", fake_stdin):
|
|
||||||
guide, report = self.check_files(arglist=['--jobs=4'],
|
|
||||||
explicit_stdin=True)
|
|
||||||
self.assertEqual(self.count, 1)
|
|
||||||
|
|
||||||
def test_stdin_fail(self):
|
|
||||||
def fake_stdin():
|
|
||||||
return "notathing\n"
|
|
||||||
with mock.patch("pycodestyle.stdin_get_value", fake_stdin):
|
|
||||||
# only assert needed is in check_files
|
|
||||||
guide, report = self.check_files(arglist=['--jobs=4'],
|
|
||||||
explicit_stdin=True,
|
|
||||||
count=1)
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue