optimisations and all is properties
[tiramisu.git] / tiramisu / setting.py
1 # -*- coding: utf-8 -*-
2 "sets the options of the configuration objects Config object itself"
3 # Copyright (C) 2012-2013 Team tiramisu (see AUTHORS for all contributors)
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 #
19 # The original `Config` design model is unproudly borrowed from
20 # the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
21 # the whole pypy projet is under MIT licence
22 # ____________________________________________________________
23
24
25 class _const:
26     """convenient class that emulates a module
27     and builds constants (that is, unique names)"""
28     class ConstError(TypeError):
29         pass
30
31     def __setattr__(self, name, value):
32         if name in self.__dict__:
33             raise self.ConstError, "Can't rebind group ({})".format(name)
34         self.__dict__[name] = value
35
36     def __delattr__(self, name):
37         if name in self.__dict__:
38             raise self.ConstError, "Can't unbind group ({})".format(name)
39         raise NameError(name)
40
41
42 # ____________________________________________________________
43 class GroupModule(_const):
44     "emulates a module to manage unique group (OptionDescription) names"
45     class GroupType(str):
46         """allowed normal group (OptionDescription) names
47         *normal* means : groups that are not master
48         """
49         pass
50
51     class DefaultGroupType(GroupType):
52         """groups that are default (typically 'default')"""
53         pass
54
55     class MasterGroupType(GroupType):
56         """allowed normal group (OptionDescription) names
57         *master* means : groups that have the 'master' attribute set
58         """
59         pass
60 # setting.groups (emulates a module)
61 groups = GroupModule()
62
63
64 def populate_groups():
65     "populates the available groups in the appropriate namespaces"
66     groups.master = groups.MasterGroupType('master')
67     groups.default = groups.DefaultGroupType('default')
68     groups.family = groups.GroupType('family')
69
70 # names are in the module now
71 populate_groups()
72
73
74 # ____________________________________________________________
75 class OwnerModule(_const):
76     """emulates a module to manage unique owner names.
77
78     owners are living in `Config._cfgimpl_value_owners`
79     """
80     class Owner(str):
81         """allowed owner names
82         """
83         pass
84
85     class DefaultOwner(Owner):
86         """groups that are default (typically 'default')"""
87         pass
88 # setting.owners (emulates a module)
89 owners = OwnerModule()
90
91
92 def populate_owners():
93     """populates the available owners in the appropriate namespaces
94
95     - 'user' is the generic is the generic owner.
96     - 'default' is the config owner after init time
97     """
98     setattr(owners, 'default', owners.DefaultOwner('default'))
99     setattr(owners, 'user', owners.Owner('user'))
100
101     def add_owner(name):
102         """
103         :param name: the name of the new owner
104         """
105         setattr(owners, name, owners.Owner(name))
106     setattr(owners, 'add_owner', add_owner)
107
108 # names are in the module now
109 populate_owners()
110
111
112 class MultiTypeModule(_const):
113     class MultiType(str):
114         pass
115
116     class DefaultMultiType(MultiType):
117         pass
118
119     class MasterMultiType(MultiType):
120         pass
121
122     class SlaveMultiType(MultiType):
123         pass
124
125 multitypes = MultiTypeModule()
126
127
128 def populate_multitypes():
129     setattr(multitypes, 'default', multitypes.DefaultMultiType('default'))
130     setattr(multitypes, 'master', multitypes.MasterMultiType('master'))
131     setattr(multitypes, 'slave', multitypes.SlaveMultiType('slave'))
132
133 populate_multitypes()
134
135
136 #____________________________________________________________
137 class Setting(object):
138     "``Config()``'s configuration options"
139     __slots__ = ('properties', 'permissives', 'owner')
140
141     def __init__(self):
142         # properties attribute: the name of a property enables this property
143         # key is None for global properties
144         self.properties = {None: []}  # ['hidden', 'disabled', 'mandatory', 'frozen', 'validator']}
145         # permissive properties
146         self.permissives = {}
147         # generic owner
148         self.owner = owners.user
149
150     #____________________________________________________________
151     # properties methods
152     def has_properties(self, opt=None):
153         "has properties means the Config's properties attribute is not empty"
154         return bool(len(self.get_properties(opt)))
155
156     def get_properties(self, opt=None):
157         if opt is None:
158             default = []
159         else:
160             default = list(opt._properties)
161         return self.properties.get(opt, default)
162
163     def has_property(self, propname, opt=None):
164         """has property propname in the Config's properties attribute
165         :param property: string wich is the name of the property"""
166         return propname in self.get_properties(opt)
167
168     def enable_property(self, propname):
169         "puts property propname in the Config's properties attribute"
170         props = self.get_properties()
171         if propname not in props:
172             props.append(propname)
173         self.set_properties(props)
174
175     def disable_property(self, propname):
176         "deletes property propname in the Config's properties attribute"
177         props = self.get_properties()
178         if propname in props:
179             props.remove(propname)
180         self.set_properties(props)
181
182     def set_properties(self, properties, opt=None):
183         """save properties for specified opt
184         (never save properties if same has option properties)
185         """
186         if opt is None:
187             self.properties[opt] = properties
188         else:
189             if opt._properties == properties:
190                 if opt in self.properties:
191                     del(self.properties[opt])
192             else:
193                 self.properties[opt] = properties
194
195     def add_property(self, propname, opt):
196         properties = self.get_properties(opt)
197         if not propname in properties:
198             properties.append(propname)
199             self.set_properties(properties, opt)
200
201     def del_property(self, propname, opt):
202         properties = self.get_properties(opt)
203         if propname in properties:
204             properties.remove(propname)
205             self.set_properties(properties, opt)
206
207     #____________________________________________________________
208     def get_permissive(self, config=None):
209         return self.permissives.get(config, [])
210
211     def set_permissive(self, permissive, config=None):
212         if not isinstance(permissive, list):
213             raise TypeError('permissive must be a list')
214         self.permissives[config] = permissive
215
216     #____________________________________________________________
217     def setowner(self, owner):
218         ":param owner: sets the default value for owner at the Config level"
219         if not isinstance(owner, owners.Owner):
220             raise TypeError("invalid generic owner {0}".format(str(owner)))
221         self.owner = owner
222
223     def getowner(self):
224         return self.owner
225
226     #____________________________________________________________
227     def read_only(self):
228         "convenience method to freeze, hidde and disable"
229         self.enable_property('everything_frozen')
230         self.enable_property('frozen')  # can be usefull...
231         self.disable_property('hidden')
232         self.enable_property('disabled')
233         self.enable_property('mandatory')
234         self.enable_property('validator')
235         self.disable_property('permissive')
236
237     def read_write(self):
238         "convenience method to freeze, hidde and disable"
239         self.disable_property('everything_frozen')
240         self.enable_property('frozen')  # can be usefull...
241         self.enable_property('hidden')
242         self.enable_property('disabled')
243         self.disable_property('mandatory')
244         self.disable_property('validator')
245         self.enable_property('permissive')