Skip to content

Commit

Permalink
Prototype of --replace mode, refs #31
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Jun 29, 2023
1 parent b4b3c04 commit dfe471e
Showing 1 changed file with 38 additions and 0 deletions.
38 changes: 38 additions & 0 deletions symbex/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import inspect
import pathlib
import site
import sys

from .lib import (
code_for_node,
Expand Down Expand Up @@ -137,6 +138,11 @@
is_flag=True,
help="Filter to exclude any __init__ methods",
)
@click.option(
"--replace",
is_flag=True,
help="Replace a single matching symbol with text from stdin",
)
def cli(
symbols,
files,
Expand All @@ -161,6 +167,7 @@ def cli(
partially_typed,
fully_typed,
no_init,
replace,
):
"""
Find symbols in Python code and print the code for them.
Expand Down Expand Up @@ -263,6 +270,11 @@ def cli(
ctx = click.get_current_context()
click.echo(ctx.get_help())
ctx.exit()

if replace and signatures:
raise click.ClickException("--replace cannot be used with --signatures")
if replace:
no_file = True
# Default to '*' if --signatures or filters are provided without symbols
if (
any(
Expand Down Expand Up @@ -354,6 +366,7 @@ def filter(node: ast.AST) -> bool:

pwd = pathlib.Path(".").resolve()
num_matches = 0
replace_matches = []
for file in iterate_files():
try:
code = read_file(file)
Expand All @@ -380,6 +393,9 @@ def filter(node: ast.AST) -> bool:
# else print absolute path
path = file.resolve()
snippet, line_no = code_for_node(code, node, class_name, signatures, docs)
if replace:
replace_matches.append((file.resolve(), snippet, line_no))
continue
if not no_file:
bits = ["# File:", path]
if class_name:
Expand All @@ -401,6 +417,28 @@ def filter(node: ast.AST) -> bool:
if count:
click.echo(num_matches)

if replace:
# Only works if we got a single match
if len(replace_matches) != 1:
raise click.ClickException(
"--replace only works with a single match, got {}".format(
len(replace_matches)
)
)
filepath, to_replace = replace_matches[0][:2]
if sys.stdin.isatty():
raise click.ClickException(
"--replace only works with text piped to it on stdin"
)
new_lines = sys.stdin.readlines()
# Check if any lines were read
if len(new_lines) == 0:
raise click.ClickException("No input for --replace found on stdin")
replacement = "".join(new_lines)
old = filepath.read_text("utf-8")
new = old.replace(to_replace, replacement)
filepath.write_text(new, "utf-8")


def is_subpath(path: pathlib.Path, parent: pathlib.Path) -> bool:
try:
Expand Down

0 comments on commit dfe471e

Please sign in to comment.