optimisations and all is properties
[tiramisu.git] / tiramisu / setting.py
index 7477fd9..1c1e8db 100644 (file)
 # the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
 # the whole pypy projet is under MIT licence
 # ____________________________________________________________
+
+
 class _const:
     """convenient class that emulates a module
     and builds constants (that is, unique names)"""
-    class ConstError(TypeError): pass
+    class ConstError(TypeError):
+        pass
 
     def __setattr__(self, name, value):
-        if self.__dict__.has_key(name):
-            raise self.ConstError, "Can't rebind group (%s)"%name
+        if name in self.__dict__:
+            raise self.ConstError, "Can't rebind group ({})".format(name)
         self.__dict__[name] = value
 
     def __delattr__(self, name):
-        if self.__dict__.has_key(name):
-            raise self.ConstError, "Can't unbind group (%s)"%name
-        raise NameError, name
+        if name in self.__dict__:
+            raise self.ConstError, "Can't unbind group ({})".format(name)
+        raise NameError(name)
+
+
 # ____________________________________________________________
 class GroupModule(_const):
     "emulates a module to manage unique group (OptionDescription) names"
@@ -42,6 +47,7 @@ class GroupModule(_const):
         *normal* means : groups that are not master
         """
         pass
+
     class DefaultGroupType(GroupType):
         """groups that are default (typically 'default')"""
         pass
@@ -54,6 +60,7 @@ class GroupModule(_const):
 # setting.groups (emulates a module)
 groups = GroupModule()
 
+
 def populate_groups():
     "populates the available groups in the appropriate namespaces"
     groups.master = groups.MasterGroupType('master')
@@ -62,6 +69,8 @@ def populate_groups():
 
 # names are in the module now
 populate_groups()
+
+
 # ____________________________________________________________
 class OwnerModule(_const):
     """emulates a module to manage unique owner names.
@@ -72,12 +81,14 @@ class OwnerModule(_const):
         """allowed owner names
         """
         pass
+
     class DefaultOwner(Owner):
         """groups that are default (typically 'default')"""
         pass
 # setting.owners (emulates a module)
 owners = OwnerModule()
 
+
 def populate_owners():
     """populates the available owners in the appropriate namespaces
 
@@ -85,7 +96,8 @@ def populate_owners():
     - 'default' is the config owner after init time
     """
     setattr(owners, 'default', owners.DefaultOwner('default'))
-    setattr(owners,'user', owners.Owner('user'))
+    setattr(owners, 'user', owners.Owner('user'))
+
     def add_owner(name):
         """
         :param name: the name of the new owner
@@ -96,18 +108,23 @@ def populate_owners():
 # names are in the module now
 populate_owners()
 
+
 class MultiTypeModule(_const):
     class MultiType(str):
         pass
+
     class DefaultMultiType(MultiType):
         pass
+
     class MasterMultiType(MultiType):
         pass
+
     class SlaveMultiType(MultiType):
         pass
 
 multitypes = MultiTypeModule()
 
+
 def populate_multitypes():
     setattr(multitypes, 'default', multitypes.DefaultMultiType('default'))
     setattr(multitypes, 'master', multitypes.MasterMultiType('master'))
@@ -115,123 +132,114 @@ def populate_multitypes():
 
 populate_multitypes()
 
+
 #____________________________________________________________
-class Setting():
+class Setting(object):
     "``Config()``'s configuration options"
-    # properties attribute: the name of a property enables this property
-    properties = ['hidden', 'disabled']
-    # overrides the validations in the acces of the option values
-    permissive = []
-    # a mandatory option must have a value that is not None
-    mandatory = True
-    frozen = True
-    # enables validation function for options if set
-    validator = False
-    # generic owner
-    owner = owners.user
-    # in order to freeze everything, not **only** the frozen options
-    everything_frozen = False
-    # enables at build time to raise an exception if the option's name
-    # has the name of a config's method
-    valid_opt_names = True
+    __slots__ = ('properties', 'permissives', 'owner')
+
+    def __init__(self):
+        # properties attribute: the name of a property enables this property
+        # key is None for global properties
+        self.properties = {None: []}  # ['hidden', 'disabled', 'mandatory', 'frozen', 'validator']}
+        # permissive properties
+        self.permissives = {}
+        # generic owner
+        self.owner = owners.user
+
     #____________________________________________________________
     # properties methods
-    def has_properties(self):
+    def has_properties(self, opt=None):
         "has properties means the Config's properties attribute is not empty"
-        return bool(len(self.properties))
-
+        return bool(len(self.get_properties(opt)))
 
-    def get_properties(self):
-        return self.properties
+    def get_properties(self, opt=None):
+        if opt is None:
+            default = []
+        else:
+            default = list(opt._properties)
+        return self.properties.get(opt, default)
 
-    def has_property(self, propname):
+    def has_property(self, propname, opt=None):
         """has property propname in the Config's properties attribute
         :param property: string wich is the name of the property"""
-        return propname in self.properties
+        return propname in self.get_properties(opt)
 
     def enable_property(self, propname):
         "puts property propname in the Config's properties attribute"
-        if propname not in self.properties:
-            self.properties.append(propname)
+        props = self.get_properties()
+        if propname not in props:
+            props.append(propname)
+        self.set_properties(props)
 
     def disable_property(self, propname):
         "deletes property propname in the Config's properties attribute"
-        if self.has_property(propname):
-            self.properties.remove(propname)
+        props = self.get_properties()
+        if propname in props:
+            props.remove(propname)
+        self.set_properties(props)
+
+    def set_properties(self, properties, opt=None):
+        """save properties for specified opt
+        (never save properties if same has option properties)
+        """
+        if opt is None:
+            self.properties[opt] = properties
+        else:
+            if opt._properties == properties:
+                if opt in self.properties:
+                    del(self.properties[opt])
+            else:
+                self.properties[opt] = properties
+
+    def add_property(self, propname, opt):
+        properties = self.get_properties(opt)
+        if not propname in properties:
+            properties.append(propname)
+            self.set_properties(properties, opt)
+
+    def del_property(self, propname, opt):
+        properties = self.get_properties(opt)
+        if propname in properties:
+            properties.remove(propname)
+            self.set_properties(properties, opt)
+
     #____________________________________________________________
-    def get_permissive(self):
-        return self.permissive
+    def get_permissive(self, config=None):
+        return self.permissives.get(config, [])
 
-    def set_permissive(self, permissive):
+    def set_permissive(self, permissive, config=None):
         if not isinstance(permissive, list):
             raise TypeError('permissive must be a list')
-        self.permissive = permissive
+        self.permissives[config] = permissive
+
     #____________________________________________________________
-    # complete freeze methods
-    def freeze_everything(self):
-        """everything is frozen, not only the option that are tagged "frozen"
-        """
-        self.everything_frozen = True
+    def setowner(self, owner):
+        ":param owner: sets the default value for owner at the Config level"
+        if not isinstance(owner, owners.Owner):
+            raise TypeError("invalid generic owner {0}".format(str(owner)))
+        self.owner = owner
 
-    def un_freeze_everything(self):
-        """everything is frozen, not only the option that are tagged "frozen"
-        """
-        self.everything_frozen = False
+    def getowner(self):
+        return self.owner
 
-    def is_frozen_for_everything(self):
-        """frozen for a whole config (not only the options
-        that have been set to frozen)"""
-        return self.everything_frozen
     #____________________________________________________________
     def read_only(self):
         "convenience method to freeze, hidde and disable"
-        self.freeze_everything()
-        self.freeze() # can be usefull...
+        self.enable_property('everything_frozen')
+        self.enable_property('frozen')  # can be usefull...
         self.disable_property('hidden')
         self.enable_property('disabled')
-        self.mandatory = True
-        self.validator = True
+        self.enable_property('mandatory')
+        self.enable_property('validator')
+        self.disable_property('permissive')
 
     def read_write(self):
         "convenience method to freeze, hidde and disable"
-        self.un_freeze_everything()
-        self.freeze()
+        self.disable_property('everything_frozen')
+        self.enable_property('frozen')  # can be usefull...
         self.enable_property('hidden')
         self.enable_property('disabled')
-        self.mandatory = False
-        self.validator = False
-
-    def non_mandatory(self):
-        """mandatory at the Config level means that the Config raises an error
-        if a mandatory option is found"""
-        self.mandatory = False
-
-    def mandatory(self):
-        """mandatory at the Config level means that the Config raises an error
-        if a mandatory option is found"""
-        self.mandatory = True
-
-    def is_mandatory(self):
-        "all mandatory Options shall have a value"
-        return self.mandatory
-
-    def freeze(self):
-        "cannot modify the frozen `Option`'s"
-        self.frozen = True
-
-    def unfreeze(self):
-        "can modify the Options that are frozen"
-        self.frozen = False
-
-    def is_frozen(self):
-        "freeze flag at Config level"
-        return self.frozen
-
-    def setowner(self, owner):
-        ":param owner: sets the default value for owner at the Config level"
-        if not isinstance(owner, owners.Owner):
-            raise TypeError("invalid generic owner {0}".format(str(owner)))
-        self.owner = owner
-
-    def getowner(self):
-        return self.owner
+        self.disable_property('mandatory')
+        self.disable_property('validator')
+        self.enable_property('permissive')