Permalink
Browse files

First tests

  • Loading branch information...
1 parent e8fbbb4 commit 3fc0bb9ff311da3290652d9fa6f6fd6e22337d00 @heynemann heynemann committed Aug 1, 2012
Showing with 247 additions and 0 deletions.
  1. +9 −0 LICENSE
  2. +2 −0 Makefile
  3. 0 derpconf/__init__.py
  4. +161 −0 derpconf/config.py
  5. +4 −0 requirements.txt
  6. 0 vows/__init__.py
  7. +71 −0 vows/config_vows.py
View
@@ -0,0 +1,9 @@
+The MIT License
+
+Copyright (c) 2012 globo.com timehome@corp.globo.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
@@ -0,0 +1,2 @@
+test pyvows:
+ @PYTHONPATH=.:$$PYTHONPATH pyvows -v --profile --cover --cover_package=derpconf --cover_threshold=90 vows/
View
No changes.
View
@@ -0,0 +1,161 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# derpconf
+# https://github.com/globocom/derpconf
+
+# Licensed under the MIT license:
+# http://www.opensource.org/licenses/mit-license
+# Copyright (c) 2012 globo.com timehome@corp.globo.com
+
+import os
+import logging
+from collections import defaultdict
+from os.path import join, exists, expanduser, dirname, abspath
+import imp
+
+from textwrap import fill
+
+class ConfigurationError(RuntimeError):
+ pass
+
+class Config(object):
+ class_defaults = {}
+ class_group_items = defaultdict(list)
+ class_groups = []
+ class_descriptions = {}
+
+ class_aliases = defaultdict(list)
+ class_aliased_items = {}
+
+ @classmethod
+ def define(cls, key, value, description, group='General'):
+ cls.class_defaults[key] = value
+ cls.class_descriptions[key] = description
+ cls.class_group_items[group].append(key)
+ if not group in cls.class_groups:
+ cls.class_groups.append(group)
+
+ @classmethod
+ def alias(cls, new_key, aliased_key):
+ if aliased_key in cls.class_aliased_items:
+ aliased_key = cls.class_aliased_items[aliased_key]
+ cls.class_aliases[aliased_key].append(new_key)
+ cls.class_aliased_items[new_key] = aliased_key
+
+ @classmethod
+ def get_conf_file(cls, conf_name, lookup_paths):
+ #lookup_conf_file_paths = [
+ #os.curdir,
+ #expanduser('~'),
+ #'/etc/',
+ #dirname(__file__)
+ #]
+ for conf_path in lookup_paths:
+ conf_path_file = abspath(join(conf_path, conf_name))
+ if exists(conf_path_file):
+ return conf_path_file
+
+ raise ConfigurationError('%s file not passed and not found on the lookup paths %s' % (conf_name, lookup_paths))
+
+ @classmethod
+ def load(cls, path, conf_name=None, lookup_paths=[]):
+ if path is None and conf_name is not None and lookup_paths:
+ path = cls.get_conf_file(conf_name, lookup_paths)
+
+ if not exists(path):
+ raise ConfigurationError('Configuration file not found')
+
+ with open(path) as config_file:
+ name='configuration'
+ code = config_file.read()
+ module = imp.new_module(name)
+ exec code in module.__dict__
+
+ conf = cls()
+ conf.config_file = path
+ for name, value in module.__dict__.iteritems():
+ setattr(conf, name, value)
+
+ return conf
+
+ def __init__(self, **kw):
+ if 'defaults' in kw:
+ self.defaults = kw['defaults']
+
+ for key, value in kw.iteritems():
+ setattr(self, key, value)
+
+ def validates_presence_of(self, *args):
+ for arg in args:
+ if not hasattr(self, arg):
+ raise ConfigurationError('Configuration %s was not found and does not have a default value. Please verify your thumbor.conf file' % arg)
+
+ def get(self, name, default=None):
+ if hasattr(self, name):
+ return getattr(self, name)
+ return default
+
+ def __setattr__(self, name, value):
+ if name in Config.class_aliased_items:
+ logging.warn('Option %s is marked as deprecated please use %s instead.' % (name, Config.class_aliased_items[name]))
+ self.__setattr__(Config.class_aliased_items[name], value)
+ else:
+ super(Config, self).__setattr__(name, value)
+
+ def __getattr__(self, name):
+ if name in self.__dict__:
+ return self.__dict__[name]
+
+ if name in Config.class_aliased_items:
+ logging.warn('Option %s is marked as deprecated please use %s instead.' % (name, Config.class_aliased_items[name]))
+ return self.__getattr__(Config.class_aliased_items[name])
+
+ if 'defaults' in self.__dict__ and name in self.__dict__['defaults']:
+ return self.__dict__['defaults'][name]
+
+ if name in Config.class_defaults:
+ return Config.class_defaults[name]
+
+ raise AttributeError(name)
+
+def generate_config():
+ MAX_LEN = 80
+ SEPARATOR = '#'
+ for group in Config.class_groups:
+ keys = Config.class_group_items[group]
+ sep_size = int(round((MAX_LEN - len(group)) / 2, 0)) - 1
+ group_name = SEPARATOR * sep_size + ' ' + group + ' ' + SEPARATOR * sep_size
+ if len(group_name) < MAX_LEN:
+ group_name += SEPARATOR
+ print group_name
+ for key in keys:
+ print
+ value = Config.class_defaults[key]
+ description = Config.class_descriptions[key]
+
+ wrapped = fill(description, width=78, subsequent_indent='## ')
+
+ print '## %s' % wrapped
+ if key in Config.class_aliases:
+ print '## Aliases: %s' % ', '.join(Config.class_aliases[key])
+ print '## Defaults to: %s' % value
+ print '#%s = %s' % (key, format_value(value))
+ print
+ print SEPARATOR * MAX_LEN
+ print
+ print
+
+def format_value(value):
+ if isinstance(value, basestring):
+ return "'%s'" % value
+ if isinstance(value, (tuple, list, set)):
+ representation = '[\n'
+ for item in value:
+ representation += '# %s' % item
+ representation += '#]'
+ return representation
+ return value
+
+if __name__ == '__main__':
+ generate_config()
View
@@ -0,0 +1,4 @@
+http://gevent.googlecode.com/files/gevent-1.0b2.tar.gz
+tornado-pyvows
+coverage
+colorama
View
No changes.
View
@@ -0,0 +1,71 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# derpconf
+# https://github.com/globocom/derpconf
+
+# Licensed under the MIT license:
+# http://www.opensource.org/licenses/mit-license
+# Copyright (c) 2012 globo.com timehome@corp.globo.com
+
+from os.path import abspath, join, dirname
+
+from pyvows import Vows, expect
+
+from derpconf.config import Config, ConfigurationError
+
+fix = lambda name: abspath(join(dirname(__file__), 'fixtures', name))
+
+@Vows.batch
+class Configuration(Vows.Context):
+ class WhenLoading(Vows.Context):
+ class WhenFileDoesNotExist(Vows.Context):
+ def topic(self):
+ Config.load(fix('not-existent.conf'))
+
+ def should_be_an_error(self, topic):
+ expect(topic).to_be_an_error()
+ expect(topic).to_be_an_error_like(ConfigurationError)
+
+
+ #class WhenSettingAnAlias(Vows.Context):
+
+ #def topic(self):
+ #Config.alias('OTHER_ENGINE', 'ENGINE')
+ #return Config(OTHER_ENGINE='x')
+
+ #def should_set_engine_attribute(self, config):
+ #expect(config.ENGINE).to_equal('x')
+
+ #def should_set_other_engine_attribute(self, config):
+ #expect(config.OTHER_ENGINE).to_equal('x')
+
+ #class WhenSettingAnAliasedKey(Vows.Context):
+ #def topic(self):
+ #Config.alias('LOADER_ALIAS', 'LOADER')
+ #return Config(LOADER='y')
+
+ #def should_set_loader_attribute(self, config):
+ #expect(config.LOADER).to_equal('y')
+
+ #def should_set_loader_alias_attribute(self, config):
+ #expect(config.LOADER_ALIAS).to_equal('y')
+
+ #class WithAliasedAliases(Vows.Context):
+ #def topic(self):
+ #Config.alias('STORAGE_ALIAS', 'STORAGE')
+ #Config.alias('STORAGE_ALIAS_ALIAS', 'STORAGE_ALIAS')
+ #return Config(STORAGE_ALIAS_ALIAS='z')
+
+ #def should_set_storage_attribute(self, config):
+ #expect(config.STORAGE).to_equal('z')
+
+ #def should_set_storage_alias_attribute(self, config):
+ #expect(config.STORAGE_ALIAS).to_equal('z')
+
+ #def should_set_storage_alias_alias_attribute(self, config):
+ #expect(config.STORAGE_ALIAS_ALIAS).to_equal('z')
+
+ #class WithDefaultValues(Vows.Context):
+ #def topic(self):
+ #return Config()

0 comments on commit 3fc0bb9

Please sign in to comment.