Commit
·
0fe181b
1
Parent(s):
c8d97e7
config.py
CHANGED
|
@@ -1,27 +1,20 @@
|
|
| 1 |
# app/config.py
|
| 2 |
import json
|
| 3 |
import os
|
| 4 |
-
import re
|
| 5 |
from functools import lru_cache
|
| 6 |
from urllib.parse import quote
|
| 7 |
|
|
|
|
| 8 |
APPSETTINGS_PATH = os.environ.get("APPSETTINGS_JSON", "appsettings.json")
|
| 9 |
|
| 10 |
|
| 11 |
class Settings:
|
| 12 |
-
"""
|
| 13 |
def __init__(self, data: dict):
|
| 14 |
for k, v in data.items():
|
| 15 |
setattr(self, k, v)
|
| 16 |
|
| 17 |
|
| 18 |
-
def _to_upper_snake(name: str) -> str:
|
| 19 |
-
"""Convert CamelCase or mixedCase to UPPER_SNAKE_CASE."""
|
| 20 |
-
s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name)
|
| 21 |
-
s2 = re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1)
|
| 22 |
-
return s2.upper()
|
| 23 |
-
|
| 24 |
-
|
| 25 |
def _load_json(path):
|
| 26 |
if not os.path.exists(path):
|
| 27 |
return {}
|
|
@@ -30,35 +23,27 @@ def _load_json(path):
|
|
| 30 |
|
| 31 |
|
| 32 |
def _replace_env_vars(d, parent_key=None):
|
|
|
|
|
|
|
|
|
|
| 33 |
if isinstance(d, dict):
|
| 34 |
return {k: _replace_env_vars(v, k) for k, v in d.items()}
|
| 35 |
elif isinstance(d, str) and d.strip() == ".env":
|
| 36 |
-
env_key =
|
| 37 |
return os.environ.get(env_key)
|
| 38 |
else:
|
| 39 |
return d
|
| 40 |
|
| 41 |
|
| 42 |
-
def
|
| 43 |
-
"""Recursively normalize dict keys to UPPER_SNAKE_CASE."""
|
| 44 |
-
if isinstance(d, dict):
|
| 45 |
-
return {_to_upper_snake(k): _normalize_keys(v) for k, v in d.items()}
|
| 46 |
-
elif isinstance(d, list):
|
| 47 |
-
return [_normalize_keys(i) for i in d]
|
| 48 |
-
else:
|
| 49 |
-
return d
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
def build_amqp_url(cfg: dict):
|
| 53 |
-
local = cfg.get("LOCAL_SYSTEM_URL")
|
| 54 |
if not local:
|
| 55 |
return None
|
| 56 |
-
scheme = "amqps" if local.get("
|
| 57 |
-
host = local.get("
|
| 58 |
-
port = local.get("
|
| 59 |
-
user = local.get("
|
| 60 |
-
pwd = local.get("
|
| 61 |
-
vhost = local.get("
|
| 62 |
vhost_enc = quote(vhost, safe="")
|
| 63 |
if not (host and user and pwd):
|
| 64 |
return None
|
|
@@ -69,11 +54,33 @@ def build_amqp_url(cfg: dict):
|
|
| 69 |
def get_settings() -> Settings:
|
| 70 |
cfg = _load_json(APPSETTINGS_PATH)
|
| 71 |
cfg = _replace_env_vars(cfg)
|
| 72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
if not cfg.get("AMQP_URL"):
|
| 74 |
-
amqp_url =
|
| 75 |
if amqp_url:
|
| 76 |
cfg["AMQP_URL"] = amqp_url
|
|
|
|
| 77 |
return Settings(cfg)
|
| 78 |
|
| 79 |
|
|
|
|
| 1 |
# app/config.py
|
| 2 |
import json
|
| 3 |
import os
|
|
|
|
| 4 |
from functools import lru_cache
|
| 5 |
from urllib.parse import quote
|
| 6 |
|
| 7 |
+
|
| 8 |
APPSETTINGS_PATH = os.environ.get("APPSETTINGS_JSON", "appsettings.json")
|
| 9 |
|
| 10 |
|
| 11 |
class Settings:
|
| 12 |
+
"""Settings object with attribute access."""
|
| 13 |
def __init__(self, data: dict):
|
| 14 |
for k, v in data.items():
|
| 15 |
setattr(self, k, v)
|
| 16 |
|
| 17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
def _load_json(path):
|
| 19 |
if not os.path.exists(path):
|
| 20 |
return {}
|
|
|
|
| 23 |
|
| 24 |
|
| 25 |
def _replace_env_vars(d, parent_key=None):
|
| 26 |
+
"""
|
| 27 |
+
Replace ".env" values with env var lookups using uppercase key name.
|
| 28 |
+
"""
|
| 29 |
if isinstance(d, dict):
|
| 30 |
return {k: _replace_env_vars(v, k) for k, v in d.items()}
|
| 31 |
elif isinstance(d, str) and d.strip() == ".env":
|
| 32 |
+
env_key = (parent_key or "").upper()
|
| 33 |
return os.environ.get(env_key)
|
| 34 |
else:
|
| 35 |
return d
|
| 36 |
|
| 37 |
|
| 38 |
+
def _build_amqp_url(local: dict):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
if not local:
|
| 40 |
return None
|
| 41 |
+
scheme = "amqps" if local.get("UseTls", True) else "amqp"
|
| 42 |
+
host = local.get("RabbitHostName")
|
| 43 |
+
port = local.get("RabbitPort") or (5671 if scheme == "amqps" else 5672)
|
| 44 |
+
user = local.get("RabbitUserName")
|
| 45 |
+
pwd = local.get("RabbitPassword") or os.environ.get("RABBIT_PASSWORD")
|
| 46 |
+
vhost = local.get("RabbitVHost") or "/"
|
| 47 |
vhost_enc = quote(vhost, safe="")
|
| 48 |
if not (host and user and pwd):
|
| 49 |
return None
|
|
|
|
| 54 |
def get_settings() -> Settings:
|
| 55 |
cfg = _load_json(APPSETTINGS_PATH)
|
| 56 |
cfg = _replace_env_vars(cfg)
|
| 57 |
+
|
| 58 |
+
# Flatten relevant LocalSystemUrl fields
|
| 59 |
+
local = cfg.get("LocalSystemUrl", {})
|
| 60 |
+
if local:
|
| 61 |
+
cfg["RABBIT_INSTANCE_NAME"] = local.get("RabbitInstanceName")
|
| 62 |
+
cfg["RABBIT_HOST_NAME"] = local.get("RabbitHostName")
|
| 63 |
+
cfg["RABBIT_PORT"] = local.get("RabbitPort")
|
| 64 |
+
cfg["RABBIT_USER_NAME"] = local.get("RabbitUserName")
|
| 65 |
+
cfg["RABBIT_PASSWORD"] = local.get("RabbitPassword") or os.environ.get("RABBIT_PASSWORD")
|
| 66 |
+
cfg["RABBIT_VHOST"] = local.get("RabbitVHost")
|
| 67 |
+
cfg["RABBIT_USE_TLS"] = local.get("UseTls")
|
| 68 |
+
|
| 69 |
+
# Map JSON keys to what Python code expects
|
| 70 |
+
cfg["SERVICE_ID"] = cfg.get("ServiceID")
|
| 71 |
+
cfg["RABBIT_ROUTING_KEY"] = cfg.get("RabbitRoutingKey")
|
| 72 |
+
cfg["RABBIT_EXCHANGE_TYPE"] = cfg.get("RabbitExhangeType") or "topic"
|
| 73 |
+
cfg["REDIS_URL"] = cfg.get("RedisUrl")
|
| 74 |
+
cfg["REDIS_SECRET"] = cfg.get("RedisSecret")
|
| 75 |
+
cfg["EXCHANGE_TYPES"] = cfg.get("EXCHANGE_TYPES", {}) # default empty dict
|
| 76 |
+
cfg["RABBIT_PREFETCH"] = cfg.get("RABBIT_PREFETCH", 1)
|
| 77 |
+
|
| 78 |
+
# Build AMQP_URL if not already provided
|
| 79 |
if not cfg.get("AMQP_URL"):
|
| 80 |
+
amqp_url = _build_amqp_url(local)
|
| 81 |
if amqp_url:
|
| 82 |
cfg["AMQP_URL"] = amqp_url
|
| 83 |
+
|
| 84 |
return Settings(cfg)
|
| 85 |
|
| 86 |
|