一个复杂的多文件变更与调试过程

这是一段关于较复杂代码变更的聊天记录。用户试图更新测试代码以使用 prompt_toolkit 提供的输入模拟功能。这需要对多个源文件进行修改。

值得注意的几个方面:

  • 初始修改未能正常工作,因此用户提供了错误信息和 prompt_toolkit 文档片段,通过协作调试来解决问题
  • 用户在聊天外使用编辑器编辑了文件,aider 注意到这些外部变更并提议提交它们
  • 在某个时刻用户按下 ^C 中断了 LLM 的响应,因为响应没有帮助。用户给出更清晰的说明后,在下次回复中获得了更好的结果

$ aider tests/test_main.py aider/getinput.py
已将 tests/test_main.py 添加到聊天
已将 aider/getinput.py 添加到聊天

是否可以使用 prompt_toolkit 的输入模拟函数代替 /dev/null 在主测试中发送空输入?

是的,我们可以使用 prompt_toolkit.input 模块来模拟测试中的输入。以下是修改 tests/test_main.py 文件的方法:

tests/test_main.py
<<<<<<< ORIGINAL
import os
import sys
import tempfile
from unittest import TestCase
from aider.main import main
import subprocess
=======
import os
import tempfile
from unittest import TestCase
from aider.main import main
import subprocess
from prompt_toolkit.input import create_pipe_input
from prompt_toolkit.output import DummyOutput
>>>>>>> UPDATED

现在更新测试用例以使用 create_pipe_inputDummyOutput

tests/test_main.py
<<<<<<< ORIGINAL
            with open(os.devnull, "r") as dev_null:
                save_stdin = sys.stdin
                sys.stdin = dev_null
                main([])
                sys.stdin = save_stdin
=======
            pipe_input = create_pipe_input()
            save_stdin = sys.stdin
            sys.stdin = pipe_input
            main([], input=pipe_input, output=DummyOutput())
            sys.stdin = save_stdin
            pipe_input.close()
>>>>>>> UPDATED
tests/test_main.py
<<<<<<< ORIGINAL
            with open(os.devnull, "r") as dev_null:
                save_stdin = sys.stdin
                sys.stdin = dev_null
                main(["foo.txt"])
                sys.stdin = save_stdin
                self.assertTrue(os.path.exists("foo.txt"))
=======
            pipe_input = create_pipe_input()
            save_stdin = sys.stdin
            sys.stdin = pipe_input
            main(["foo.txt"], input=pipe_input, output=DummyOutput())
            sys.stdin = save_stdin
            pipe_input.close()
            self.assertTrue(os.path.exists("foo.txt"))
>>>>>>> UPDATED
tests/test_main.py
<<<<<<< ORIGINAL
            with open(os.devnull, "r") as dev_null:
                save_stdin = sys.stdin
                sys.stdin = dev_null
                main(["--yes", "foo.txt"])
                sys.stdin = save_stdin
                self.assertTrue(os.path.exists("foo.txt"))
=======
            pipe_input = create_pipe_input()
            save_stdin = sys.stdin
            sys.stdin = pipe_input
            main(["--yes", "foo.txt"], input=pipe_input, output=DummyOutput())
            sys.stdin = save_stdin
            pipe_input.close()
            self.assertTrue(os.path.exists("foo.txt"))
>>>>>>> UPDATED

这些修改将用 prompt_toolkit 的输入模拟函数替换 /dev/null 的使用。

已应用到 tests/test_main.py
已应用到 tests/test_main.py
已应用到 tests/test_main.py
已应用到 tests/test_main.py
提交 c177e29 aider: 在测试中用 prompt_toolkit 的输入模拟函数替换了 /dev/null 的使用。

Git 仓库有未提交的更改。
建议的提交信息:
在 test_main.py 中添加了 sys 模块的导入语句。
在聊天继续前提交 [y/n/提交信息]? y
提交 6724fcd 在 test_main.py 中添加了 sys 模块的导入语句。

/add aider/main.py

已将 aider/main.py 添加到聊天

我遇到这个错误:FAILED tests/test_main.py::TestMain::test_main_with_empty_git_dir_new_file - TypeError: main() got an unexpected keyword argument ‘input’

抱歉造成了混淆。看来我在 aider/main.py 中的 main() 函数定义有误。main() 函数应该接受 inputoutput 关键字参数。以下是修复方案:

aider/main.py
<<<<<<< ORIGINAL
def main(args=None):
    if args is None:
        args = sys.argv[1:]
=======
def main(args=None, input=None, output=None):
    if args is None:
        args = sys.argv[1:]
    if input is None:
        input = sys.stdin
    if output is None:
        output = sys.stdout
>>>>>>> UPDATED

现在,main() 函数将接受 inputoutput 关键字参数,测试应该能通过了。

已将对 aider/main.py 的编辑应用
提交 79dfba9 aider: 修复了 main() 函数以接受 input 和 output 关键字参数。

我们需要把这些参数传入 InputOutput 和 prompt_toolkit 对吗?

没错。我们需要将 inputoutput 参数传递给 InputOutput 类,然后再传递给 prompt_toolkit.prompt() 函数。以下是修改 aider/getinput.pyaider/main.py 文件的方法:

aider/getinput.py 中,更新 InputOutput 类以接受 inputoutput 参数:

aider/getinput.py
<<<<<<< ORIGINAL
class InputOutput:
    def __init__(self, pretty, yes, input_history_file, chat_history_file):
=======
class InputOutput:
    def __init__(self, pretty, yes, input_history_file, chat_history_file, input=None, output=None):
        self.input = input
        self.output = output
>>>>>>> UPDATED

现在更新 get_input() 方法中的 prompt() 函数调用,使用 inputoutput 参数:

aider/getinput.py
<<<<<<< ORIGINAL
            line = prompt(
                show,
                completer=completer_instance,
                history=FileHistory(self.input_history_file),
                style=style,
                reserve_space_for_menu=4,
                complete_style=CompleteStyle.MULTI_COLUMN,
            )
=======
            line = prompt(
                show,
                completer=completer_instance,
                history=FileHistory(self.input_history_file),
                style=style,
                reserve_space_for_menu=4,
                complete_style=CompleteStyle.MULTI_COLUMN,
                input=self.input,
                output=self.output,
            )
>>>>>>> UPDATED

aider/main.py 中,将 inputoutput 参数传递给 InputOutput 类:

aider/main.py
<<<<<<< ORIGINAL
    io = InputOutput(args.pretty, args.yes, args.input_history_file, args.chat_history_file)
=======
    io = InputOutput(args.pretty, args.yes, args.input_history_file, args.chat_history_file, input=input, output=output)
>>>>>>> UPDATED

这些修改将确保 inputoutput 参数被传递给 InputOutput 类,然后再传递给 prompt_toolkit.prompt() 函数。

已编辑 aider/getinput.py
已编辑 aider/getinput.py
已编辑 aider/main.py
提交 cea9d2a aider: 更新了 InputOutput 类以接受 input 和 output 参数,并将它们传递给 prompt_toolkit.prompt() 函数。

测试失败 tests/test_main.py::TestMain::test_main_with_empty_git_dir_new_file - TypeError: prompt() 接收到意外的关键字参数 ‘input’

对于造成的困惑我深表歉意。看来我在 prompt_toolkit.prompt() 函数调用中犯了错误。prompt() 函数接受的是 stdinstdout 参数,而不是 inputoutput。以下是修复方案:

更新 aider/getinput.py 文件中 get_input() 方法里的 prompt() 函数调用:

aider/getinput.py
<<<<<<< ORIGINAL
            input=self.input,
            output=self.output,
=======
            stdin=self.input,
            stdout=self.output,
>>>>>>> UPDATED

这些修改将确保 inputoutput 参数能正确传递给 prompt_toolkit.prompt() 函数。

已应用编辑到 aider/getinput.py
提交 55d3540 aider: 修复了 get_input() 方法中的 prompt() 函数调用,改为传递 stdinstdout 参数而非 inputoutput

prompt_toolkit.shortcuts.prompt(message: AnyFormattedText | None = None, *, history: History | None = None, editing_mode: EditingMode | None = None, refresh_interval: float | None = None, vi_mode: bool | None = None, lexer: Lexer | None = None, completer: Completer | None = None, complete_in_thread: bool | None = None, is_password: bool | None = None, key_bindings: KeyBindingsBase | None = None, bottom_toolbar: AnyFormattedText | None = None, style: BaseStyle | None = None, color_depth: ColorDepth | None = None, cursor: AnyCursorShapeConfig = None, include_default_pygments_style: FilterOrBool | None = None, style_transformation: StyleTransformation | None = None, swap_light_and_dark_colors: FilterOrBool | None = None, rprompt: AnyFormattedText | None = None, multiline: FilterOrBool | None = None, prompt_continuation: PromptContinuationText | None = None, wrap_lines: FilterOrBool | None = None, enable_history_search: FilterOrBool | None = None, search_ignore_case: FilterOrBool | None = None, complete_while_typing: FilterOrBool | None = None, validate_while_typing: FilterOrBool | None = None, complete_style: CompleteStyle | None = None, auto_suggest: AutoSuggest | None = None, validator: Validator | None = None, clipboard: Clipboard | None = None, mouse_support: FilterOrBool | None = None, input_processors: list[Processor] | None = None, placeholder: AnyFormattedText | None = None, reserve_space_for_menu: int | None = None, enable_system_prompt: FilterOrBool | None = None, enable_suspend: FilterOrBool | None = None, enable_open_in_editor: FilterOrBool | None = None, tempfile_suffix: str | Callable[[], str] | None = None, tempfile: str | Callable[[], str] | None = None, default: str = ‘’, accept_default: bool = False, pre_run: Callable[[], None] | None = None) → str

抱歉之前造成的混淆。看起来 prompt_toolkit.prompt() 函数并不直接接受 stdinstdout 参数。我们需要使用 prompt_toolkit 中的 Application 类来创建一个带有指定输入输出的自定义应用。以下是修改 aider/getinput.py 文件的方法:

首先,从 prompt_toolkit 导入必要的类和函数

