Skip to content

Commit

Permalink
Correctly working singleton for configuration
Browse files Browse the repository at this point in the history
Update the way the 'singleton' decorator works. Now aims to result in a
single state, not a single instance. The previous design pattern caused
problems in testing (we maintained a single instance of `config`
throughout the entire test suite, which led to test failure when running
test_config - the `config` instance was instantiated in KDEOrigin.
  • Loading branch information
wcarthur committed Nov 2, 2015
1 parent 8304ca0 commit 2cfa206
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 22 deletions.
6 changes: 3 additions & 3 deletions StatInterface/KDEOrigin.py
Expand Up @@ -79,12 +79,12 @@ def __init__(self, configFile, gridLimit, kdeStep, lonLat=None,
self.cz = None

self.configFile = configFile
config = ConfigParser()
config.read(configFile)
self.config = ConfigParser()
self.config.read(configFile)

if lonLat is None:
# Load the data from file:
self.outputPath = config.get('Output', 'Path')
self.outputPath = self.config.get('Output', 'Path')
self.processPath = pjoin(self.outputPath, 'process')
LOGGER.debug("Loading " + pjoin(self.processPath, 'init_lon_lat'))
ll = flLoadFile(pjoin(self.processPath, 'init_lon_lat'), '%', ',')
Expand Down
36 changes: 20 additions & 16 deletions Utilities/config.py
Expand Up @@ -231,23 +231,27 @@ def formatList(lst):
filename=slp.day.ltm.nc
"""


def singleton(cls):
instances = {}

def getinstance(*args, **kwargs):
"""
Retrieve an instance of a class. If one (instantiated with
the provided args & kwargs) does not exist, then
create an instance and return it.
"""

if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return getinstance
"""
Actually a Borg!
Ensure only a single state for all instances of the class
See http://code.activestate.com/recipes/66531/#c30 - I added the _drop()
method to permit clean up in testing frameworks.
"""
cls._state = {}
originit = cls.__init__
def newinit(self, *args, **kwargs):
self.__dict__ = cls._state
originit(self, *args, **kwargs)
def _drop(self):
cls._state = {}
self.__dict__ = {}

cls._drop = _drop
cls.__init__ = newinit
return cls

@singleton
class ConfigParser(RawConfigParser):
Expand All @@ -262,7 +266,7 @@ def __init__(self, defaults=DEFAULTS):
RawConfigParser.__init__(self)
self.readfp(io.BytesIO(defaults))
self.readonce = False

def geteval(self, section, option):
"""
:param str section: Section name to evaluate.
Expand Down
3 changes: 3 additions & 0 deletions tests/test_KDEOrigin.py
Expand Up @@ -32,6 +32,9 @@ def setUp(self):
lonLat = cPickle.load(open(os.path.join(unittest_dir, 'test_data', 'kde_origin_lonLat.pck')))
self.kdeOrigin = KDEOrigin.KDEOrigin(None, gridLimit, kdeStep, lonLat)

def tearDown(self):
self.kdeOrigin.config._drop()

def test_GenerateKDE(self):
"""Testing GenerateKDE for 2D data"""
pkl_file = open(os.path.join(unittest_dir, 'test_data', 'kdeOrigin_xyz.pck'), 'r')
Expand Down
8 changes: 5 additions & 3 deletions tests/test_config.py
Expand Up @@ -43,7 +43,10 @@ def setUp(self):
self.evalopt = {'x':1.0,'y':0.5}
self.listopt1 = ["A", "B", "C", "D", "E"]
self.listopt2 = ["A"]


def tearDown(self):
self.config._drop()

def test_geteval(self):
"""Test geteval returns correct object"""
self.assertIsInstance(self.config.geteval('Evaluate', 'Option'), dict)
Expand All @@ -56,7 +59,7 @@ def test_geteval(self):
class TestOldStyleConfig(unittest.TestCase):
def setUp(self):
self.configFile = pjoin(unittest_dir, 'test_data', 'test_config.ini')

def test_cnfReadIniValue(self):
self.assertEqual(config.cnfGetIniValue(self.configFile, 'Integer', 'Option1'), 1)
self.assertEqual(config.cnfGetIniValue(self.configFile, 'Integer', 'Option2'), 10)
Expand All @@ -69,7 +72,6 @@ def test_cnfReadIniValue(self):
self.assertEqual(config.cnfGetIniValue(self.configFile, 'String', 'Option'), 'randomstring')
self.assertEqual(config.cnfGetIniValue(self.configFile, 'Evaluate', 'Option'), {'x':1.0,'y':0.5})


def test_returnDefault(self):
self.assertEqual(config.cnfGetIniValue(self.configFile, 'Integer', 'Option3', 1), 1)
self.assertEqual(config.cnfGetIniValue(self.configFile, 'String', 'Option2', 'otherstring'), 'otherstring')
Expand Down

0 comments on commit 2cfa206

Please sign in to comment.