Skip to content
Snippets Groups Projects
Commit b03f7421 authored by André Anjos's avatar André Anjos :speech_balloon:
Browse files

Add test unit; Remove six dep

parent 14e40137
Branches
Tags
1 merge request!54Python-based configuration system (closes #43)
Pipeline #
......@@ -5,7 +5,6 @@
import os
import imp
import six
import collections
import logging
......@@ -53,7 +52,7 @@ def _load_context(path, context):
return dict((k,v) for k,v in retval.__dict__.items() if not k.startswith('_'))
def load(path, context=None):
def load(paths, context=None):
'''Loads a set of configuration files, in sequence
This method will load one or more configuration files. Everytime a
......@@ -63,10 +62,10 @@ def load(path, context=None):
Parameters:
path (:py:class:`str`, :py:class:`list`): The full path of the Python file
to load the module contents from. If an iterable is passed, then it is
iterated and each configuration file is loaded by creating/modifying the
context generated after each file readout.
paths (:py:class:`list`): A list or iterable containing paths (relative or
absolute) of configuration files that need to be loaded in sequence.
Each configuration file is loaded by creating/modifying the context
generated after each file readout.
context (:py:class:`dict`, Optional): If passed, start the readout of the
first configuration file with the given context. Otherwise, create a new
......@@ -80,24 +79,16 @@ def load(path, context=None):
'''
if isinstance(path, six.string_types):
if context is None:
context = dict(defaults={})
else:
if 'defaults' not in context:
context['defaults'] = {}
return _load_context(os.path.realpath(os.path.expanduser(path)), context)
elif isinstance(path, collections.Iterable):
for k in path: context = load(k, context)
return context
if context is None:
context = dict(defaults={})
else:
if 'defaults' not in context:
context['defaults'] = {}
for k in paths:
context = _load_context(os.path.realpath(os.path.expanduser(k)), context)
raise TypeError('path must be either a string or iterable over strings')
return context
def loadrc(context=None):
......@@ -138,4 +129,4 @@ def loadrc(context=None):
logger.debug("No RC file found", path)
return {}
return load(path, context)
return load([path], context)
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
'''Tests for the config module and functionality'''
import os
import pkg_resources
path = pkg_resources.resource_filename('bob.extension', 'data')
from .config import load, loadrc, ENVNAME
def test_basic():
c = load([os.path.join(path, 'basic-config.py')])
assert c == {'a': 1, 'b': 3, 'defaults': {}}
def test_defaults():
c = load([os.path.join(path, 'defaults-config.py')])
assert c == {'defaults': {'bob.db.atnt': {'directory': '/directory/to/root/of/atnt-database', 'extension': '.ppm'} } }
def test_chain_loading():
file1 = os.path.join(path, 'defaults-config.py')
file2 = os.path.join(path, 'load-config.py')
c = load([file1, file2])
assert c == {'defaults': {'bob.db.atnt': {'directory': '/directory/to/root/of/atnt-database', 'extension': '.hdf5'} } }
def test_rc_env():
os.environ[ENVNAME] = os.path.join(path, 'basic-config.py')
c = loadrc() #should load from environment variable
assert c == {'a': 1, 'b': 3, 'defaults': {}}
......@@ -13,7 +13,7 @@ programs while configuring, import modules, create classes and more.
The configuration system is centered around a single function called
:py:func:`bob.extension.config.load`. You call it to load the configuration
objects from a given configuration file, like this:
objects from one or more configuration files, like this:
.. testsetup:: *
......@@ -26,7 +26,7 @@ objects from a given configuration file, like this:
>>> from bob.extension.config import load
>>> #the variable `path` points to <path-to-bob.extension's root>/data
>>> configuration = load(os.path.join(path, 'basic-config.py'))
>>> configuration = load([os.path.join(path, 'basic-config.py')])
If the function :py:func:`bob.extension.config.load` succeeds, it returns a
......@@ -100,7 +100,7 @@ When loaded, this configuration file produces the result:
.. doctest:: defaults-config
>>> #the variable `path` points to <path-to-bob.extension's root>/data
>>> configuration = load(os.path.join(path, 'defaults-config.py'))
>>> configuration = load([os.path.join(path, 'defaults-config.py')])
>>> print(json.dumps(configuration, indent=2, sort_keys=True)) # doctest: +NORMALIZE_WHITESPACE
{
"defaults": {
......@@ -126,9 +126,9 @@ Chain Loading
-------------
It is possible to implement chain configuration loading and overriding by
either calling :py:func:`bob.extension.config.load` many times or by passing
iterables with filenames to that function. Suppose we have two configuration
files which must be loaded in sequence:
passing iterables with more than one filename to
:py:func:`bob.extension.config.load`. Suppose we have two configuration files
which must be loaded in sequence:
.. literalinclude:: ../bob/extension/data/defaults-config.py
:caption: "defaults-config.py" (first to be loaded)
......
......@@ -11,7 +11,7 @@ from setuptools import setup, find_packages
# Define package version
version = open("version.txt").read().rstrip()
requires = ['setuptools', 'six']
requires = ['setuptools']
import sys
if sys.version_info[0] == 2 and sys.version_info[1] <= 6:
requires.append('importlib')
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment