--- a/iro/config.py Wed Feb 22 03:47:25 2012 +0100
+++ b/iro/config.py Wed Feb 22 03:48:10 2012 +0100
@@ -1,15 +1,59 @@
from ConfigParser import ConfigParser
+import signal
+from functools import partial
+
+from validate import vInteger
+from error import ValidateException
class Config(ConfigParser):
def __init__(self):
ConfigParser.__init__(self)
self.reloadList=[]
- def reload(self):
- for f in self.reloadlist:
+ def read(self,files):
+ from offer import providers
+ ConfigParser.read(self, files)
+ for s in self.sections():
+ if s == "main":
+ opts=main
+ else:
+ opts=providers[self.get(s,'typ')].options
+
+ for o in opts:
+ try:
+ opts[o].validate(self.get(s,o),o)
+ except ValidateException:
+ if opts[o].must:
+ raise
+
+ def reload_(self):
+ for f in self.reloadList:
f()
def registerReload(self, func):
self.reloadList.append(func)
-
+
+class Option():
+ def __init__(self, validate, long="", help="", must=False, default=None):
+ self.validate = validate
+ self.long=long
+ self.help = help
+ self.must = must
+ self.default = default
+
+def readConfig():
+ config.read(confFiles)
+ config.reload()
+
+def registerSignal():
+ '''register readConfig to SIGUSR2'''
+ def rC(signal, frame):
+ readConfig()
+
+ signal.signal(signal.SIGUSR2,rC)
+
config=Config()
+confFiles=["iro.conf", "~/iro.conf","/etc/iro/iro.conf"]
+main={"hostname":Option(lambda x,y:x,long="Hostname under that twisted is running",must=True),
+ "port":Option(partial(vInteger,minv=0),long="Port under that twisted is running",must=True),
+ }
--- a/tests/config.py Wed Feb 22 03:47:25 2012 +0100
+++ b/tests/config.py Wed Feb 22 03:48:10 2012 +0100
@@ -1,5 +1,86 @@
-from .dbtestcase import DBTestCase
+from mock import patch, Mock
+from twisted.trial import unittest
+import signal
+import io
+import ConfigParser
+from iro import config
+
+class TestConfig(unittest.TestCase):
+ '''test config class'''
+
+ def setUp(self):
+ self._reloadList=config.config.reloadList
+ config.config.reloadlist=[]
+
+ def tearDown(self):
+ config.config.reloadlist = self._reloadList
+
+ @patch('iro.config.config')
+ def testReadConfig(self,pConfig):
+ config.readConfig()
+ self.assertEqual([i[0] for i in pConfig.method_calls],["read","reload"])
+ pConfig.read.assert_called_once_with(config.confFiles)
+ pConfig.reload.assert_called_once_with()
+
+ @patch('signal.signal')
+ @patch('iro.config.readConfig')
+ def testRegisterSignal(self, pReadConfig, pSignal):
+ config.registerSignal()
+ self.assertEqual(pSignal.call_args[0][0],signal.SIGUSR2)
+ self.assertEqual(pReadConfig.called,0)
+ pSignal.call_args[0][1](None, None)
+ pReadConfig.assert_called_once_with()
+
+ def testRegisterReload(self):
+ def x():
+ pass
+ config.config.registerReload(x)
+ self.assertEqual(config.config.reloadList,[x])
-class TestConfig(DBTestCase):
- '''test config class'''
- pass
+ def testReload(self):
+ x = Mock()
+ config.config.reloadList = [x]
+ config.config.reload_()
+ x.assert_called_once_with()
+
+
+class TestRead(unittest.TestCase):
+
+ def tearDown(self):
+ for s in config.config.sections():
+ config.config.remove_section(s)
+
+ @patch('iro.config.ConfigParser.read')
+ def testMain(self,pRead):
+ sample_config = """[main]
+hostname = localhost
+port = 8000
+"""
+ config.config.readfp(io.BytesIO(sample_config))
+ config.config.read([])
+ pRead.assert_called_once_with(config.config,[])
+
+ @patch('iro.config.ConfigParser.read')
+ def testMainBadPort(self,pRead):
+ sample_config = """[main]
+hostname = localhost
+port = -8000
+"""
+ config.config.readfp(io.BytesIO(sample_config))
+ self.assertRaises(config.ValidateException, config.config.read, [])
+
+ @patch('iro.config.ConfigParser.read')
+ def testMainNoMust(self,pRead):
+ sample_config = """[main]
+port = 8000
+"""
+ config.config.readfp(io.BytesIO(sample_config))
+ self.assertRaises(ConfigParser.NoOptionError, config.config.read, [])
+
+ def testMust(self):
+ pass
+ testMust.todo= "To implement"
+
+ def testProviders(self):
+ pass
+ testProviders.todo = "to implement"