Files
shell_gpt/sgpt/config.py
T
Farkhod Sadykov 12134c2c95 Migrating to TOML new linting and stricted typing (#165)
* pyproject.toml
* sdist and bdist specific files.
* CONTRIBUITNG.md.
* New linters and CI/CD.
* Mypy stricted types.
* Shell scripts to run linters and tests.
2023-04-15 01:22:23 +02:00

81 lines
2.8 KiB
Python

import os
from getpass import getpass
from pathlib import Path
from tempfile import gettempdir
from typing import Any
from click import UsageError
from sgpt.utils import ModelOptions
CONFIG_FOLDER = os.path.expanduser("~/.config")
CONFIG_PATH = Path(CONFIG_FOLDER) / "shell_gpt" / ".sgptrc"
# TODO: Refactor ENV variables with SGPT_ prefix.
DEFAULT_CONFIG = {
# TODO: Refactor it to CHAT_STORAGE_PATH.
"CHAT_CACHE_PATH": os.getenv(
"CHAT_CACHE_PATH", str(Path(gettempdir()) / "shell_gpt" / "chat_cache")
),
"CACHE_PATH": os.getenv(
"CACHE_PATH", str(Path(gettempdir()) / "shell_gpt" / "cache")
),
"CHAT_CACHE_LENGTH": int(os.getenv("CHAT_CACHE_LENGTH", "100")),
"CACHE_LENGTH": int(os.getenv("CHAT_CACHE_LENGTH", "100")),
"REQUEST_TIMEOUT": int(os.getenv("REQUEST_TIMEOUT", "60")),
"DEFAULT_MODEL": os.getenv("DEFAULT_MODEL", ModelOptions.GPT3.value),
"OPENAI_API_HOST": os.getenv("OPENAI_API_HOST", "https://api.openai.com"),
"DEFAULT_COLOR": os.getenv("DEFAULT_COLOR", "magenta"),
# New features might add their own config variables here.
}
class Config(dict): # type: ignore
def __init__(self, config_path: Path, **defaults: Any):
self.config_path = config_path
if self._exists:
self._read()
has_new_config = False
for key, value in defaults.items():
if key not in self:
has_new_config = True
self[key] = value
if has_new_config:
self._write()
else:
config_path.parent.mkdir(parents=True, exist_ok=True)
# Don't write API key to config file if it is in the environment.
if not defaults.get("OPENAI_API_KEY") and not os.getenv("OPENAI_API_KEY"):
api_key = getpass(prompt="Please enter your OpenAI API key: ")
defaults["OPENAI_API_KEY"] = api_key
super().__init__(**defaults)
self._write()
@property
def _exists(self) -> bool:
return self.config_path.exists()
def _write(self) -> None:
with open(self.config_path, "w", encoding="utf-8") as file:
string_config = ""
for key, value in self.items():
string_config += f"{key}={value}\n"
file.write(string_config)
def _read(self) -> None:
with open(self.config_path, "r", encoding="utf-8") as file:
for line in file:
key, value = line.strip().split("=")
self[key] = value
def get(self, key: str) -> str: # type: ignore
# Prioritize environment variables over config file.
value = os.getenv(key) or super().get(key)
if not value:
raise UsageError(f"Missing config key: {key}")
return value
cfg = Config(CONFIG_PATH, **DEFAULT_CONFIG)