Skip to content

Commit 9bbfc48

Browse files
claude[bot]jgwill
andcommitted
feat: add environment variable fallback for Langfuse configuration
- Add simple .env file parser (Python 3.6 compatible, no dependencies) - Support LANGFUSE_SECRET_KEY, LANGFUSE_PUBLIC_KEY, LANGFUSE_HOST, LANGFUSE_AUTH3 - Priority order: .env file → system environment → coaia.json → defaults - Maintains backward compatibility with existing environment variables - Resolves issue #26 Co-authored-by: Guillaume Descoteaux-Isabelle <jgwill@users.noreply.github.com>
1 parent 92ff092 commit 9bbfc48

File tree

1 file changed

+45
-11
lines changed

1 file changed

+45
-11
lines changed

coaiapy/coaiamodule.py

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,27 @@ def find_existing_config():
5151

5252
return None
5353

54+
def load_env_file(env_path='.env'):
55+
"""Simple .env file loader compatible with Python 3.6"""
56+
env_vars = {}
57+
if os.path.exists(env_path):
58+
try:
59+
with open(env_path, 'r') as f:
60+
for line in f:
61+
line = line.strip()
62+
if line and not line.startswith('#') and '=' in line:
63+
key, value = line.split('=', 1)
64+
key = key.strip()
65+
value = value.strip()
66+
# Remove surrounding quotes if present
67+
if (value.startswith('"') and value.endswith('"')) or \
68+
(value.startswith("'") and value.endswith("'")):
69+
value = value[1:-1]
70+
env_vars[key] = value
71+
except Exception as e:
72+
print(f"Warning: Error loading .env file: {e}")
73+
return env_vars
74+
5475
def merge_configs(base_config, override_config):
5576
"""Deep merge two configuration dictionaries"""
5677
merged = base_config.copy()
@@ -65,6 +86,9 @@ def read_config():
6586
global config
6687

6788
if config is None:
89+
# Load .env file first if it exists
90+
env_vars = load_env_file()
91+
6892
# Default configuration
6993
config = {
7094
"jtaleconf": {
@@ -110,21 +134,31 @@ def read_config():
110134
except Exception as e:
111135
print(f"Warning: Error loading fallback config: {e}")
112136

137+
# Helper function to get value from .env first, then environment, then config
138+
def get_env_value(env_key, config_value, env_vars=env_vars):
139+
return env_vars.get(env_key) or os.getenv(env_key, config_value)
140+
113141
# Check for placeholder values and replace with environment variables if needed
114-
config["openai_api_key"] = os.getenv("OPENAI_API_KEY", config["openai_api_key"])
115-
config["pollyconf"]["key"] = os.getenv("AWS_KEY_ID", config["pollyconf"]["key"])
116-
config["pollyconf"]["secret"] = os.getenv("AWS_SECRET_KEY", config["pollyconf"]["secret"])
117-
config["pollyconf"]["region"] = os.getenv("AWS_REGION", config["pollyconf"]["region"])
142+
config["openai_api_key"] = get_env_value("OPENAI_API_KEY", config["openai_api_key"])
143+
config["pollyconf"]["key"] = get_env_value("AWS_KEY_ID", config["pollyconf"]["key"])
144+
config["pollyconf"]["secret"] = get_env_value("AWS_SECRET_KEY", config["pollyconf"]["secret"])
145+
config["pollyconf"]["region"] = get_env_value("AWS_REGION", config["pollyconf"]["region"])
118146

119-
config["jtaleconf"]["host"] = os.getenv("REDIS_HOST", config["jtaleconf"]["host"])
120-
if config["jtaleconf"]["host"] == config["jtaleconf"]["host"] or os.getenv("REDIS_HOST") is None:
121-
config["jtaleconf"]["host"] = os.getenv("UPSTASH_HOST", config["jtaleconf"]["host"])
147+
config["jtaleconf"]["host"] = get_env_value("REDIS_HOST", config["jtaleconf"]["host"])
148+
if config["jtaleconf"]["host"] == config["jtaleconf"]["host"] or (not env_vars.get("REDIS_HOST") and not os.getenv("REDIS_HOST")):
149+
config["jtaleconf"]["host"] = get_env_value("UPSTASH_HOST", config["jtaleconf"]["host"])
122150

123-
config["jtaleconf"]["port"] = int(os.getenv("REDIS_PORT", config["jtaleconf"]["port"]))
151+
config["jtaleconf"]["port"] = int(get_env_value("REDIS_PORT", config["jtaleconf"]["port"]))
152+
153+
config["jtaleconf"]["password"] = get_env_value("REDIS_PASSWORD", config["jtaleconf"]["password"])
154+
if config["jtaleconf"]["password"] == config["jtaleconf"]["password"] or (not env_vars.get("REDIS_PASSWORD") and not os.getenv("REDIS_PASSWORD")):
155+
config["jtaleconf"]["password"] = get_env_value("UPSTASH_PASSWORD", config["jtaleconf"]["password"])
124156

125-
config["jtaleconf"]["password"] = os.getenv("REDIS_PASSWORD", config["jtaleconf"]["password"])
126-
if config["jtaleconf"]["password"] == config["jtaleconf"]["password"] or os.getenv("REDIS_PASSWORD") is None:
127-
config["jtaleconf"]["password"] = os.getenv("UPSTASH_PASSWORD", config["jtaleconf"]["password"])
157+
# Add Langfuse environment variable support
158+
config["langfuse_secret_key"] = get_env_value("LANGFUSE_SECRET_KEY", config.get("langfuse_secret_key", ""))
159+
config["langfuse_public_key"] = get_env_value("LANGFUSE_PUBLIC_KEY", config.get("langfuse_public_key", ""))
160+
config["langfuse_base_url"] = get_env_value("LANGFUSE_HOST", config.get("langfuse_base_url", "https://us.cloud.langfuse.com"))
161+
config["langfuse_auth3"] = get_env_value("LANGFUSE_AUTH3", config.get("langfuse_auth3", ""))
128162

129163
return config
130164

0 commit comments

Comments
 (0)