Merge branch 'main' into call-graph

This commit is contained in:
Paul Gauthier 2023-05-29 11:18:30 -07:00
commit 27bd993cab
26 changed files with 788 additions and 202 deletions

View file

@ -2,25 +2,25 @@
import os
import sys
import traceback
import time
from openai.error import RateLimitError
from rich.console import Console
from rich.live import Live
from rich.markdown import Markdown
import traceback
from pathlib import Path
import git
import openai
from openai.error import RateLimitError
from rich.console import Console
from rich.live import Live
from rich.markdown import Markdown
# from aider.dump import dump
from aider import utils
from aider import prompts
from aider import prompts, utils
from aider.commands import Commands
from aider.repomap import RepoMap
openai.api_key = os.getenv("OPENAI_API_KEY")
class MissingAPIKeyError(ValueError):
pass
class Coder:
@ -37,10 +37,17 @@ class Coder:
pretty=True,
show_diffs=False,
auto_commits=True,
dirty_commits=True,
dry_run=False,
use_ctags=False,
verbose=False,
openai_api_key=None,
):
if openai_api_key:
openai.api_key = openai_api_key
else:
raise MissingAPIKeyError("No OpenAI API key provided.")
self.verbose = verbose
self.abs_fnames = set()
self.cur_messages = []
@ -48,6 +55,7 @@ class Coder:
self.io = io
self.auto_commits = auto_commits
self.dirty_commits = dirty_commits
self.dry_run = dry_run
if pretty:
@ -66,7 +74,7 @@ class Coder:
if self.repo:
rel_repo_dir = os.path.relpath(self.repo.git_dir, os.getcwd())
self.io.tool("Using git repo:", rel_repo_dir)
self.io.tool_output("Using git repo:", rel_repo_dir)
else:
self.io.tool_error("No suitable git repo, will not automatically commit edits.")
self.find_common_root()
@ -83,7 +91,7 @@ class Coder:
else:
self.root = os.getcwd()
self.io.tool(f"Common root directory: {self.root}")
self.io.tool_output(f"Common root directory: {self.root}")
def set_repo(self, cmd_line_fnames):
if not cmd_line_fnames:
@ -93,7 +101,7 @@ class Coder:
for fname in cmd_line_fnames:
fname = Path(fname)
if not fname.exists():
self.io.tool(f"Creating empty file {fname}")
self.io.tool_output(f"Creating empty file {fname}")
fname.parent.mkdir(parents=True, exist_ok=True)
fname.touch()
@ -106,7 +114,7 @@ class Coder:
if fname.is_dir():
continue
self.io.tool(f"Added {fname} to the chat")
self.io.tool_output(f"Added {fname} to the chat")
fname = fname.resolve()
self.abs_fnames.add(str(fname))
@ -135,18 +143,18 @@ class Coder:
if new_files:
rel_repo_dir = os.path.relpath(repo.git_dir, os.getcwd())
self.io.tool(f"Files not tracked in {rel_repo_dir}:")
self.io.tool_output(f"Files not tracked in {rel_repo_dir}:")
for fn in new_files:
self.io.tool(f" - {fn}")
self.io.tool_output(f" - {fn}")
if self.io.confirm_ask("Add them?"):
for relative_fname in new_files:
repo.git.add(relative_fname)
self.io.tool(f"Added {relative_fname} to the git repo")
self.io.tool_output(f"Added {relative_fname} to the git repo")
show_files = ", ".join(new_files)
commit_message = f"Added new files to the git repo: {show_files}"
repo.git.commit("-m", commit_message, "--no-verify")
commit_hash = repo.head.commit.hexsha[:7]
self.io.tool(f"Commit {commit_hash} {commit_message}")
self.io.tool_output(f"Commit {commit_hash} {commit_message}")
else:
self.io.tool_error("Skipped adding new files to the git repo.")
return
@ -216,7 +224,7 @@ class Coder:
if is_commit_command:
return
if not self.auto_commits:
if not self.dirty_commits:
return
if not self.repo:
return
@ -227,7 +235,12 @@ class Coder:
return True
def run_loop(self):
inp = self.io.get_input(self.abs_fnames, self.commands)
inp = self.io.get_input(
self.root,
self.get_inchat_relative_files(),
self.get_addable_relative_files(),
self.commands,
)
self.num_control_c = 0
@ -243,7 +256,7 @@ class Coder:
self.cur_messages = []
if inp.strip():
self.io.tool("Use up-arrow to retry previous command:", inp)
self.io.tool_output("Use up-arrow to retry previous command:", inp)
return
if not inp:
@ -252,6 +265,8 @@ class Coder:
if self.commands.is_command(inp):
return self.commands.run(inp)
self.check_for_file_mentions(inp)
return self.send_new_user_message(inp)
def send_new_user_message(self, inp):
@ -279,7 +294,7 @@ class Coder:
dict(role="assistant", content=content),
]
self.io.tool()
self.io.tool_output()
if interrupted:
return
@ -327,20 +342,29 @@ class Coder:
quotes = "".join(['"', "'", "`"])
words = set(word.strip(quotes) for word in words)
addable_rel_fnames = set(self.get_all_relative_files()) - set(
self.get_inchat_relative_files()
)
addable_rel_fnames = self.get_addable_relative_files()
mentioned_rel_fnames = set()
for word in words:
if word in addable_rel_fnames:
mentioned_rel_fnames.add(word)
fname_to_rel_fnames = {}
for rel_fname in addable_rel_fnames:
fname = os.path.basename(rel_fname)
if fname not in fname_to_rel_fnames:
fname_to_rel_fnames[fname] = []
fname_to_rel_fnames[fname].append(rel_fname)
for fname, rel_fnames in fname_to_rel_fnames.items():
if len(rel_fnames) == 1 and fname in words:
mentioned_rel_fnames.add(rel_fnames[0])
else:
for rel_fname in rel_fnames:
if rel_fname in words:
mentioned_rel_fnames.add(rel_fname)
if not mentioned_rel_fnames:
return
for rel_fname in mentioned_rel_fnames:
self.io.tool(rel_fname)
self.io.tool_output(rel_fname)
if not self.io.confirm_ask("Add these files to the chat?"):
return
@ -450,9 +474,9 @@ class Coder:
edited.add(path)
if utils.do_replace(full_path, original, updated, self.dry_run):
if self.dry_run:
self.io.tool(f"Dry run, did not apply edit to {path}")
self.io.tool_output(f"Dry run, did not apply edit to {path}")
else:
self.io.tool(f"Applied edit to {path}")
self.io.tool_output(f"Applied edit to {path}")
else:
self.io.tool_error(f"Failed to apply edit to {path}")
@ -490,7 +514,9 @@ class Coder:
)
return
commit_message = commit_message.strip().strip('"').strip()
commit_message = commit_message.strip()
if commit_message and commit_message[0] == '"' and commit_message[-1] == '"':
commit_message = commit_message[1:-1].strip()
if interrupted:
self.io.tool_error(
@ -548,7 +574,7 @@ class Coder:
raise ValueError(f"Invalid value for 'which': {which}")
if self.show_diffs or ask:
# don't use io.tool() because we don't want to log or further colorize
# don't use io.tool_output() because we don't want to log or further colorize
print(diffs)
context = self.get_context_from_history(history)
@ -562,9 +588,9 @@ class Coder:
if ask:
if which == "repo_files":
self.io.tool("Git repo has uncommitted changes.")
self.io.tool_output("Git repo has uncommitted changes.")
else:
self.io.tool("Files have uncommitted changes.")
self.io.tool_output("Files have uncommitted changes.")
res = self.io.prompt_ask(
"Commit before the chat proceeds [y/n/commit message]?",
@ -572,7 +598,7 @@ class Coder:
).strip()
self.last_asked_for_commit_time = self.get_last_modified()
self.io.tool()
self.io.tool_output()
if res.lower() in ["n", "no"]:
self.io.tool_error("Skipped commmit.")
@ -585,7 +611,7 @@ class Coder:
full_commit_message = commit_message + "\n\n" + context
repo.git.commit("-m", full_commit_message, "--no-verify")
commit_hash = repo.head.commit.hexsha[:7]
self.io.tool(f"Commit {commit_hash} {commit_message}")
self.io.tool_output(f"Commit {commit_hash} {commit_message}")
return commit_hash, commit_message
@ -615,6 +641,9 @@ class Coder:
return 0
return max(Path(path).stat().st_mtime for path in files)
def get_addable_relative_files(self):
return set(self.get_all_relative_files()) - set(self.get_inchat_relative_files())
def apply_updates(self, content, inp):
try:
edited = self.update_files(content, inp)

View file

@ -1,9 +1,11 @@
import sys
import os
import git
import subprocess
import shlex
import subprocess
import sys
import git
from prompt_toolkit.completion import Completion
from aider import prompts
@ -37,7 +39,7 @@ class Commands:
if cmd_method:
return cmd_method(args)
else:
self.io.tool(f"Error: Command {cmd_name} not found.")
self.io.tool_output(f"Error: Command {cmd_name} not found.")
def run(self, inp):
words = inp.strip().split()
@ -110,7 +112,7 @@ class Commands:
self.io.tool_error("The last commit was not made by aider in this chat session.")
return
self.coder.repo.git.reset("--hard", "HEAD~1")
self.io.tool(
self.io.tool_output(
f"{last_commit.message.strip()}\n"
f"The above commit {self.coder.last_aider_commit_hash} "
"was reset and removed from git.\n"
@ -131,7 +133,7 @@ class Commands:
commits = f"{self.coder.last_aider_commit_hash}~1"
diff = self.coder.get_diffs(commits, self.coder.last_aider_commit_hash)
# don't use io.tool() because we don't want to log or further colorize
# don't use io.tool_output() because we don't want to log or further colorize
print(diff)
def completions_add(self, partial):
@ -177,7 +179,7 @@ class Commands:
abs_file_path = os.path.abspath(os.path.join(self.coder.root, matched_file))
if abs_file_path not in self.coder.abs_fnames:
self.coder.abs_fnames.add(abs_file_path)
self.io.tool(f"Added {matched_file} to the chat")
self.io.tool_output(f"Added {matched_file} to the chat")
added_fnames.append(matched_file)
else:
self.io.tool_error(f"{matched_file} is already in the chat")
@ -214,7 +216,7 @@ class Commands:
for matched_file in matched_files:
relative_fname = os.path.relpath(matched_file, self.coder.root)
self.coder.abs_fnames.remove(matched_file)
self.io.tool(f"Removed {relative_fname} from the chat")
self.io.tool_output(f"Removed {relative_fname} from the chat")
def cmd_run(self, args):
"Run a shell command and optionally add the output to the chat"
@ -229,15 +231,15 @@ class Commands:
print(combined_output)
ok = self.io.confirm_ask("Add the output to the chat?", default="y")
if not ok:
return
if self.io.confirm_ask("Add the output to the chat?", default="y"):
for line in combined_output.splitlines():
self.io.tool_output(line, log_only=True)
msg = prompts.run_output.format(
command=args,
output=combined_output,
)
return msg
msg = prompts.run_output.format(
command=args,
output=combined_output,
)
return msg
def cmd_exit(self, args):
"Exit the application"
@ -258,14 +260,14 @@ class Commands:
other_files.append(file)
if chat_files:
self.io.tool("Files in chat:\n")
self.io.tool_output("Files in chat:\n")
for file in chat_files:
self.io.tool(f" {file}")
self.io.tool_output(f" {file}")
if other_files:
self.io.tool("\nRepo files not in the chat:\n")
self.io.tool_output("\nRepo files not in the chat:\n")
for file in other_files:
self.io.tool(f" {file}")
self.io.tool_output(f" {file}")
def cmd_help(self, args):
"Show help about all commands"
@ -275,6 +277,6 @@ class Commands:
cmd_method = getattr(self, cmd_method_name, None)
if cmd_method:
description = cmd_method.__doc__
self.io.tool(f"{cmd} {description}")
self.io.tool_output(f"{cmd} {description}")
else:
self.io.tool(f"{cmd} No description available.")
self.io.tool_output(f"{cmd} No description available.")

View file

@ -1,5 +1,5 @@
import traceback
import json
import traceback
def cvt(s):

View file

@ -1,24 +1,49 @@
import os
from prompt_toolkit.styles import Style
from prompt_toolkit.shortcuts import PromptSession, prompt
from collections import defaultdict
from datetime import datetime
from pathlib import Path
from prompt_toolkit.completion import Completer, Completion
from prompt_toolkit.history import FileHistory
from prompt_toolkit.shortcuts import CompleteStyle
from prompt_toolkit.shortcuts import CompleteStyle, PromptSession, prompt
from prompt_toolkit.styles import Style
from pygments.lexers import guess_lexer_for_filename
from pygments.token import Token
from pygments.util import ClassNotFound
from rich.console import Console
from rich.text import Text
from pathlib import Path
from datetime import datetime
from aider import utils
class FileContentCompleter(Completer):
def __init__(self, fnames, commands):
def __init__(self, root, rel_fnames, addable_rel_fnames, commands):
self.commands = commands
self.addable_rel_fnames = addable_rel_fnames
self.rel_fnames = rel_fnames
fname_to_rel_fnames = defaultdict(list)
for rel_fname in addable_rel_fnames:
fname = os.path.basename(rel_fname)
if fname != rel_fname:
fname_to_rel_fnames[fname].append(rel_fname)
self.fname_to_rel_fnames = fname_to_rel_fnames
self.words = set()
for fname in fnames:
self.words.update(utils.get_name_identifiers(fname))
for rel_fname in addable_rel_fnames:
self.words.add(rel_fname)
for rel_fname in rel_fnames:
self.words.add(rel_fname)
fname = os.path.join(root, rel_fname)
with open(fname, "r") as f:
content = f.read()
try:
lexer = guess_lexer_for_filename(fname, content)
except ClassNotFound:
continue
tokens = list(lexer.get_tokens(content))
self.words.update(token[1] for token in tokens if token[0] in Token.Name)
def get_completions(self, document, complete_event):
text = document.text_before_cursor
@ -35,11 +60,17 @@ class FileContentCompleter(Completer):
return
else:
candidates = self.words
candidates.update(set(self.fname_to_rel_fnames))
last_word = words[-1]
for word in candidates:
if word.lower().startswith(last_word.lower()):
yield Completion(word, start_position=-len(last_word))
rel_fnames = self.fname_to_rel_fnames.get(word, [])
if rel_fnames:
for rel_fname in rel_fnames:
yield Completion(rel_fname, start_position=-len(last_word))
else:
yield Completion(word, start_position=-len(last_word))
class InputOutput:
@ -51,7 +82,18 @@ class InputOutput:
chat_history_file=None,
input=None,
output=None,
user_input_color="blue",
tool_output_color=None,
tool_error_color="red",
):
no_color = os.environ.get("NO_COLOR")
if no_color is not None and no_color != "":
pretty = False
self.user_input_color = user_input_color if pretty else None
self.tool_output_color = tool_output_color if pretty else None
self.tool_error_color = tool_error_color if pretty else None
self.input = input
self.output = output
self.pretty = pretty
@ -65,29 +107,20 @@ class InputOutput:
if pretty:
self.console = Console()
else:
self.console = Console(force_terminal=True, no_color=True)
self.console = Console(no_color=True)
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.append_chat_history(f"\n# aider chat started at {current_time}\n\n")
def get_input(self, fnames, commands):
def get_input(self, root, rel_fnames, addable_rel_fnames, commands):
if self.pretty:
self.console.rule()
style = dict(style=self.user_input_color) if self.user_input_color else dict()
self.console.rule(**style)
else:
print()
fnames = list(fnames)
if len(fnames) > 1:
common_prefix = os.path.commonpath(fnames)
if not common_prefix.endswith(os.path.sep):
common_prefix += os.path.sep
short_fnames = [fname.replace(common_prefix, "", 1) for fname in fnames]
elif len(fnames):
short_fnames = [os.path.basename(fnames[0])]
else:
short_fnames = []
show = " ".join(short_fnames)
rel_fnames = list(rel_fnames)
show = " ".join(rel_fnames)
if len(show) > 10:
show += "\n"
show += "> "
@ -95,22 +128,29 @@ class InputOutput:
inp = ""
multiline_input = False
style = Style.from_dict({"": "green"})
if self.user_input_color:
style = Style.from_dict({"": self.user_input_color})
else:
style = None
while True:
completer_instance = FileContentCompleter(fnames, commands)
completer_instance = FileContentCompleter(
root, rel_fnames, addable_rel_fnames, commands
)
if multiline_input:
show = ". "
session_kwargs = {
"message": show,
"completer": completer_instance,
"style": style,
"reserve_space_for_menu": 4,
"complete_style": CompleteStyle.MULTI_COLUMN,
"input": self.input,
"output": self.output,
}
if style:
session_kwargs["style"] = style
if self.input_history_file is not None:
session_kwargs["history"] = FileHistory(self.input_history_file)
@ -180,9 +220,10 @@ class InputOutput:
self.append_chat_history(hist, linebreak=True, blockquote=True)
message = Text(message)
self.console.print(message, style="red")
style = dict(style=self.tool_error_color) if self.tool_error_color else dict()
self.console.print(message, **style)
def tool(self, *messages, log_only=False):
def tool_output(self, *messages, log_only=False):
if messages:
hist = " ".join(messages)
hist = f"{hist.strip()}"
@ -190,7 +231,8 @@ class InputOutput:
if not log_only:
messages = list(map(Text, messages))
self.console.print(*messages)
style = dict(style=self.tool_output_color) if self.tool_output_color else dict()
self.console.print(*messages, **style)
def append_chat_history(self, text, linebreak=False, blockquote=False):
if blockquote:

View file

@ -1,8 +1,9 @@
import os
import sys
import git
import configargparse
from dotenv import load_dotenv
import git
from aider.coder import Coder
from aider.io import InputOutput
@ -19,13 +20,11 @@ def main(args=None, input=None, output=None):
if args is None:
args = sys.argv[1:]
load_dotenv()
env_prefix = "AIDER_"
git_root = get_git_root()
default_config_files = [
os.path.expanduser("~/.aider.conf.yml"),
]
git_root = get_git_root()
if git_root:
default_config_files.insert(0, os.path.join(git_root, ".aider.conf.yml"))
@ -34,6 +33,7 @@ def main(args=None, input=None, output=None):
add_config_file_help=True,
default_config_files=default_config_files,
config_file_parser_class=configargparse.YAMLConfigFileParser,
auto_env_var_prefix="AIDER_",
)
parser.add_argument(
@ -63,21 +63,18 @@ def main(args=None, input=None, output=None):
parser.add_argument(
"--input-history-file",
metavar="INPUT_HISTORY_FILE",
env_var=f"{env_prefix}INPUT_HISTORY_FILE",
default=default_input_history_file,
help=f"Specify the chat input history file (default: {default_input_history_file})",
)
parser.add_argument(
"--chat-history-file",
metavar="CHAT_HISTORY_FILE",
env_var=f"{env_prefix}CHAT_HISTORY_FILE",
default=default_chat_history_file,
help=f"Specify the chat history file (default: {default_chat_history_file})",
)
parser.add_argument(
"--model",
metavar="MODEL",
env_var=f"{env_prefix}MODEL",
default="gpt-4",
help="Specify the model to use for the main chat (default: gpt-4)",
)
@ -91,17 +88,30 @@ def main(args=None, input=None, output=None):
parser.add_argument(
"--pretty",
action="store_true",
env_var=f"{env_prefix}PRETTY",
default=True,
help="Enable pretty, colorized output (default: True)",
)
parser.add_argument(
"--no-pretty",
action="store_false",
dest="pretty",
help="Disable pretty, colorized output",
)
parser.add_argument(
"--user-input-color",
default="green",
help="Set the color for user input (default: green)",
)
parser.add_argument(
"--tool-output-color",
default=None,
help="Set the color for tool output (default: None)",
)
parser.add_argument(
"--tool-error-color",
default="red",
help="Set the color for tool error messages (default: red)",
)
parser.add_argument(
"--apply",
metavar="FILE",
@ -110,7 +120,7 @@ def main(args=None, input=None, output=None):
parser.add_argument(
"--auto-commits",
action="store_true",
env_var=f"{env_prefix}AUTO_COMMIT",
dest="auto_commits",
default=True,
help="Enable auto commit of changes (default: True)",
)
@ -118,9 +128,28 @@ def main(args=None, input=None, output=None):
parser.add_argument(
"--no-auto-commits",
action="store_false",
dest="auto_commit",
dest="auto_commits",
help="Disable auto commit of changes",
)
parser.add_argument(
"--dirty-commits",
action="store_true",
dest="dirty_commits",
help="Enable dirty commit of changes",
default=True,
)
parser.add_argument(
"--no-dirty-commits",
action="store_false",
dest="dirty_commits",
help="Disable dirty commit of changes",
)
parser.add_argument(
"--openai-api-key",
metavar="OPENAI_API_KEY",
help="Specify the OpenAI API key",
env_var="OPENAI_API_KEY",
)
parser.add_argument(
"--dry-run",
action="store_true",
@ -130,7 +159,6 @@ def main(args=None, input=None, output=None):
parser.add_argument(
"--show-diffs",
action="store_true",
env_var=f"{env_prefix}SHOW_DIFFS",
help="Show diffs when committing changes (default: False)",
default=False,
)
@ -140,7 +168,6 @@ def main(args=None, input=None, output=None):
nargs="?",
const=True,
default=None,
env_var=f"{env_prefix}CTAGS",
help=(
"Add ctags to the chat to help GPT understand the codebase (default: check for ctags"
" executable)"
@ -168,9 +195,23 @@ def main(args=None, input=None, output=None):
args.chat_history_file,
input=input,
output=output,
user_input_color=args.user_input_color,
tool_output_color=args.tool_output_color,
tool_error_color=args.tool_error_color,
)
io.tool(*sys.argv, log_only=True)
if args.verbose:
show = parser.format_values()
io.tool_output(show)
io.tool_output("Option settings:")
for arg, val in sorted(vars(args).items()):
io.tool_output(f" - {arg}: {val}")
io.tool_output(*sys.argv, log_only=True)
if not args.openai_api_key:
io.tool_error("No OpenAI API key provided. Use --openai-api-key or env OPENAI_API_KEY.")
return 1
coder = Coder(
io,
@ -179,12 +220,15 @@ def main(args=None, input=None, output=None):
pretty=args.pretty,
show_diffs=args.show_diffs,
auto_commits=args.auto_commits,
dirty_commits=args.dirty_commits,
dry_run=args.dry_run,
use_ctags=args.ctags,
verbose=args.verbose,
openai_api_key=args.openai_api_key,
)
if args.auto_commits:
coder.commit(ask=True, prefix="wip: ", which="repo_files")
if args.dirty_commits:
coder.commit(ask=True, which="repo_files")
if args.apply:
with open(args.apply, "r") as f:
@ -192,6 +236,7 @@ def main(args=None, input=None, output=None):
coder.update_files(content, inp="")
return
io.tool_output("Use /help to see in-chat commands.")
coder.run()

View file

@ -8,7 +8,7 @@ Take requests for changes to the supplied code.
If the request is ambiguous, ask questions.
Once you understand the request you MUST:
1. List the files you need to modify. If they are *read-only* ask the user to make them *read-write* using the file's full path name.
1. List the files you need to modify. Do not suggest changes to *read-only* files. You *MUST* ask the user to make them *read-write* using the file's full path name. End your reply and wait for their approval.
2. Think step-by-step and explain the needed changes.
3. Describe each change with an *edit block* per the example below.
"""
@ -74,7 +74,7 @@ Reply with JUST the commit message, without quotes, comments, questions, etc!
# COMMANDS
undo_command_reply = "I did `git reset --hard HEAD~1` to discard the last edits."
added_files = "I added the content of these additional files: {fnames}"
added_files = "I added these *read-write* files: {fnames}"
run_output = """I ran this command:

View file

@ -1,15 +1,14 @@
import os
import json
import sys
import os
import subprocess
import tiktoken
import sys
import tempfile
from collections import defaultdict, Counter
from collections import Counter, defaultdict
import networkx as nx
import tiktoken
from aider import prompts, utils
from aider.dump import dump
# Global cache for tags
TAGS_CACHE = {}
@ -203,6 +202,7 @@ def find_py_files(directory):
def call_map():
import random
import graphviz
fnames = sys.argv[1:]
@ -322,3 +322,4 @@ def call_map():
if __name__ == "__main__":
call_map()
# print(rm.get_tags_map(sys.argv[1:]))

View file

@ -1,11 +1,11 @@
import re
import math
import re
from difflib import SequenceMatcher
from pathlib import Path
from pygments.util import ClassNotFound
from pygments.lexers import guess_lexer_for_filename
from pygments.token import Token
from pygments.util import ClassNotFound
# from aider.dump import dump
@ -234,10 +234,15 @@ def find_original_update_blocks(content):
processed.append(cur) # original_marker
filename = processed[-2].splitlines()[-1].strip()
if not len(filename) or "`" in filename:
filename = processed[-2].splitlines()[-2].strip()
try:
if not len(filename) or "`" in filename:
raise ValueError(f"Bad/missing filename. It should go right above {ORIGINAL}")
filename = processed[-2].splitlines()[-2].strip()
if not len(filename) or "`" in filename:
raise ValueError(
f"Bad/missing filename. It should go right above {ORIGINAL}"
)
except IndexError:
raise ValueError(f"Bad/missing filename. It should go right above {ORIGINAL}")
original_text = pieces.pop()
processed.append(original_text)
@ -248,8 +253,10 @@ def find_original_update_blocks(content):
raise ValueError(f"Expected {DIVIDER}")
updated_text = pieces.pop()
processed.append(updated_text)
updated_marker = pieces.pop()
processed.append(updated_marker)
if updated_marker.strip() != UPDATED:
raise ValueError(f"Expected {UPDATED}")