-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
27 changed files
with
1,655 additions
and
1,516 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
#!/usr/bin/env python2 | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 | ||
|
||
# Copyright (C) 2010 Stefan Hacker <[email protected]> | ||
|
@@ -29,40 +29,42 @@ | |
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
|
||
import ConfigParser | ||
import configparser | ||
import types | ||
|
||
|
||
class Config(object): | ||
""" | ||
Small abstraction for config loading | ||
""" | ||
|
||
def __init__(self, filename = None, default = None): | ||
def __init__(self, filename=None, default=None): | ||
if (filename and not default) or \ | ||
(not filename and not default): return | ||
sections = set(default.iterkeys()) | ||
(not filename and not default): return | ||
|
||
sections = set(default.keys()) | ||
if filename: | ||
cfg = ConfigParser.RawConfigParser() | ||
cfg = configparser.RawConfigParser() | ||
cfg.optionxform = str | ||
with open(filename) as f: | ||
cfg.readfp(f) | ||
cfg.read_file(f) | ||
sections.update(cfg.sections()) | ||
|
||
for section in sections: | ||
if type(section) == types.FunctionType: continue | ||
|
||
if isinstance(section, types.FunctionType): | ||
continue | ||
|
||
match = None | ||
for default_section in default.iterkeys(): | ||
for default_section in default.keys(): | ||
try: | ||
if section == default_section or \ | ||
(type(default_section) == types.FunctionType and default_section(section)): | ||
(isinstance(default_section, types.FunctionType) and default_section(section)): | ||
match = default_section | ||
break | ||
except ValueError: | ||
continue | ||
if match == None: | ||
|
||
if match is None: | ||
continue | ||
|
||
optiondefaults = default[match] | ||
|
@@ -74,7 +76,7 @@ def __init__(self, filename = None, default = None): | |
else: | ||
try: | ||
self.__dict__[section] = cfg.items(section) | ||
except ConfigParser.NoSectionError: | ||
except configparser.NoSectionError: | ||
self.__dict__[section] = [] | ||
else: | ||
self.__dict__[section] = Config() | ||
|
@@ -84,42 +86,46 @@ def __init__(self, filename = None, default = None): | |
else: | ||
try: | ||
self.__dict__[section].__dict__[name] = conv(cfg.get(section, name)) | ||
except (ValueError, ConfigParser.NoSectionError, ConfigParser.NoOptionError): | ||
except (ValueError, configparser.NoSectionError, configparser.NoOptionError): | ||
self.__dict__[section].__dict__[name] = vdefault | ||
|
||
def __getitem__(self, key): | ||
return self.__dict__.__getitem__(key) | ||
|
||
def __contains__(self, key): | ||
return self.__dict__.__contains__(key) | ||
|
||
|
||
def x2bool(s): | ||
""" | ||
Helper function to convert strings from the config to bool | ||
""" | ||
if isinstance(s, bool): | ||
return s | ||
elif isinstance(s, basestring): | ||
elif isinstance(s, str): | ||
return s.strip().lower() in ['1', 'true'] | ||
raise ValueError() | ||
|
||
|
||
def commaSeperatedIntegers(s): | ||
""" | ||
Helper function to convert a string from the config | ||
containing comma seperated integers into a list of integers | ||
""" | ||
return map(int, s.split(',')) | ||
return list(map(int, s.split(','))) | ||
|
||
|
||
def commaSeperatedStrings(s): | ||
""" | ||
Helper function to convert a string from the config | ||
containing comma seperated strings into a list of strings | ||
""" | ||
return map(str.strip, s.split(',')) | ||
return list(map(str.strip, s.split(','))) | ||
|
||
|
||
def commaSeperatedBool(s): | ||
""" | ||
Helper function to convert a string from the config | ||
containing comma seperated strings into a list of booleans | ||
""" | ||
return map(x2bool, s.split(',')) | ||
return list(map(x2bool, s.split(','))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
#!/usr/bin/env python2 | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 | ||
|
||
# Copyright (C) 2010 Stefan Hacker <[email protected]> | ||
|
@@ -29,25 +29,28 @@ | |
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
|
||
import unittest | ||
from config import Config, x2bool, commaSeperatedIntegers, commaSeperatedStrings, commaSeperatedBool | ||
from tempfile import mkstemp | ||
import os | ||
import re | ||
import unittest | ||
from tempfile import mkstemp | ||
|
||
def create_file(content = None): | ||
from config import Config, x2bool, commaSeperatedIntegers, commaSeperatedStrings, commaSeperatedBool | ||
|
||
|
||
def create_file(content=None): | ||
""" | ||
Creates a temp file filled with 'content' and returns its path. | ||
The file has to be manually deleted later on | ||
""" | ||
fd, path = mkstemp() | ||
f = os.fdopen(fd, "wb") | ||
if content: | ||
f.write(content) | ||
f.write(content.encode()) | ||
f.flush() | ||
f.close() | ||
return path | ||
|
||
|
||
class ConfigTest(unittest.TestCase): | ||
cfg_content = """[world] | ||
domination = True | ||
|
@@ -62,92 +65,91 @@ class ConfigTest(unittest.TestCase): | |
[Server_2] | ||
value = True | ||
""" | ||
cfg_default = {'world':(('domination', x2bool, False), | ||
('somestr', str, "fail"), | ||
('somenum', int, 0), | ||
('somenumtest', int, 1), | ||
('blubber', str, "empty"), | ||
('serverregex', re.compile, '.*')), | ||
(lambda x: re.match("Server_\d+",x)):(('value', x2bool, True),), | ||
'somethingelse':(('bla', str, "test"),)} | ||
|
||
cfg_default = {'world': (('domination', x2bool, False), | ||
('somestr', str, "fail"), | ||
('somenum', int, 0), | ||
('somenumtest', int, 1), | ||
('blubber', str, "empty"), | ||
('serverregex', re.compile, '.*')), | ||
(lambda x: re.match("Server_\d+", x)): (('value', x2bool, True),), | ||
'somethingelse': (('bla', str, "test"),)} | ||
|
||
def setUp(self): | ||
pass | ||
|
||
def tearDown(self): | ||
pass | ||
|
||
|
||
def testEmpty(self): | ||
path = create_file() | ||
try: | ||
cfg = Config(path, self.cfg_default) | ||
assert(cfg.world.domination == False) | ||
assert(cfg.world.somestr == "fail") | ||
assert(cfg.world.somenum == 0) | ||
assert (cfg.world.domination == False) | ||
assert (cfg.world.somestr == "fail") | ||
assert (cfg.world.somenum == 0) | ||
self.assertRaises(AttributeError, getattr, cfg.world, "testfallbacknum") | ||
assert(cfg.somethingelse.bla == "test") | ||
assert (cfg.somethingelse.bla == "test") | ||
finally: | ||
os.remove(path) | ||
|
||
def testX2bool(self): | ||
assert(x2bool(" true") == True) | ||
assert(x2bool("false") == False) | ||
assert(x2bool(" TrUe") == True) | ||
assert(x2bool("FaLsE ") == False) | ||
assert(x2bool("0 ") == False) | ||
assert(x2bool("1") == True) | ||
assert(x2bool(" 10") == False) | ||
assert(x2bool("notabool") == False) | ||
assert (x2bool(" true") == True) | ||
assert (x2bool("false") == False) | ||
assert (x2bool(" TrUe") == True) | ||
assert (x2bool("FaLsE ") == False) | ||
assert (x2bool("0 ") == False) | ||
assert (x2bool("1") == True) | ||
assert (x2bool(" 10") == False) | ||
assert (x2bool("notabool") == False) | ||
|
||
def testCommaSeperatedIntegers(self): | ||
assert(commaSeperatedIntegers(" 1,2 , 333 ") == [1,2,333]) | ||
assert (commaSeperatedIntegers(" 1,2 , 333 ") == [1, 2, 333]) | ||
self.assertRaises(ValueError, commaSeperatedIntegers, "1,2,a") | ||
|
||
def testCommaSeperatedStrings(self): | ||
assert(commaSeperatedStrings("Bernd, the, bred !") == ["Bernd", "the", "bred !"]) | ||
assert (commaSeperatedStrings("Bernd, the, bred !") == ["Bernd", "the", "bred !"]) | ||
|
||
def testCommaSeperatedBool(self): | ||
assert(commaSeperatedBool("tRue ,false, 0, 0, 1,1, test") == [True, False, False, False, True, True, False]) | ||
assert (commaSeperatedBool("tRue ,false, 0, 0, 1,1, test") == [True, False, False, False, True, True, False]) | ||
|
||
def testConfig(self): | ||
path = create_file(self.cfg_content) | ||
try: | ||
try: | ||
cfg = Config(path, self.cfg_default) | ||
except Exception, e: | ||
print e | ||
assert(cfg.world.domination == True) | ||
assert(cfg.world.somestr == "Blabla") | ||
assert(cfg.world.somenum == 10) | ||
except Exception as e: | ||
print(e) | ||
assert (cfg.world.domination == True) | ||
assert (cfg.world.somestr == "Blabla") | ||
assert (cfg.world.somenum == 10) | ||
self.assertRaises(AttributeError, getattr, cfg.world, "testfallbacknum") | ||
self.assertEqual(cfg.world.blubber, "Things %(doesnotexistsasdefault)s") | ||
self.assertEqual(cfg.world.serverregex, re.compile("^\[[\w\d\-\(\):]{1,20}\]$")) | ||
assert(cfg.somethingelse.bla == "test") | ||
assert(cfg.Server_10.value == False) | ||
assert(cfg.Server_2.value == True) | ||
assert(cfg.Server_9.value == True) | ||
assert (cfg.somethingelse.bla == "test") | ||
assert (cfg.Server_10.value == False) | ||
assert (cfg.Server_2.value == True) | ||
assert (cfg.Server_9.value == True) | ||
finally: | ||
os.remove(path) | ||
|
||
def testLoadDefault(self): | ||
cfg = Config(default=self.cfg_default) | ||
assert(cfg.world.domination == False) | ||
assert(cfg.somethingelse.bla == "test") | ||
assert(cfg.world.somenum == 0) | ||
assert (cfg.world.domination == False) | ||
assert (cfg.somethingelse.bla == "test") | ||
assert (cfg.world.somenum == 0) | ||
|
||
def testGetItem(self): | ||
cfg = Config(default=self.cfg_default) | ||
assert(cfg["world"]["domination"] == False) | ||
assert("world" in cfg) | ||
assert (cfg["world"]["domination"] == False) | ||
assert ("world" in cfg) | ||
|
||
def invalidaccess(c): | ||
c["nointhisconfig"] | ||
|
||
self.assertRaises(KeyError, invalidaccess, cfg) | ||
|
||
|
||
if __name__ == "__main__": | ||
#import sys;sys.argv = ['', 'Test.testName'] | ||
# import sys;sys.argv = ['', 'Test.testName'] | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
# No real module, just here to keep pydev and its | ||
# test runner happy. | ||
# test runner happy. |
Oops, something went wrong.