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

env source: superflous deep env conflicts with non-dict model #275

Closed
diefans opened this issue Apr 23, 2024 · 0 comments · Fixed by #276 or #281
Closed

env source: superflous deep env conflicts with non-dict model #275

diefans opened this issue Apr 23, 2024 · 0 comments · Fixed by #276 or #281
Assignees

Comments

@diefans
Copy link
Contributor

diefans commented Apr 23, 2024

If you define a nested model with a leaf annotated as a string and have deeper nesting environment variables in place, an exception is raised:

class NestedSettings(BaseModel):
    foo: str

class Settings(BaseSettings):
    model_config = SettingsConfigDict(env_nested_delimiter='__')

    nested: NestedSettings
export nested__foo=string
export nested__foo__bar=conflicts_with_string

Exception:

Traceback (most recent call last):
  File "/home/olli/code/bm/pydantic-settings/tests/foo.py", line 40, in <module>
    s = Settings()
        ^^^^^^^^^^
  File "/home/olli/code/bm/pydantic-settings/pydantic_settings/main.py", line 108, in __init__
    **__pydantic_self__._settings_build_values(
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/olli/code/bm/pydantic-settings/pydantic_settings/main.py", line 215, in _settings_build_values
    return deep_update(*reversed([source() for source in sources]))
                                  ^^^^^^^^
  File "/home/olli/code/bm/pydantic-settings/pydantic_settings/sources.py", line 326, in __call__
    field_value = self.prepare_field_value(field_name, field, field_value, value_is_complex)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/olli/code/bm/pydantic-settings/pydantic_settings/sources.py", line 517, in prepare_field_value
    env_val_built = self.explode_env_vars(field_name, field, self.env_vars)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/olli/code/bm/pydantic-settings/pydantic_settings/sources.py", line 641, in explode_env_vars
    env_var[last_key] = env_val
    ~~~~~~~^^^^^^^^^^
TypeError: 'str' object does not support item assignment
diefans added a commit to bettermarks/pydantic-settings that referenced this issue Apr 23, 2024
If a model defines a leaf as e.g. a string and the user or system sets
an environment var with an additional `env_nested_delimiter + suffix`,
`explode_env_vars` was treating the string as a `dict` (trying to add an
item to it).

This fix checks if the target is indeed a `dict`.

In that regard, the whole `explode_env_vars` seems a bit wasteful, in
terms of possible throwing away already computed values, if a deeper
environment variable is processed earlier (which is possible, since the
iteration order of `os.environ` seems unpredictable).

resolves pydantic#275
diefans added a commit to bettermarks/pydantic-settings that referenced this issue Apr 23, 2024
If a model defines a leaf as e.g. a string and the user or system sets
an environment var with an additional `env_nested_delimiter + suffix`,
`explode_env_vars` was treating the string as a `dict` (trying to add an
item to it).

This fix checks if the target is indeed a `dict`.

In that regard, the whole `explode_env_vars` seems a bit wasteful, in
terms of possible throwing away already computed values, if a deeper
environment variable is processed earlier (which is possible, since the
iteration order of `os.environ` seems unpredictable).

resolves pydantic#275
diefans added a commit to bettermarks/pydantic-settings that referenced this issue Apr 23, 2024
If a model defines a leaf as e.g. a string and the user or system sets
an environment var with an additional `env_nested_delimiter + suffix`,
`explode_env_vars` was treating the string as a `dict` (trying to add an
item to it).

This fix checks if the target is indeed a `dict`.

In that regard, the whole `explode_env_vars` seems a bit wasteful, in
terms of possible throwing away already computed values, if a deeper
environment variable is processed earlier (which is possible, since the
iteration order of `os.environ` seems unpredictable).

resolves pydantic#275
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment