Skip to content

Commit

Permalink
added support for configobj
Browse files Browse the repository at this point in the history
  • Loading branch information
twobraids committed Mar 26, 2012
1 parent 61925d4 commit 4989477
Show file tree
Hide file tree
Showing 8 changed files with 382 additions and 41 deletions.
5 changes: 3 additions & 2 deletions configman/config_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,8 +510,9 @@ def _setup_admin_options(self, values_source_list):
base_namespace.admin = admin = Namespace()
admin.add_option(name='print_conf',
default=None,
doc='write current config to stdout '
'(conf, ini, json)',
doc='write current config to stdout (%s)'
% ', '.join(
value_sources.file_extension_dispatch.keys())
)
admin.add_option(name='dump_conf',
default='',
Expand Down
33 changes: 19 additions & 14 deletions configman/tests/test_config_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,20 @@
import os
import unittest
from contextlib import contextmanager
import ConfigParser
import io
from cStringIO import StringIO
import getopt
import ConfigParser

import configman.config_manager as config_manager
from configman.dotdict import DotDict
import configman.datetime_util as dtu
from configman.config_exceptions import NotAnOptionError
from configman.value_sources.source_exceptions import \
AllHandlersFailedException

#from configobj import ConfigObj


class TestCase(unittest.TestCase):

Expand Down Expand Up @@ -517,15 +520,16 @@ def test_overlay_config_9(self):
def test_overlay_config_10(self):
"""test namespace definition ini file"""
n = config_manager.Namespace()
n.add_option('t', 'tee', 'the t')
n.other = config_manager.Namespace()
n.other.add_option('t', 'tee', 'the t')
n.d = config_manager.Namespace()
n.d.add_option('a', 1, 'the a')
n.d.b = 17
n.c = config_manager.Namespace()
n.c.add_option('extra', 3.14159, 'the x')
n.c.add_option('string', 'fred', doc='str')
ini_data = """
[top_level]
[other]
t=tea
[d]
# blank line to be ignored
Expand All @@ -538,7 +542,8 @@ def test_overlay_config_10(self):
config.readfp(io.BytesIO(ini_data))
#g = config_manager.IniValueSource(config)
e = DotDict()
e.t = 'T'
e.other = DotDict()
e.other.t = 'T'
e.d = DotDict()
e.d.a = 16
e.c = DotDict()
Expand All @@ -552,8 +557,8 @@ def test_overlay_config_10(self):
argv_source=['--c.extra', '11.0'],
#use_config_files=False,
use_auto_help=False)
self.assertEqual(c.option_definitions.t.name, 't')
self.assertEqual(c.option_definitions.t.value, 'tea')
self.assertEqual(c.option_definitions.other.t.name, 't')
self.assertEqual(c.option_definitions.other.t.value, 'tea')
self.assertEqual(c.option_definitions.d.a, n.d.a)
self.assertEqual(type(c.option_definitions.d.b), config_manager.Option)
self.assertEqual(c.option_definitions.d.a.value, 22)
Expand Down Expand Up @@ -1109,8 +1114,8 @@ def test_print_conf_some_options_excluded(self):
sys.stdout = old_stdout

printed = temp_output.getvalue()
self.assertTrue('name: gender' in printed)
self.assertTrue('name: salary' not in printed)
self.assertTrue('gender' in printed)
self.assertTrue('salary' not in printed)

def test_dump_conf_some_options_excluded(self):
n = config_manager.Namespace()
Expand All @@ -1131,17 +1136,17 @@ def test_dump_conf_some_options_excluded(self):
use_admin_controls=True,
use_auto_help=False,
quit_after_admin=False,
argv_source=['--admin.dump_conf=foo.ini'],
argv_source=['--admin.dump_conf=foo.conf'],
config_pathname='fred'
)

printed = open('foo.ini').read()
self.assertTrue('name: gender' in printed)
self.assertTrue('name: salary' not in printed)
printed = open('foo.conf').read()
self.assertTrue('gender' in printed)
self.assertTrue('salary' not in printed)

finally:
if os.path.isfile('foo.ini'):
os.remove('foo.ini')
if os.path.isfile('foo.conf'):
os.remove('foo.conf')

def test_config_pathname_set(self):

Expand Down
184 changes: 184 additions & 0 deletions configman/tests/test_val_for_configobj.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is configman
#
# The Initial Developer of the Original Code is
# Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2011
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# K Lars Lohn, lars@mozilla.com
# Peter Bengtsson, peterbe@mozilla.com
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****

import unittest
import os
import tempfile
from cStringIO import StringIO
import contextlib

import configman.datetime_util as dtu
import configman.config_manager as config_manager
try:
from ..value_sources.for_configobj import ValueSource
except ImportError:
# this module is optional. If it doesn't exsit, that's ok, we'll just
# igrore the tests
pass
else:

def stringIO_context_wrapper(a_stringIO_instance):
@contextlib.contextmanager
def stringIS_context_manager():
yield a_stringIO_instance
return stringIS_context_manager


class TestCase(unittest.TestCase):
def _some_namespaces(self):
"""set up some namespaces"""
n = config_manager.Namespace(doc='top')
n.add_option('aaa', '2011-05-04T15:10:00', 'the a',
short_form='a',
from_string_converter=dtu.datetime_from_ISO_string
)
n.c = config_manager.Namespace(doc='c space')
n.c.add_option('fred', 'stupid', 'husband from Flintstones')
n.c.add_option('wilma', 'waspish', 'wife from Flintstones')
n.d = config_manager.Namespace(doc='d space')
n.d.add_option('fred', 'crabby', 'male neighbor from I Love Lucy')
n.d.add_option('ethel', 'silly', 'female neighbor from I Love Lucy')
n.x = config_manager.Namespace(doc='x space')
n.x.add_option('size', 100, 'how big in tons', short_form='s')
n.x.add_option('password', 'secret', 'the password')
return n

def test_for_configobj_basics(self):
"""test basic use of for_configobj"""
tmp_filename = os.path.join(tempfile.gettempdir(), 'test.ini')
open(tmp_filename, 'w').write("""
# comment
name=Peter
awesome=
# comment
[othersection]
foo=bar # other comment
""")

try:
o = ValueSource(tmp_filename)
r = {'othersection': {'foo': 'bar'},
'name': 'Peter',
'awesome': ''}
print o.get_values(None, None)
assert o.get_values(None, None) == r
# in the case of this implementation of a ValueSource,
# the two parameters to get_values are dummies. That may
# not be true for all ValueSource implementations
self.assertEqual(o.get_values(0, False), r)
self.assertEqual(o.get_values(1, True), r)
self.assertEqual(o.get_values(2, False), r)
self.assertEqual(o.get_values(3, True), r)

# XXX (peterbe): commented out because I'm not sure if
# OptionsByIniFile get_values() should depend on the configuration
# manager it is given as first argument or not.
#c = config_manager.ConfigurationManager([],
#use_admin_controls=True,
##use_config_files=False,
#auto_help=False,
#argv_source=[])
#self.assertEqual(o.get_values(c, True), {})
#self.assertRaises(config_manager.NotAnOptionError,
# o.get_values, c, False)

#c.option_definitions.add_option('limit', default=0)
#self.assertEqual(o.get_values(c, False), {'limit': '20'})
#self.assertEqual(o.get_values(c, True), {'limit': '20'})
finally:
if os.path.isfile(tmp_filename):
os.remove(tmp_filename)

def test_for_configobj_basics_2(self):
tmp_filename = os.path.join(tempfile.gettempdir(), 'test.ini')
open(tmp_filename, 'w').write("""
# comment
name=Peter
awesome=
# comment
[othersection]
foo=bar # other comment
""")

try:
o = ValueSource(tmp_filename)
c = config_manager.ConfigurationManager([],
use_admin_controls=True,
#use_config_files=False,
use_auto_help=False,
argv_source=[])

self.assertEqual(o.get_values(c, False),
{'othersection': {'foo': 'bar'},
'name': 'Peter',
'awesome': ''})
self.assertEqual(o.get_values(c, True),
{'othersection': {'foo': 'bar'},
'name': 'Peter',
'awesome': ''})
finally:
if os.path.isfile(tmp_filename):
os.remove(tmp_filename)

def test_write_ini(self):
n = self._some_namespaces()
c = config_manager.ConfigurationManager(
[n],
use_admin_controls=True,
#use_config_files=False,
use_auto_help=False,
argv_source=[]
)
expected = """aaa = 2011-05-04T15:10:00
[x]
password = secret
size = 100
[c]
wilma = waspish
fred = stupid
[d]
ethel = silly
fred = crabby
"""
out = StringIO()
c.write_conf('ini', opener=stringIO_context_wrapper(out))
received = out.getvalue()
out.close()
print received.strip()
print expected.strip()
self.assertEqual(expected.strip(), received.strip())
25 changes: 18 additions & 7 deletions configman/tests/test_val_for_configparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@
import tempfile
from cStringIO import StringIO
import contextlib
import ConfigParser

import configman.datetime_util as dtu
import configman.config_manager as config_manager

from ..value_sources import for_configparse
from ..value_sources.for_configparse import ValueSource


Expand Down Expand Up @@ -75,7 +78,10 @@ def _some_namespaces(self):

def test_for_configparse_basics(self):
"""test basic use of for_configparse"""
tmp_filename = os.path.join(tempfile.gettempdir(), 'test.ini')
tmp_filename = os.path.join(
tempfile.gettempdir(),
'test.%s' % for_configparse.file_name_extension
)
open(tmp_filename, 'w').write("""
; comment
[top_level]
Expand Down Expand Up @@ -120,7 +126,10 @@ def test_for_configparse_basics(self):
os.remove(tmp_filename)

def test_for_configparse_basics_2(self):
tmp_filename = os.path.join(tempfile.gettempdir(), 'test.ini')
tmp_filename = os.path.join(
tempfile.gettempdir(),
'test.%s' % for_configparse.file_name_extension
)
open(tmp_filename, 'w').write("""
; comment
[top_level]
Expand Down Expand Up @@ -155,11 +164,17 @@ def test_write_ini(self):
n = self._some_namespaces()
c = config_manager.ConfigurationManager(
[n],
use_admin_controls=True,
[ConfigParser],
use_admin_controls=False,
#use_config_files=False,
use_auto_help=False,
argv_source=[]
)
out = StringIO()
c.write_conf(for_configparse.file_name_extension,
opener=stringIO_context_wrapper(out))
received = out.getvalue()
out.close()
expected = """[top_level]
# name: aaa
# doc: the a
Expand Down Expand Up @@ -205,8 +220,4 @@ def test_write_ini(self):
# converter: int
size=100
"""
out = StringIO()
c.write_conf('ini', opener=stringIO_context_wrapper(out))
received = out.getvalue()
out.close()
self.assertEqual(expected.strip(), received.strip())
13 changes: 9 additions & 4 deletions configman/value_sources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,23 @@
#import for_xml
import for_getopt
import for_json
import for_configparse
import for_conf
import for_mapping
import for_configparse

# please replace with dynamic discovery
for_handlers = [for_mapping,
for_getopt,
for_json,
for_configparse,
for_conf
for_conf,
for_configparse
]

try:
import for_configobj
for_handlers.append(for_configobj)
except ImportError:
# the module configobj is not loaded, ignore the error
pass

# create a dispatch table of types/objects to modules. Each type should have
# a list of modules that can handle that type.
Expand Down
Loading

0 comments on commit 4989477

Please sign in to comment.