Skip to content

Commit

Permalink
fix: Ruff code quality checks correction for config.py
Browse files Browse the repository at this point in the history
  • Loading branch information
rv2931 committed Feb 29, 2024
1 parent e1145e4 commit fc9a323
Showing 1 changed file with 66 additions and 40 deletions.
106 changes: 66 additions & 40 deletions bloom/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,51 +4,55 @@

from pydantic import BaseSettings

def extract_values_from_env(config:dict,allow_extend:bool=False):
def extract_values_from_env(config:dict,allow_extend:bool=False) -> dict:
""" function that extrat key=value pairs from a file
Parameters:
- config: dict to extend/update with new key/value pairs found in environment
- allow_extend: allows to extend extracted keys with new keys that are not in actuel config if True,
restrict to already existing keys in config of False
- allow_extend: allows to extend extracted keys with new keys that are not in
actuel config if True, restrict to already existing keys in config of False
Returns a dict contains key/value
"""
for k,v in os.environ.items():
# Processing of indirect affectation via [ATTR]_FILE=VALUE_PATH => ATTR=VALUE
if k in [f"{k}_FILE" for k in config.keys()]\
and ( k.removesuffix('_FILE') in config.keys() or allow_extend == True):
if(os.path.isfile(v)):
file = open(v, mode='r')
config[k.removesuffix('_FILE')]=file.readline().strip()
and ( k.removesuffix('_FILE') in config.keys() or allow_extend == True)\
and Path(v).is_file():
with Path.open(v, mode='r') as file:
config[k.removesuffix('_FILE')]=file.readline().strip()
# Processing of direct affectation via ATTR=VALUE
# if extracted key already exist in config OR if allowed to add new keys to config
# Then adding/updating key/value
if k in config.keys() or allow_extend == True:
config[k]=v
return config

def extract_values_from_file(filename:str,config:dict,allow_extend:bool=False,env_priority=True):
def extract_values_from_file(filename:str,config:dict,
allow_extend:bool=False,
env_priority:bool=True
)-> dict:
""" function that extrat key=value pairs from a file
Parameters:
- filename: filename/filepath from which to extract key/value pairs found in .env.* file
- config: dict to extend/update with new key/value pairs
- allow_extend: allows to extend extracted keys with new keys that are not in actuel config if True,
restrict to already existing keys in config of False
- allow_extend: allows to extend extracted keys with new keys that are not in actuel
config if True, restrict to already existing keys in config of False
Returns a dict contains key/value
"""
FILEPATH=Path(os.path.dirname(__file__)).joinpath(filename)
for l in open(FILEPATH):
# Split line at first occurence of '='. This allows to have values containing '=' character
split=l.strip().split('=',1)
filepath=Path(Path(__file__).parent).joinpath(filename)
for line in open(filepath):
# Split line at first occurence of '='.
# This allows to have values containing '=' character
split=line.strip().split('=',1)
# if extraction contains 2 items and strictly 2 items
if(len(split)==2):
k=split[0]
v=split[1]
# Processing of indirect affectation via [ATTR]_FILE=VALUE_PATH => ATTR=VALUE
if k in [f"{k}_FILE" for k in config.keys()]\
and ( k.removesuffix('_FILE') in config.keys() or allow_extend == True):
if(os.path.isfile(v)):
file = open(v, mode='r')
config[k.removesuffix('_FILE')]=file.readline().strip()
and ( k.removesuffix('_FILE') in config.keys() or allow_extend == True)\
and Path(v).is_file():
with Path.open(v, mode='r') as file:
config[k.removesuffix('_FILE')]=file.readline().strip()
# if extracted key already exist in config OR if allowed to add new keys to config
# Then adding/updating key/value
if k in config.keys() or allow_extend == True:
Expand All @@ -65,46 +69,66 @@ def __init__(self,*arg, **args):
# dict to store temporary/overrided config parameters
config={}

# Here we extract value according to PHP Symfony Framework principles (https://symfony.com/doc/current/configuration.html#configuration-based-on-environment-variable)
# Here we extract value according to PHP Symfony Framework principles:
# See: https://symfony.com/doc/current/configuration.html
# See Section configuration-based-on-environment-variable
# The idea is to load sequentialy
# - .env (for default values and common values for all runtime environment dev/test/prod/...). APP_ENV has to be defined here as default env (APP_ENV='dev' i.e.)
# - .env (default values and common values for all environments dev/test/prod/...).
# APP_ENV has to be defined here as default env (APP_ENV='dev' i.e.)
# - .env.local (for local common overrided values)
# - .env.${APP_ENV} (for default values for the specific environment APP_ENV defined and overrided before)
# - .env.${APP_ENV} (default values for the specific environment APP_ENV defined
# and overrided before)
# - .env.${APP_ENV}.local (for local APP_ENV specific values)
#
# Some princpales are coming with that:
# - All configuration variables presents in theses files MUST be declare in .env file. If not they won't be accessible in application.
# This is a good way to have a file containging all parameters avialables, don't hésitate to document them in .env
# - All default files (.env, .env.APP_ENV) are optional but not ignored by git if created
# - All local files (*.local) are optionel and ignored by git if created so theses files are specific and locl to deployment platform
# - All configuration variables presents in theses files MUST be declare in .env file.
# If not they won't be accessible in application.
# This is a good way to have a file containging all parameters avialables,
# don't hésitate to document them in .env.template
# - All default files (.env, .env.APP_ENV) are optional but not ignored
# by git if created
# - All local files (*.local) are optionel and ignored by git if created so theses
# files are specific and locl to deployment platform

