From 58a4bdc3e1a0d493640fa2146e61f40144dde751 Mon Sep 17 00:00:00 2001 From: Nick Sullivan Date: Mon, 26 Jun 2023 23:06:09 -0600 Subject: [PATCH] Minor text changes, additional comment dividers, and additional comments --- README.md | 4 +- aicodebot/cli.py | 100 +++++++++++++++++++++-------------- requirements/requirements.in | 9 +++- tests/conftest.py | 2 + tests/test_cli.py | 6 +-- 5 files changed, 74 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 9ee03c8..fbf3968 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ AICodeBot is a coding assistant designed to make your coding life easier. With c ⚠️ Status: This project is in its infancy with very limited features, but it already improves the software development workflow. -⚠️ It uses OpenAI's ChatGPT large language model, which can hallucinate and be confidently wrong. Sometimes it does dumb things, which is why we have you confirm before it does anything permanent. +⚠️ It uses OpenAI's ChatGPT large language model, which can hallucinate and be confidently wrong. Sometimes it does dumb things, which is why we have you confirm before it does anything permanent. We're working on it and it's getting better all the time. @@ -93,7 +93,7 @@ The first time you run it, you'll be prompted to enter your OpenAI API Key, whic #### Test and Build [![GitHub Build](https://github.com/novara-ai/aicodebot/actions/workflows/build.yml/badge.svg)](https://github.com/novara-ai/aicodebot/actions?query=build) -[![CodeCov](https://codecov.io/gh/novara-ai/aicodebot/branch/main/graph/badge.svg)](https://codecov.io/gh/novara_ai/aicodebot) +[![CodeCov](https://codecov.io/gh/novara-ai/aicodebot/branch/main/graph/badge.svg)](https://codecov.io/gh/novara-ai/aicodebot) [![Pytest](https://img.shields.io/badge/%F0%9F%A7%AA-Pytest-blue)](https://docs.pytest.org/en/stable/contents.html) #### Code Quality diff --git a/aicodebot/cli.py b/aicodebot/cli.py index 4d00fb1..dcf3868 100644 --- a/aicodebot/cli.py +++ b/aicodebot/cli.py @@ -9,56 +9,19 @@ from rich.style import Style import click, datetime, openai, os, random, subprocess, sys, tempfile, webbrowser +# ----------------------------- Default settings ----------------------------- # + DEFAULT_MAX_TOKENS = 1024 DEFAULT_TEMPERATURE = 0.1 DEFAULT_MODEL = "gpt-3.5-turbo" # Can't wait to use GPT-4, as the results are much better. On the waitlist. DEFAULT_SPINNER = "point" +# ----------------------- Setup for rich console output ---------------------- # console = Console() bot_style = Style(color="#30D5C8") -def setup_environment(): - # Load environment variables from the config file - config_file = Path(Path.home() / ".aicodebot") - load_dotenv(config_file) - - if os.getenv("OPENAI_API_KEY"): - openai.api_key = os.getenv("OPENAI_API_KEY") - return True - - openai_api_key_url = "https://platform.openai.com/account/api-keys" - - console.print( - "[bold red]The OPENAI_API_KEY environment variable is not set.[/bold red]\n" - f"The OpenAI API key is required to use aicodebot. You can get one for free on the OpenAI website.\n" - f"Let's create a config file for you at {config_file}" - ) - - if click.confirm("Open the OpenAI API keys page for you in a browser?"): - webbrowser.open(openai_api_key_url) - - if click.confirm(f"Create the {config_file} file for you?"): - api_key = click.prompt("Please enter your OpenAI API key") - - # Copy .env.template to .env and insert the API key - template_file = Path(__file__).parent / ".aicodebot.template" - with Path.open(template_file, "r") as template, Path.open(config_file, "w") as env: - for line in template: - if line.startswith("OPENAI_API_KEY="): - env.write(f"OPENAI_API_KEY={api_key}\n") - else: - env.write(line) - - console.print( - f"[bold green]Created {config_file} with your OpenAI API key.[/bold green] " - "Now, please re-run aicodebot and let's get started!" - ) - sys.exit(0) - - raise click.ClickException( - "🛑 Please set an API key in the OPENAI_API_KEY environment variable or in a .aicodebot file." - ) +# -------------------------- Top level command group ------------------------- # @click.group() @@ -68,6 +31,15 @@ def cli(): pass +# ---------------------------------------------------------------------------- # +# Commands # +# ---------------------------------------------------------------------------- # + +# Commands are defined as functions with the @click decorator. +# The function name is the command name, and the docstring is the help text. +# Keep the commands in alphabetical order. + + @cli.command() @click.option("-v", "--verbose", count=True) def alignment(verbose): @@ -275,5 +247,51 @@ def review(commit, verbose): console.print(response, style=bot_style) +# ------------------------------- End Commands ------------------------------- # + + +def setup_environment(): + # Load environment variables from the config file + config_file = Path(Path.home() / ".aicodebot") + load_dotenv(config_file) + + if os.getenv("OPENAI_API_KEY"): + openai.api_key = os.getenv("OPENAI_API_KEY") + return True + + openai_api_key_url = "https://platform.openai.com/account/api-keys" + + console.print( + "[bold red]The OPENAI_API_KEY environment variable is not set.[/bold red]\n" + f"The OpenAI API key is required to use aicodebot. You can get one for free on the OpenAI website.\n" + f"Let's create a config file for you at {config_file}" + ) + + if click.confirm("Open the OpenAI API keys page for you in a browser?"): + webbrowser.open(openai_api_key_url) + + if click.confirm(f"Create the {config_file} file for you?"): + api_key = click.prompt("Please enter your OpenAI API key") + + # Copy .env.template to .env and insert the API key + template_file = Path(__file__).parent / ".aicodebot.template" + with Path.open(template_file, "r") as template, Path.open(config_file, "w") as env: + for line in template: + if line.startswith("OPENAI_API_KEY="): + env.write(f"OPENAI_API_KEY={api_key}\n") + else: + env.write(line) + + console.print( + f"[bold green]Created {config_file} with your OpenAI API key.[/bold green] " + "Now, please re-run aicodebot and let's get started!" + ) + sys.exit(0) + + raise click.ClickException( + "🛑 Please set an API key in the OPENAI_API_KEY environment variable or in a .aicodebot file." + ) + + if __name__ == "__main__": cli() diff --git a/requirements/requirements.in b/requirements/requirements.in index 5de298d..7a06c7c 100644 --- a/requirements/requirements.in +++ b/requirements/requirements.in @@ -1,5 +1,12 @@ +# We use pip-tools to manage dependencies, which means that this +# file just lists them without version numbers. If you add a new +# dependency, you need to run `pip-compile` to update the +# requirements.txt file. + +# Keep this list sorted alphabetically. + beautifulsoup4 # needed by langchain -click +click # command line interface helpers GitPython langchain openai diff --git a/tests/conftest.py b/tests/conftest.py index 34f71e2..fe6d159 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -6,11 +6,13 @@ @pytest.fixture def cli_runner(): + # Create a Click CLI runner that can be used to invoke the CLI return CliRunner() @pytest.fixture def temp_git_repo(): + # Create a temporary git repository that can be used for testing with tempfile.TemporaryDirectory() as temp_dir: repo = Repo.init(temp_dir) with repo.config_writer() as git_config: diff --git a/tests/test_cli.py b/tests/test_cli.py index 4b5aa7b..836b842 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -10,7 +10,7 @@ def test_version(cli_runner): @pytest.mark.skipif(os.getenv("OPENAI_API_KEY") is None, reason="Skipping live tests without an API key.") -def test_funfact(cli_runner): +def test_fun_fact(cli_runner): result = cli_runner.invoke(cli, ["fun-fact"]) assert result.exit_code == 0 @@ -24,7 +24,7 @@ def test_alignment(cli_runner): def test_debug_success(cli_runner): result = cli_runner.invoke(cli, ["debug", "echo", "Hello, world!"]) assert result.exit_code == 0 - assert "Running:\necho Hello, world!" in result.output + assert "echo Hello, world!" in result.output assert "The command completed successfully." in result.output @@ -32,4 +32,4 @@ def test_debug_success(cli_runner): def test_debug_failure(cli_runner): result = cli_runner.invoke(cli, ["debug", "ls", "-9"]) assert result.exit_code > 0 - assert "Running:\nls -9" in result.output + assert "ls -9" in result.output