Skip to content
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

BaseSettings: Environment variable is not loaded in nested model if defined in Field() #27

Closed
5 of 15 tasks
RafaelWO opened this issue Jan 25, 2023 · 4 comments
Closed
5 of 15 tasks

Comments

@RafaelWO
Copy link

Initial Checks

  • I have searched GitHub for a duplicate issue and I'm sure this is something new
  • I have searched Google & StackOverflow for a solution and couldn't find anything
  • I have read and followed the docs and still think this is a bug
  • I am confident that the issue is with pydantic (not my code, or another library in the ecosystem like FastAPI or mypy)

Description

I have a class BaseSettings with a nested BaseModel. Within the nested model (named nested), I defined a variable with sub_var1: str = Field(..., env="SUB_VAR") (as mentioned in the docs).

I would expect that the environment variable name specified in the nested Field is loaded from my .env file. But it's not (see the example below). My .env file looks as follows:

MAIN_VAR=main
SUB_VAR=sub

It only works with env_nested_delimiter='__' and an environment variable NESTED__SUB_VAR1 but I would expect it to work with SUB_VAR (as it's set in the Field).

I'm not sure if this is a bug or expected behavior. If it's the latter I'm doing a feature request, I guess.

Example Code

from pydantic import BaseSettings, BaseModel, Field


class SubModel(BaseModel):
    sub_var1: str = Field(..., env="SUB_VAR")
    sub_var2: str = "bar"


class Settings(BaseSettings):
    main_var: str = Field(..., env="MAIN_VAR")
    nested: SubModel

    class Config:
        env_file = '.env'
        env_nested_delimiter = '__'


print(Settings().dict())

Python, Pydantic & OS Version

pydantic version: 1.10.4
            pydantic compiled: True
                 install path: /home/rafael/miniconda3/envs/ds/lib/python3.8/site-packages/pydantic
               python version: 3.8.13 (default, Mar 28 2022, 11:38:47)  [GCC 7.5.0]
                     platform: Linux-5.15.0-58-generic-x86_64-with-glibc2.17
     optional deps. installed: ['dotenv', 'typing-extensions']

Affected Components

@RafaelWO RafaelWO changed the title BaseSettings: Environment variable is not loaded in nested model if set in Field() BaseSettings: Environment variable is not loaded in nested model if defined in Field() Jan 25, 2023
@samuelcolvin
Copy link
Member

samuelcolvin commented Jan 25, 2023

Thanks for reporting.

Looks like env isn't recognised in sub models, as you say it works with NESTED__SUB_VAR1.

if this is simple to fix in V1.10, happy to accept a PR. We should also make sure this is fixed in V2 with the new pydantic-settings package.

@RafaelWO
Copy link
Author

if this is simple to fix in V1.10, happy to accept a PR

Does this mean I would have to create a branch from 1.10.X-fixes and then also a PR to this branch? AFAIK, the settings management was removed in main.

Sorry, I haven't contributed yet to this great project 🙃

@hramezani
Copy link
Member

if this is simple to fix in V1.10, happy to accept a PR

Does this mean I would have to create a branch from 1.10.X-fixes and then also a PR to this branch? AFAIK, the settings management was removed in main.

Sorry, I haven't contributed yet to this great project upside_down_face

Yes, you need to create a PR based on 1.10.X-fixes

@hramezani
Copy link
Member

I would expect that the environment variable name specified in the nested Field is loaded from my .env file. But it's not

I think it shouldn't work like you expect because you are initializing Settings model and sub_var1 is a field in the nested model.

FYI, pydantic-settings now is a separate package and is in alpha state. you can install it by pip install pydantic-settings --pre and test it.

Here is your example in pydantic-settings:

from pydantic import BaseModel, ConfigDict, Field
from pydantic_settings import BaseSettings


class SubModel(BaseModel):
    sub_var1: str = Field(validation_alias="SUB_VAR")
    sub_var2: str = "bar"


class Settings(BaseSettings):
    main_var: str = Field(validation_alias="MAIN_VAR")
    nested: SubModel

    model_config = ConfigDict(env_file='.env', env_nested_delimiter='__')


print(Settings().model_dump())

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants