import configparser
from flask import request
from pydantic import ValidationError
from toolchest.yaml import parse
from flask_container_scaffold.base import BaseApiView
# TODO: extract this method out to toolchest library.
[docs]
def load_yaml(filename='config.yml', logger=None):
"""
Convenience wrapper around toolchest.yaml::parse to allow you to parse a
file by path+name
:param str filename: A yaml file to be parsed
:param Logger logger: Optional logger for potential errors
:return: A dictionary formed out of the yaml data
"""
config = {}
with open(filename, 'r') as file_handle:
config = parse(file_handle, logger=logger)
return config
[docs]
def load_cfg(conf_file):
"""
Load a cfg file
:param str conf_file: A cfg/ini file to be parsed
:return: A dictionary formed out of the cfg file data
:raises: configparser.MissingSectionHeaderError, FileNotFoundError
"""
config = configparser.ConfigParser()
# The following setting tells the parser not to alter the keys it
# has read in. The default behavior converts these to lowercase:
# https://docs.python.org/3/library/configparser.html#configparser.ConfigParser.optionxform
config.optionxform = lambda option: option
with open(conf_file) as conf:
config.read_file(conf)
return _parse_cfg(config)
def _parse_cfg(config):
config_dict = {}
for section in config.sections():
settings_dict = {}
for key in config[section]:
settings_dict[key] = config[section][key]
config_dict.update({section: settings_dict})
return config_dict
def _preprocess_request() -> dict:
"""
Checks the various places in a request that could contain parameters, and
extracts them into a dictionary that can then be used for further parsing.
This dictionary should contain no duplicates, and chooses what to use based
on the following rules:
1. If a request contains both parameters embedded in the url (like
endpoint/1) AND
* json data, they will be preferred in this order:
- url-embedded
- json data
* query string and/or form data, they will be preferred in this order:
- url-embedded
- query string
- form data
2. If a request contains both json data AND either query strings or form
data, only the json will be parsed. However, Flask currently prevents this
from happening, as it will not allow a user to pass both types of data at
the same time. The `curl` command is similarly mutually exclusive.
:returns: dict containing the parsed parameters
"""
processed_request = {}
# Check for URL Parameters
if request.view_args:
processed_request = request.view_args
# If the request has json input, parse that and combine with URL
# parameters, preferring the latter.
if request.is_json:
processed_request = {**request.json, **processed_request}
else:
# Check in query-string for additional parameters. Prefer any that were
# previously found in URL parameters.
if request.args:
processed_request = {**request.args.to_dict(), **processed_request}
# Check in form for additional parameters. Prefer any that were previously
# found in URL parameters or query-string.
if request.form:
processed_request = {**request.form.to_dict(), **processed_request}
return processed_request