mirror of
https://github.com/kennethreitz/pydantic.git
synced 2026-06-05 23:00:18 +00:00
feat: add support for case insensitive env names (#313)
* feat: add support for case insensitive env names Closes #277 * feedback: just alias os.environ * doc: update history * doc: mention case_insensitive option * refactor: feedback if-else expression assignment * fix: formatting * chore: encode black configuration in file to support IDEs * docs: fix example * feedback: no suppport for IDEs in this PR * feedback: style
This commit is contained in:
committed by
Samuel Colvin
parent
94706bc834
commit
a0aa9e78cd
@@ -8,6 +8,7 @@ v0.16.0 (2018-XX-XX)
|
||||
|
||||
* refactor schema generation to be compatible with JSON Schema and OpenAPI specs, #308 by @tiangolo
|
||||
* add ``schema`` to ``schema`` module to generate top-level schemas from base models, #308 by @tiangolo
|
||||
* add ``case_insensitive`` option to ``BaseSettings`` ``Config``, #277 by @jasonkuhrt
|
||||
|
||||
v0.15.0 (2018-11-18)
|
||||
....................
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
from pydantic import BaseSettings
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
redis_host = 'localhost'
|
||||
|
||||
class Config:
|
||||
case_insensitive = True
|
||||
+7
-1
@@ -231,7 +231,7 @@ Outputs:
|
||||
|
||||
The generated schemas are compliant with the specifications:
|
||||
`JSON Schema Core <https://json-schema.org/latest/json-schema-core.html>`__,
|
||||
`JSON Schema Validation <https://json-schema.org/latest/json-schema-validation.html>`__ and
|
||||
`JSON Schema Validation <https://json-schema.org/latest/json-schema-validation.html>`__ and
|
||||
`OpenAPI <https://github.com/OAI/OpenAPI-Specification>`__.
|
||||
|
||||
``BaseModel.schema`` will return a dict of the schema, while ``BaseModel.schema_json`` will return a JSON string
|
||||
@@ -459,6 +459,12 @@ Here ``redis_port`` could be modified via ``export MY_PREFIX_REDIS_PORT=6380`` o
|
||||
|
||||
Complex types like ``list``, ``set``, ``dict`` and submodels can be set by using JSON environment variables.
|
||||
|
||||
Environment variables can be read in a case insensitive manner:
|
||||
|
||||
.. literalinclude:: examples/settings_case_insensitive.py
|
||||
|
||||
Here ``redis_port`` could be modified via ``export APP_REDIS_HOST``, ``export app_redis_host``, ``export app_REDIS_host``, etc.
|
||||
|
||||
Dynamic model creation
|
||||
......................
|
||||
|
||||
|
||||
@@ -21,7 +21,9 @@ class BaseSettings(BaseModel):
|
||||
"""
|
||||
Base class for settings, allowing values to be overridden by environment variables.
|
||||
|
||||
Environment variables must be upper case. Eg. to override foobar, `export APP_FOOBAR="whatever"`.
|
||||
Environment variables must be upper case and prefixed by APP_ by default. Eg. to override foobar,
|
||||
`export APP_FOOBAR="whatever"`. To change this behaviour set Config options case_insensitive and
|
||||
env_prefix.
|
||||
|
||||
This is useful in production for secrets you do not wish to save in code, it places nicely with docker(-compose),
|
||||
Heroku and any 12 factor app design.
|
||||
@@ -36,23 +38,34 @@ class BaseSettings(BaseModel):
|
||||
Substitute environment variables into values.
|
||||
"""
|
||||
d = {}
|
||||
|
||||
if self.__config__.case_insensitive:
|
||||
env_vars = {k.lower(): v for (k, v) in os.environ.items()}
|
||||
else:
|
||||
env_vars = os.environ
|
||||
|
||||
for field in self.__fields__.values():
|
||||
|
||||
if field.has_alias:
|
||||
env_name = field.alias
|
||||
else:
|
||||
env_name = self.__config__.env_prefix + field.name.upper()
|
||||
env_var = os.getenv(env_name, None)
|
||||
if env_var:
|
||||
|
||||
env_name_ = env_name.lower() if self.__config__.case_insensitive else env_name
|
||||
env_val = env_vars.get(env_name_, None)
|
||||
|
||||
if env_val:
|
||||
if _complex_field(field):
|
||||
try:
|
||||
env_var = json.loads(env_var)
|
||||
env_val = json.loads(env_val)
|
||||
except ValueError as e:
|
||||
raise SettingsError(f'error parsing JSON for "{env_name}"') from e
|
||||
d[field.alias] = env_var
|
||||
d[field.alias] = env_val
|
||||
return d
|
||||
|
||||
class Config:
|
||||
env_prefix = 'APP_'
|
||||
env_prefix = "APP_"
|
||||
validate_all = True
|
||||
ignore_extra = False
|
||||
arbitrary_types_allowed = True
|
||||
case_insensitive = False
|
||||
|
||||
@@ -110,3 +110,18 @@ def test_alias_matches_name(env):
|
||||
env.set('foobar', 'xxx')
|
||||
s = Settings()
|
||||
assert s.foobar == 'xxx'
|
||||
|
||||
|
||||
def test_case_insensitive(env):
|
||||
class Settings(BaseSettings):
|
||||
foo: str
|
||||
bAR: str
|
||||
|
||||
class Config:
|
||||
case_insensitive = True
|
||||
|
||||
env.set('apP_foO', 'foo')
|
||||
env.set('app_bar', 'bar')
|
||||
s = Settings()
|
||||
assert s.foo == 'foo'
|
||||
assert s.bAR == 'bar'
|
||||
|
||||
Reference in New Issue
Block a user