Skip to content

Commit

Permalink
Added config_manager to handle keys
Browse files Browse the repository at this point in the history
  • Loading branch information
dougollerenshaw committed Oct 15, 2024
1 parent 82a4b73 commit 9388821
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 40 deletions.
43 changes: 5 additions & 38 deletions codeaide/utils/api_utils.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import os
import anthropic
import openai
import google.generativeai as genai
from decouple import AutoConfig
import hjson
import re
from google.generativeai.types import GenerationConfig
from google.api_core import exceptions as google_exceptions
from codeaide.utils.config_manager import ConfigManager

from codeaide.utils.constants import (
AI_PROVIDERS,
Expand All @@ -16,6 +15,7 @@
from codeaide.utils.logging_config import get_logger

logger = get_logger()
config_manager = ConfigManager()


class MissingAPIKeyException(Exception):
Expand All @@ -28,18 +28,8 @@ def __init__(self, service):

def get_api_client(provider=DEFAULT_PROVIDER, model=None):
try:
root_dir = os.path.dirname(
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
)

# Use AutoConfig to automatically find and load the .env file in the project root
config = AutoConfig(search_path=root_dir)

api_key_name = AI_PROVIDERS[provider]["api_key_name"]
api_key = config(api_key_name, default=None)
logger.info(
f"Attempting to get API key for {provider} with key name: {api_key_name}"
)
api_key = config_manager.get_api_key(provider)
logger.info(f"Attempting to get API key for {provider}")
logger.info(f"API key found: {'Yes' if api_key else 'No'}")

if api_key is None or api_key.strip() == "":
Expand All @@ -64,30 +54,7 @@ def get_api_client(provider=DEFAULT_PROVIDER, model=None):
def save_api_key(service, api_key):
try:
cleaned_key = api_key.strip().strip("'\"") # Remove quotes and whitespace
root_dir = os.path.dirname(
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
)
env_path = os.path.join(root_dir, ".env")

if os.path.exists(env_path):
with open(env_path, "r") as file:
lines = file.readlines()

key_exists = False
for i, line in enumerate(lines):
if line.startswith(f"{service.upper()}_API_KEY="):
lines[i] = f'{service.upper()}_API_KEY="{cleaned_key}"\n'
key_exists = True
break

if not key_exists:
lines.append(f'{service.upper()}_API_KEY="{cleaned_key}"\n')
else:
lines = [f'{service.upper()}_API_KEY="{cleaned_key}"\n']

with open(env_path, "w") as file:
file.writelines(lines)

config_manager.set_api_key(service, cleaned_key)
return True
except Exception as e:
logger.error(f"Error saving API key: {str(e)}")
Expand Down
63 changes: 63 additions & 0 deletions codeaide/utils/config_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import os
import platform
import sys
from pathlib import Path
from decouple import Config, RepositoryEnv


class ConfigManager:
def __init__(self):
self.is_packaged_app = getattr(sys, "frozen", False)
if self.is_packaged_app:
self.config_dir = self._get_app_config_dir()
self.keyring_service = "CodeAIde"
else:
self.config_dir = Path(__file__).parent.parent.parent
self.env_file = self.config_dir / ".env"

def _get_app_config_dir(self):
system = platform.system()
if system == "Darwin": # macOS
return Path.home() / "Library" / "Application Support" / "CodeAIde"
elif system == "Windows":
return Path(os.getenv("APPDATA")) / "CodeAIde"
else: # Linux and others
return Path.home() / ".config" / "codeaide"

def get_api_key(self, provider):
if self.is_packaged_app:
import keyring

return keyring.get_password(
self.keyring_service, f"{provider.upper()}_API_KEY"
)
else:
config = Config(RepositoryEnv(self.env_file))
return config(f"{provider.upper()}_API_KEY", default=None)

def set_api_key(self, provider, api_key):
if self.is_packaged_app:
import keyring

keyring.set_password(
self.keyring_service, f"{provider.upper()}_API_KEY", api_key
)
else:
with open(self.env_file, "a") as f:
f.write(f'\n{provider.upper()}_API_KEY="{api_key}"\n')

def delete_api_key(self, provider):
if self.is_packaged_app:
import keyring

keyring.delete_password(self.keyring_service, f"{provider.upper()}_API_KEY")
else:
# Read the .env file, remove the line with the API key, and write it back
if self.env_file.exists():
lines = self.env_file.read_text().splitlines()
lines = [
line
for line in lines
if not line.startswith(f"{provider.upper()}_API_KEY=")
]
self.env_file.write_text("\n".join(lines) + "\n")
3 changes: 1 addition & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ google-generativeai==0.8.3
python-decouple==3.8
virtualenv==20.16.2
numpy==1.26.4
numpy==1.26.4
keyring
openai
hjson
pyyaml
Expand All @@ -20,4 +20,3 @@ autoflake
openai-whisper
sounddevice
scipy
ffmpeg-python

0 comments on commit 9388821

Please sign in to comment.