Skip to content
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

echo "replacement function" | symbex old_function --replace #31

Closed
simonw opened this issue Jun 29, 2023 · 6 comments
Closed

echo "replacement function" | symbex old_function --replace #31

simonw opened this issue Jun 29, 2023 · 6 comments

Comments

@simonw
Copy link
Owner

simonw commented Jun 29, 2023

Idea would be to support this:

symbex test_filters | llm -m 4 "Add comments to this" | symbex --replace test_filters

Inspired by: https://mastodon.social/@webology/110628240726665098

@simonw
Copy link
Owner Author

simonw commented Jun 29, 2023

Partial prototype:

```diff
diff --git a/symbex/cli.py b/symbex/cli.py
index 65d673c..d08ec75 100644
--- a/symbex/cli.py
+++ b/symbex/cli.py
@@ -137,6 +137,11 @@ from .lib import (
     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,
@@ -161,6 +166,7 @@ def cli(
     partially_typed,
     fully_typed,
     no_init,
+    replace,
 ):
     """
     Find symbols in Python code and print the code for them.
@@ -263,6 +269,9 @@ 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")
     # Default to '*' if --signatures or filters are provided without symbols
     if (
         any(
@@ -354,6 +363,7 @@ def cli(
 
     pwd = pathlib.Path(".").resolve()
     num_matches = 0
+    replace_matches = []
     for file in iterate_files():
         try:
             code = read_file(file)
@@ -380,6 +390,9 @@ def cli(
                 # else print absolute path
                 path = file.resolve()
             snippet, line_no = code_for_node(code, node, class_name, signatures, docs)
+            if replace:
+                replace_matches.append((snippet, line_no))
+                continue
             if not no_file:
                 bits = ["# File:", path]
                 if class_name:
@@ -401,6 +414,11 @@ def cli(
     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)))
+        click.echo(repr(replace_matches))
 
 def is_subpath(path: pathlib.Path, parent: pathlib.Path) -> bool:
     try:

Hard bit is figuring out how to cleanly replace just the first matching instance in the file.

@simonw
Copy link
Owner Author

simonw commented Jun 29, 2023

Might work to just do text.replace(old_code, new_code) seeing as the snippet should be the exact bytes from the file. Could show a "could not apply patch" error otherwise.

@simonw simonw changed the title --replace mode for symbex echo "replacement function" | symbex old_function --replace Jun 29, 2023
@simonw simonw transferred this issue from another repository Jun 29, 2023
@simonw simonw transferred this issue from simonw/temp Jun 29, 2023
simonw added a commit that referenced this issue Jun 29, 2023
@simonw
Copy link
Owner Author

simonw commented Jun 29, 2023

I ran this against the prototype:

symbex is_subpath -n | llm -m 4 --system 'Add comments to every line' | symbex is_subpath --replace

And got this (output of git diff):

diff --git a/symbex/cli.py b/symbex/cli.py
index 9510627..87351af 100644
--- a/symbex/cli.py
+++ b/symbex/cli.py
@@ -441,8 +441,13 @@ def cli(
 
 
 def is_subpath(path: pathlib.Path, parent: pathlib.Path) -> bool:
+    # Try to find the relative path of the current path to the parent path
     try:
+        # If this operation is successful, it means that 'path' is a sub-path of 'parent'
         path.relative_to(parent)
+        # Return True if the 'path' is a sub-directory of 'parent'
         return True
+    # If the operation fails, it raises a ValueError
     except ValueError:
+        # Catch the ValueError and return False, since 'path' is now not a sub-directory of 'parent'
         return False

@jefftriplett
Copy link

I assume the https://github.com/simonw/symbex/tree/replace branch is the best place to git pull and test too?

@simonw
Copy link
Owner Author

simonw commented Jun 29, 2023

Yes, pip install https://github.com/simonw/symbex/archive/refs/heads/replace.zip should do it.

simonw added a commit that referenced this issue Jun 29, 2023
@simonw simonw closed this as completed in 82c078f Jun 29, 2023
simonw added a commit that referenced this issue Jun 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants