From bc931ba790d910efa876f90ed00ecef76313a78b Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Mon, 13 Nov 2017 15:12:23 +0000 Subject: [PATCH] safe check for complex models with env settings --- HISTORY.rst | 3 ++- pydantic/env_settings.py | 10 +++++++++- tests/test_settings.py | 11 ++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 99b52aa..dac6f1b 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -3,9 +3,10 @@ History ------- -v0.6.2 (2017-11-XX) +v0.6.2 (2017-11-13) ................... * errors for invalid validator use +* safer check for complex models in ``Settings`` v0.6.1 (2017-11-08) ................... diff --git a/pydantic/env_settings.py b/pydantic/env_settings.py index 0630463..dabe76e 100644 --- a/pydantic/env_settings.py +++ b/pydantic/env_settings.py @@ -9,6 +9,14 @@ class SettingsError(ValueError): pass +def _complex_field(field): + try: + return field and (field.shape != Shape.SINGLETON or issubclass(field.type_, (BaseModel, list, set, dict))) + except TypeError: + # if field.type_ is not a class + return False + + class BaseSettings(BaseModel): """ Base class for settings, allowing values to be overridden by environment variables. @@ -38,7 +46,7 @@ class BaseSettings(BaseModel): env_name = self.config.env_prefix + field.name.upper() env_var = os.getenv(env_name, None) if env_var: - if field and (field.shape != Shape.SINGLETON or issubclass(field.type_, (BaseModel, list, set, dict))): + if _complex_field(field): try: env_var = json.loads(env_var) except ValueError as e: diff --git a/tests/test_settings.py b/tests/test_settings.py index fd7f5e8..d944b81 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -2,7 +2,7 @@ from typing import List, Set import pytest -from pydantic import BaseModel, BaseSettings, ValidationError +from pydantic import BaseModel, BaseSettings, NoneStr, ValidationError from pydantic.env_settings import SettingsError @@ -92,3 +92,12 @@ def test_required_sub_model(env): env.set('APP_FOOBAR', '{"pips": "TRUE"}') s = Settings() assert s.foobar.pips is True + + +def test_non_class(env): + class Settings(BaseSettings): + foobar: NoneStr + + env.set('APP_FOOBAR', 'xxx') + s = Settings() + assert s.foobar == 'xxx'