Переглянути джерело

Fix arg parser help message display (#1247)

* Fix arg parser help message display

* Add unittest
Boxuan Li 1 рік тому
батько
коміт
cf3372a5fe
3 змінених файлів з 88 додано та 51 видалено
  1. 45 2
      opendevin/config.py
  2. 1 49
      opendevin/main.py
  3. 42 0
      tests/test_arg_parser.py

+ 45 - 2
opendevin/config.py

@@ -49,7 +49,7 @@ for k, v in config.items():
         config[k] = tomlConfig[k]
         config[k] = tomlConfig[k]
 
 
 
 
-def parse_arguments():
+def get_parser():
     parser = argparse.ArgumentParser(
     parser = argparse.ArgumentParser(
         description='Run an agent with a specific task')
         description='Run an agent with a specific task')
     parser.add_argument(
     parser.add_argument(
@@ -58,13 +58,56 @@ def parse_arguments():
         type=str,
         type=str,
         help='The working directory for the agent',
         help='The working directory for the agent',
     )
     )
+    parser.add_argument(
+        '-t', '--task', type=str, default='', help='The task for the agent to perform'
+    )
+    parser.add_argument(
+        '-f',
+        '--file',
+        type=str,
+        help='Path to a file containing the task. Overrides -t if both are provided.',
+    )
+    parser.add_argument(
+        '-c',
+        '--agent-cls',
+        default='MonologueAgent',
+        type=str,
+        help='The agent class to use',
+    )
+    parser.add_argument(
+        '-m',
+        '--model-name',
+        default=config.get(ConfigType.LLM_MODEL),
+        type=str,
+        help='The (litellm) model name to use',
+    )
+    parser.add_argument(
+        '-i',
+        '--max-iterations',
+        default=config.get(ConfigType.MAX_ITERATIONS),
+        type=int,
+        help='The maximum number of iterations to run the agent',
+    )
+    parser.add_argument(
+        '-n',
+        '--max-chars',
+        default=config.get(ConfigType.MAX_CHARS),
+        type=int,
+        help='The maximum number of characters to send to and receive from LLM per task',
+    )
+    return parser
+
+
+def parse_arguments():
+    parser = get_parser()
     args, _ = parser.parse_known_args()
     args, _ = parser.parse_known_args()
     if args.directory:
     if args.directory:
         config[ConfigType.WORKSPACE_BASE] = os.path.abspath(args.directory)
         config[ConfigType.WORKSPACE_BASE] = os.path.abspath(args.directory)
         print(f'Setting workspace base to {config[ConfigType.WORKSPACE_BASE]}')
         print(f'Setting workspace base to {config[ConfigType.WORKSPACE_BASE]}')
+    return args
 
 
 
 
-parse_arguments()
+args = parse_arguments()
 
 
 
 
 def finalize_config():
 def finalize_config():

+ 1 - 49
opendevin/main.py

@@ -1,11 +1,9 @@
 import asyncio
 import asyncio
-import argparse
 import sys
 import sys
 from typing import Type
 from typing import Type
 
 
 import agenthub  # noqa F401 (we import this to get the agents registered)
 import agenthub  # noqa F401 (we import this to get the agents registered)
-from opendevin import config
-from opendevin.schema import ConfigType
+from opendevin.config import args
 from opendevin.agent import Agent
 from opendevin.agent import Agent
 from opendevin.controller import AgentController
 from opendevin.controller import AgentController
 from opendevin.llm.llm import LLM
 from opendevin.llm.llm import LLM
@@ -22,54 +20,8 @@ def read_task_from_stdin() -> str:
     return sys.stdin.read()
     return sys.stdin.read()
 
 
 
 
-def parse_arguments():
-    """Parse command-line arguments."""
-    parser = argparse.ArgumentParser(
-        description='Run an agent with a specific task')
-    parser.add_argument(
-        '-t', '--task', type=str, default='', help='The task for the agent to perform'
-    )
-    parser.add_argument(
-        '-f',
-        '--file',
-        type=str,
-        help='Path to a file containing the task. Overrides -t if both are provided.',
-    )
-    parser.add_argument(
-        '-c',
-        '--agent-cls',
-        default='MonologueAgent',
-        type=str,
-        help='The agent class to use',
-    )
-    parser.add_argument(
-        '-m',
-        '--model-name',
-        default=config.get(ConfigType.LLM_MODEL),
-        type=str,
-        help='The (litellm) model name to use',
-    )
-    parser.add_argument(
-        '-i',
-        '--max-iterations',
-        default=config.get(ConfigType.MAX_ITERATIONS),
-        type=int,
-        help='The maximum number of iterations to run the agent',
-    )
-    parser.add_argument(
-        '-n',
-        '--max-chars',
-        default=config.get(ConfigType.MAX_CHARS),
-        type=int,
-        help='The maximum number of characters to send to and receive from LLM per task',
-    )
-    args, _ = parser.parse_known_args()
-    return args
-
-
 async def main():
 async def main():
     """Main coroutine to run the agent controller with task input flexibility."""
     """Main coroutine to run the agent controller with task input flexibility."""
-    args = parse_arguments()
 
 
     # Determine the task source
     # Determine the task source
     if args.file:
     if args.file:

+ 42 - 0
tests/test_arg_parser.py

@@ -0,0 +1,42 @@
+from opendevin.config import get_parser
+
+import pytest
+
+
+def test_help_message(capsys):
+    parser = get_parser()
+    with pytest.raises(SystemExit):  # `--help` causes SystemExit
+        parser.parse_args(['--help'])
+    captured = capsys.readouterr()
+    expected_help_message = """
+usage: pytest [-h] [-d DIRECTORY] [-t TASK] [-f FILE] [-c AGENT_CLS]
+[-m MODEL_NAME] [-i MAX_ITERATIONS] [-n MAX_CHARS]
+
+Run an agent with a specific task
+
+options:
+  -h, --help            show this help message and exit
+  -d DIRECTORY, --directory DIRECTORY
+                        The working directory for the agent
+  -t TASK, --task TASK  The task for the agent to perform
+  -f FILE, --file FILE  Path to a file containing the task. Overrides -t if
+  both are provided.
+  -c AGENT_CLS, --agent-cls AGENT_CLS
+                        The agent class to use
+  -m MODEL_NAME, --model-name MODEL_NAME
+                        The (litellm) model name to use
+  -i MAX_ITERATIONS, --max-iterations MAX_ITERATIONS
+                        The maximum number of iterations to run the agent
+  -n MAX_CHARS, --max-chars MAX_CHARS
+                        The maximum number of characters to send to and
+                        receive from LLM per task
+"""
+    actual_lines = captured.out.strip().split('\n')
+    expected_lines = expected_help_message.strip().split('\n')
+
+    # Ensure both outputs have the same number of lines
+    assert len(actual_lines) == len(expected_lines), 'The number of lines in the help message does not match.'
+
+    # Compare each line
+    for actual, expected in zip(actual_lines, expected_lines):
+        assert actual.strip() == expected.strip(), f"Expected '{expected}', got '{actual}'"