GithubHelp home page GithubHelp logo

sco1 / flake8-annotations Goto Github PK

View Code? Open in Web Editor NEW
156.0 156.0 7.0 724 KB

Flake8 Type Annotation Checking

Home Page: https://pypi.org/project/flake8-annotations/

License: MIT License

Python 100.00%
flake8 flake8-plugin python python3 type-annotations

flake8-annotations's Introduction

Hi there, I'm sco1! 👋

StackOverflow Slack HackerNews Mastodon

I'm a Boston-based Aerospace Engineer focused on test & evaluation.

Programming Interests

  • Data collection, postprocessing, and visualization
  • CLI and GUI tooling
  • Code quality
  • Software testing

I also find joy in making hilarious things like:

flake8-annotations's People

Contributors

asottile avatar dependabot-preview[bot] avatar dependabot[bot] avatar ghostofgoes avatar kianmeng avatar nat-n avatar pre-commit-ci[bot] avatar roym899 avatar sco1 avatar scragly avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flake8-annotations's Issues

Error codes emitted in reverse order

Currently, error codes are being emitted backwards:

./test.py:4:5: TYP204 Missing return type annotation for magic function
./test.py:4:18: TYP101 Missing type annotation for self in class method

This bothers my brain so the logic should be adjusted so that argument codes are emitted before return codes

Support stub files (PEP 484)

Add the ability to read type information from a stub file, per PEP 484. This goes somewhat in hand with issue #36 and there is likely some overlap (namely with parsing).

Rationale/use cases (from PEP 484)

  • Extension modules
  • Third-party modules whose authors have not yet added type hints
  • Standard library modules for which type hints have not yet been written
  • Modules that must be compatible with Python 2 and 3
  • Modules that use annotations for other purposes

Combine CI Coverage Files Across Environments

This needs validation, but I believe that the coverage report currently being provided by the CI is only for whatever test environment runs the tests last. While not an immediate issue for the current codebase, as Python 3.8-specific logic starts to be added to the codebase the coverage reported by a single test environment will decrease.

To remedy this, the coverage report should be generated from the combination of reports across all of the test environments.

