-
-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Now able to run as a standalone module or shell program, with limited functionality #146
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,11 +12,14 @@ | |
from __future__ import annotations | ||
|
||
import ast | ||
import functools | ||
import keyword | ||
import os | ||
import re | ||
import subprocess | ||
import sys | ||
import tokenize | ||
from argparse import ArgumentTypeError, Namespace | ||
from argparse import ArgumentParser, ArgumentTypeError, Namespace | ||
from typing import TYPE_CHECKING | ||
|
||
import libcst as cst | ||
|
@@ -37,6 +40,24 @@ | |
__version__ = "23.2.5" | ||
|
||
|
||
# taken from https://github.com/Zac-HD/shed | ||
@functools.lru_cache | ||
def _get_git_repo_root(cwd: str | None = None) -> str: | ||
return subprocess.run( | ||
["git", "rev-parse", "--show-toplevel"], | ||
check=True, | ||
timeout=10, | ||
capture_output=True, | ||
text=True, | ||
cwd=cwd, | ||
).stdout.strip() | ||
|
||
|
||
@functools.cache | ||
def _should_format(fname: str) -> bool: | ||
return fname.endswith((".py",)) | ||
|
||
|
||
# Enable support in libcst for new grammar | ||
# See e.g. https://github.com/Instagram/LibCST/issues/862 | ||
# wrapping the call and restoring old values in case there's other libcst parsers | ||
|
@@ -53,6 +74,44 @@ def cst_parse_module_native(source: str) -> cst.Module: | |
return mod | ||
|
||
|
||
def main(): | ||
parser = ArgumentParser(prog="flake8_trio") | ||
parser.add_argument( | ||
nargs="*", | ||
metavar="file", | ||
dest="files", | ||
help="Files(s) to format, instead of autodetection.", | ||
) | ||
Plugin.add_options(parser) | ||
args = parser.parse_args() | ||
Plugin.parse_options(args) | ||
if args.files: | ||
# TODO: go through subdirectories if directory/ies specified | ||
all_filenames = args.files | ||
else: | ||
# Get all tracked files from `git ls-files` | ||
try: | ||
root = os.path.relpath(_get_git_repo_root()) | ||
all_filenames = subprocess.run( | ||
["git", "ls-files"], | ||
check=True, | ||
timeout=10, | ||
stdout=subprocess.PIPE, | ||
text=True, | ||
cwd=root, | ||
).stdout.splitlines() | ||
except (subprocess.SubprocessError, FileNotFoundError): | ||
print("Doesn't seem to be a git repo; pass filenames to format.") | ||
sys.exit(1) | ||
all_filenames = [ | ||
os.path.join(root, f) for f in all_filenames if _should_format(f) | ||
] | ||
for file in all_filenames: | ||
plugin = Plugin.from_filename(file) | ||
for error in sorted(plugin.run()): | ||
print(f"{file}:{error}") | ||
Comment on lines
+109
to
+112
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A small |
||
|
||
|
||
class Plugin: | ||
name = __name__ | ||
version = __version__ | ||
|
@@ -86,16 +145,23 @@ def run(self) -> Iterable[Error]: | |
yield from Flake8TrioRunner_cst(self.options).run(self._module) | ||
|
||
@staticmethod | ||
def add_options(option_manager: OptionManager): | ||
# Disable TRIO9xx calls | ||
option_manager.extend_default_ignore(default_disabled_error_codes) | ||
def add_options(option_manager: OptionManager | ArgumentParser): | ||
if isinstance(option_manager, ArgumentParser): | ||
# if run as standalone | ||
add_argument = option_manager.add_argument | ||
else: # if run as a flake8 plugin | ||
# Disable TRIO9xx calls | ||
jakkdl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
option_manager.extend_default_ignore(default_disabled_error_codes) | ||
# add parameter to parse from flake8 config | ||
add_argument = functools.partial( | ||
option_manager.add_option, parse_from_config=True | ||
) | ||
|
||
option_manager.add_option( | ||
add_argument( | ||
"--no-checkpoint-warning-decorators", | ||
default="asynccontextmanager", | ||
parse_from_config=True, | ||
required=False, | ||
comma_separated_list=True, | ||
type=comma_separated_list, | ||
help=( | ||
"Comma-separated list of decorators to disable TRIO910 & TRIO911 " | ||
"checkpoint warnings for. " | ||
|
@@ -104,11 +170,10 @@ def add_options(option_manager: OptionManager): | |
"mydecorator,mypackage.mydecorators.*``" | ||
), | ||
) | ||
option_manager.add_option( | ||
add_argument( | ||
"--startable-in-context-manager", | ||
type=parse_trio114_identifiers, | ||
default="", | ||
parse_from_config=True, | ||
required=False, | ||
help=( | ||
"Comma-separated list of method calls to additionally enable TRIO113 " | ||
|
@@ -119,23 +184,21 @@ def add_options(option_manager: OptionManager): | |
"myfunction``" | ||
), | ||
) | ||
option_manager.add_option( | ||
add_argument( | ||
"--trio200-blocking-calls", | ||
type=parse_trio200_dict, | ||
default={}, | ||
parse_from_config=True, | ||
required=False, | ||
help=( | ||
"Comma-separated list of key->value pairs, where key is a [dotted] " | ||
"function that if found inside an async function will raise TRIO200, " | ||
"suggesting it be replaced with {value}" | ||
), | ||
) | ||
option_manager.add_option( | ||
add_argument( | ||
"--enable-visitor-codes-regex", | ||
type=re.compile, | ||
default=".*", | ||
parse_from_config=True, | ||
required=False, | ||
help=( | ||
"Regex string of visitors to enable. Can be used to disable broken " | ||
|
@@ -145,12 +208,11 @@ def add_options(option_manager: OptionManager): | |
"not report codes matching this regex." | ||
), | ||
) | ||
option_manager.add_option( | ||
add_argument( | ||
"--anyio", | ||
# action=store_true + parse_from_config does seem to work here, despite | ||
# https://github.com/PyCQA/flake8/issues/1770 | ||
action="store_true", | ||
parse_from_config=True, | ||
required=False, | ||
default=False, | ||
help=( | ||
|
@@ -165,11 +227,12 @@ def parse_options(options: Namespace): | |
Plugin.options = options | ||
|
||
|
||
# flake8 ignores type parameters if using comma_separated_list | ||
# so we need to reimplement that ourselves if we want to use "type" | ||
# to check values | ||
def comma_separated_list(raw_value: str) -> list[str]: | ||
return [s.strip() for s in raw_value.split(",") if s.strip()] | ||
|
||
|
||
def parse_trio114_identifiers(raw_value: str) -> list[str]: | ||
values = [s.strip() for s in raw_value.split(",") if s.strip()] | ||
values = comma_separated_list(raw_value) | ||
for value in values: | ||
if keyword.iskeyword(value) or not value.isidentifier(): | ||
raise ArgumentTypeError(f"{value!r} is not a valid method identifier") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
"""Entry file when executed with `python -m`.""" | ||
from . import main | ||
|
||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤷♂️, I'm pretty happy to say that you have to pass exact files if you're passing files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I figured, since that's how shed does it, but I would like to support as much of flake8's functionality as possible to ease any transition from running [name of this project] as a flake8 plugin to running it standalone. Ofc flake8 is kinda crazy so I won't bother supporting everything (e.g.
--extend-ignore
,--ignore
,--select
,--extend-select
I think kinda just makes everything more complicated), but I think supporting directories shouldn't be very complicated and doesn't have much downsides.