Source code for khoros.utils.helper

# -*- coding: utf-8 -*-
"""
:Module:            khoros.utils.helper
:Synopsis:          Module that allows the khoros library to leverage a helper configuration file
:Usage:             ``from khoros.utils import helper``
:Example:           ``helper_settings = helper.get_settings('/tmp/helper.yml', 'yaml')``
:Created By:        Jeff Shurtliff
:Last Modified:     Jeff Shurtliff
:Modified Date:     12 Mar 2022
"""

import json

import yaml

from .. import errors
from . import log_utils
from .core_utils import get_file_type

# Initialize logging within the module
logger = log_utils.initialize_logging(__name__)


[docs] def import_helper_file(file_path, file_type): """This function imports a YAML (.yml) or JSON (.json) helper config file. .. versionchanged:: 3.3.0 A log entry was added to report when the helper file has been imported successfully. .. versionchanged:: 2.2.0 Changed the name and replaced the ``yaml.load`` function call with ``yaml.safe_load`` to be more secure. :param file_path: The file path to the YAML file :type file_path: str :param file_type: Defines the file type as either ``yaml`` or ``json`` :type file_type: str :returns: The parsed configuration data :raises: :py:exc:`FileNotFoundError`, :py:exc:`khoros.errors.exceptions.InvalidHelperFileTypeError` """ with open(file_path, 'r') as cfg_file: if file_type == 'yaml': helper_cfg = yaml.safe_load(cfg_file) elif file_type == 'json': helper_cfg = json.load(cfg_file) else: raise errors.exceptions.InvalidHelperFileTypeError() logger.info(f'The helper file {file_path} was imported successfully.') return helper_cfg
def _convert_yaml_to_bool(_yaml_bool_value): """This function converts the 'yes' and 'no' YAML values to traditional Boolean values.""" true_values = ['yes', 'true'] if _yaml_bool_value.lower() in true_values: _bool_value = True else: _bool_value = False return _bool_value def _get_connection_info(_helper_cfg): """This function parses any connection information found in the helper file. .. versionchanged:: 5.0.0 Added function call to parse the Bulk Data API connection information .. versionchanged:: 2.2.0 Removed one of the preceding underscores in the function name """ _connection_info = {} _connection_keys = ['community_url', 'tenant_id', 'default_auth_type'] for _key in _connection_keys: if _key in _helper_cfg['connection']: _connection_info[_key] = _helper_cfg['connection'][_key] # Parse OAuth 2.0 information if found if 'oauth2' in _helper_cfg['connection']: _connection_info['oauth2'] = _get_oauth2_info(_helper_cfg) # Parse session authentication information if found if 'session_auth' in _helper_cfg['connection']: _connection_info['session_auth'] = _get_session_auth_info(_helper_cfg) # Parse Bulk Data API information if found if 'bulk_data' in _helper_cfg['connection']: _connection_info['bulk_data'] = _get_bulk_data_info(_helper_cfg) return _connection_info def _get_oauth2_info(_helper_cfg): """This function parses OAuth 2.0 information if found in the helper file. .. versionchanged:: 2.2.0 Removed one of the preceding underscores in the function name """ _oauth2 = {} _oauth2_keys = ['client_id', 'client_secret', 'redirect_url'] for _key in _oauth2_keys: if _key in _helper_cfg['connection']['oauth2']: _oauth2[_key] = _helper_cfg['connection']['oauth2'][_key] else: _oauth2[_key] = '' return _oauth2 def _get_session_auth_info(_helper_cfg): """This function parses session authentication information if found in the helper file. .. versionchanged:: 2.2.0 Removed one of the preceding underscores in the function name """ _session_auth = {} _session_info = ['username', 'password'] for _key in _session_info: if _key in _helper_cfg['connection']['session_auth']: _session_auth[_key] = _helper_cfg['connection']['session_auth'][_key] else: _session_auth[_key] = None return _session_auth def _get_bulk_data_info(_helper_cfg): """This function parses the Bulk Data API connection information if found in the helper file. .. versionadded:: 5.0.0 """ _bulk_data = {} _bulk_data_fields = ['community_id', 'client_id', 'token', 'europe'] if 'bulk_data' in _helper_cfg['connection']: # Populate the fields for _field in _bulk_data_fields: if _field in _helper_cfg['connection']['bulk_data']: _bulk_data[_field] = _helper_cfg['connection']['bulk_data'][_field] elif _field == 'europe': _bulk_data[_field] = False else: _bulk_data[_field] = None # Define the base URL value if 'europe' in _bulk_data and _bulk_data.get('europe') is True: _bulk_data['base_url'] = f'https://eu.api.lithium.com/lsi-data/v2/data/export/community/' else: _bulk_data['base_url'] = f'https://api.lithium.com/lsi-data/v2/data/export/community/' if _bulk_data.get('community_id'): _bulk_data['base_url'] = f'{_bulk_data["base_url"]}{_bulk_data.get("community_id")}' return _bulk_data def _get_discussion_styles(_helper_cfg): """This function defines (when present in the configuration) the enabled discussion styles in the environment. :param _helper_cfg: The configuration parsed from the helper configuration file :type _helper_cfg: dict :returns: List of enabled discussion styles in the environment """ _discussion_styles = ['blog', 'contest', 'forum', 'idea', 'qanda', 'tkb'] if 'discussion_styles' in _helper_cfg: if isinstance(_helper_cfg.get('discussion_styles'), list): _discussion_styles = _helper_cfg.get('discussion_styles') return _discussion_styles def _get_construct_info(_helper_cfg): """This function parses settings that can be leveraged in constructing API responses and similar tasks. .. versionchanged:: 2.8.0 The function was refactored to leverage the :py:func:`khoros.utils.helper._collect_values` function. .. versionchanged:: 2.2.0 Removed one of the preceding underscores in the function name :param _helper_cfg: The configuration parsed from the helper configuration file :type _helper_cfg: dict :returns: A dictionary with the key value pair for the ``prefer_json`` key if found in the config file """ _top_level_keys = ['prefer_json'] return _collect_values(_top_level_keys, _helper_cfg) def _collect_values(_top_level_keys, _helper_cfg, _helper_dict=None, _ignore_missing=False): """This function loops through a list of top-level keys to collect their corresponding values. .. versionchanged:: 3.4.0 This function now supports the ``ssl_verify`` key and defines a default value when not found. .. versionadded:: 2.8.0 :param _top_level_keys: One or more top-level keys that might be found in the helper config file :type _top_level_keys: list, tuple, set, str :param _helper_cfg: The configuration parsed from the helper configuration file :type _helper_cfg: dict :param _helper_dict: A predefined dictionary to which the key value pairs should be added :type _helper_dict: dict, None :param _ignore_missing: Indicates whether or not fields with null values should be ignored (``False`` by default) :type _ignore_missing: bool :returns: A dictionary with the identified key value pairs """ _helper_dict = {} if not _helper_dict else _helper_dict _top_level_keys = (_top_level_keys, ) if isinstance(_top_level_keys, str) else _top_level_keys for _key in _top_level_keys: if _key in _helper_cfg: _key_val = _helper_cfg[_key] if _key_val in HelperParsing.yaml_boolean_values: _key_val = HelperParsing.yaml_boolean_values.get(_key_val) _helper_dict[_key] = _key_val elif _key == "ssl_verify": # Verify SSL certificates by default unless explicitly set to false _helper_dict[_key] = True else: if not _ignore_missing: _helper_dict[_key] = None return _helper_dict
[docs] def get_helper_settings(file_path, file_type='yaml', defined_settings=None): """This function returns a dictionary of the defined helper settings. .. versionchanged:: 4.3.0 Fixed an issue where the ``ssl_verify`` field was being overridden even if defined elsewhere. .. versionchanged:: 3.4.0 This function now supports the ``ssl_verify`` key and defines a default value when not found. .. versionchanged:: 2.8.0 The function was updated to capture the ``translate_errors`` value when defined. .. versionchanged:: 2.2.0 Support was added for JSON-formatted helper configuration files. :param file_path: The file path to the helper configuration file :type file_path: str :param file_type: Defines the helper configuration file as a ``yaml`` file (default) or a ``json`` file :type file_type: str :param defined_settings: Core object settings (if any) defined via the ``defined_settings`` parameter :type defined_settings: dict, None :returns: Dictionary of helper variables :raises: :py:exc:`khoros.errors.exceptions.InvalidHelperFileTypeError` """ # Initialize the helper_settings dictionary helper_settings = {} # Convert the defined_settings parameter to an empty dictionary if null defined_settings = {} if not defined_settings else defined_settings if file_type != 'yaml' and file_type != 'json': file_type = get_file_type(file_path) # Import the helper configuration file helper_cfg = import_helper_file(file_path, file_type) # Populate the connection information in the helper dictionary if 'connection' in helper_cfg and 'connection' not in defined_settings: helper_settings['connection'] = _get_connection_info(helper_cfg) # Populate the construct information in the helper dictionary helper_settings['construct'] = _get_construct_info(helper_cfg) # Populate the enabled discussion styles in the helper dictionary helper_settings['discussion_styles'] = _get_discussion_styles(helper_cfg) # Populate the SSL certificate verification setting in the helper dictionary if 'ssl_verify' not in defined_settings: helper_settings.update(_collect_values('ssl_verify', helper_cfg)) # Populate the error translation setting in the helper dictionary helper_settings.update(_collect_values('translate_errors', helper_cfg, _ignore_missing=True)) # Return the helper_settings dictionary return helper_settings
[docs] class HelperParsing: """This class is used to help parse values imported from a YAML configuration file.""" # Define dictionary to map YAML Boolean to Python Boolean yaml_boolean_values = { True: True, False: False, 'yes': True, 'no': False }