mirror of
https://github.com/PyCQA/flake8.git
synced 2026-04-04 12:16:53 +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
|
||||
.tox
|
||||
.eggs
|
||||
*.egg
|
||||
*.egg-info
|
||||
build
|
||||
dist
|
||||
*.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:
|
||||
include:
|
||||
- python: 2.6
|
||||
env: TOXENV=py26
|
||||
- python: 2.7
|
||||
env: TOXENV=py27
|
||||
- python: 3.3
|
||||
|
|
@ -24,6 +22,14 @@ matrix:
|
|||
- python: pypy
|
||||
env: TOXENV=pypy
|
||||
- python: 2.7
|
||||
env: TOXENV=py27-flake8
|
||||
env: TOXENV=readme
|
||||
- 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) ==
|
||||
|
||||
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
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
include *.rst
|
||||
include CONTRIBUTORS.txt
|
||||
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
|
||||
pyflakes
|
||||
mccabe
|
||||
mock
|
||||
nose
|
||||
tox
|
||||
|
|
|
|||
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 -*-
|
||||
#
|
||||
# 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
|
||||
# containing dir.
|
||||
#
|
||||
|
|
@ -12,29 +15,35 @@
|
|||
import sys
|
||||
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,
|
||||
# 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.
|
||||
sys.path.insert(0, os.path.abspath('..'))
|
||||
import flake8
|
||||
#sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# -- General configuration ----------------------------------------------------
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# 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
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc']
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# 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.
|
||||
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'
|
||||
|
||||
# The encoding of source files.
|
||||
|
|
@ -45,8 +54,10 @@ master_doc = 'index'
|
|||
|
||||
# General information about the project.
|
||||
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
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
|
|
@ -54,11 +65,18 @@ copyright = u'2012-2013 - Tarek Ziade, Ian Cordasco, Florent Xicluna'
|
|||
# The short X.Y version.
|
||||
version = flake8.__version__
|
||||
# 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
|
||||
# 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
|
||||
# non-false value, then it is used:
|
||||
|
|
@ -68,10 +86,10 @@ release = version
|
|||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# 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
|
||||
# all documents.
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
|
|
@ -86,17 +104,23 @@ exclude_patterns = ['_build']
|
|||
#show_authors = False
|
||||
|
||||
# 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.
|
||||
#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
|
||||
# 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
|
||||
# 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,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# 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,
|
||||
# using the given strftime format.
|
||||
|
|
@ -152,10 +181,10 @@ exclude_patterns = ['_build']
|
|||
#html_split_index = False
|
||||
|
||||
# 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.
|
||||
#html_show_sphinx = False
|
||||
#html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
|
|
@ -168,24 +197,45 @@ exclude_patterns = ['_build']
|
|||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#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.
|
||||
htmlhelp_basename = 'flake8_doc'
|
||||
htmlhelp_basename = 'flake8doc'
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
# -- Options for LaTeX output -------------------------------------------------
|
||||
|
||||
# The paper size ('letter' or 'a4').
|
||||
#latex_paper_size = 'letter'
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# 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
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto/manual]).
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
('index', 'flake8.tex', u'flake8 Documentation',
|
||||
u'Tarek Ziade', 'manual'),
|
||||
(master_doc, 'flake8.tex', u'flake8 Documentation',
|
||||
u'Ian Cordasco', 'manual'),
|
||||
]
|
||||
|
||||
# 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.
|
||||
#latex_show_urls = False
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#latex_preamble = ''
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
|
|
@ -212,29 +259,42 @@ latex_documents = [
|
|||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output -------------------------------------------
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'flake8', u'flake8 Documentation',
|
||||
[u'Tarek Ziade', u'Ian Cordasco', u'Florent Xicluna'], 1)
|
||||
(master_doc, 'flake8', u'flake8 Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output -----------------------------------------------
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'flake8', u'flake8 Documentation', u'Tarek Ziade',
|
||||
'flake8', 'Code checking using pycodestyle, pyflakes and mccabe',
|
||||
('index', 'Flake8', u'Flake8 Documentation', u'Tarek Ziade',
|
||||
'Flake8', 'Code checking using pycodestyle, pyflakes and mccabe',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
# 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