Source code for tzf.pyramid_yml

# Copyright (c) 2013 - 2014 by tzf.pyramid_yml authors and contributors
# <see AUTHORS file>
#
# This module is part of tzf.pyramid_yml and is released under
# the MIT License (MIT): http://opensource.org/licenses/MIT
"""pyramid_yml main functionality."""

import os
import logging

from pyramid.asset import resolve_asset_spec
from pyramid.path import package_path
from pymlconf import ConfigManager

__version__ = '1.0.1'


logger = logging.getLogger(__name__)


[docs]def includeme(configurator): """ Add yaml configuration utilities. :param pyramid.config.Configurator configurator: pyramid's app configurator """ settings = configurator.registry.settings # lets default it to running path yaml_locations = settings.get('yaml.location', settings.get('yml.location', os.getcwd())) configurator.add_directive('config_defaults', config_defaults) configurator.config_defaults(yaml_locations) # reading yml configuration if configurator.registry['config']: config = configurator.registry['config'] logger.debug('Yaml config created') # extend settings object if 'configurator' in config and config.configurator: _extend_settings(settings, config.configurator) # run include's if 'include' in config: _run_includemes(configurator, config.include) # let's calla a convenience request method configurator.add_request_method( lambda request: request.registry['config'], name='config', property=True )
[docs]def config_defaults( configurator, config_locations, files=['config.yaml', 'config.yml']): """ Read and extends/creates configuration from yaml source. .. note:: If exists, this method extends config with defaults, so it will not override existing values, merely add those, that were not defined already! :param pyramid.config.Configurator configurator: pyramid's app configurator :param list config_locations: list of yaml file locations :param list files: list of files to include from location """ if not isinstance(config_locations, (list, tuple)): config_locations = config_locations.split(',') env = configurator.registry.settings.get('env', 'dev') file_paths = [] for location in config_locations: path = _translate_config_path(location) current_files = files if os.path.isfile(path): path, current_files = os.path.split(path) current_files = [current_files] for config_path in [ os.path.join(path, f) for f in _env_filenames(current_files, env) ]: if os.path.isfile(config_path): file_paths.append(config_path) config = ConfigManager(files=file_paths) # we could use this method both for creating and extending. # Hence the checks to not override if 'config' not in configurator.registry: configurator.registry['config'] = config else: config.merge(configurator.registry['config']) configurator.registry['config'] = config
def _translate_config_path(location): """ Translate location into fullpath according asset specification. Might be package:path for package related paths, or simply path :param str location: resource location :returns: fullpath :rtype: str """ # getting spec path package_name, filename = resolve_asset_spec(location.strip()) if not package_name: path = filename else: package = __import__(package_name) path = os.path.join(package_path(package), filename) return path def _env_filenames(filenames, env): """ Extend filenames with ennv indication of environments. :param list filenames: list of strings indicating filenames :param str env: environment indicator :returns: list of filenames extended with environment version :rtype: list """ env_filenames = [] for filename in filenames: filename_parts = filename.split('.') filename_parts.insert(1, env) env_filenames.extend([filename, '.'.join(filename_parts)]) return env_filenames def _extend_settings(settings, configurator_config, prefix=None): """ Extend settings dictionary with content of yaml's configurator key. .. note:: This methods changes multilayered subkeys defined within **configurator** into dotted keys in settings dictionary: .. code-block:: yaml configurator: sqlalchemy: url: mysql://user:password@host/dbname will result in **sqlalchemy.url**: mysql://user:password@host/dbname key value in settings dictionary. :param dict settings: settings dictionary :param dict configurator_config: yml defined settings :param str prefix: prefix for settings dict key """ for key in configurator_config: settings_key = '.'.join([prefix, key]) if prefix else key if hasattr(configurator_config[key], 'keys') and\ hasattr(configurator_config[key], '__getitem__'): _extend_settings( settings, configurator_config[key], prefix=settings_key ) else: settings[settings_key] = configurator_config[key] def _run_includemes(configurator, includemes): """ Automatically include packages defined in **include** configuration key. :param pyramid.config.Configurator configurator: pyramid's app configurator :param dict includemes: include, a list of includes or dictionary """ for include in includemes: if includemes[include]: try: configurator.include(include, includemes[include]) except AttributeError: configurator.include(include)