00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 __facility__ = "Online"
00011 __abstract__ = "Script Engine Preferences manager GUI module"
00012 __author__ = "S. Tuvi <stuvi@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online"
00013 __date__ = "2005/07/23 00:08:27"
00014 __updated__ = "$Date: 2006/04/11 20:10:07 $"
00015 __version__ = "$Revision: 1.9 $"
00016 __release__ = "$Name: HEAD $"
00017 __credits__ = "SLAC"
00018
00019 import LICOS.copyright_SLAC
00020
00021 import sys
00022 import os
00023 import types
00024 import re
00025 import string
00026 import logging as log
00027 import logging.handlers
00028 from ConfigParser import *
00029 from rcUsers import rcUser, rcUsers
00030
00031 class rcPreferencesManager(object):
00032 """!\brief Class for managing the preferences.
00033
00034 """
00035 def __init__(self, configFile):
00036 """!\brief rcPreferencesManager constructor
00037
00038 \param configFile Configuration file name
00039 """
00040 self.__prefs = Preferences()
00041 self.__configFile = configFile
00042 self.__pythonPath = sys.path
00043 self.__configFile = os.path.abspath(configFile)
00044 confParser = self.loadDefaults(os.getcwd())
00045 self.__defPrefs = self.parserToPrefs(confParser)
00046
00047 def loadConfig(self):
00048 """!\brief Parse and load the configuration file
00049
00050 \return 1
00051 """
00052 confParser = ConfigParser()
00053 if os.path.exists(self.__configFile):
00054 confParser.read(self.__configFile)
00055 else:
00056 return None
00057
00058 self.parserToPrefs(confParser, self.__prefs)
00059
00060
00061
00062
00063
00064
00065
00066
00067 for choice in (Preferences.CHOICE_LIST +
00068 Preferences.LOGGING_LIST +
00069 Preferences.SYSTEM_LIST):
00070 if not self.__prefs.has_key(choice):
00071 self.__prefs[choice] = self.__defPrefs[choice]
00072
00073 return 1
00074
00075 def writeConfig(self):
00076 """!\brief Write the configuration back to the file.
00077
00078 """
00079 confParser = self.prefsToParser()
00080 try:
00081 confParser.write(file(self.getConfigFile(), "w+"))
00082 except IOError, (errno, errdetail):
00083 log.error("*** rcPreferencesGUIImpl cannot save preferences to \'%s\': %s" \
00084 %(self.getConfigFile(), errdetail))
00085
00086 def preferences(self):
00087 """!\brief Retrieve the preferences.
00088
00089 \return Preferences instance.
00090 """
00091 return self.__prefs
00092
00093 def defPrefs(self):
00094 """!\brief Retrive the default preferences.
00095
00096 \return Default preferences
00097 """
00098 return self.__defPrefs
00099
00100 def getConfigFile(self):
00101 """!\brief Retrieve the configuration file name.
00102
00103 \return Configuration file name
00104 """
00105 return self.__configFile
00106
00107 def refreshPrefs(self, newPrefs):
00108 """!\brief Refresh the preferences from \a newPrefs.
00109
00110 """
00111 for (key, val) in newPrefs.items():
00112 self.__prefs[key] = val
00113
00114 def setPref(self, keyword, value):
00115 """!\brief Set a preference value.
00116
00117 \param keyword Preference keyword
00118 \param value Preference value
00119 """
00120 self.__prefs[keyword] = value
00121
00122 def parserToPrefs(self, confParser, prefs={}):
00123 """!\brief Populate preferences from the parser.
00124
00125 \param confParser ConfigParser instance
00126 \param prefs Preferences instance
00127
00128 \return Preferences instance
00129 """
00130
00131 lastuser = None
00132 if 'users' in prefs:
00133 userList = prefs['users']
00134 else:
00135 userList = rcUsers()
00136 sections = confParser.sections()
00137 for section in sections:
00138 if section in ('paths', 'choices', 'logging', 'system'):
00139 options = confParser.options(section)
00140 for option in options:
00141 prefs[option] = confParser.get(section, option)
00142 elif section == 'users':
00143 options = confParser.options(section)
00144 for option in options:
00145 value = confParser.get(section, option).split(',',1)
00146 if len(value) == 2:
00147
00148 user = rcUser(option, value[0].strip(), value[1].strip())
00149 else:
00150
00151 user = rcUser(option, value[0].strip(), value[0].strip())
00152 if option == 'lastuser':
00153 lastuser = user
00154 else:
00155 userList.addUser(user)
00156 else:
00157
00158 if section in prefs:
00159 optionList = prefs[section]
00160 else:
00161 optionList = {}
00162 options = confParser.options(section)
00163 for option in options:
00164 if option in Preferences.LAST_ITEMS:
00165 prefs[option] = confParser.get(section, option)
00166 else:
00167 optionList[confParser.get(section, option)] = option
00168 prefs[section] = optionList
00169 prefs['users'] = userList
00170 if lastuser is None:
00171
00172 userIds = prefs["users"].getUsers().keys()
00173 userIds.sort()
00174 if len(userIds) > 0:
00175 lastuser = userList.getUser(userIds[0])
00176 if lastuser is not None:
00177
00178 lastuser = userList.getUserByName(lastuser.getName())
00179 prefs["operatorobj"] = lastuser
00180 prefs["operator"] = lastuser.getName()
00181 prefs["userid"] = lastuser.getId()
00182
00183
00184 if prefs.has_key('pythonpath'):
00185 additionalpaths = os.path.expandvars(prefs['pythonpath']).split(';')
00186 if prefs['pythonpath'].strip() != '':
00187 sys.path = map(string.strip, additionalpaths) + self.__pythonPath
00188 return prefs
00189
00190 def prefsToParser(self):
00191 """!\brief Populate the parser from the preferences.
00192
00193 \return ConfigParser instance
00194 """
00195 prefs = self.__prefs
00196 confParser = ConfigParser()
00197 confParser.add_section("paths")
00198 confParser.add_section("choices")
00199 confParser.add_section("logging")
00200 confParser.add_section("users")
00201 confParser.add_section("system")
00202 for (option, value) in prefs.items():
00203 if option in Preferences.DIR_LIST:
00204 confParser.set("paths", option, prefs.get(option))
00205 elif option in Preferences.CHOICE_LIST:
00206 confParser.set("choices", option, str(prefs[option]))
00207 elif option in Preferences.LOGGING_LIST:
00208 confParser.set("logging", option, str(prefs[option]))
00209 elif option in Preferences.SYSTEM_LIST:
00210 confParser.set("system", option, prefs[option])
00211 elif option == 'users':
00212 for (userId, user) in value.getUsers().items():
00213 confParser.set("users", "%03d" % int(userId), "%s,%s" % (user.getLoginId(), user.getName()))
00214 elif option == 'operatorobj':
00215 confParser.set("users", "lastuser", "%s,%s" % (value.getLoginId(), value.getName()))
00216 elif type(value) == types.DictType:
00217 if option in Preferences.EXCLUDED_DICTS:
00218 continue
00219 confParser.add_section(option)
00220 for (key, val) in value.items():
00221 confParser.set(option, val, key)
00222 if option == 'instrument type':
00223 self.processLastItem(option, 'lastinstrumenttype', confParser)
00224 elif option == 'phase':
00225 self.processLastItem(option, 'lastphase', confParser)
00226 elif option == 'site':
00227 self.processLastItem(option, 'lastsite', confParser)
00228 elif option == 'orientation':
00229 self.processLastItem(option, 'lastorientation', confParser)
00230 elif option == 'particle type':
00231 self.processLastItem(option, 'lastparticletype', confParser)
00232 return confParser
00233
00234
00235 def processLastItem(self, option, item, confParser):
00236 """!\brief Retrieve the last item of a preference and update the parser.
00237
00238 \param option Preference option name
00239 \param item Preference name for the last item
00240 \param confParser ConfigParser instance
00241 """
00242 prefs = self.__prefs
00243 if prefs.has_key(item):
00244 last = prefs[item]
00245 if last == 'NOT-DEFINED':
00246 last = prefs.getLastItem(item)
00247 confParser.set(option, item, last)
00248
00249
00250 def loadDefaults(self, currentDir):
00251 """!\brief Load default preferences in to the parser.
00252
00253 \return ConfigParser instance
00254 """
00255 cp = ConfigParser()
00256 cp.add_section("paths")
00257 cp.add_section("choices")
00258 cp.add_section("logging")
00259 cp.add_section("system")
00260 cp.set("paths","reposdir",currentDir)
00261 cp.set("paths","appdir",currentDir)
00262 cp.set("paths","datadir",currentDir)
00263 cp.set("paths","logdir",currentDir)
00264 cp.set("paths","reportdir",currentDir)
00265 cp.set("paths","snapshotdir",currentDir)
00266 cp.set("paths","exportdir",currentDir)
00267 cp.set("paths","runiddir",currentDir)
00268 cp.set("choices","datasave","1")
00269 cp.set("choices","dataexport","1")
00270 cp.set("choices","snapnbl","1")
00271 cp.set("choices","versionnbl","1")
00272 cp.set("choices","elognbl","0")
00273 cp.set("logging","lognbl","1")
00274 cp.set("logging","loglevel","INFO")
00275 cp.set("logging","loghost","localhost")
00276 cp.set("logging","logport",str(logging.handlers.DEFAULT_TCP_LOGGING_PORT))
00277 cp.set("system","pythonpath","")
00278 cp.set("system","elogurl","")
00279 cp.set("system","server","1")
00280 cp.set("system","servernbl","0")
00281 cp.set("system","dontreload","")
00282 cp.set("system","preload","")
00283 cp.set("system","disablereload","0")
00284 cp.set("system","showunloaded","0")
00285 cp.set("system","disableverification","0")
00286
00287 return cp
00288
00289 def isnumeric(self, str):
00290 """!\brief Determine whether the passed string is numeric.
00291
00292 \return False if \a str is not numeric.
00293 True if \a str is numeric.
00294 """
00295 return re.match('^[0-9]+$', str) is not None
00296
00297
00298 def setOperator(self, operator):
00299 """!\brief Set the current operator and update the configuration file.
00300
00301 \param operator Operator name
00302 """
00303 operator = str(operator).strip()
00304 if operator == 'NOT-DEFINED':
00305 self.setPref("operator", operator)
00306 self.setPref("userid", '000')
00307 else:
00308 user = self.__prefs["users"].getUserByName(operator)
00309 self.setPref("operator", user.getName())
00310 self.setPref("operatorobj", user)
00311 self.setPref("userid", user.getId())
00312 self.writeConfig()
00313
00314 def setParticleType(self, particleType):
00315 """!\brief Set the particle type and update the configuration file.
00316
00317 \param particleType Particle type
00318 """
00319 self.setPref("lastparticletype", str(particleType))
00320 if particleType != 'NOT-DEFINED':
00321 self.writeConfig()
00322
00323 def setOrientation(self, orientation):
00324 """!\brief Set the orientatino and update the configuration file.
00325
00326 \param orientation Orientation
00327 """
00328 self.setPref("lastorientation", str(orientation))
00329 if orientation != 'NOT-DEFINED':
00330 self.writeConfig()
00331
00332 def setSite(self, site):
00333 """!\brief Set the site and update the configuration file.
00334
00335 \param site Site
00336 """
00337 self.setPref("lastsite", str(site))
00338 if site != 'NOT-DEFINED':
00339 self.writeConfig()
00340
00341 def setPhase(self, phase):
00342 """!\brief Set the phase and update the configuration file.
00343
00344 \param phase Phase
00345 """
00346 self.setPref("lastphase", str(phase))
00347 if phase != 'NOT-DEFINED':
00348 self.writeConfig()
00349
00350 def setInstrumentType(self, instrumentType):
00351 """!\brief Set the instrument type and update the configuration file.
00352
00353 \param instrumentType Instrument type
00354 """
00355 self.setPref("lastinstrumenttype", str(instrumentType))
00356 if instrumentType != 'NOT-DEFINED':
00357 self.writeConfig()
00358
00359
00360 def userId(self):
00361 """!\brief Get the user id.
00362
00363 """
00364 if self.__prefs.has_key("userid"):
00365 return int(self.__prefs["userid"])
00366 else:
00367 return 1234
00368
00369
00370 class Preferences(dict):
00371 """!\brief Preferences dictionary.
00372
00373 Preferences needs a special dictionary class since the data it stores
00374 may have macros and environment variables in it.
00375
00376 In order to read the values unprocessed use the self.__prefs.get(item)
00377 method. If you need to resolve all the macros and environment variables
00378 then access it like any other dictionary (self.__prefs[item])
00379
00380 """
00381 ROOT_DIR_ENVS = ['ONLINE_ROOT']
00382
00383 DIR_LIST = ("reposdir", "appdir", "datadir",
00384 "logdir", "reportdir",
00385 "snapshotdir", "exportdir", "runiddir")
00386
00387 CHOICE_LIST = ("datasave", "dataexport",
00388 "snapnbl", "versionnbl", "elognbl")
00389
00390 LOGGING_LIST = ("lognbl", "loglevel", "loghost", "logport")
00391
00392 SYSTEM_LIST = ("pythonpath", "elogurl", "server", "servernbl",
00393 "fontfamily", "fontsize", "fontweight", "fontitalic",
00394 "style", "preload", "dontreload", "disablereload",
00395 "showunloaded", "disableverification")
00396
00397 LAST_ITEMS = ("lastuser", "lastsite", "lastorientation", "lastparticletype",
00398 "lastinstrumenttype", "lastphase")
00399
00400 TREAT_AS_INT = ("datasave", "dataexport",
00401 "snapnbl", "versionnbl", "elognbl", "lognbl", "servernbl",
00402 "disablereload", "showunloaded", "logport", "disableverification")
00403
00404 EXCLUDED_DICTS = ("hwConfig")
00405
00406 def __init__(self):
00407 """!\brief Preferences constructor.
00408
00409 """
00410 dict.__init__(self)
00411 self.__saveLastItem = {}
00412
00413 def __getitem__(self, item):
00414 """!\brief Overridden method to process the item before returning it.
00415
00416 \param item Preference item
00417 """
00418 value = dict.__getitem__(self, item)
00419 if self.isDir(item):
00420 return self.expandVars(value)
00421 elif self.isNumber(item):
00422 return int(value)
00423 else:
00424 return value
00425
00426 def __setitem__(self, item, value):
00427 """!\brief Overridden method to set the last item.
00428
00429 \param item Preference item
00430 \param value Preference value
00431 """
00432 if self.isLastItem(item) and value != 'NOT-DEFINED':
00433 self.__saveLastItem[item] = value
00434 dict.__setitem__(self, item, value)
00435
00436 def isDir(self, item):
00437 """!\brief Is the item a path preference?
00438
00439 \param item Preference item
00440 """
00441 return item in Preferences.DIR_LIST
00442
00443 def isNumber(self, item):
00444 """!\brief Is the item a numeric preference?
00445
00446 \param item Preference item
00447 """
00448 return item in Preferences.TREAT_AS_INT
00449
00450 def isLastItem(self, item):
00451 """!\brief Is the preference item a last item?
00452
00453 \param item Preference item
00454 """
00455 return item in Preferences.LAST_ITEMS
00456
00457 def expandVars(self, path):
00458 """!\brief Expand the environment variables and macros in path.
00459
00460 \param path Path preference value
00461 """
00462 p = os.path.expandvars(path)
00463 dirs = os.path.normpath(p).split(os.sep)
00464 i = 0
00465 for d in dirs:
00466 if d.startswith('@') and d[1:] in dict.keys(self):
00467 dirs[i] = dict.get(self,d[1:])
00468
00469 if d.startswith('@') and d[1:] in dict.keys(self):
00470 if d[1:] == 'lastinstrumenttype':
00471 dirs[i] = dict.get(self,'instrument type')[dict.get(self,d[1:])]
00472 else:
00473 dirs[i] = dict.get(self,d[1:])
00474
00475 i+=1
00476 if not dirs[0].endswith(os.sep):
00477 dirs[0]+=os.sep
00478 return reduce(os.path.join, dirs)
00479
00480 def composePath(self, path):
00481 """!\brief Convert the path value back to its macro form.
00482
00483 \param path Path preference value
00484 """
00485 for env in Preferences.ROOT_DIR_ENVS:
00486 if env in os.environ:
00487 if os.path.normpath(path).lower().startswith(os.path.normpath(os.environ[env]).lower() + os.sep):
00488 return '$' + env + path[len(os.environ[env]):]
00489 return path
00490
00491 def getLastItem(self, item):
00492 """!\brief Retrieve the last item for the preference.
00493
00494 \param item Preference item
00495 """
00496 if item in self.__saveLastItem:
00497 return self.__saveLastItem[item]