[pypy-svn] r29777 - in pypy/dist/pypy/config: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Fri Jul 7 21:42:28 CEST 2006


Author: cfbolz
Date: Fri Jul  7 21:42:24 2006
New Revision: 29777

Modified:
   pypy/dist/pypy/config/config.py
   pypy/dist/pypy/config/test/test_config.py
Log:
prevent changing of a frozen config object. add hash and equality to config


Modified: pypy/dist/pypy/config/config.py
==============================================================================
--- pypy/dist/pypy/config/config.py	(original)
+++ pypy/dist/pypy/config/config.py	Fri Jul  7 21:42:24 2006
@@ -8,6 +8,7 @@
         config is divided in groups, each group is an instance on the root
         (this object)
     """
+    _frozen = False
     
     def __init__(self, descr, **overrides):
         self._descr = descr
@@ -25,6 +26,8 @@
             setattr(self, name, value)
 
     def __setattr__(self, name, value):
+        if self._frozen:
+            raise TypeError("trying to change a frozen option object")
         if name.startswith('_'):
             self.__dict__[name] = value
             return
@@ -44,6 +47,9 @@
         child.setoption(self, value)
         self._value_owners[name] = who
 
+    def require(self, name, value):
+        self.setoption(name, value, "required")
+
     def _get_by_path(self, path):
         """returns tuple (config, name)"""
         path = path.split('.')
@@ -52,8 +58,21 @@
         return self, path[-1]
 
     def _freeze_(self):
+        self._frozen = True
         return True
 
+    def getkey(self):
+        return self._descr.getkey(self)
+
+    def __hash__(self):
+        return hash(self.getkey())
+
+    def __eq__(self, other):
+        return self.getkey() == other.getkey()
+
+    def __ne__(self, other):
+        return not self == other
+
 class Option(object):
     def validate(self, value):
         raise NotImplementedError('abstract base class')
@@ -67,6 +86,9 @@
             raise ValueError('invalid value %s for option %s' % (value, name))
         config.__dict__[name] = value
 
+    def getkey(self, value):
+        return value
+
 class ChoiceOption(Option):
     def __init__(self, name, doc, values, default):
         self._name = name
@@ -86,9 +108,10 @@
         name = self._name
         for path, reqvalue in self._requires:
             subconfig, name = config._get_by_path(path)
-            subconfig.setoption(name, reqvalue, 'required')
+            subconfig.require(name, reqvalue)
         super(BoolOption, self).setoption(config, value)
 
+
 class ListOption(Option):
     def __init__(self, name, doc, allowed_values, default=None):
         self._name = name
@@ -106,6 +129,11 @@
     def getdefault(self):
         return self.default[:]
 
+    def getkey(self, value):
+        key = value[:]
+        value.sort()
+        return tuple(value)
+
 class OptionDescription(object):
     def __init__(self, name, children):
         self._name = name
@@ -115,3 +143,7 @@
     def _build(self):
         for child in self._children:
             setattr(self, child._name, child)
+
+    def getkey(self, config):
+        return tuple([child.getkey(getattr(config, child._name))
+                      for child in self._children])

Modified: pypy/dist/pypy/config/test/test_config.py
==============================================================================
--- pypy/dist/pypy/config/test/test_config.py	(original)
+++ pypy/dist/pypy/config/test/test_config.py	Fri Jul  7 21:42:24 2006
@@ -1,7 +1,7 @@
 from pypy.config.config import *
 import py
 
-def test_base_config():
+def make_description():
     gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref')
     objspaceoption = ChoiceOption('objspace', 'Object space', 
                                 ['std', 'logic'], 'std')
@@ -15,6 +15,11 @@
     gcgroup = OptionDescription('gc', [gcoption])
     descr = OptionDescription('pypy', [gcgroup, booloption, objspaceoption,
                                         listoption, wantref_option])
+    return descr
+    
+
+def test_base_config():
+    descr = make_description()
     config = Config(descr, bool=False)
     
     assert config.gc.name == 'ref'
@@ -43,6 +48,7 @@
     config.wantref = True
     assert config.gc.name == 'ref'
     py.test.raises(ValueError, 'config.gc.name = "framework"')
+    config.gc.name = "ref"
 
 def test_annotator_folding():
     from pypy.translator.interactive import Translation
@@ -67,3 +73,17 @@
     assert len(block.exits) == 1
     assert block.operations[0].opname == 'int_add'
 
+    # the config should be frozen now
+    py.test.raises(TypeError, 'config.gc.name = "framework"')
+
+def test_compare_configs():
+    descr = make_description()
+    conf1 = Config(descr)
+    conf2 = Config(descr, wantref=True)
+    assert conf1 != conf2
+    assert hash(conf1) != hash(conf2)
+    assert conf1.getkey() != conf2.getkey()
+    conf1.wantref = True
+    assert conf1 == conf2
+    assert hash(conf1) == hash(conf2)
+    assert conf1.getkey() == conf2.getkey()



More information about the Pypy-commit mailing list