Menu

[25510f]: / variableVariablesManager.py  Maximize  Restore  History

Download this file

230 lines (203 with data), 8.4 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
"""
this file provides the VariableVariablesManager class for manually handling
variable variables, i.e. variables with variable name.
The class:
- handles local and global variables
- can handle renaming of variable
- will provide basic constness
- can check for type equality, if desired
example:
x = VariableVariablesManager()
x['test'] = 25
x.defineConstVariable('myconst', 13)
x.renameVariable('myconst', 'myconstOther')
The code and the unit tests both work for python 2 and 3 (tested with 2.7 and 3.5)
See the respective unit test file for some examples.
"""
__author__ = "Dominik Rueß"
__copyright__ = "Copyright 2016, Dominik Rueß"
__credits__ = ["Dominik Rueß"]
__license__ = "GPLv3"
__version__ = "1.0.1"
__maintainer__ = "Dominik Rueß"
__email__ = "info@dominik-ruess.de"
__status__ = "Development"
def globalSingleton(cls):
"""
a quasi singleton pattern decorator which keeps one global instance and
returns new instances on every request, linking to the global one
"""
globalInstance = None
instances = {}
def getinstance(*args, **kwargs):
if cls not in instances:
if 'globalManager' in kwargs:
del kwargs['globalManager']
instances[cls] = cls(*args, **kwargs)
kwargs['globalManager'] = instances[cls]
out = cls(*args, **kwargs)
return out
return getinstance
def variableExists(func):
"""
a decorator for classes which asserts that in the dict class.variables
a variable exists
"""
def checkIfVariableExists(*args):
"""
test, if in VariableVariablesManager object's dict 'variables' a
key exists and if so, run decorated function
"""
manager = args[0]
variableName = args[1]
foundGlobally = manager.globalManager \
and variableName in manager.globalManager.variables
foundLocally = variableName in manager.variables
if not foundGlobally and not foundLocally:
raise NameError("variable variable '%s' not defined"
% variableName)
return func(*args)
return checkIfVariableExists
@globalSingleton
class VariableVariablesManager:
"""
VariableVariablesManager is a class, loosely based on the singleton and
object-pool pattern.
It will provide a centralized variable pool with variable names. You can:
- define variables as const
- enforce type equality on re-assignment
- define variables with local scope
"""
DEBUG_PREFIX = "Variable variables manager"
def __init__(self,
enforceSameTypeOnOverride = False,
debug = False,
globalManager = None):
"""
initialize the settings for the variables manager
(only once, due to singleton)
note: parameter 'globalManager' is for internal use, it will be
overridden
"""
self.enforceSameTypeOnOverride = enforceSameTypeOnOverride
self.printDebug = debug
self.variables = {}
self.constVariables = []
self.globalManager = globalManager
if not self.globalManager:
self.DEBUG_PREFIX += " (global variables manager)"
def _debug(self, message):
"""
if debug mode is on, print the message
"""
if self.printDebug:
print(self.DEBUG_PREFIX + ": " + message)
def _isGlobal(self, variableName):
"""
test if a given variable is already declared global
"""
# test this is not already the globalManager
return self.globalManager \
and variableName in self.globalManager.variables
@variableExists
def __getitem__(self, variableName):
"""
return the content of a named variable
"""
if self._isGlobal(variableName):
return self.globalManager.__getitem__(variableName)
else:
self._debug("getting var '%s'" % variableName)
return self.variables[variableName]
def __setitem__(self, variableName, value):
"""
assign content to a named variable.
- will check for constness, if a variable exists
- will check for type equality if a variable exists
"""
if self._isGlobal(variableName):
self.globalManager.__setitem__(variableName, value)
else:
# test for type equality (if desired)
if variableName in self.variables \
and self.enforceSameTypeOnOverride \
and type(value) != type(self.variables[variableName]):
raise TypeError("VariableVariablesManager was set up "
"to enforce type equality: tried to assign to "
"variable '%s' of type '%s' a value of type '%s'"
" with value: '%s')"
% (variableName,
type(self.variables[variableName]),
type(value),
str(value)))
# test for constness (if desired)
if variableName in self.constVariables:
raise AttributeError("tried assigning a value to"
"const variable '%s'" % variableName)
self._debug("assigning var '%s' with value '%s'"
% (variableName, str(value)))
self.variables[variableName] = value
@variableExists
def __delitem__(self, variableName):
"""
delete a variable variable, e.g.
del manager['myVariableName']
"""
if self._isGlobal(variableName):
self.globalManager.__delitem__(variableName)
else:
del self.variables[variableName]
# don't forget to remove possible appearance in const-references
#(and global references)
if variableName in self.constVariables:
self.constVariables.remove(variableName)
self._debug("deleted var '%s'" % variableName)
def defineConstVariable(self, variableName, value, setGlobal = False):
"""
mark the (new) variable variable as constant, such that the
value cannot be changed
"""
if self._isGlobal(variableName) or setGlobal:
self.globalManager.defineConstVariable(variableName, value)
else:
self._debug("assigning const variable '%s':" % variableName)
self.__setitem__(variableName, value)
self.constVariables.append(variableName)
def defineGlobalVariable(self, variableName, value):
"""
mark the (new) variable variable as global
(and possibly remove old, matching local content)
"""
if self.globalManager:
# we're in local scope
self.globalManager.__setitem__(variableName, value)
if variableName in self.variables:
# delete local variable with same name
del self.variables[variableName]
else:
# this is the global manager
variablePath = self._getCallStackStr(variableName)
self._debug("assigning const variable '%s':" % variableName)
self.__setitem__(variableName, value)
@variableExists
def renameVariable(self, currentName, newName):
"""
rename a variable variable to a different variable name. The
value will stay the same
"""
if self._isGlobal(currentName):
self.globalManager.renameVariable(currentName, newName)
else:
if newName in self.variables:
raise NameError("variable variable '%s' already defined"
" when renaming variable '%s'"
% (newName, currentName))
self.variables[newName] = self.variables[currentName]
del self.variables[currentName]
if currentName in self.constVariables:
self.constVariables.remove(currentName)
self.constVariables.append(newName)
self._debug("renamed var '%s' to var '%s'"
% (currentName, newName))