Newer
Older
Chandrasekhar Ramakrishnan
committed
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
config.py
Configuration for obis.
Created by Chandrasekhar Ramakrishnan on 2017-02-10.
Copyright (c) 2017 Chandrasekhar Ramakrishnan. All rights reserved.
"""
Chandrasekhar Ramakrishnan
committed
import os
Chandrasekhar Ramakrishnan
committed
class ConfigLocation(object):
"""Path for configuration information."""
Chandrasekhar Ramakrishnan
committed
def __init__(self, desc, root, basename):
Chandrasekhar Ramakrishnan
committed
"""
Chandrasekhar Ramakrishnan
committed
:param desc: A description for the location in the form of a list of keys.
Chandrasekhar Ramakrishnan
committed
:param root: The root for the path
Chandrasekhar Ramakrishnan
committed
:param basename: The name of the folder for this location.
Chandrasekhar Ramakrishnan
committed
"""
self.desc = desc
self.root = root
Chandrasekhar Ramakrishnan
committed
self.basename = basename
Chandrasekhar Ramakrishnan
committed
class ConfigParam(object):
"""Class for configuration parameters."""
def __init__(self, name, private):
Chandrasekhar Ramakrishnan
committed
"""
:param name: Name of the parameter.
:param private: Should the parameter be private to the repo or visible in the data set?
Chandrasekhar Ramakrishnan
committed
"""
self.name = name
self.private = private
Chandrasekhar Ramakrishnan
committed
class ConfigEnv(object):
"""The environment in which configurations are constructed."""
def __init__(self):
self.locations = {}
self.params = {}
self.initialize_locations()
self.initialize_params()
def initialize_locations(self):
Chandrasekhar Ramakrishnan
committed
self.add_location(ConfigLocation(['global'], 'user_home', '.obis'))
self.add_location(ConfigLocation(['local', 'public'], 'data_set', '.obis'))
self.add_location(ConfigLocation(['local', 'private'], 'data_set', '.git/obis'))
Chandrasekhar Ramakrishnan
committed
def add_location(self, loc):
Chandrasekhar Ramakrishnan
committed
desc = loc.desc
depth = len(desc) - 1
locations = self.locations
for i, sub_desc in enumerate(desc):
if i == depth:
locations[sub_desc] = loc
else:
if locations.get(sub_desc) is None:
locations[sub_desc] = {}
Chandrasekhar Ramakrishnan
committed
locations = locations[sub_desc]
Chandrasekhar Ramakrishnan
committed
def initialize_params(self):
self.add_param(ConfigParam(name='openbis_url', private=True))
self.add_param(ConfigParam(name='user', private=False))
self.add_param(ConfigParam(name='data_set_type', private=True))
self.add_param(ConfigParam(name='data_set_properties', private=True))
Chandrasekhar Ramakrishnan
committed
def add_param(self, param):
self.params[param.name] = param
def default_location_resolver(location):
"""Given a location, return a path"""
if location.root == 'user_home':
root = os.path.expanduser('~')
else:
# The remaining case is data_set -- find the root of the data set we are in
root = './'
return os.path.join(root, location.basename)
Chandrasekhar Ramakrishnan
committed
class ConfigResolver(object):
"""Construct a config dictionary."""
def __init__(self, env=None, location_resolver=None):
self.env = env if env is not None else ConfigEnv()
self.location_resolver = location_resolver if location_resolver is not None else default_location_resolver
self.location_search_order = ['global', 'local']
self.location_cache = {}
self.initialize_location_cache()
def initialize_location_cache(self):
env = self.env
for k, v in env.locations.items():
self.initialize_location(k, v, self.location_cache)
def initialize_location(self, key, loc, cache):
cache[key] = {} # Default value is empty dict
if isinstance(loc, dict):
for k, v in loc.items():
self.initialize_location(k, v, cache[key])
else:
root_path = self.location_resolver(loc)
config_path = os.path.join(root_path, 'config.json')
if os.path.exists(config_path):
with open(config_path) as f:
config = json.load(f)
cache[key] = config
Chandrasekhar Ramakrishnan
committed
def config_dict(self):
"""Return a configuration dictionary by applying the lookup/resolution rules."""
env = self.env
result = {}
# Iterate over the locations in the specified order searching for parameter values.
# Later entries override earlier.
for name, param in env.params.items():
result[name] = None
for l in self.location_search_order:
val = self.value_for_parameter(param, l)
if val is not None:
result[name] = val
return result
def value_for_parameter(self, param, loc):
config = self.location_cache[loc]
if loc != 'global':
if param.private:
config = config['private']
else:
config = config['public']
return config.get(param.name)