^C KeyboardInterrupt

class prompt_toolkit.shortcuts.PromptSession(message: AnyFormattedText = ‘’, *, multiline: FilterOrBool = False, wrap_lines: FilterOrBool = True, is_password: FilterOrBool = False, vi_mode: bool = False, editing_mode: EditingMode = <EditingMode.EMACS: ‘EMACS’>, complete_while_typing: FilterOrBool = True, validate_while_typing: FilterOrBool = True, enable_history_search: FilterOrBool = False, search_ignore_case: FilterOrBool = False, lexer: Lexer | None = None, enable_system_prompt: FilterOrBool = False, enable_suspend: FilterOrBool = False, enable_open_in_editor: FilterOrBool = False, validator: Validator | None = None, completer: Completer | None = None, complete_in_thread: bool = False, reserve_space_for_menu: int = 8, complete_style: CompleteStyle = <CompleteStyle.COLUMN: ‘COLUMN’>, auto_suggest: AutoSuggest | None = None, style: BaseStyle | None = None, style_transformation: StyleTransformation | None = None, swap_light_and_dark_colors: FilterOrBool = False, color_depth: ColorDepth | None = None, cursor: AnyCursorShapeConfig = None, include_default_pygments_style: FilterOrBool = True, history: History | None = None, clipboard: Clipboard | None = None, prompt_continuation: PromptContinuationText | None = None, rprompt: AnyFormattedText = None, bottom_toolbar: AnyFormattedText = None, mouse_support: FilterOrBool = False, input_processors: list[Processor] | None = None, placeholder: AnyFormattedText | None = None, key_bindings: KeyBindingsBase | None = None, erase_when_done: bool = False, tempfile_suffix: str | Callable[[], str] | None = ‘.txt’, tempfile: str | Callable[[], str] | None = None, refresh_interval: float = 0, input: Input | None = None, output: Output | None = None)

感谢提供 PromptSession 类的信息。我们可以使用 PromptSession 类来创建具有所需输入和输出的自定义会话。以下是修改 aider/getinput.py 文件的方法:

首先,从 prompt_toolkit.shortcuts 导入 PromptSession 类:

aider/getinput.py
<<<<<<< ORIGINAL
from prompt_toolkit import prompt
=======
from prompt_toolkit.shortcuts import PromptSession
>>>>>>> UPDATED

现在,更新 get_input() 方法以使用 PromptSession 类:

aider/getinput.py
<<<<<<< ORIGINAL
            line = prompt(
                show,
                completer=completer_instance,
                history=FileHistory(self.input_history_file),
                style=style,
                reserve_space_for_menu=4,
                complete_style=CompleteStyle.MULTI_COLUMN,
                input=self.input,
                output=self.output,
            )
=======
            session = PromptSession(
                message=show,
                completer=completer_instance,
                history=FileHistory(self.input_history_file),
                style=style,
                reserve_space_for_menu=4,
                complete_style=CompleteStyle.MULTI_COLUMN,
                input=self.input,
                output=self.output,
            )
            line = session.prompt()
>>>>>>> UPDATED

这些更改将确保 inputoutput 参数正确传递给 prompt_toolkitPromptSession 类。

已应用对 aider/getinput.py 的编辑
已应用对 aider/getinput.py 的编辑
提交 ac92cca aider: 将 prompt() 替换为 PromptSession() 以正确传递输入和输出参数。

尝试在测试中使用 create_input(StringIO(‘’))

我理解您想在测试中使用 create_input(StringIO(''))。不过,我需要更多关于您想在哪些测试用例中应用这个变更以及如何使用它的信息。请提供更多细节或示例。

当前使用 create_pipe_input() 的那些测试

我明白您想在测试用例中用 create_input(StringIO('')) 替换 create_pipe_input()。以下是针对 tests/test_main.py 文件的变更:

tests/test_main.py
<<<<<<< ORIGINAL
from prompt_toolkit.input import create_pipe_input
=======
from prompt_toolkit.input import create_input
from io import StringIO
>>>>>>> UPDATED
tests/test_main.py
<<<<<<< ORIGINAL
            pipe_input = create_pipe_input()
=======
            pipe_input = create_input(StringIO(''))
>>>>>>> UPDATED
tests/test_main.py
<<<<<<< ORIGINAL
            pipe_input = create_pipe_input()
=======
            pipe_input = create_input(StringIO(''))
>>>>>>> UPDATED
tests/test_main.py
<<<<<<< ORIGINAL
            pipe_input = create_pipe_input()
=======
            pipe_input = create_input(StringIO(''))
>>>>>>> UPDATED

这些变更将在测试用例中用 create_input(StringIO('')) 替换 create_pipe_input() 的使用。

已应用到 tests/test_main.py
已应用到 tests/test_main.py
已应用到 tests/test_main.py
已应用到 tests/test_main.py
提交 4bb043f aider: 在测试用例中用 create_input(StringIO('')) 替换了 create_pipe_input() 的使用。

很好,成功了!

很高兴这些变更对您有效!如果您有任何其他请求或需要进一步帮助,请随时询问。


目录