# In addition we impement the Docker standard that manage configuration base on files AND enviornment variables
# - At each previous step, key=value pairs found in files are systematically override by its equivalent in environment variables if this one has been declared in env vars
# This mecanism is usefull when deploying application in Docker as docker specific values can override files configuration just by adding env vars
# - All attributes can be set by a direct KEY=VALUE pair or indirectly by adding a _FILE suffix to the name of the KEY, this KEY_FILE pointing to a file local to the deployment system that will give the final value to the attribute
# In addition we impement the Docker standard that manage configuration base on files
# AND environment variables
# - At each previous step, key=value pairs found in files are systematically override
# by its equivalent in environment variables if this one has been declared in env vars
# This mecanism is usefull when deploying application in Docker as docker specific
# values can override files configuration just by adding env vars
# - All attributes can be set by a direct KEY=VALUE pair or indirectly by adding
# a _FILE suffix to the name of the KEY, this KEY_FILE pointing to a file local to
# the deployment system that will give the final value to the attribute
# - Exemple: POSTGRES_PASSWORD_FILE=/run/secrets/postgres_password will give a

# Extract .env.template as default values
file_to_process=Path(os.path.dirname(__file__)).joinpath(f"../.env")
if os.path.isfile(file_to_process):
file_to_process=Path(Path(__file__).parent).joinpath(f"../.env")
if Path(file_to_process).is_file():
extract_values_from_file(file_to_process,config,allow_extend=True,env_priority=True)

# Extract .env.local and override existing values
file_to_process=Path(os.path.dirname(__file__)).joinpath(f"../.env.local")
if os.path.isfile(file_to_process):
extract_values_from_file(file_to_process,config,allow_extend=False,env_priority=True)
file_to_process=Path(Path(__file__).parent).joinpath(f"../.env.local")
if Path(file_to_process).is_file():
extract_values_from_file(file_to_process,config,allow_extend=False,
env_priority=True)

# if APP_ENV has been defined
if 'APP_ENV' in config:
# Extract .env.${APP_ENV} and override existing values
file_to_process=Path(os.path.dirname(__file__)).joinpath(f"../.env.{config['APP_ENV']}")
if os.path.isfile(file_to_process): extract_values_from_file(file_to_process,config,allow_extend=False,env_priority=True)
file_to_process=Path(Path(__file__).parent).joinpath(f"../.env.{config['APP_ENV']}")
if Path(file_to_process).is_file():
extract_values_from_file(file_to_process,config,allow_extend=False,
env_priority=True)

# Extract .env.${APP_ENV}.local and override existing values
file_to_process=Path(os.path.dirname(__file__)).joinpath(f"../.env.{config['APP_ENV']}.local")
if os.path.isfile(file_to_process): extract_values_from_file(file_to_process,config,allow_extend=False,env_priority=True)
file_to_process=Path(Path(__file__).parent)\
.joinpath(f"../.env.{config['APP_ENV']}.local")
if Path(file_to_process).is_file():
extract_values_from_file(file_to_process,config,allow_extend=False,
env_priority=True)

# Now we extract key/value pairs from config and add/update them to current class Settings class as attributes
# Now we extract key/value pairs from config and add/update them to current
# class Settings class as attributes
# All attributes declared in template
self.__dict__.update(config)

Expand All @@ -126,7 +150,9 @@ def __init__(self,*arg, **args):
print(f"writing {PATH_ENV}")
f = open(PATH_ENV, "w")
f.truncate(0)
f.write("# This file was generated automaticaly by bloom.config\n# Don't modify values directly here\n# Use .env.* files instead then restart application\n")
f.write("# This file was generated automaticaly by bloom.config\n"
"# Don't modify values directly here\n"
"# Use .env.* files instead then restart application\n")
for k,v in config.items():
f.write(f"{k}={v}\n")
f.close()
Expand Down

0 comments on commit fc9a323

Please sign in to comment.