This will likely be easiest to work on after Microsoft adds 3.8 environment support (See: #43)

Add Issue & PR templates

This project could use issue and PR templates to help customize and standardize the information we'd like contributors to include when issues & PRs are created.

Add Test Case for Proper Checker Invocation

As seen in #54, specific parameter(s) are required in the checker function signature in order to signal to Flake8 that the checker needs to be run on the specified input. While this pitfall was identified previously, a regression was introduced by #53 that prevented Flake8 from determining that this plugin needed to be run. This case is missed by our unit tests, as the way they are mocked assumes that Flake8 has invoked the checker & provided the information that was requested.

To guard against any future regressions, a test case should be developed that invokes Flake8 on an input & checks that the flake8-annotations checker is being run. From some initial mucking around, it seems like a simple stdin test case may be a good candidate for at least an initial approach.

Using a simple test case:

def bar(x) -> None:
    pass

Flake8 should yield a TYP001 error:

$ printf "def bar(x) -> None:\n    pass\n" | flake8 -
stdin:1:9: TYP001 Missing type annotation for function argument 'x'

Incorrect line number when using multiline docstrings

ANN201 is giving the wrong line number if using a multi-line docstring. I assume all the ANN20x would fail for the same reason.

Related to #32, was not fixed correctly.
The logic is searching backwards from a function's body to find : to make the end of the function signature. This is easily broken by having a : inside a docstring, which is fairly common.

def foo(n: int):
    """Multi-line docstring.

    Args:
        n (int):
    """
    return n

Version Information
Please provide the full output of flake8 --version

$ flake8 --version
3.7.9 (flake8-annotations: 2.1.0, flake8-blind-except: 0.1.1, flake8-docstrings: 1.5.0, pydocstyle: 5.0.2, flake8-fixme: 1.1.1, flake8-pytest: 1.3, flake8-spellcheck: 0.12.1, flake8_builtins: 1.5.2, flake8_coding: 1.3.2, import-order: 0.18.1, mccabe: 0.6.1, naming: 0.10.0, pycodestyle: 2.5.0, pyflakes: 2.1.1) CPython 3.6.10 on Linux

As well as your Python version:

$ python -V
Python 3.6.10

Class Methods Not Correctly Tagged

With the change to FunctionVisitor to properly walk over nested functions, the ability to tag class methods was lost so they are not being properly differentiated during error classification.

Add pep8-naming to the linting toolchain

We've decided to use this plugin in our linting toolchain, which allows us to test things like variable name casing (no camelCase please!) and whether classes and methods use cls and self.

Implementation

Here are the errors it can catch:

code sample message
N801 class names should use CapWords convention
N802 function name should be lowercase
N803 argument name should be lowercase
N804 first argument of a classmethod should be named 'cls'
N805 first argument of a method should be named 'self'
N806 variable in function should be lowercase
N807 function name should not start and end with '__'
   
N811 constant imported as non constant
N812 lowercase imported as non lowercase
N813 camelcase imported as lowercase
N814 camelcase imported as constant
N815 mixedCase variable in class scope
N816 mixedCase variable in global scope

We have not decided exactly which of these we should ignore, so it will be up to the person who handles this issue to discuss this with the core devs and come to a consensus on whether we should ignore some of these. It will probably be easier to see which ones here are not necessary after actually running a lint with this plugin on our current codebase.

The person implementing this will also need to fix all the linting errors that occur once this has been added to the toolchain.

Steps

  • Add the plugin to the toolchain
  • Run it and look through the errors that are created. Are any of them out of touch with our style guidelines, and should we ignore some of these rules? Discuss with the core developers if you think so.
  • Fix all the linting problems.

Update Documentation

Before releasing on PyPi, the documentation for this package should be updated to ensure that everything is understandable.

  • Ensure that inline documentation appropriately explains how the checker functions
  • Update README
    • Installation from PyPi
    • Installation from source
    • Configuration
    • Development tasks (dev dependency installation, contrib guidelines)
    • Testing

Leverage tox in CI

Tangentially related to #43 and #47, and a bit of thinking out loud: it might be easier in the long run to reconfigure the Azure pipeline to utilize the tox configuration we’ve generating for local dev

Tox should be able to accomplish pretty much all of the same tasks, and it would make life a bit easier not having to synchronize the tox and azure configurations so the user isn’t getting surprised when they get to CI.

Ability to ignore ANN001 errors for specific argument names

Description
Add a new option like allowed-unannotated-argument-names which is a comma separated list of argument names that are fine to not have annotated.

Rationale/Use Case
Examples: often I need to ingest variables in my functions that I never use (callbacks from another library for example). In these cases, I often will just use _ as my variable.

Here is an example of a GTK callback:

    def on_download_all_click(self, _: Any):
        CacheManager.batch_download_songs(
            self.get_artist_song_ids(),
            before_download=lambda: self.update_artist_view(
                self.artist_id,
                order_token=self.update_order_token,
            ),
            on_song_download_complete=lambda i: self.update_artist_view(
                self.artist_id,
                order_token=self.update_order_token,
            ),
        )

it would be nice if I could avoid having to have the Any annotation here.

ANN202 reported on the wrong column

Describe the bug
The ANN202 is reported in the incorrect column location when the last parameter has a type annotation.

To Reproduce
Minimal code example to reproduce the behavior:

def foo(bar: int):
    return 1


def bar():
    return 1

Results:

test.py:1:13: ANN201 Missing return type annotation for public function
test.py:5:11: ANN201 Missing return type annotation for public function

Expected: the first one should have a column number of 17 or 18.

Version Information
Please provide the full output of flake8 --version

$ flake8 --version
3.7.9 (flake8-annotations: 2.0.0, flake8-comprehensions: 3.2.2, flake8-print: 3.1.4, flake8_pep3101: 1.2.1, import-order: 0.18.1, mccabe: 0.6.1, pycodestyle: 2.5.0, pyflakes: 2.1.1) CPython 3.8.1 on Linux

As well as your Python version:

$ python -V
Python 3.8.1

Python 3.8 Compatibility

With the release of Python 3.8 next week comes some things to do for compatibility!

  • flake8 compatibility check (pending release of flake8 v3.8)
  • Investigate changes to ast in 3.8
    • Native type comment support, likely removing dependency on typed-ast for Python versions >=3.8
    • Nodes with line & column offsets now will also have end line and column offsets, we’re currently manually calculating these
  • See if positional-only arguments have explicit handling in the parsed AST
  • Add Python 3.8 to CI pipeline

This will likely require some refactoring of the test suite in order to provide version-specific testing for the features that are new to Python 3.8

[Meta] Roadmap for Initial Package Release

Now that initial linting capability is good to go (#5), the package needs some cleaning before it's ready to go up on PyPi and into production. Because the package started as an AST parsing experiment, there's a decent bit of "this code looks like someone stumbling through how to write a flake8 plugin" because, well, I was stumbling through figuring out how to write a flake8 plugin (e.g. #12).

Here's an initial summary of tasks:

  • Settle on a name
  • Add support for ignoring errors via .flake8 & similar (#8)
  • Add support for inline # noqa (#8)
  • Profile code & refactor as necessary to streamline inefficiencies
  • Update __repr__ and __str__ methods, where appropriate, to provide proper (non-debugging) strings (#7, #27)
  • Write unit tests & generate testing files (#16, #27)
  • Generate comprehensive documentation (#19)
  • Generate CI pipelines (#17, #27)
  • Lock in package name on PyPi
  • Settle on a versioning scheme (#24)
  • Add webhook to Discord
  • Any misc. bugfixes/enhancements that come up before the above tasks are complete

Initial PyPi release will be 1.0.0, we'll need to archive the current version (2019.0) once we hit our initial release to avoid conflict.

Migrate from Pipenv to Poetry

I'd like to propose for discussion migrating the management of the developer environment from Pipenv to Poetry.

I've created a branch with a complete migration of the project for investigation here: https://github.com/python-discord/flake8-annotations/tree/poetry-adventures

I will state up front that there is no major advantage to making this switch, but rather a collection of minor differences that contribute to what I believe is an overall improvement for the developer. In the fairly recent past PyDis looked into migrating all of the repositories to Poetry, as at the time there was a mix between Pipenv and Poetry utilization. It was decided to unify on Pipenv, as it provides some functionality that's very useful for local development, like pipenv run scripts and support for local .env files when executing these scripts. It also provides the useful check for an up-to-date lock file during deployment for the build to proceed. Poetry's advantages related to building & uploading to PyPI are not useful for most of our repositories since they do not live on PyPI.

Pipenv's deployment-specific advantages

As flake8-annotations is a library, Pipenv's deployment-specific advantages & .env file support are not relevant here.

Poetry's lack of a pipenv run script equivalent

While Poetry does have a poetry run command, it lacks Pipenv's capability for defining scripts in the project configuration and instead is limited to executing the project via defined entry points. While a disadvantage for some of our other repositories that utilize some fairly detailed scripts to reduce developmoent tasks to one-liners, development of flake8-annotations has no need for this enhanced functionality. Both linting (poetry run flake8) and testing (tox) are similarly simply accomplished. poetry run flake8 is also insertable into the pre-commit config, preventing us from having to sync linting dependencies in the config file; we're currently using pipenv run lint to accomplish the same.

Simplification of dependency definition

Currently, project dependencies need to be synced between the Pipfile and setup.py. While we have a CI tool to check for synchronization (pipenv-check), which helps, it only checks for version conflicts and not absolute synchronization. Migrating to Poetry allows us to utilize a singular pyproject.toml file for dependency specifications. As it is a Python standard (ish?) format, it's supported by pip for installation without requiring Poetry as well. As the support landscape expands, things like tox and flake8 would also be able to be migrated into the file as well (tox currently has support but it's as a giant string, which I feel is less readable). This is a pretty significant quality of life advantage over Pipenv.

I have plans to declare black as an explicit dev dependency (it's already run locally), which requires pyproject.toml anyway.

Poetry's build tools

Poetry also provides built-in build tools, allowing for distributions to be built via the poetry built one-liner. While the python setup.py sdist bdist_wheel isn't super challenging, and is run by CI only anyway, it's still a nice simplifying one-liner to have.

Pipenv's future?

With pipenv's transfer of ownership to PyPA, development publically seems to have stalled. While the developers have fairly recently stated that work is progressing & blocked by a myriad of issues, communication has been scarce. Poetry, on the other hand, has a very active development cycle, with a recent 1.0 release & impending addition of a plugin API to support OSS contributions of functionality that is lacking from the core tool.

[Meta] Proposed Error Codes

This issue lays out proposed error codes for the linter. These are partially derived from PEP 484

Function Annotations

  • TYP001: Missing type annotation for function argument
  • TYP002: Missing type annotation for *args
  • TYP003: Missing type annotation for **kwargs

Method Annotations

  • TYP101: Missing type annotation for self in class method
  • TYP102: Missing type annotation for cls in classmethod

Return Annotations

  • TYP201: Missing return type annotation for public method
  • TYP202: Missing return type annotation for protected method
  • TYP203: Missing return type annotation for secret method
  • TYP204: Missing return type annotation for magic method
  • TYP205: Missing return type annotation for staticmethod
  • TYP206: Missing return type annotation for classmethod

ANN201 false positive when functions are defined within functions

Describe the bug
When an outer function returns None, but a function which is defined within it returns something that isn't None, the outer function is falsly marked with an ANN2** error.

Edit: Note this happens even when suppress-none-returning = True.

To Reproduce
Minimal code example to reproduce the behavior:

def foo():
    def bar() -> int:
        return 1

    print(bar())


foo()

When running with --supress-none-returning:

$ flake8 --suppress-none-returning test.py
test.py:1:11: ANN201 Missing return type annotation for public function

Version Information

$ flake8 --version
3.7.9 (flake8-annotations: 2.0.0, flake8-comprehensions: 3.2.2, flake8-print: 3.1.4, flake8_pep3101: 1.2.1, import-order: 0.18.1, mccabe: 0.6.1, pycodestyle: 2.5.0, pyflakes: 2.1.1) CPython 3.8.1 on Linux

As well as your Python version:

$ python -V
Python 3.8.1

Roadmap for Alpha Release

Now that the metadata experiment is more or less complete, the parsing now needs to be made compatible with flake8

Based on flake8's plugin development docs and looking at some existing flake8 plugins, this seems like the general set of tasks that needs to be done:

  • Register checker as a flake8 plugin via setup.py
  • Create checker functionality that accepts the AST from flake8 and integrate with existing function metadata walking
  • Create an Error object & generate our error codes from what's framed in error_codes.py (#10)
  • Capture & prioritize Errors before emitting via flake8 (#9)
  • Emit errors to flake8
  • Pin dependencies appropriately
  • Ensure that the package is pip installable
  • Come up with a rock solid package name

Flake8 optparse conflict when invoking as a module

As noticed in the recent CI failure, flake8 is raising a configuration option conflict when attempting to add the newly inserted configuration option:

Traceback (most recent call last):
  File "/opt/hostedtoolcache/Python/3.6.9/x64/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/opt/hostedtoolcache/Python/3.6.9/x64/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/opt/hostedtoolcache/Python/3.6.9/x64/lib/python3.6/site-packages/flake8/__main__.py", line 4, in <module>
    cli.main()
  File "/opt/hostedtoolcache/Python/3.6.9/x64/lib/python3.6/site-packages/flake8/main/cli.py", line 18, in main
    app.run(argv)
  File "/opt/hostedtoolcache/Python/3.6.9/x64/lib/python3.6/site-packages/flake8/main/application.py", line 393, in run
    self._run(argv)
  File "/opt/hostedtoolcache/Python/3.6.9/x64/lib/python3.6/site-packages/flake8/main/application.py", line 380, in _run
    self.initialize(argv)
  File "/opt/hostedtoolcache/Python/3.6.9/x64/lib/python3.6/site-packages/flake8/main/application.py", line 364, in initialize
    self.register_plugin_options()
  File "/opt/hostedtoolcache/Python/3.6.9/x64/lib/python3.6/site-packages/flake8/main/application.py", line 205, in register_plugin_options
    self.check_plugins.register_options(self.option_manager)
  File "/opt/hostedtoolcache/Python/3.6.9/x64/lib/python3.6/site-packages/flake8/plugins/manager.py", line 489, in register_options
    list(self.manager.map(register_and_enable))
  File "/opt/hostedtoolcache/Python/3.6.9/x64/lib/python3.6/site-packages/flake8/plugins/manager.py", line 297, in map
    yield func(self.plugins[name], *args, **kwargs)
  File "/opt/hostedtoolcache/Python/3.6.9/x64/lib/python3.6/site-packages/flake8/plugins/manager.py", line 485, in register_and_enable
    call_register_options(plugin)
  File "/opt/hostedtoolcache/Python/3.6.9/x64/lib/python3.6/site-packages/flake8/plugins/manager.py", line 397, in generated_function
    return method(optmanager, *args, **kwargs)
  File "/opt/hostedtoolcache/Python/3.6.9/x64/lib/python3.6/site-packages/flake8/plugins/manager.py", line 216, in register_options
    add_options(optmanager)
  File "/home/vsts/work/1/s/flake8_annotations/checker.py", line 86, in add_options
    "Suppress TYP200-level errors for functions that contain no return statement or "
  File "/opt/hostedtoolcache/Python/3.6.9/x64/lib/python3.6/site-packages/flake8/options/manager.py", line 231, in add_option
    self.parser.add_option(option.to_optparse())

I've traced this to a discrepancy in behavior between invoking flake8 via the installed entry point (e.g. flake8) and invoking as a module (e.g. python3 -m flake8) as we're doing in the CI configuration.

While adjusting the CI configuration should resolve the issue, I've reported upstream to see if this is indeed a bug or something working as intended that I've missed.

[Meta] Versioning Scheme

What versioning scheme would make sense for this package?

I'm debating between the following two options:

I'm leaning towards CalVer. Because this is a utility plugin to flake8 with nothing externally facing or backwards incompatible (flake8 compatibility is handled by version pinning), I'm finding it hard to come up with a meaningful metric to use for incrementing major/minor versions of the package; major, in particular.

One caveat to this would be the addition of error codes that would require the user to adjust their ignore settings, but I think this would be an issue with SemVer as well. This seems pretty simply solved by suffixing the error codes table in the README with something like "introduced in ..."

Return Error Code Line Numbers incorrect for decorated functions

When a function is decorated, it appears that ast gives the line number for the function node as the line where the first decorator starts.

For example:

@property
@some_decorator
@some_other_decorator
def bar():
    pass

Gives:

foo.py:1:1: TYP201 Missing return type annotation for public function

Which may or may not be the best line number to provide to the user. I think a good compromise would be to see if this line number can be set to where the function's def lies.

To stave off questions on the contrived-ness of the example, allow me to introduce the wonderful world of packages like Click:

@click.command()
@click.option('--interactive' ,'-i', is_flag=True, help='Enable interactive mode')
@click.option('--starttime', '-s', default='0700', help="Start time, 'HHMM'")
@click.option('--endtime', '-e', default='1530', help="End time, 'HHMM'")
@click.option('--workday', '-wd', default=8.5, help='Length of workday, decimal hours')
@click.option('--startend', '-se', nargs=2, help="Shortcut for standard workday, 'HHMM' 'HHMM'")
@click.option('--nonstandard', '-ns', nargs=3, help="Shortcut for nonstandard workday, 'HHMM' 'HHMM' x.x")
@click.version_option()
def cli(starttime, endtime, interactive, workday, nonstandard, startend):

Add handling for @property decorator

The @property decorator was overlooked when creating the initial parsing logic.

Support for this should be added:

  • ClassDecoratorType enum constant
    • For the purposes of this tool, property, getter, setter, and deleter can probably safely be combined into a single PROPERTY constant
  • Handling by AST parser
  • Add error codes
  • Add error classification

Add support for error exclusions

Flake8 allows for ignoring errors based on adding some flavor of # noqa as well as by configuration option in .flake8, CLI arg, etc.

We'll need to support these.

  • noqa
  • Flake8 configuration

The plugin fails when flake8 is invoked with stdin

When flake8 is invoked in stdin mode, the flake8-annotations plugin fails with the error message [Errno 2] No such file or directory: 'stdin'. This is because in stdin mode, the filename argument flake8 passes to the checker class does not refer to an actual file, but contains the display name flake8 uses in the output to indicate where the code is coming from. (By default, this display name is 'stdin', hence why it's mentioned in the error message above; this display name is configurable with the CL argument --stdin-display-name.)

Since flake8-annotations does not use the input passed by flake8 but rather parses the file directly from disk itself, it tries to use filename to open a file and that fails.

To Reproduce
An easy way to reproduce the error is by piping something to flake8 when the plugin is enabled. I've added the -v verbosity option :

$ printf 'print("Hello, world!")' | flake8 -v -
(...) snipped to reduce output
flake8.checker            MainProcess    285 CRITICAL Plugin TYP raised an unexpected exception
Traceback (most recent call last):
  File "/home/sebastiaan/.local/share/virtualenvs/aoc-2019-1zqaskJS/lib/python3.8/site-packages/flake8/checker.py", line 435, in run_check
    return plugin["plugin"](**arguments)
  File "/home/sebastiaan/.local/share/virtualenvs/aoc-2019-1zqaskJS/lib/python3.8/site-packages/flake8_annotations/checker.py", line 27, in __init__
    self.tree, self.lines = self.load_file(Path(filename))
  File "/home/sebastiaan/.local/share/virtualenvs/aoc-2019-1zqaskJS/lib/python3.8/site-packages/flake8_annotations/checker.py", line 73, in load_file
    with src_filepath.open("r", encoding="utf-8") as f:
  File "/usr/local/lib/python3.8/pathlib.py", line 1200, in open
    return io.open(self, mode, buffering, encoding, errors, newline,
  File "/usr/local/lib/python3.8/pathlib.py", line 1054, in _opener
    return self._accessor.open(self, flags, mode)
FileNotFoundError: [Errno 2] No such file or directory: 'stdin'
"flake8-annotations" failed during execution due to "[Errno 2] No such file or directory: 'stdin'"
Run flake8 with greater verbosity to see more details
(...) snipped to reduce output

Version Information

[master=] -> $ pipenv run flake8 --version
3.7.9 (flake8-annotations: 1.1.1, flake8-tidy-imports: 3.1.0, import-order: 0.18.1, mccabe: 0.6.1, pycodestyle: 2.5.0, pyflakes: 2.1.1) CPython 3.8.0 on Linux
[master=] -> $ pipenv run python -V
Python 3.8.0

I have also tested this with Python 3.7.4 and the same bug occurs.

Possible solution
As far as I'm aware, there's no guaranteed way to find out whether or not flake8 was called to lint input from stdin or from a file on disk using the arguments that are (potentially) passed to the checker class. The reason is that flake8/pycodestyle takes care of processing the input (file or stdin) and then passes that parsed input to the plugin checker class. This means that there is normally no need for a plugin to parse the file contents again.

Unfortunately, since the ast tree provided by flake8 is untyped, we do need to parse the file again and the least expensive way of doing that is by reading the file again. (We could also join together the lines list for that, but that's more expensive.) However, there's another option: If you add a parse_options method to the plugin's checker class, flake8 will pass the command line arguments to it. This means we can check for the - indicating stdin mode:

    # Quick mock-up; I've set a default value of `False` for `read_from_stdin`
    @classmethod
    def parse_options(cls, option_manager: OptionManager, options: Values, args: List[str]) -> None:
        """Parse the command line options provided to `flake8`."""
        if "-" in args:
            cls.read_from_stdin = True

Obviously, we still need to actually get the value from stdin that we're supposed to lint. Since stdin has already been exhausted by pycodestyle, we can do that by adding the lines parameter to the checker's __init__:

    def __init__(self, tree: ast.Module, filename: str, lines: List[str]):
        # Unfortunately no way that I can find around requesting the ast-parsed tree from flake8
        # Removing tree unregisters the plugin, and per the documentation the alternative is
        # requesting per-line information
        self.lines = lines  # <- this also means we don't have to manually split it later
        self.tree = self.load_file(filename)

and use self.lines in read_file if we're in stdin mode:

    def load_file(self, path: str) -> ast.Module:
        """Parse the provided Python file and return an (typed AST, source) tuple."""
        if self.read_from_stdin:
            # Reconstruct source as a single string from `self.lines`
            src = "".join(self.lines)
        else:
            # Read source as single string from file on disk
            src_filepath = Path(path)
            with src_filepath.open("r", encoding="utf-8") as f:
                src = f.read()

        if PY_GTE_38:
            # Built-in ast requires a flag to parse type comments
            tree = ast.parse(src, type_comments=True)
        else:
            # typed-ast will implicitly parse type comments
            tree = ast.parse(src)

        return tree

I've confirmed that this works (and, with some small adjustments for the changed method signatures, the tests also pass), but there may be a better way.

Support type comments (PEP 484)

Add the ability to process type comments in addition to annotations, per PEP 484. Example:

def some_func(arg1, arg2, arg3=True):
    # type: (Optional[str], int, bool) -> Optional[str]
    ...

Rationale/use cases

  • Improves "out of the box" support and encourages migration for projects moving from Python 2 to Python 3
  • Projects that don't have annotations for other reasons (compatibility, DSLs, performance)
  • Extension modules
  • Modules that use annotations for other purposes

Note: mypy supports type comments, so it may have some parsing code that could be adapted.

Update linting dependencies

Three of our linting plugins are having issues with Python 3.8 and need to be updated before 3.8 can be supported:

  • flake8-docstrings
  • flake8-import-order
  • flake8-tidy-imports

False-positive for missing type annotation for "self" on nested classes

Describe the bug
In nested classes, methods which use self are flagged with ANN001 instead of ANN101. This causes problems when the user is attempting to ignore ANN101 but not ANN001 errors.

To Reproduce
Minimal code example to reproduce the behavior:

class Foo:
    class Bar:
        def __init__(self):
            pass

    def __init__(self):
        pass

Results in:

test.py:3:22: ANN001 Missing type annotation for function argument 'self'
test.py:6:18: ANN101 Missing type annotation for self in method

Version Information
Please provide the full output of flake8 --version

$ flake8 --version
3.7.9 (flake8-annotations: 2.0.0, flake8-comprehensions: 3.2.2, flake8-print: 3.1.4, flake8_pep3101: 1.2.1, import-order: 0.18.1, mccabe: 0.6.1, pycodestyle: 2.5.0, pyflakes: 2.1.1) CPython 3.8.1 on Linux

As well as your Python version:

$ python -V
Python 3.8.1

Document expected or recommended annotations to avoid ANN101 and ANN102 errors

Description
Currently flake8-annotations will report an error if the self or cls parameters are not annotated. It is not clear what flake8-annotations wants from the source code in order not to report these errors, and neither PEP 484 nor PEP 3107 offers any guidance as to how self or cls should be annotated. In fact PEP 484 suggests in Annotating class and instance methods that such annotation is not generally necessary:

In most cases the first argument of class and instance methods does not need to be annotated, and it is assumed to have the type of the containing class for instance methods, and a type object type corresponding to the containing class object for class methods.

This means that the out-of-the-box behaviour of flake8-annotations appears (at least at first glance) contrary to the guidelines of the PEPs it is supposed to be enforcing.

Given that neither PEP 484 nor PEP 3107 offer any general guidance on annotating self or cls parameters, the flake8-annotations README should add some examples of how to handle/avoid these errors.

Rationale/Use Case

Behaviour observed with flake8==3.7.9, flake8-annotations==2.0.1, running on CPython 3.7.6.

The error can be seen with even a very trivial class, e.g.:

class Foo:
    def __call__(self) -> float:
        return 1.0

I'm assuming here that the answer is not something like:

class Foo:
    def __call__(self: "Foo") -> float:
        return 1.0

which works, but is rather boilerplate-y and would make renaming a class very annoying.

I'm also assuming that the answer is not just "suppress that class of errors", e.g. with

flake8 --extend-ignore=ANN101,ANN102

which would seem a bit excessive given that there are probably a subset of cases (e.g. those mentioned in the PEP 484 link above) where one probably does want a self or cls annotation. (If it's possible to suppress ANN101 and 102 and still get validation of those special cases, it would be good to have a clear indication of that.)

Basically, please offer some clear guidance on this, given that the PEPs referred to would suggest that un-annotated self and cls is just fine most of the time, and hence flake8-annotations out-of-the-box behaviour is quite unintuitive.

Inadequate pre-commit linting configuration

This repository’s flake8 pre-commit configuration currently utilizes the latest PyPi version of flake8-annotations when building its linting environment rather than the current state of the local repo. This can potentially lead to a result that conflicts with both a manual flake8 invocation and the linting CI pipeline, which utilize the current state of the repo to lint itself.

My research into method(s) to resolve this hasn’t been fruitful. Perhaps linting ourselves is an antipattern or I’m just bad at finding things on the internet, but if there’s no way to solve this then I’m inclined to remove pre-commit completely rather than have this conflict.

Would love to have some opinions and/or leads on this!

Separate warnings for None-returning functions/methods without annotations

Description
It would be nice if flake8-annotations could tell the difference between a callable returning None or using return for flow control, and functions that actually return a value.

Rationale/Use Case
I was surprised to see this behaviour at all at first, although it makes sense now that it's been explained to me.

  • Having a separate error code and message specifically mentioning None returns helps to clarify that this is an intentional part of the project's code style
  • Doubtless, there are projects out there that would rather not annotate a None return type (even though this doesn't apply to any Python Discord projects)

Good work on this plugin, by the way. It never occurred to me how useful something like this would be!

Implement Checks for Error Codes

Once the metadata capture is completed, checks for error codes (as specified in #1) need to be implemented:

Function Annotations

  • TYP001: Missing type annotation for function argument
  • TYP002: Missing type annotation for *args
  • TYP003: Missing type annotation for **kwargs

Method Annotations

  • TYP101: Missing type annotation for self in class method
  • TYP102: Missing type annotation for cls in classmethod

Return Annotations

  • TYP201: Missing return type annotation for public method
  • TYP202: Missing return type annotation for protected method
  • TYP203: Missing return type annotation for secret method
  • TYP204: Missing return type annotation for magic method
  • TYP205: Missing return type annotation for staticmethod
  • TYP206: Missing return type annotation for classmethod

Use built-in ast over typed-ast for Python 3.8+

With Python 3.8's updates to ast adding native type comment support, we should be able to lean on the built-in module over typed-ast for 3.8 onward.

Importing and installation is handled in c78a5d5, but our type comment tests are now failing in Python 3.8 for reason(s) TBD. Fixed by 5de947b

In 3.8+, ast also natively provides node end line & column offsets, which we're currently calculating manually. Edit: Not going to use this, as it provides an incorrect location for the return hint location (: location) when docstrings are present.

Create Error Code Objects

An Error object needs to be created to encapsulate the errors to be considered for emitting by Flake8

See #1 and #9 for a list of codes & checks

Refactor Tests

Some aspects of the test suite are written in a way that makes them fairly fragile and difficult to both maintain and add additional cases to.

As an example, test_column_line_numbers relies on explicitly coded locations matching the formatting of column_line_numbers.py, making updates a manually intensive, error-prone process across multiple files.

This issue proposes investigating potential alternatives for specifying test cases & their expected returns to provide a more robust & maintainable test suite. One thought is to split monolithic source code blocks into more discrete components, allowing them to be more easily colocated with the test parameters.

Using the above example, our source file would be split into something along the lines of the following:

a_test_case = """def bar(x):
    pass
"""
# Expected yielded code definition

and

another_test_case = """@property
@some_decorator
@some_other_decorator
def foo(
    x,
    y
):
    pass
"""
# Expected yielded code definition

While this would potentially make test case specification more verbose overall, I believe it's significantly outweighed by the ease of making changes to the test suite; rather than having to adjusted every column & line number in the file, only the specific case needs to be adjusted.

With this in mind, here first-glance rundown of what's proposed to be looked at:

To be investigated:

Seems ok(ish):

flake8-annotations and flake8-typing-imports Compatibility

Hi, I ran into the below error when installing both flake8-annotations and flake8-typing-imports

optparse.OptionConflictError: option --min-python-version: conflicting option string(s): --min-python-version

Both packages use the same options flag for minimum python version and same error codes.
I opened an issue on flake8-typing-imports (link) and the package author redirected me to submit an issue here: asottile/flake8-typing-imports#10


Simple example using poetry for environment management, but also occurs with regular Python

>poetry add flake8-annotations flake8-typing-imports
>poetry run flake8 --version
(errors)
>poetry run flake8 tmp.py
(errors)

>poetry remove flake8-annotations
>poetry run flake8 --version
(passes)
>poetry run flake8 tmp.py
(passes)

Full traceback:

(base) C:\Users\king.kyle\TestFlake8>poetry run flake8 --version
Traceback (most recent call last):
  File "C:\Users\king.kyle\AppData\Local\Continuum\anaconda3\envs\py368\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "C:\Users\king.kyle\AppData\Local\Continuum\anaconda3\envs\py368\lib\runpy.py", line 85, in _run_code        
    exec(code, run_globals)
  File "C:\Users\king.kyle\AppData\Local\pypoetry\Cache\virtualenvs\testflake8-8tFupX_2-py3.6\Scripts\flake8.exe\__main__.py", line 9, in <module>
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\main\cli.py", line 18, in main
    app.run(argv)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\main\application.py", line 393, in run
    self._run(argv)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\main\application.py", line 380, in _run
    self.initialize(argv)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\main\application.py", line 364, in initialize
    self.register_plugin_options()
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\main\application.py", line 205, in register_plugin_options
    self.check_plugins.register_options(self.option_manager)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\plugins\manager.py", line 489, in register_options
    list(self.manager.map(register_and_enable))
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\plugins\manager.py", line 297, in map
    yield func(self.plugins[name], *args, **kwargs)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\plugins\manager.py", line 485, in register_and_enable
    call_register_options(plugin)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\plugins\manager.py", line 397, in generated_function
    return method(optmanager, *args, **kwargs)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\plugins\manager.py", line 216, in register_options
    add_options(optmanager)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8_typing_imports.py", line 512, in add_options
    'Minimum version of python your code supports, '
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\options\manager.py", line 231, in add_option
    self.parser.add_option(option.to_optparse())
  File "C:\Users\king.kyle\AppData\Local\Continuum\anaconda3\envs\py368\lib\optparse.py", line 1008, in add_option  
    self._check_conflict(option)
  File "C:\Users\king.kyle\AppData\Local\Continuum\anaconda3\envs\py368\lib\optparse.py", line 983, in _check_conflict
    option)
optparse.OptionConflictError: option --min-python-version: conflicting option string(s): --min-python-version       

(base) C:\Users\king.kyle\TestFlake8>

Additional Information

Full Command Prompt Output
(base) C:\Users\king.kyle\TestFlake8>poetry update
Updating dependencies
Resolving dependencies...

Writing lock file


Package operations: 1 install, 0 updates, 0 removals

  - Installing flake8-annotations (1.1.3)
  - Installing flake8-typing-imports (1.5.0)

(base) C:\Users\king.kyle\TestFlake8>poetry run flake8 --version
Traceback (most recent call last):
  File "C:\Users\king.kyle\AppData\Local\Continuum\anaconda3\envs\py368\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "C:\Users\king.kyle\AppData\Local\Continuum\anaconda3\envs\py368\lib\runpy.py", line 85, in _run_code        
    exec(code, run_globals)
  File "C:\Users\king.kyle\AppData\Local\pypoetry\Cache\virtualenvs\testflake8-8tFupX_2-py3.6\Scripts\flake8.exe\__main__.py", line 9, in <module>
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\main\cli.py", line 18, in main
    app.run(argv)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\main\application.py", line 393, in run
    self._run(argv)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\main\application.py", line 380, in _run
    self.initialize(argv)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\main\application.py", line 364, in initialize
    self.register_plugin_options()
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\main\application.py", line 205, in register_plugin_options
    self.check_plugins.register_options(self.option_manager)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\plugins\manager.py", line 489, in register_options
    list(self.manager.map(register_and_enable))
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\plugins\manager.py", line 297, in map
    yield func(self.plugins[name], *args, **kwargs)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\plugins\manager.py", line 485, in register_and_enable
    call_register_options(plugin)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\plugins\manager.py", line 397, in generated_function
    return method(optmanager, *args, **kwargs)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\plugins\manager.py", line 216, in register_options
    add_options(optmanager)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8_typing_imports.py", line 512, in add_options
    'Minimum version of python your code supports, '
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\options\manager.py", line 231, in add_option
    self.parser.add_option(option.to_optparse())
  File "C:\Users\king.kyle\AppData\Local\Continuum\anaconda3\envs\py368\lib\optparse.py", line 1008, in add_option  
    self._check_conflict(option)
  File "C:\Users\king.kyle\AppData\Local\Continuum\anaconda3\envs\py368\lib\optparse.py", line 983, in _check_conflict
    option)
optparse.OptionConflictError: option --min-python-version: conflicting option string(s): --min-python-version       

(base) C:\Users\king.kyle\TestFlake8>poetry run flake8 tmp.py
Traceback (most recent call last):
  File "C:\Users\king.kyle\AppData\Local\Continuum\anaconda3\envs\py368\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "C:\Users\king.kyle\AppData\Local\Continuum\anaconda3\envs\py368\lib\runpy.py", line 85, in _run_code        
    exec(code, run_globals)
  File "C:\Users\king.kyle\AppData\Local\pypoetry\Cache\virtualenvs\testflake8-8tFupX_2-py3.6\Scripts\flake8.exe\__main__.py", line 9, in <module>
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\main\cli.py", line 18, in main
    app.run(argv)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\main\application.py", line 393, in run
    self._run(argv)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\main\application.py", line 380, in _run
    self.initialize(argv)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\main\application.py", line 364, in initialize
    self.register_plugin_options()
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\main\application.py", line 205, in register_plugin_options
    self.check_plugins.register_options(self.option_manager)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\plugins\manager.py", line 489, in register_options
    list(self.manager.map(register_and_enable))
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\plugins\manager.py", line 297, in map
    yield func(self.plugins[name], *args, **kwargs)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\plugins\manager.py", line 485, in register_and_enable
    call_register_options(plugin)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\plugins\manager.py", line 397, in generated_function
    return method(optmanager, *args, **kwargs)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\plugins\manager.py", line 216, in register_options
    add_options(optmanager)
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8_typing_imports.py", line 512, in add_options
    'Minimum version of python your code supports, '
  File "c:\users\king.kyle\appdata\local\pypoetry\cache\virtualenvs\testflake8-8tfupx_2-py3.6\lib\site-packages\flake8\options\manager.py", line 231, in add_option
    self.parser.add_option(option.to_optparse())
  File "C:\Users\king.kyle\AppData\Local\Continuum\anaconda3\envs\py368\lib\optparse.py", line 1008, in add_option  
    self._check_conflict(option)
  File "C:\Users\king.kyle\AppData\Local\Continuum\anaconda3\envs\py368\lib\optparse.py", line 983, in _check_conflict
    option)
optparse.OptionConflictError: option --min-python-version: conflicting option string(s): --min-python-version       

(base) C:\Users\king.kyle\TestFlake8>poetry update
Updating dependencies
Resolving dependencies...

Writing lock file


Package operations: 0 installs, 0 updates, 1 removal

  - Removing flake8-annotations (1.1.3)

(base) C:\Users\king.kyle\TestFlake8>poetry run flake8 tmp.py
tmp.py:10:80: E501 line too long (87 > 79 characters)

(base) C:\Users\king.kyle\TestFlake8>poetry run pip freeze
entrypoints==0.3
flake8==3.7.9
flake8-typing-imports==1.5.0
importlib-metadata==1.5.0
mccabe==0.6.1
pycodestyle==2.5.0
pyflakes==2.1.1
typed-ast==1.4.1
zipp==2.1.0
flake8.log
2020-01-30 09:09:30,030 manager.py:238    Registered option "Option(-v, --verbose, action=count, default=0, dest=verbose, type=None, callback=None, help=Print more information about what is happening in flake8. This option is repeatable and will increase verbosity each time it is repeated., callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,031 manager.py:238    Registered option "Option(-q, --quiet, action=count, default=0, dest=quiet, type=None, callback=None, help=Report only file names, or nothing. This option is repeatable., callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,031 manager.py:238    Registered option "Option(None, --count, action=store_true, default=None, dest=count, type=None, callback=None, help=Print total number of errors and warnings to standard error and set the exit code to 1 if total is not empty., callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,036 manager.py:238    Registered option "Option(None, --diff, action=store_true, default=None, dest=diff, type=None, callback=None, help=Report changes only within line number ranges in the unified diff provided on standard in by the user., callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,037 manager.py:238    Registered option "Option(None, --exclude, action=None, default=.svn,CVS,.bzr,.hg,.git,__pycache__,.tox,.eggs,*.egg, dest=exclude, type=None, callback=None, help=Comma-separated list of files or directories to exclude. (Default: %default), callback=None, callback_args=None, callback_kwargs=None, metavar=patterns)".
2020-01-30 09:09:30,037 manager.py:238    Registered option "Option(None, --filename, action=None, default=*.py, dest=filename, type=None, callback=None, help=Only check for filenames matching the patterns in this comma-separated list. (Default: %default), callback=None, callback_args=None, callback_kwargs=None, metavar=patterns)".
2020-01-30 09:09:30,038 manager.py:238    Registered option "Option(None, --stdin-display-name, action=None, default=stdin, dest=stdin_display_name, type=None, callback=None, help=The name used when reporting errors from code passed via stdin. This is useful for editors piping the file contents to flake8. (Default: %default), callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,039 manager.py:238    Registered option "Option(None, --format, action=None, default=default, dest=format, type=None, callback=None, help=Format errors according to the chosen formatter., callback=None, callback_args=None, callback_kwargs=None, metavar=format)".
2020-01-30 09:09:30,058 manager.py:238    Registered option "Option(None, --hang-closing, action=store_true, default=None, dest=hang_closing, type=None, callback=None, help=Hang closing bracket instead of matching indentation of opening bracket's line., callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,059 manager.py:238    Registered option "Option(None, --ignore, action=None, default=E121,E123,E126,E226,E24,E704,W503,W504, dest=ignore, type=None, callback=None, help=Comma-separated list of errors and warnings to ignore (or skip). For example, ``--ignore=E4,E51,W234``. (Default: %default), callback=None, callback_args=None, callback_kwargs=None, metavar=errors)".
2020-01-30 09:09:30,060 manager.py:238    Registered option "Option(None, --extend-ignore, action=None, default=, dest=extend_ignore, type=None, callback=None, help=Comma-separated list of errors and warnings to add to the list of ignored ones. For example, ``--extend-ignore=E4,E51,W234``., callback=None, callback_args=None, callback_kwargs=None, metavar=errors)".
2020-01-30 09:09:30,060 manager.py:238    Registered option "Option(None, --per-file-ignores, action=None, default=, dest=per_file_ignores, type=None, callback=None, help=A pairing of filenames and violation codes that defines which violations to ignore in a particular file. The filenames can be specified in a manner similar to the ``--exclude`` option and the violations work similarly to the ``--ignore`` and ``--select`` options., callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,061 manager.py:238    Registered option "Option(None, --max-line-length, action=None, default=79, dest=max_line_length, type=int, callback=None, help=Maximum allowed line length for the entirety of this run. (Default: %default), callback=None, callback_args=None, callback_kwargs=None, metavar=n)".
2020-01-30 09:09:30,062 manager.py:238    Registered option "Option(None, --max-doc-length, action=None, default=None, dest=max_doc_length, type=int, callback=None, help=Maximum allowed doc line length for the entirety of this run. (Default: %default), callback=None, callback_args=None, callback_kwargs=None, metavar=n)".
2020-01-30 09:09:30,062 manager.py:238    Registered option "Option(None, --select, action=None, default=E,F,W,C90, dest=select, type=None, callback=None, help=Comma-separated list of errors and warnings to enable. For example, ``--select=E4,E51,W234``. (Default: %default), callback=None, callback_args=None, callback_kwargs=None, metavar=errors)".
2020-01-30 09:09:30,063 manager.py:238    Registered option "Option(None, --disable-noqa, action=store_true, default=False, dest=disable_noqa, type=None, callback=None, help=Disable the effect of "# noqa". This will report errors on lines with "# noqa" at the end., callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,063 manager.py:238    Registered option "Option(None, --show-source, action=store_true, default=None, dest=show_source, type=None, callback=None, help=Show the source generate each error or warning., callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,063 manager.py:238    Registered option "Option(None, --statistics, action=store_true, default=None, dest=statistics, type=None, callback=None, help=Count errors and warnings., callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,064 manager.py:238    Registered option "Option(None, --enable-extensions, action=None, default=, dest=enable_extensions, type=string, callback=None, help=Enable plugins and extensions that are otherwise disabled by default, callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,064 manager.py:238    Registered option "Option(None, --exit-zero, action=store_true, default=None, dest=exit_zero, type=None, callback=None, help=Exit with status code "0" even if there are errors., callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,065 manager.py:238    Registered option "Option(None, --install-hook, action=callback, default=None, dest=install_hook, type=choice, callback=<function install at 0x00000221C5750E18>, help=Install a hook that is run prior to a commit for the supported version control system., callback=<function install at 0x00000221C5750E18>, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,065 manager.py:238    Registered option "Option(-j, --jobs, action=None, default=auto, dest=jobs, type=string, callback=None, help=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: %default), callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,065 manager.py:238    Registered option "Option(None, --output-file, action=None, default=None, dest=output_file, type=string, callback=None, help=Redirect report to a file., callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,066 manager.py:238    Registered option "Option(None, --tee, action=store_true, default=False, dest=tee, type=None, callback=None, help=Write to stdout and output-file., callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,066 manager.py:238    Registered option "Option(None, --append-config, action=append, default=None, dest=append_config, type=None, callback=None, help=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., callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,066 manager.py:238    Registered option "Option(None, --config, action=None, default=None, dest=config, type=None, callback=None, help=Path to the config file that will be the authoritative config source. This will cause Flake8 to ignore all other configuration files., callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,067 manager.py:238    Registered option "Option(None, --isolated, action=store_true, default=False, dest=isolated, type=None, callback=None, help=Ignore all configuration files., callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,067 manager.py:238    Registered option "Option(None, --benchmark, action=store_true, default=False, dest=benchmark, type=None, callback=None, help=Print benchmark information about this run of Flake8, callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,067 manager.py:238    Registered option "Option(None, --bug-report, action=callback, default=None, dest=bug_report, type=None, callback=<function print_information at 0x00000221C56BDA60>, help=Print information necessary when preparing a bug report, callback=<function print_information at 0x00000221C56BDA60>, callback_args=None, callback_kwargs={'option_manager': <flake8.options.manager.OptionManager object at 0x00000221C52C0208>}, metavar=None)".
2020-01-30 09:09:30,070 manager.py:254    Loading entry-points for "flake8.extension".
2020-01-30 09:09:30,083 manager.py:275    Loaded Plugin(name="F", entry_point="EntryPoint('F', 'flake8.plugins.pyflakes', 'FlakesChecker', Distribution('flake8', '3.7.9'))") for plugin "F".
2020-01-30 09:09:30,083 manager.py:275    Loaded Plugin(name="pycodestyle.ambiguous_identifier", entry_point="EntryPoint('pycodestyle.ambiguous_identifier', 'pycodestyle', 'ambiguous_identifier', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.ambiguous_identifier".
2020-01-30 09:09:30,083 manager.py:275    Loaded Plugin(name="pycodestyle.bare_except", entry_point="EntryPoint('pycodestyle.bare_except', 'pycodestyle', 'bare_except', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.bare_except".
2020-01-30 09:09:30,083 manager.py:275    Loaded Plugin(name="pycodestyle.blank_lines", entry_point="EntryPoint('pycodestyle.blank_lines', 'pycodestyle', 'blank_lines', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.blank_lines".
2020-01-30 09:09:30,083 manager.py:275    Loaded Plugin(name="pycodestyle.break_after_binary_operator", entry_point="EntryPoint('pycodestyle.break_after_binary_operator', 'pycodestyle', 'break_after_binary_operator', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.break_after_binary_operator".
2020-01-30 09:09:30,083 manager.py:275    Loaded Plugin(name="pycodestyle.break_before_binary_operator", entry_point="EntryPoint('pycodestyle.break_before_binary_operator', 'pycodestyle', 'break_before_binary_operator', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.break_before_binary_operator".
2020-01-30 09:09:30,083 manager.py:275    Loaded Plugin(name="pycodestyle.comparison_negative", entry_point="EntryPoint('pycodestyle.comparison_negative', 'pycodestyle', 'comparison_negative', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.comparison_negative".
2020-01-30 09:09:30,083 manager.py:275    Loaded Plugin(name="pycodestyle.comparison_to_singleton", entry_point="EntryPoint('pycodestyle.comparison_to_singleton', 'pycodestyle', 'comparison_to_singleton', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.comparison_to_singleton".
2020-01-30 09:09:30,083 manager.py:275    Loaded Plugin(name="pycodestyle.comparison_type", entry_point="EntryPoint('pycodestyle.comparison_type', 'pycodestyle', 'comparison_type', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.comparison_type".
2020-01-30 09:09:30,083 manager.py:275    Loaded Plugin(name="pycodestyle.compound_statements", entry_point="EntryPoint('pycodestyle.compound_statements', 'pycodestyle', 'compound_statements', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.compound_statements".
2020-01-30 09:09:30,083 manager.py:275    Loaded Plugin(name="pycodestyle.continued_indentation", entry_point="EntryPoint('pycodestyle.continued_indentation', 'pycodestyle', 'continued_indentation', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.continued_indentation".
2020-01-30 09:09:30,084 manager.py:275    Loaded Plugin(name="pycodestyle.explicit_line_join", entry_point="EntryPoint('pycodestyle.explicit_line_join', 'pycodestyle', 'explicit_line_join', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.explicit_line_join".
2020-01-30 09:09:30,084 manager.py:275    Loaded Plugin(name="pycodestyle.extraneous_whitespace", entry_point="EntryPoint('pycodestyle.extraneous_whitespace', 'pycodestyle', 'extraneous_whitespace', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.extraneous_whitespace".
2020-01-30 09:09:30,084 manager.py:275    Loaded Plugin(name="pycodestyle.imports_on_separate_lines", entry_point="EntryPoint('pycodestyle.imports_on_separate_lines', 'pycodestyle', 'imports_on_separate_lines', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.imports_on_separate_lines".
2020-01-30 09:09:30,084 manager.py:275    Loaded Plugin(name="pycodestyle.indentation", entry_point="EntryPoint('pycodestyle.indentation', 'pycodestyle', 'indentation', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.indentation".
2020-01-30 09:09:30,084 manager.py:275    Loaded Plugin(name="pycodestyle.maximum_doc_length", entry_point="EntryPoint('pycodestyle.maximum_doc_length', 'pycodestyle', 'maximum_doc_length', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.maximum_doc_length".
2020-01-30 09:09:30,084 manager.py:275    Loaded Plugin(name="pycodestyle.maximum_line_length", entry_point="EntryPoint('pycodestyle.maximum_line_length', 'pycodestyle', 'maximum_line_length', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.maximum_line_length".
2020-01-30 09:09:30,084 manager.py:275    Loaded Plugin(name="pycodestyle.missing_whitespace", entry_point="EntryPoint('pycodestyle.missing_whitespace', 'pycodestyle', 'missing_whitespace', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.missing_whitespace".
2020-01-30 09:09:30,084 manager.py:275    Loaded Plugin(name="pycodestyle.missing_whitespace_after_import_keyword", entry_point="EntryPoint('pycodestyle.missing_whitespace_after_import_keyword', 'pycodestyle', 'missing_whitespace_after_import_keyword', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.missing_whitespace_after_import_keyword".
2020-01-30 09:09:30,084 manager.py:275    Loaded Plugin(name="pycodestyle.missing_whitespace_around_operator", entry_point="EntryPoint('pycodestyle.missing_whitespace_around_operator', 'pycodestyle', 'missing_whitespace_around_operator', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.missing_whitespace_around_operator".
2020-01-30 09:09:30,084 manager.py:275    Loaded Plugin(name="pycodestyle.module_imports_on_top_of_file", entry_point="EntryPoint('pycodestyle.module_imports_on_top_of_file', 'pycodestyle', 'module_imports_on_top_of_file', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.module_imports_on_top_of_file".
2020-01-30 09:09:30,084 manager.py:275    Loaded Plugin(name="pycodestyle.python_3000_async_await_keywords", entry_point="EntryPoint('pycodestyle.python_3000_async_await_keywords', 'pycodestyle', 'python_3000_async_await_keywords', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.python_3000_async_await_keywords".
2020-01-30 09:09:30,084 manager.py:275    Loaded Plugin(name="pycodestyle.python_3000_backticks", entry_point="EntryPoint('pycodestyle.python_3000_backticks', 'pycodestyle', 'python_3000_backticks', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.python_3000_backticks".
2020-01-30 09:09:30,084 manager.py:275    Loaded Plugin(name="pycodestyle.python_3000_has_key", entry_point="EntryPoint('pycodestyle.python_3000_has_key', 'pycodestyle', 'python_3000_has_key', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.python_3000_has_key".
2020-01-30 09:09:30,084 manager.py:275    Loaded Plugin(name="pycodestyle.python_3000_invalid_escape_sequence", entry_point="EntryPoint('pycodestyle.python_3000_invalid_escape_sequence', 'pycodestyle', 'python_3000_invalid_escape_sequence', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.python_3000_invalid_escape_sequence".
2020-01-30 09:09:30,084 manager.py:275    Loaded Plugin(name="pycodestyle.python_3000_not_equal", entry_point="EntryPoint('pycodestyle.python_3000_not_equal', 'pycodestyle', 'python_3000_not_equal', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.python_3000_not_equal".
2020-01-30 09:09:30,084 manager.py:275    Loaded Plugin(name="pycodestyle.python_3000_raise_comma", entry_point="EntryPoint('pycodestyle.python_3000_raise_comma', 'pycodestyle', 'python_3000_raise_comma', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.python_3000_raise_comma".
2020-01-30 09:09:30,085 manager.py:275    Loaded Plugin(name="pycodestyle.tabs_obsolete", entry_point="EntryPoint('pycodestyle.tabs_obsolete', 'pycodestyle', 'tabs_obsolete', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.tabs_obsolete".
2020-01-30 09:09:30,085 manager.py:275    Loaded Plugin(name="pycodestyle.tabs_or_spaces", entry_point="EntryPoint('pycodestyle.tabs_or_spaces', 'pycodestyle', 'tabs_or_spaces', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.tabs_or_spaces".
2020-01-30 09:09:30,085 manager.py:275    Loaded Plugin(name="pycodestyle.trailing_blank_lines", entry_point="EntryPoint('pycodestyle.trailing_blank_lines', 'pycodestyle', 'trailing_blank_lines', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.trailing_blank_lines".
2020-01-30 09:09:30,085 manager.py:275    Loaded Plugin(name="pycodestyle.trailing_whitespace", entry_point="EntryPoint('pycodestyle.trailing_whitespace', 'pycodestyle', 'trailing_whitespace', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.trailing_whitespace".
2020-01-30 09:09:30,085 manager.py:275    Loaded Plugin(name="pycodestyle.whitespace_around_comma", entry_point="EntryPoint('pycodestyle.whitespace_around_comma', 'pycodestyle', 'whitespace_around_comma', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.whitespace_around_comma".
2020-01-30 09:09:30,085 manager.py:275    Loaded Plugin(name="pycodestyle.whitespace_around_keywords", entry_point="EntryPoint('pycodestyle.whitespace_around_keywords', 'pycodestyle', 'whitespace_around_keywords', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.whitespace_around_keywords".
2020-01-30 09:09:30,085 manager.py:275    Loaded Plugin(name="pycodestyle.whitespace_around_named_parameter_equals", entry_point="EntryPoint('pycodestyle.whitespace_around_named_parameter_equals', 'pycodestyle', 'whitespace_around_named_parameter_equals', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.whitespace_around_named_parameter_equals".
2020-01-30 09:09:30,085 manager.py:275    Loaded Plugin(name="pycodestyle.whitespace_around_operator", entry_point="EntryPoint('pycodestyle.whitespace_around_operator', 'pycodestyle', 'whitespace_around_operator', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.whitespace_around_operator".
2020-01-30 09:09:30,085 manager.py:275    Loaded Plugin(name="pycodestyle.whitespace_before_comment", entry_point="EntryPoint('pycodestyle.whitespace_before_comment', 'pycodestyle', 'whitespace_before_comment', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.whitespace_before_comment".
2020-01-30 09:09:30,085 manager.py:275    Loaded Plugin(name="pycodestyle.whitespace_before_parameters", entry_point="EntryPoint('pycodestyle.whitespace_before_parameters', 'pycodestyle', 'whitespace_before_parameters', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.whitespace_before_parameters".
2020-01-30 09:09:30,085 manager.py:275    Loaded Plugin(name="TYP", entry_point="EntryPoint('TYP', 'flake8_annotations.checker', 'TypeHintChecker', Distribution('flake8_annotations', '1.1.3'))") for plugin "TYP".
2020-01-30 09:09:30,085 manager.py:275    Loaded Plugin(name="TYP", entry_point="EntryPoint('TYP', 'flake8_typing_imports', 'Plugin', Distribution('flake8_typing_imports', '1.5.0'))") for plugin "TYP".
2020-01-30 09:09:30,085 manager.py:275    Loaded Plugin(name="C90", entry_point="EntryPoint('C90', 'mccabe', 'McCabeChecker', Distribution('mccabe', '0.6.1'))") for plugin "C90".
2020-01-30 09:09:30,085 manager.py:254    Loading entry-points for "flake8.report".
2020-01-30 09:09:30,096 manager.py:275    Loaded Plugin(name="default", entry_point="EntryPoint('default', 'flake8.formatting.default', 'Default', Distribution('flake8', '3.7.9'))") for plugin "default".
2020-01-30 09:09:30,096 manager.py:275    Loaded Plugin(name="pylint", entry_point="EntryPoint('pylint', 'flake8.formatting.default', 'Pylint', Distribution('flake8', '3.7.9'))") for plugin "pylint".
2020-01-30 09:09:30,096 manager.py:275    Loaded Plugin(name="quiet-filename", entry_point="EntryPoint('quiet-filename', 'flake8.formatting.default', 'FilenameOnly', Distribution('flake8', '3.7.9'))") for plugin "quiet-filename".
2020-01-30 09:09:30,096 manager.py:275    Loaded Plugin(name="quiet-nothing", entry_point="EntryPoint('quiet-nothing', 'flake8.formatting.default', 'Nothing', Distribution('flake8', '3.7.9'))") for plugin "quiet-nothing".
2020-01-30 09:09:30,096 manager.py:156    Loading plugin "F" from entry-point.
2020-01-30 09:09:30,124 manager.py:156    Loading plugin "pycodestyle.ambiguous_identifier" from entry-point.
2020-01-30 09:09:30,131 manager.py:156    Loading plugin "pycodestyle.bare_except" from entry-point.
2020-01-30 09:09:30,131 manager.py:156    Loading plugin "pycodestyle.blank_lines" from entry-point.
2020-01-30 09:09:30,131 manager.py:156    Loading plugin "pycodestyle.break_after_binary_operator" from entry-point.
2020-01-30 09:09:30,131 manager.py:156    Loading plugin "pycodestyle.break_before_binary_operator" from entry-point.
2020-01-30 09:09:30,131 manager.py:156    Loading plugin "pycodestyle.comparison_negative" from entry-point.
2020-01-30 09:09:30,131 manager.py:156    Loading plugin "pycodestyle.comparison_to_singleton" from entry-point.
2020-01-30 09:09:30,131 manager.py:156    Loading plugin "pycodestyle.comparison_type" from entry-point.
2020-01-30 09:09:30,131 manager.py:156    Loading plugin "pycodestyle.compound_statements" from entry-point.
2020-01-30 09:09:30,131 manager.py:156    Loading plugin "pycodestyle.continued_indentation" from entry-point.
2020-01-30 09:09:30,132 manager.py:156    Loading plugin "pycodestyle.explicit_line_join" from entry-point.
2020-01-30 09:09:30,132 manager.py:156    Loading plugin "pycodestyle.extraneous_whitespace" from entry-point.
2020-01-30 09:09:30,132 manager.py:156    Loading plugin "pycodestyle.imports_on_separate_lines" from entry-point.
2020-01-30 09:09:30,132 manager.py:156    Loading plugin "pycodestyle.indentation" from entry-point.
2020-01-30 09:09:30,132 manager.py:156    Loading plugin "pycodestyle.maximum_doc_length" from entry-point.
2020-01-30 09:09:30,132 manager.py:156    Loading plugin "pycodestyle.maximum_line_length" from entry-point.
2020-01-30 09:09:30,132 manager.py:156    Loading plugin "pycodestyle.missing_whitespace" from entry-point.
2020-01-30 09:09:30,132 manager.py:156    Loading plugin "pycodestyle.missing_whitespace_after_import_keyword" from entry-point.
2020-01-30 09:09:30,132 manager.py:156    Loading plugin "pycodestyle.missing_whitespace_around_operator" from entry-point.
2020-01-30 09:09:30,132 manager.py:156    Loading plugin "pycodestyle.module_imports_on_top_of_file" from entry-point.
2020-01-30 09:09:30,132 manager.py:156    Loading plugin "pycodestyle.python_3000_async_await_keywords" from entry-point.
2020-01-30 09:09:30,132 manager.py:156    Loading plugin "pycodestyle.python_3000_backticks" from entry-point.
2020-01-30 09:09:30,132 manager.py:156    Loading plugin "pycodestyle.python_3000_has_key" from entry-point.
2020-01-30 09:09:30,133 manager.py:156    Loading plugin "pycodestyle.python_3000_invalid_escape_sequence" from entry-point.
2020-01-30 09:09:30,133 manager.py:156    Loading plugin "pycodestyle.python_3000_not_equal" from entry-point.
2020-01-30 09:09:30,133 manager.py:156    Loading plugin "pycodestyle.python_3000_raise_comma" from entry-point.
2020-01-30 09:09:30,133 manager.py:156    Loading plugin "pycodestyle.tabs_obsolete" from entry-point.
2020-01-30 09:09:30,133 manager.py:156    Loading plugin "pycodestyle.tabs_or_spaces" from entry-point.
2020-01-30 09:09:30,133 manager.py:156    Loading plugin "pycodestyle.trailing_blank_lines" from entry-point.
2020-01-30 09:09:30,133 manager.py:156    Loading plugin "pycodestyle.trailing_whitespace" from entry-point.
2020-01-30 09:09:30,133 manager.py:156    Loading plugin "pycodestyle.whitespace_around_comma" from entry-point.
2020-01-30 09:09:30,133 manager.py:156    Loading plugin "pycodestyle.whitespace_around_keywords" from entry-point.
2020-01-30 09:09:30,133 manager.py:156    Loading plugin "pycodestyle.whitespace_around_named_parameter_equals" from entry-point.
2020-01-30 09:09:30,133 manager.py:156    Loading plugin "pycodestyle.whitespace_around_operator" from entry-point.
2020-01-30 09:09:30,133 manager.py:156    Loading plugin "pycodestyle.whitespace_before_comment" from entry-point.
2020-01-30 09:09:30,134 manager.py:156    Loading plugin "pycodestyle.whitespace_before_parameters" from entry-point.
2020-01-30 09:09:30,134 manager.py:156    Loading plugin "TYP" from entry-point.
2020-01-30 09:09:30,168 manager.py:156    Loading plugin "C90" from entry-point.
2020-01-30 09:09:30,169 manager.py:156    Loading plugin "default" from entry-point.
2020-01-30 09:09:30,171 manager.py:156    Loading plugin "pylint" from entry-point.
2020-01-30 09:09:30,171 manager.py:156    Loading plugin "quiet-filename" from entry-point.
2020-01-30 09:09:30,171 manager.py:156    Loading plugin "quiet-nothing" from entry-point.
2020-01-30 09:09:30,173 manager.py:216    Registering options from plugin "F" on OptionManager <flake8.options.manager.OptionManager object at 0x00000221C52C0208>
2020-01-30 09:09:30,174 manager.py:238    Registered option "Option(None, --builtins, action=None, default=None, dest=builtins, type=None, callback=None, help=define more built-ins, comma separated, callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,174 manager.py:238    Registered option "Option(None, --doctests, action=store_true, default=False, dest=doctests, type=None, callback=None, help=check syntax of the doctests, callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,175 manager.py:238    Registered option "Option(None, --include-in-doctest, action=None, default=, dest=include_in_doctest, type=string, callback=None, help=Run doctests only on these files, callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,176 manager.py:238    Registered option "Option(None, --exclude-from-doctest, action=None, default=, dest=exclude_from_doctest, type=string, callback=None, help=Skip these files when running doctests, callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
2020-01-30 09:09:30,176 manager.py:247    Removing ['F'] from the default ignore list
2020-01-30 09:09:30,176 manager.py:255    Attempted to remove F from default ignore but it was not a member of the list.
2020-01-30 09:09:30,176 manager.py:275    Extending default select list with ['F']
2020-01-30 09:09:30,177 manager.py:216    Registering options from plugin "TYP" on OptionManager <flake8.options.manager.OptionManager object at 0x00000221C52C0208>
2020-01-30 09:09:30,178 manager.py:238    Registered option "Option(None, --min-python-version, action=None, default=3.5.0, dest=min_python_version, type=str, callback=None, help=Minimum version of python your code supports, (default: %(default)s), callback=None, callback_args=None, callback_kwargs=None, metavar=VERSION)".
2020-01-30 09:09:30,178 manager.py:247    Removing ['TYP'] from the default ignore list
2020-01-30 09:09:30,178 manager.py:255    Attempted to remove TYP from default ignore but it was not a member of the list.
2020-01-30 09:09:30,178 manager.py:275    Extending default select list with ['TYP']
2020-01-30 09:09:30,179 manager.py:216    Registering options from plugin "TYP" on OptionManager <flake8.options.manager.OptionManager object at 0x00000221C52C0208>
flake8                    MainProcess    117 DEBUG    Added a C:/Users/king.kyle/Downloads/flake8.log logging handler to logger root at flake8
flake8.plugins.manager    MainProcess    119 INFO     Loading entry-points for "flake8.extension".
flake8.plugins.manager    MainProcess    232 DEBUG    Loaded Plugin(name="F", entry_point="EntryPoint('F', 'flake8.plugins.pyflakes', 'FlakesChecker', Distribution('flake8', '3.7.9'))") for plugin "F".
flake8.plugins.manager    MainProcess    232 DEBUG    Loaded Plugin(name="pycodestyle.ambiguous_identifier", entry_point="EntryPoint('pycodestyle.ambiguous_identifier', 'pycodestyle', 'ambiguous_identifier', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.ambiguous_identifier".
flake8.plugins.manager    MainProcess    232 DEBUG    Loaded Plugin(name="pycodestyle.bare_except", entry_point="EntryPoint('pycodestyle.bare_except', 'pycodestyle', 'bare_except', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.bare_except".
flake8.plugins.manager    MainProcess    232 DEBUG    Loaded Plugin(name="pycodestyle.blank_lines", entry_point="EntryPoint('pycodestyle.blank_lines', 'pycodestyle', 'blank_lines', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.blank_lines".
flake8.plugins.manager    MainProcess    232 DEBUG    Loaded Plugin(name="pycodestyle.break_after_binary_operator", entry_point="EntryPoint('pycodestyle.break_after_binary_operator', 'pycodestyle', 'break_after_binary_operator', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.break_after_binary_operator".
flake8.plugins.manager    MainProcess    232 DEBUG    Loaded Plugin(name="pycodestyle.break_before_binary_operator", entry_point="EntryPoint('pycodestyle.break_before_binary_operator', 'pycodestyle', 'break_before_binary_operator', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.break_before_binary_operator".
flake8.plugins.manager    MainProcess    232 DEBUG    Loaded Plugin(name="pycodestyle.comparison_negative", entry_point="EntryPoint('pycodestyle.comparison_negative', 'pycodestyle', 'comparison_negative', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.comparison_negative".
flake8.plugins.manager    MainProcess    232 DEBUG    Loaded Plugin(name="pycodestyle.comparison_to_singleton", entry_point="EntryPoint('pycodestyle.comparison_to_singleton', 'pycodestyle', 'comparison_to_singleton', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.comparison_to_singleton".
flake8.plugins.manager    MainProcess    232 DEBUG    Loaded Plugin(name="pycodestyle.comparison_type", entry_point="EntryPoint('pycodestyle.comparison_type', 'pycodestyle', 'comparison_type', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.comparison_type".
flake8.plugins.manager    MainProcess    232 DEBUG    Loaded Plugin(name="pycodestyle.compound_statements", entry_point="EntryPoint('pycodestyle.compound_statements', 'pycodestyle', 'compound_statements', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.compound_statements".
flake8.plugins.manager    MainProcess    232 DEBUG    Loaded Plugin(name="pycodestyle.continued_indentation", entry_point="EntryPoint('pycodestyle.continued_indentation', 'pycodestyle', 'continued_indentation', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.continued_indentation".
flake8.plugins.manager    MainProcess    232 DEBUG    Loaded Plugin(name="pycodestyle.explicit_line_join", entry_point="EntryPoint('pycodestyle.explicit_line_join', 'pycodestyle', 'explicit_line_join', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.explicit_line_join".
flake8.plugins.manager    MainProcess    232 DEBUG    Loaded Plugin(name="pycodestyle.extraneous_whitespace", entry_point="EntryPoint('pycodestyle.extraneous_whitespace', 'pycodestyle', 'extraneous_whitespace', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.extraneous_whitespace".
flake8.plugins.manager    MainProcess    232 DEBUG    Loaded Plugin(name="pycodestyle.imports_on_separate_lines", entry_point="EntryPoint('pycodestyle.imports_on_separate_lines', 'pycodestyle', 'imports_on_separate_lines', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.imports_on_separate_lines".
flake8.plugins.manager    MainProcess    232 DEBUG    Loaded Plugin(name="pycodestyle.indentation", entry_point="EntryPoint('pycodestyle.indentation', 'pycodestyle', 'indentation', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.indentation".
flake8.plugins.manager    MainProcess    232 DEBUG    Loaded Plugin(name="pycodestyle.maximum_doc_length", entry_point="EntryPoint('pycodestyle.maximum_doc_length', 'pycodestyle', 'maximum_doc_length', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.maximum_doc_length".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.maximum_line_length", entry_point="EntryPoint('pycodestyle.maximum_line_length', 'pycodestyle', 'maximum_line_length', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.maximum_line_length".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.missing_whitespace", entry_point="EntryPoint('pycodestyle.missing_whitespace', 'pycodestyle', 'missing_whitespace', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.missing_whitespace".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.missing_whitespace_after_import_keyword", entry_point="EntryPoint('pycodestyle.missing_whitespace_after_import_keyword', 'pycodestyle', 'missing_whitespace_after_import_keyword', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.missing_whitespace_after_import_keyword".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.missing_whitespace_around_operator", entry_point="EntryPoint('pycodestyle.missing_whitespace_around_operator', 'pycodestyle', 'missing_whitespace_around_operator', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.missing_whitespace_around_operator".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.module_imports_on_top_of_file", entry_point="EntryPoint('pycodestyle.module_imports_on_top_of_file', 'pycodestyle', 'module_imports_on_top_of_file', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.module_imports_on_top_of_file".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.python_3000_async_await_keywords", entry_point="EntryPoint('pycodestyle.python_3000_async_await_keywords', 'pycodestyle', 'python_3000_async_await_keywords', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.python_3000_async_await_keywords".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.python_3000_backticks", entry_point="EntryPoint('pycodestyle.python_3000_backticks', 'pycodestyle', 'python_3000_backticks', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.python_3000_backticks".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.python_3000_has_key", entry_point="EntryPoint('pycodestyle.python_3000_has_key', 'pycodestyle', 'python_3000_has_key', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.python_3000_has_key".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.python_3000_invalid_escape_sequence", entry_point="EntryPoint('pycodestyle.python_3000_invalid_escape_sequence', 'pycodestyle', 'python_3000_invalid_escape_sequence', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.python_3000_invalid_escape_sequence".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.python_3000_not_equal", entry_point="EntryPoint('pycodestyle.python_3000_not_equal', 'pycodestyle', 'python_3000_not_equal', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.python_3000_not_equal".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.python_3000_raise_comma", entry_point="EntryPoint('pycodestyle.python_3000_raise_comma', 'pycodestyle', 'python_3000_raise_comma', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.python_3000_raise_comma".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.tabs_obsolete", entry_point="EntryPoint('pycodestyle.tabs_obsolete', 'pycodestyle', 'tabs_obsolete', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.tabs_obsolete".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.tabs_or_spaces", entry_point="EntryPoint('pycodestyle.tabs_or_spaces', 'pycodestyle', 'tabs_or_spaces', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.tabs_or_spaces".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.trailing_blank_lines", entry_point="EntryPoint('pycodestyle.trailing_blank_lines', 'pycodestyle', 'trailing_blank_lines', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.trailing_blank_lines".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.trailing_whitespace", entry_point="EntryPoint('pycodestyle.trailing_whitespace', 'pycodestyle', 'trailing_whitespace', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.trailing_whitespace".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.whitespace_around_comma", entry_point="EntryPoint('pycodestyle.whitespace_around_comma', 'pycodestyle', 'whitespace_around_comma', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.whitespace_around_comma".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.whitespace_around_keywords", entry_point="EntryPoint('pycodestyle.whitespace_around_keywords', 'pycodestyle', 'whitespace_around_keywords', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.whitespace_around_keywords".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.whitespace_around_named_parameter_equals", entry_point="EntryPoint('pycodestyle.whitespace_around_named_parameter_equals', 'pycodestyle', 'whitespace_around_named_parameter_equals', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.whitespace_around_named_parameter_equals".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.whitespace_around_operator", entry_point="EntryPoint('pycodestyle.whitespace_around_operator', 'pycodestyle', 'whitespace_around_operator', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.whitespace_around_operator".
flake8.plugins.manager    MainProcess    233 DEBUG    Loaded Plugin(name="pycodestyle.whitespace_before_comment", entry_point="EntryPoint('pycodestyle.whitespace_before_comment', 'pycodestyle', 'whitespace_before_comment', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.whitespace_before_comment".
flake8.plugins.manager    MainProcess    234 DEBUG    Loaded Plugin(name="pycodestyle.whitespace_before_parameters", entry_point="EntryPoint('pycodestyle.whitespace_before_parameters', 'pycodestyle', 'whitespace_before_parameters', Distribution('flake8', '3.7.9'))") for plugin "pycodestyle.whitespace_before_parameters".
flake8.plugins.manager    MainProcess    234 DEBUG    Loaded Plugin(name="TYP", entry_point="EntryPoint('TYP', 'flake8_annotations.checker', 'TypeHintChecker', Distribution('flake8_annotations', '1.1.3'))") for plugin "TYP".
flake8.plugins.manager    MainProcess    234 DEBUG    Loaded Plugin(name="TYP", entry_point="EntryPoint('TYP', 'flake8_typing_imports', 'Plugin', Distribution('flake8_typing_imports', '1.5.0'))") for plugin "TYP".
flake8.plugins.manager    MainProcess    234 DEBUG    Loaded Plugin(name="C90", entry_point="EntryPoint('C90', 'mccabe', 'McCabeChecker', Distribution('mccabe', '0.6.1'))") for plugin "C90".
flake8.plugins.manager    MainProcess    234 INFO     Loading entry-points for "flake8.report".
flake8.plugins.manager    MainProcess    243 DEBUG    Loaded Plugin(name="default", entry_point="EntryPoint('default', 'flake8.formatting.default', 'Default', Distribution('flake8', '3.7.9'))") for plugin "default".
flake8.plugins.manager    MainProcess    243 DEBUG    Loaded Plugin(name="pylint", entry_point="EntryPoint('pylint', 'flake8.formatting.default', 'Pylint', Distribution('flake8', '3.7.9'))") for plugin "pylint".
flake8.plugins.manager    MainProcess    243 DEBUG    Loaded Plugin(name="quiet-filename", entry_point="EntryPoint('quiet-filename', 'flake8.formatting.default', 'FilenameOnly', Distribution('flake8', '3.7.9'))") for plugin "quiet-filename".
flake8.plugins.manager    MainProcess    243 DEBUG    Loaded Plugin(name="quiet-nothing", entry_point="EntryPoint('quiet-nothing', 'flake8.formatting.default', 'Nothing', Distribution('flake8', '3.7.9'))") for plugin "quiet-nothing".
flake8.plugins.manager    MainProcess    243 INFO     Loading plugin "F" from entry-point.
flake8.plugins.manager    MainProcess    268 INFO     Loading plugin "pycodestyle.ambiguous_identifier" from entry-point.
flake8.plugins.manager    MainProcess    273 INFO     Loading plugin "pycodestyle.bare_except" from entry-point.
flake8.plugins.manager    MainProcess    273 INFO     Loading plugin "pycodestyle.blank_lines" from entry-point.
flake8.plugins.manager    MainProcess    273 INFO     Loading plugin "pycodestyle.break_after_binary_operator" from entry-point.
flake8.plugins.manager    MainProcess    273 INFO     Loading plugin "pycodestyle.break_before_binary_operator" from entry-point.
flake8.plugins.manager    MainProcess    274 INFO     Loading plugin "pycodestyle.comparison_negative" from entry-point.
flake8.plugins.manager    MainProcess    274 INFO     Loading plugin "pycodestyle.comparison_to_singleton" from entry-point.
flake8.plugins.manager    MainProcess    274 INFO     Loading plugin "pycodestyle.comparison_type" from entry-point.
flake8.plugins.manager    MainProcess    274 INFO     Loading plugin "pycodestyle.compound_statements" from entry-point.
flake8.plugins.manager    MainProcess    274 INFO     Loading plugin "pycodestyle.continued_indentation" from entry-point.
flake8.plugins.manager    MainProcess    274 INFO     Loading plugin "pycodestyle.explicit_line_join" from entry-point.
flake8.plugins.manager    MainProcess    274 INFO     Loading plugin "pycodestyle.extraneous_whitespace" from entry-point.
flake8.plugins.manager    MainProcess    274 INFO     Loading plugin "pycodestyle.imports_on_separate_lines" from entry-point.
flake8.plugins.manager    MainProcess    274 INFO     Loading plugin "pycodestyle.indentation" from entry-point.
flake8.plugins.manager    MainProcess    274 INFO     Loading plugin "pycodestyle.maximum_doc_length" from entry-point.
flake8.plugins.manager    MainProcess    274 INFO     Loading plugin "pycodestyle.maximum_line_length" from entry-point.
flake8.plugins.manager    MainProcess    274 INFO     Loading plugin "pycodestyle.missing_whitespace" from entry-point.
flake8.plugins.manager    MainProcess    274 INFO     Loading plugin "pycodestyle.missing_whitespace_after_import_keyword" from entry-point.
flake8.plugins.manager    MainProcess    274 INFO     Loading plugin "pycodestyle.missing_whitespace_around_operator" from entry-point.
flake8.plugins.manager    MainProcess    275 INFO     Loading plugin "pycodestyle.module_imports_on_top_of_file" from entry-point.
flake8.plugins.manager    MainProcess    275 INFO     Loading plugin "pycodestyle.python_3000_async_await_keywords" from entry-point.
flake8.plugins.manager    MainProcess    275 INFO     Loading plugin "pycodestyle.python_3000_backticks" from entry-point.
flake8.plugins.manager    MainProcess    275 INFO     Loading plugin "pycodestyle.python_3000_has_key" from entry-point.
flake8.plugins.manager    MainProcess    275 INFO     Loading plugin "pycodestyle.python_3000_invalid_escape_sequence" from entry-point.
flake8.plugins.manager    MainProcess    275 INFO     Loading plugin "pycodestyle.python_3000_not_equal" from entry-point.
flake8.plugins.manager    MainProcess    275 INFO     Loading plugin "pycodestyle.python_3000_raise_comma" from entry-point.
flake8.plugins.manager    MainProcess    275 INFO     Loading plugin "pycodestyle.tabs_obsolete" from entry-point.
flake8.plugins.manager    MainProcess    275 INFO     Loading plugin "pycodestyle.tabs_or_spaces" from entry-point.
flake8.plugins.manager    MainProcess    275 INFO     Loading plugin "pycodestyle.trailing_blank_lines" from entry-point.
flake8.plugins.manager    MainProcess    275 INFO     Loading plugin "pycodestyle.trailing_whitespace" from entry-point.
flake8.plugins.manager    MainProcess    276 INFO     Loading plugin "pycodestyle.whitespace_around_comma" from entry-point.
flake8.plugins.manager    MainProcess    276 INFO     Loading plugin "pycodestyle.whitespace_around_keywords" from entry-point.
flake8.plugins.manager    MainProcess    276 INFO     Loading plugin "pycodestyle.whitespace_around_named_parameter_equals" from entry-point.
flake8.plugins.manager    MainProcess    276 INFO     Loading plugin "pycodestyle.whitespace_around_operator" from entry-point.
flake8.plugins.manager    MainProcess    276 INFO     Loading plugin "pycodestyle.whitespace_before_comment" from entry-point.
flake8.plugins.manager    MainProcess    276 INFO     Loading plugin "pycodestyle.whitespace_before_parameters" from entry-point.
flake8.plugins.manager    MainProcess    276 INFO     Loading plugin "TYP" from entry-point.
flake8.plugins.manager    MainProcess    310 INFO     Loading plugin "C90" from entry-point.
flake8.plugins.manager    MainProcess    312 INFO     Loading plugin "default" from entry-point.
flake8.plugins.manager    MainProcess    314 INFO     Loading plugin "pylint" from entry-point.
flake8.plugins.manager    MainProcess    314 INFO     Loading plugin "quiet-filename" from entry-point.
flake8.plugins.manager    MainProcess    314 INFO     Loading plugin "quiet-nothing" from entry-point.
flake8.plugins.manager    MainProcess    315 DEBUG    Registering options from plugin "F" on OptionManager <flake8.options.manager.OptionManager object at 0x0000022D72A02D30>
flake8.options.manager    MainProcess    316 DEBUG    Registered option "Option(None, --builtins, action=None, default=None, dest=builtins, type=None, callback=None, help=define more built-ins, comma separated, callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
flake8.options.manager    MainProcess    335 DEBUG    Registered option "Option(None, --doctests, action=store_true, default=False, dest=doctests, type=None, callback=None, help=check syntax of the doctests, callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
flake8.options.manager    MainProcess    336 DEBUG    Registered option "Option(None, --include-in-doctest, action=None, default=, dest=include_in_doctest, type=string, callback=None, help=Run doctests only on these files, callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
flake8.options.manager    MainProcess    337 DEBUG    Registered option "Option(None, --exclude-from-doctest, action=None, default=, dest=exclude_from_doctest, type=string, callback=None, help=Skip these files when running doctests, callback=None, callback_args=None, callback_kwargs=None, metavar=None)".
flake8.options.manager    MainProcess    337 DEBUG    Removing ['F'] from the default ignore list
flake8.options.manager    MainProcess    337 DEBUG    Attempted to remove F from default ignore but it was not a member of the list.
flake8.options.manager    MainProcess    337 DEBUG    Extending default select list with ['F']
flake8.plugins.manager    MainProcess    339 DEBUG    Registering options from plugin "TYP" on OptionManager <flake8.options.manager.OptionManager object at 0x0000022D72A02D30>
flake8.options.manager    MainProcess    339 DEBUG    Registered option "Option(None, --min-python-version, action=None, default=3.5.0, dest=min_python_version, type=str, callback=None, help=Minimum version of python your code supports, (default: %(default)s), callback=None, callback_args=None, callback_kwargs=None, metavar=VERSION)".
flake8.options.manager    MainProcess    339 DEBUG    Removing ['TYP'] from the default ignore list
flake8.options.manager    MainProcess    340 DEBUG    Attempted to remove TYP from default ignore but it was not a member of the list.
flake8.options.manager    MainProcess    340 DEBUG    Extending default select list with ['TYP']
flake8.plugins.manager    MainProcess    340 DEBUG    Registering options from plugin "TYP" on OptionManager <flake8.options.manager.OptionManager object at 0x0000022D72A02D30>

Develop Tests

Initial functionality for this package was only evaluated against a basic sample file. Before this goes live to PyPi, more comprehensive testing should be developed to ensure we're appropriately covering as many scenarios as possible.

The currently brainstormed testing points:

  • Argument parsing
  • Warning classification
  • Emitting correct line & column numbers
  • Formatting warning message with argument name (where relevant)
  • Outputting correct tuple for flake8

Once these are all implemented there are a couple follow-on housekeeping items:

  • Update README
  • Add testing to CI pipeline

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.