This file is indexed.

/usr/share/pyshared/scitools/PrmDictBase.py is in python-scitools 0.9.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
#!/usr/bin/env python
"""
Module for managing parameters.
"""
import re, os, sys

def message(m):
    if os.environ.get('DEBUG', '0') == '1':
        print m
    

class PrmDictBase(object):
    """
Base class for managing parameters stored in dictionaries.
Typical use includes data or solver classes for solving physical
problems numerically. One may then choose to hold all physical
parameters in a dictionary physical_prm, containing
(parameter name, value) pairs, and all numerical parameters in
a dictionary numerical_prm. The physical_prm and numerical_prm
dictionaries can then be defined in a subclass of PrmDictBase
and managed by PrmDictBase. The management includes several
convenient features:

 - keeping all input data in one place
 - setting of one or more parameters where the type of the value
   must match the type of the previous (initial) value
 - pretty print of all defined parameters
 - copying parameters from dictionaries to, e.g., local variables
   and back again, or to local namespaces and back again
 - easy transition from parameter dictionaries to more sophisticated
   handling of input data, e.g., class scitools.ParameterInterface
   (GUI, CGI, command-line args)

The subclass typically defines the dictionaries, say
self.physical_prm and self.numerical_prm. Then these are
appended to the inherited self._prm_list list to be registered.
All members of this list are dictionaries that will not accept
new keys (i.e., all parameters must be defined prior to registering
them in self._prm_list). With this list one has a collection of all
parameter dictionaries in the application.

self._type_check[prm] is defined if we want to type check
a parameter prm.
if self._type_check[prm] is True (or False), prm must either
be None, of the same type as the previously registered
value of prm, or any number (float, int, complex) if
the previous value prm was any number. Instead of a boolean
value, self._type_check[prm] may hold a tuple of class types
(to be used in isinstance checks), or a function which takes
the value as argument and returns True if the that value is
of the right type (otherwise False).


In addition to the parameter dictionaries with fixed keys, class
PrmDictBase also holds a self.user_prm, which is a dictionary
of "meta data", i.e., an arbitrary set of keys and values that
can arbitrarily extended anywhere. If self.user_prm is None,
no such meta data can exists (implying that only parameters
registered in the dictionaries in self._prm_list are allowed - the
programmer of subclasses can of course extend these parameter
sets whenever desired; disallowing a parameter name is only a
feature of the set function for setting the value of a (registered)
parameter).

Here is an example::

    from scitools.PrmDictBase import PrmDictBase

    class SomeSolver(PrmDictBase):
        def __init__(self, **kwargs):
            PrmDictBase.__init__(self)
            # register parameters in dictionaries:
            self.physical_prm = {'density': 1.0, 'Cp': 1.0,
                                       'k': 1.0, 'L': 1.0}
            self.numerical_prm =  {'n': 10, 'dt': 0.1, 'tstop': 3}

            # attach dictionaries to base class list (required):
            self._prm_list = [self.physical_prm, self.numerical_prm]

            # specify parameters to be type checked when set:
            self._type_check.update({'n': True, 'dt': (float,),
                  'k': lambda k: isinstance(int,float) and k>0})

            # disallow arbitrary meta data
            self.user_prm = None # set to {} if meta data are allowed

            # initialize parameters according to keyword arguments:
            self.set(**kwargs)


        def _update(self):
            # dt depends on n, L, k; update dt in case the three
            # others parameters have been changed
            # (in general this method is used to check consistency
            # between parameters and perform updates if necessary)
            n = self.numerical_prm['n']
            L = self.physical_prm['L']
            k = self.physical_prm['k']

            self.u = zeros(n+1, Float)
            h = L/float(n)
            dt_limit = h**2/(2*k)
            if self.numerical_prm['dt'] > dt_limit:
                self.numerical_prm['dt'] = dt_limit

        def compute1(self):
            # compute something
            return self.physical_prm['k']/self.physical_prm['Cp']

        def compute2(self):
            # turn numerical parameters into local variables:
            exec self.dicts2variables(self._prm_list)
            # or exec self.dicts2variables(self.numerical_prm)  # selected prms

            # now we have local variables n, dt, tstop, density, Cp, k, L
            # that we can compute with, say

            Q = k/Cp
            dt = 0.9*dt

            # if some of the local variables are changed, say dt, they must
            # be inserted back into the parameter dictionaries:
            self.variables2dicts(self.numerical_prm, dt=dt)    

    """
    
    def __init__(self):
        # dicts whose keys are fixed (non-extensible):
        self._prm_list = []     # fill in subclass
        self.user_prm = None    # user's meta data
        self._type_check = {}   # fill in subclass

    def _prm_dict_names(self):
        """Return the name of all self.*_prm dictionaries."""
        return [attr for attr in self.__dict__ if \
                re.search(r'^[^_].*_prm$', attr)]
                
    def usage(self):
        """Print the name of all parameters that can be set."""
        prm_dict_names = self._prm_dict_names()
        prm_names = []
        for name in prm_dict_names:
            d = self.__dict__[name]
            if isinstance(d, dict):
                k = d.keys()
                k.sort(lambda a,b: cmp(a.lower(),b.lower()))
                prm_names += k
        print 'registered parameters:\n'
        for i in prm_names:
            print i
        # alternative (sort all in one bunch):
        # names = []
        # for d in self._prm_list:
        #     names += d.keys()
        # names.sort
        # print names

    def dump(self):
        """Dump all parameters and their values."""
        for d in self._prm_list:
            keys = d.keys()
            keys.sort(lambda a,b: cmp(a.lower(),b.lower()))
            for prm in keys:
                print '%s = %s' % (prm, d[prm])

    def set(self, **kwargs):
        """Set kwargs data in parameter dictionaries."""
        # print usage message if no arguments:
        if len(kwargs) == 0:
            self.usage()
            return
        
        for prm in kwargs:
            _set = False
            for d in self._prm_list:
                if len(d.keys()) == 0:
                    raise ValueError('self._prm_list is wrong (empty)')
                try:
                    if self.set_in_dict(prm, kwargs[prm], d):
                        _set = True
                        break
                except TypeError, msg:
                    print msg
                    #break
                    sys.exit(1)  # type error is fatal

            if not _set:   # maybe set prm as meta data?
                if isinstance(self.user_prm, dict):
                    # not a registered parameter:
                    self.user_prm[prm] = kwargs[prm]
                    message('%s=%s assigned in self.user_prm' % \
                            (prm, kwargs[prm]))
                else:
                    raise NameError('parameter "%s" not registered' % prm)
        self._update()

    def set_in_dict(self, prm, value, d):
        """
        Set d[prm]=value, but check if prm is registered in class
        dictionaries, if the type is acceptable, etc.
        """
        can_set = False
        # check that prm is a registered key
        if prm in d:
            if prm in self._type_check:
                # prm should be type-checked
                if isinstance(self._type_check[prm], (int,float)):
                    # (bool is subclass of int)
                    if self._type_check[prm]:
                        # type check against prev. value or None:
                        if isinstance(value, (type(d[prm]), None)):
                            can_set = True
                        # allow mixing int, float, complex:
                        elif operator.isNumberType(value) and\
                                 operator.isNumberType(d[prm]):
                            can_set = True
                elif isinstance(self._type_check[prm], (tuple,list,type)):
                    # self._type_check[prm] holds either the type or
                    # a tuple/list of types; test against them
                    #print 'testing %s=%s against type %s' % (prm,value,self._type_check[prm])
                    if isinstance(value, self._type_check[prm]):
                        can_set = True
                    else:
                        raise TypeError('\n\n%s=%s: %s has type %s, not %s' % \
                                        (prm, value, prm, self._type_check[prm],
                                         type(value)))

                elif callable(self._type_check[prm]):
                    can_set = self._type_check[prm](value)
                else:
                    raise TypeError('self._type_check["%s"] has an '\
                                    'illegal value %s' % \
                                    (prm, self._type_check[prm]))
            else:
                can_set = True
        else:
            message('%s is not registered in\n%s' % (prm, d))
        if can_set:
            d[prm] = value
            message('%s=%s is assigned' % (prm, value))
            return True
        return False
        

    def _update(self):
        """Check data consistency and make updates."""
        # to be implemented in subclasses
        pass

    def get(self, **kwargs):
        return [self._solver_prm[prm] \
                for prm in kwargs if prm in self._solver_prm]
                
    def properties(self, global_namespace):
        """Make properties out of local dictionaries."""
        for ds in self._prm_dict_names():
            d = eval('self.' + ds)
            for prm in d: # or for prm in self.__dict__[ds]
                # properties cannot have whitespace:
                prm = prm.replace(' ', '_')
                cmd = '%s.%s = property(fget='\
                      'lambda self: self.%s["%s"], %s)' % \
                      (self.__class__.__name__, prm, ds, prm,
                       ' doc="read-only property"')
                print cmd
                exec cmd in global_namespace, locals()

    def dicts2namespace(self, namespace, dicts, overwrite=True):
        """
        Make namespace variables out of dict items.
        That is, for all dicts, insert all (key,value) pairs in
        the namespace dict.
        namespace is a dictionary, dicts is a list of dictionaries.
        """
        # can be tuned in subclasses

        # allow dicts to be a single dictionary:
        if not isinstance(dicts, (list,tuple)):
            dicts = [dicts]

        for d in dicts:
            if overwrite:
                namespace.update(d)
            else:
                for key in d:
                    if key in namespace and not overwrite:
                        print 'cannot overwrite %s' % key
                    else:
                        namespace[key] = d[key]

    def dicts2namespace2(self, namespace, dicts):
        """As dicts2namespace2, but use exec."""
        # can be tuned in subclasses

        # allow dicts to be a single dictionary:
        if not isinstance(dicts, (list,tuple)):
            dicts = [dicts]
            
        for d in dicts:
            for key in d:
                exec '%s=%s' % (key,repr(d[key])) in globals(), namespace

    def namespace2dicts(self, namespace, dicts):
        """
        Update dicts from variables in a namespace.
        That is, for all keys in namespace, insert (key,value) pair
        in the dict in dicts that has the same key registered.
        namespace is a dictionary, dicts is a list of dictionaries.
        """
        # allow dicts to be a single dictionary:
        if not isinstance(dicts, (list,tuple)):
            dicts = [dicts]

        keys = []    # all keys in namespace that are keys in dicts
        for key in namespace:
            for d in dicts:
                if key in d:
                    d[key] = namespace[key]  # update value
                    keys.append(key)         # mark for delete
        # clean up what we made in self.dicts2namespace:
        for key in keys:
            del namespace[key]

    def dicts2variables(self, dicts):
        """
        Make Python code string that defines local variables from
        all parameters in dicts (list of dictionaries of parameters).
        For example, if dicts[1] has a key n with value 1.0, the
        statement 'n=1.0' will be included in the returned string.
        The calling code will typically exec this returned string
        to make local variables (short hands) from parameters stored
        in dictionaries. (Note that such local variables are read-only,
        changing their values will not be reflected in the dictionaries!).
        """
        # allow dicts to be a single dictionary:
        if not isinstance(dicts, (list,tuple)):
            dicts = [dicts]

        s = ''
        for d in dicts:
            for name in d:
                s += '%s = %s\n' % (name, d[name])
        return s

    def variables2dicts(self, dicts, **variables):
        """
        Insert the name=value keyword arguments in variables into
        the dictionaries in dicts (list of dictionaries).
        This is the inverse of the dicts2variables function.

        Usage:
        exec self.dicts2variables(self.numerical_prm)
        # work with read-only n, dt, tstop
        ...
        # update (in case n, dt, tstop was changed):
        self.variables2dicts(self.numerical_prm, n=n, dt=dt, tstop=tstop)
        """
        for name in variables:
            for d in dicts:
                if name in d:
                    d[name] = variables[name]
    

# initial tests are found in src/py/examples/classdicts.py