-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using multiple BaseSettings with different prefixes #1727
Comments
Hello @lesnek Currently the subclass config overwrites the parent config making from pydantic.env_settings import BaseSettings
class MyConfig(BaseSettings.Config):
@classmethod
def prepare_field(cls, field) -> None:
if 'env_names' in field.field_info.extra:
return
return super().prepare_field(field)
class KubectlSecrets(BaseSettings):
credentials: str
google_auth_key: str
class Config(MyConfig):
env_prefix = 'K8S_SECRET_'
class Settings(KubectlSecrets):
environment: str
redis_db: str
class Config(MyConfig):
env_prefix = '' Hope it helps ! |
This is something I've run into as well. It's a tricky thing, and I don't believe there is a solution using inheritance, since that will by definition merge things before initialization. One possibility I came up with just now is to merge the dictionaries of the resulting objects and create a new one: import os
from pydantic import BaseSettings
os.environ["K8S_SECRET_CREDENTIALS"] = "dummy"
os.environ["K8S_SECRET_GOOGLE_AUTH_KEY"] = "dummy_key"
os.environ["ENVIRONMENT"] = "prod"
os.environ["REDIS_DB"] = "1"
class KubectlSecrets(BaseSettings):
credentials: str
google_auth_key: str
class Config:
env_prefix = "K8S_SECRET_"
class EnvSettings(BaseSettings):
environment: str = "development"
redis_db: str = "0"
class Settings:
__dict__ = {}
def __init__(self, *settings):
for s in settings:
self.__dict__.update(s)
for k, v in self.__dict__.items():
setattr(self, k, v)
def __iter__(self):
"""
so `dict(model)` works
"""
yield from self.__dict__.items()
print(KubectlSecrets())
print(EnvSettings())
settings = Settings(KubectlSecrets(), EnvSettings())
print(f"{settings=}")
print(f"{dict(settings)=}")
print(f"{settings.environment=}")
print(f"{settings.redis_db=}") which prints:
Meaning you lose some of the pydantic niceness, but can still access things as attributes on the Settings class, after validation by Pydantic happens. EDIT: Looks like I was a little too slow, and @PrettyWood 's solution looks much better. |
Thank you both guys, super fast response 👌. I had similar solution as @StephenBrown2 but I like solution of @PrettyWood . Again thanks for help 👌 |
Question
Hi, I have problem with joining multiple BaseSettings into one config.
First I tried:
But this going to overwrite prefix and I cannot find k8s secrets
Next I tried
Output:
It is again overwritten by prefix and default values are used, when there is not default val it raises error:
Is there some best practices to join BaseSettings with different prefixes? We want it to get secrets nicely in namespace with multiple services.
I know the solution to use Field, but then I have to use it everywhere (30+ envs) or write it as big dict of fields or rewrite codebase to uses multiple settings.
The text was updated successfully, but these errors were encountered: