Skip to content

Commit

Permalink
feat: support cat foo.py | fixit lint --stdin --stdin-filepath foo.py
Browse files Browse the repository at this point in the history
Similarly for `fixit fix`
  • Loading branch information
llllvvuu committed Sep 6, 2023
1 parent 84378a8 commit 8de748b
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 7 deletions.
22 changes: 20 additions & 2 deletions docs/guide/commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,20 @@ Lint one or more paths, and print a list of lint errors.

.. code:: console
$ fixit lint [--diff] [PATH ...]
$ fixit lint [--diff] [--stdin --stdin-filepath] [PATH ...]
.. attribute:: --diff / -d

Show suggested fixes, in unified diff format, when available.

.. attribute:: --stdin

Lint code from stdin.

.. attribute:: --stdin-filepath

Required with --stdin; Analyze code from stdin as if it is from this filepath.


``fix``
^^^^^^^
Expand All @@ -64,7 +72,8 @@ Lint one or more paths, and apply suggested fixes.

.. code:: console
$ fixit fix [--interactive | --automatic [--diff]] [PATH ...]
$ fixit fix [--interactive | --automatic [--diff]] \
[--stdin --stdin-filepath] [PATH ...]
.. attribute:: --interactive / -i

Expand All @@ -79,6 +88,15 @@ Lint one or more paths, and apply suggested fixes.

Show applied fixes in unified diff format when applied automatically.

.. attribute:: --stdin

Fix code from stdin and output fixed code to stdout. Ignores --interactive/--automatic/--diff.

.. attribute:: --stdin-filepath

Required with --stdin; Analyze code from stdin as if it is from this filepath.



``test``
^^^^^^^^
Expand Down
57 changes: 52 additions & 5 deletions src/fixit/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from fixit import __version__

from .api import fixit_paths, print_result
from .api import fixit_bytes, fixit_paths, print_result
from .config import collect_rules, generate_config, parse_rule
from .ftypes import Config, Options, QualifiedRule, Tags
from .rule import LintRule
Expand Down Expand Up @@ -101,25 +101,42 @@ def main(
@main.command()
@click.pass_context
@click.option("--diff", "-d", is_flag=True, help="Show diff of suggested changes")
@click.option("--stdin", is_flag=True, default=False, help="Lint code from stdin")
@click.option(
"--stdin-filepath",
type=click.Path(path_type=Path),
default=None,
help="Analyze code from stdin as if it is from this filepath",
)
@click.argument("paths", nargs=-1, type=click.Path(path_type=Path))
def lint(
ctx: click.Context,
diff: bool,
stdin: bool,
stdin_filepath: Optional[Path],
paths: Sequence[Path],
):
"""
lint one or more paths and return suggestions
lint stdin or one or more paths and return suggestions
"""
options: Options = ctx.obj

if not paths:
paths = [Path.cwd()]
if stdin:
if not stdin_filepath:
ctx.fail("--stdin-filepath is required with --stdin")
content = sys.stdin.buffer.read()
config = generate_config(stdin_filepath, options=options)
results = fixit_bytes(stdin_filepath, content, config=config)
else:
if not paths:
paths = [Path.cwd()]
results = fixit_paths(paths, options=options)

exit_code = 0
visited: Set[Path] = set()
dirty: Set[Path] = set()
autofixes = 0
for result in fixit_paths(paths, options=options):
for result in results:
visited.add(result.path)

if print_result(result, show_diff=diff):
Expand All @@ -145,11 +162,25 @@ def lint(
help="how to apply fixes; interactive by default",
)
@click.option("--diff", "-d", is_flag=True, help="show diff even with --automatic")
@click.option(
"--stdin",
is_flag=True,
default=False,
help="fix code from stdin and output fixed code to stdout",
)
@click.option(
"--stdin-filepath",
type=click.Path(path_type=Path),
default=None,
help="analyze code from stdin as if it is from this filepath",
)
@click.argument("paths", nargs=-1, type=click.Path(path_type=Path))
def fix(
ctx: click.Context,
interactive: bool,
diff: bool,
stdin: bool,
stdin_filepath: Optional[Path],
paths: Sequence[Path],
):
"""
Expand All @@ -168,10 +199,26 @@ def fix(
autofixes = 0
fixed = 0

if stdin:
if not stdin_filepath:
ctx.fail("--stdin-filepath is required with --stdin")
content = sys.stdin.buffer.read()
config = generate_config(stdin_filepath, options=options)
generator = capture(
fixit_bytes(stdin_filepath, content, autofix=True, config=config)
)
for result in generator:
pass
if not generator.result:
raise Exception("Internal Error: fixit_bytes returned None")
print(generator.result.decode(), end="")
ctx.exit(exit_code)

# TODO: make this parallel
generator = capture(
fixit_paths(paths, autofix=autofix, options=options, parallel=False)
)

for result in generator:
visited.add(result.path)
if print_result(result, show_diff=interactive or diff):
Expand Down
34 changes: 34 additions & 0 deletions src/fixit/tests/smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,40 @@ def func():
expected_format, path.read_text(), "unexpected file output"
)

with self.subTest("linting via stdin"):
result = self.runner.invoke(
main,
["lint", "--stdin", "--stdin-filepath", path.as_posix()],
input=content, # provide content via stdin
catch_exceptions=False,
)

self.assertNotEqual(result.output, "")
self.assertNotEqual(result.exit_code, 0)
self.assertRegex(
result.output,
r"file\.py@\d+:\d+ NoRedundantFString: .+ \(has autofix\)",
)

with self.subTest("fixing with formatting via stdin"):
(tdp / "pyproject.toml").write_text("[tool.fixit]\nformatter='ufmt'\n")

result = self.runner.invoke(
main,
[
"fix",
"--automatic",
"--stdin",
"--stdin-filepath",
path.as_posix(),
],
input=content,
catch_exceptions=False,
)

self.assertEqual(result.exit_code, 0)
self.assertEqual(expected_format, result.output, "unexpected stdout")

def test_this_file_is_clean(self) -> None:
path = Path(__file__).resolve().as_posix()
result = self.runner.invoke(main, ["lint", path], catch_exceptions=False)
Expand Down

0 comments on commit 8de748b

Please sign in to comment.