Package pysql :: Module pysqlconf
[hide private]
[frames] | no frames]

Source Code for Module pysql.pysqlconf

  1  #!/usr/bin/python 
  2  # -*- coding: utf-8 -*- 
  3   
  4  """This module defines the PysqlConf class 
  5  that handles all pysql configuration stuff 
  6  @author: Sébastien Renard (sebastien.renard@digitalfox.org) 
  7  @license: GNU GPL V3 
  8  """ 
  9   
 10  # Python imports: 
 11  import sys 
 12  import os 
 13  from os.path import expandvars, join 
 14  import cPickle 
 15  from ConfigParser import ConfigParser 
 16  import readline 
 17   
 18  # Pysql imports: 
 19  from pysqlexception import PysqlException 
 20  from pysqlcolor import BOLD, CYAN, GREEN, RED, RESET 
 21   
22 -class PysqlConf:
23 """ Handles configuration stuff""" 24 25 # Config instance (singleton) 26 configInstance=None 27
28 - def __init__(self):
29 """Config instance creation. Read the config file""" 30 31 if os.name=="nt": 32 # Home directory of windows world 33 basePath=join(expandvars("$APPDATA"), "pysql") 34 else: 35 basePath=join(expandvars("$HOME"), ".pysql") 36 37 # Create conf dir if it does not exist 38 if not self.__isReadWrite(basePath): 39 os.mkdir(basePath) 40 41 # Config Parser 42 self.configParser=None 43 44 # Config file path 45 self.configPath=join(basePath, "pysqlrc") 46 47 # Cache file path 48 self.cachePath=join(basePath, "pysqlcache") 49 50 # History file path 51 self.historyPath=join(basePath, "pysqlhistory") 52 53 # User SQL library file path 54 self.sqlLibPath=join(basePath, "pysqlsqllibrary") 55 56 # Config changed flag 57 self.changed=False 58 59 # Completionlist dictionary 60 self.completeLists={} 61 62 # User defined sql Library 63 self.sqlLibrary={} 64 65 # Tries to load previous completion List from disk 66 try: 67 self.completeLists=cPickle.load(file(self.cachePath)) 68 except Exception, e: 69 # Cannot load any previous cache, start from a clear one 70 pass 71 72 # Tries to load previous history list from disk 73 try: 74 readline.read_history_file(self.historyPath) 75 except Exception, e: 76 # Cannot load any previous history. Start from a clear one 77 pass 78 79 # Tries to load previous sqlLibrary from disk 80 try: 81 self.sqlLibrary=cPickle.load(file(self.sqlLibPath)) 82 except Exception, e: 83 # Cannot load any previous sqlLibrary, start from a clear one 84 pass 85 86 # Load default value for all parameters 87 self.default={ 88 "case_sensitive" : "no", 89 "completionlistsize" : 100, 90 "fetchsize" : 30, 91 "termwidth" : "auto", 92 "widthmin" : 5, 93 "transpose" : "no", 94 "colsep" : "space", 95 "shrink" : "yes", 96 "echo" : "no", 97 "unit" : "mb", 98 "graph_program" : "auto", 99 "graph_format" : "png", 100 "graph_fontname" : "courier", 101 "graph_fontsize" : "10.0", 102 "graph_fontcolor" : "black", 103 "graph_tablecolor" : "ivory", 104 "graph_linkcolor" : "black", 105 "graph_indexcolor" : "skyblue", 106 "graph_bordercolor" : "black", 107 "graph_linklabel" : "off", 108 "graph_depmaxdepth" : 8, 109 "graph_depmaxnodes" : 100, 110 "graph_viewer" : "auto" 111 } 112 113 # Searches for config file in $HOME (Unix) or %HOMEPATH% (Windows) 114 115 if self.__isReadWrite(self.configPath) and sys.stdin.isatty() and sys.stdout.isatty(): 116 print CYAN+_("Using config file %s") % self.configPath + RESET 117 118 # Reads config file 119 self.configParser=ConfigParser() 120 try: 121 self.configParser.readfp(open(self.configPath)) 122 except Exception, e: 123 # Silently create empty conf and only complain if this fails 124 try: 125 file(self.configPath, "w") 126 except Exception, e: 127 print RED+BOLD+_("Failed to create personnal configuration file") 128 print "%s" % e + RESET 129 130 # Host codec used to display on and read from string on terminal 131 self.codec=None
132
133 - def getConfig(cls):
134 """Factory for configuration instance singleton 135 @return: PysqlConf instance""" 136 if cls.configInstance is None: 137 cls.configInstance=PysqlConf() 138 return cls.configInstance
139 getConfig=classmethod(getConfig) 140
141 - def get(self, key):
142 """ Gets the value of the parameter key 143 @param key: parameter name 144 @type key: string 145 @return: str or int (if cast if possible) 146 """ 147 key=key.lower() 148 if self.configParser is not None: 149 try: 150 value=self.configParser.get("PYSQL", key) 151 except Exception: 152 value=self.getDefault(key) 153 else: 154 value=self.getDefault(key) 155 156 # Tries to cast to numeric. If it does not work, we assume the value is a string 157 try: 158 value=int(value) 159 except (ValueError, TypeError): 160 try: 161 value=float(value) 162 except (ValueError, TypeError): 163 pass 164 return value
165
166 - def getAll(self):
167 """Gets all defined parameters 168 @return: list of (key, userValue, defaultValue) 169 """ 170 result={} 171 # Populates with user value 172 if self.configParser is not None: 173 if self.configParser.has_section("PYSQL"): 174 all=self.configParser.items("PYSQL") 175 if all is not None: 176 for (key, value) in all: 177 # Try to cast to int 178 try: 179 value=int(value) 180 except (ValueError, TypeError): 181 pass 182 result[key]=[value, ""] 183 # Populates with default value 184 for (key, value) in self.default.items(): 185 if result.has_key(key): 186 result[key]=[result[key][0], value] 187 else: 188 result[key]=["", value] 189 190 # Transforms dict into list 191 result=[[i[0]]+i[1] for i in result.items()] 192 # Alphabetic sort 193 result.sort() 194 return result
195
196 - def getDefault(self, key):
197 """Returns the default value for a parameter. If no default value is defined, return None""" 198 if self.default.has_key(key): 199 return self.default[key] 200 else: 201 print "(DEBUG) Key %s has no default value !" % key 202 return None
203
204 - def verify(self, key, value):
205 """Checks if the key has correct value 206 It does not update the value. 207 @param key: key parameter to be tested 208 @param value: value to be tested 209 @return: True if value is correct, else False""" 210 # Expanding shell variables 211 if isinstance(value, str): 212 value=os.path.expandvars(value) 213 214 # Integer parameter 215 if key=="termwidth" and value=="auto": 216 return True 217 elif key in ("termwidth", 218 "fetchsize", 219 "widthmin", 220 "completionlistsize", 221 "graph_fontsize", 222 "graph_depmaxdepth", 223 "graph_depmaxnodes"): 224 try: 225 value=int(value) 226 except (ValueError, TypeError): 227 return False 228 if value>10000: 229 return False 230 if value>1: 231 return True 232 else: 233 return False 234 # Boolean parameter 235 elif key in ("transpose", "shrink", "echo", "graph_linklabel", "case_sensitive"): 236 if value in ("yes", "no"): 237 return True 238 else: 239 return False 240 # String parameter 241 elif key in ("colsep", "graph_viewer"): 242 if len(value)>0: 243 return True 244 else: 245 return False 246 # Lists defined string parameter 247 elif key=="unit": 248 if value in ("b", "kb", "mb", "gb", "tb", "pb"): 249 return True 250 else: 251 return False 252 elif key=="graph_program": 253 if value in ("auto", "circo", "dot", "dotty", "fdp", "lefty", "neato", "twopi"): 254 return True 255 else: 256 return False 257 elif key=="graph_format": 258 if value in ("dia", "dot", "gif", "jpg", "jpeg", "mp", "pcl", "pic", \ 259 "plain", "png", "ps", "ps2", "svg", "svgz", "wbmp"): 260 return True 261 else: 262 return False 263 elif key=="graph_fontname": 264 if value in ("arial", "courier", "times-roman", "verdana"): 265 return True 266 else: 267 return False 268 elif key in ("graph_bordercolor", "graph_linkcolor", "graph_indexcolor", "graph_tablecolor"): 269 return True 270 else: 271 print "(DEBUG) Key %s does not exist or does not have a verify routine !" % key 272 return False
273
274 - def set(self, key, value):
275 """Sets the parameter « key » to « value »""" 276 key=str(key).lower() 277 value=str(value).lower() 278 if self.configParser is not None: 279 if not self.configParser.has_section("PYSQL"): 280 self.configParser.add_section("PYSQL") 281 print GREEN+_("(Config file created)")+RESET 282 if self.verify(key, value): 283 self.configParser.set("PYSQL", key, value) 284 self.setChanged(True) 285 else: 286 raise PysqlException(_("Sorry, value %s is not valid for parameter %s") % (value, key)) 287 else: 288 raise PysqlException(_("Cannot set config, no configParser exist !"))
289
290 - def write(self):
291 """Writes config to disk""" 292 if self.changed: 293 try: 294 configFile=file(self.configPath, "w") 295 self.configParser.write(configFile) 296 configFile.close() 297 self.setChanged(False) 298 print GREEN+_("(config file saved successfully)")+RESET 299 except Exception, e: 300 raise PysqlException(_("fail to write file: %s") % e) 301 else: 302 print CYAN+_("(no need to save)")+RESET
303
304 - def writeCache(self):
305 """Writes completion list cache to disk""" 306 try: 307 cPickle.dump(self.completeLists, file(self.cachePath, "w")) 308 except Exception, e: 309 raise PysqlException(_("Fail to save completion cache to %s. Error was:\n\t%s") 310 % (self.cachePath, e))
311
312 - def writeSqlLibrary(self):
313 """Writes user sql library to disk""" 314 try: 315 cPickle.dump(self.sqlLibrary, file(self.sqlLibPath, "w")) 316 except Exception, e: 317 raise PysqlException(_("Fail to save user sql library to %s. Error was:\n\t%s") 318 % (self.sqlLibPath, e))
319
320 - def writeHistory(self):
321 """Writes shell history to disk""" 322 try: 323 # Open r/w and close file to create one if needed 324 historyFile=file(self.historyPath, "w") 325 historyFile.close() 326 readline.set_history_length(1000) 327 readline.write_history_file(self.historyPath) 328 except Exception, e: 329 raise PysqlException(_("Fail to save history to %s. Error was:\n\t%s") 330 % (self.historyPath, e))
331 - def setChanged(self, state):
332 """Indicates if config data has changed. This is used 333 to detect if it is necessary to save config file to disk""" 334 self.changed=state
335
336 - def isChanged(self):
337 """@return: change state (boolean)""" 338 return self.changed
339
340 - def setCodec(self, codec):
341 """Sets the host codec used to display on and read from string on terminal 342 @arg codec: codec name 343 @type codec: str""" 344 self.codec=codec
345
346 - def getCodec(self):
347 """@return: host codec used to display on and from string on terminal""" 348 return self.codec
349
350 - def __which(self, command):
351 """Emulates the Unix which to search if command is in the PATH 352 Instead of which, if multiple args are given, consider it as a command line 353 and test only the first one. 354 Returns the full path to command if found or None""" 355 command=command.split()[0] 356 for directory in os.getenv("PATH").split(":"): 357 fullpath=os.path.join(directory,command) 358 if os.access(fullpath, os.X_OK): 359 return fullpath 360 return None
361
362 - def __isReadWrite(self, filepath):
363 """Checks if filepath is readable and writable. Returns a boolean 364 @param filepath: the full path to the file 365 @type filepath: str 366 @return: Boolean""" 367 if(os.access(filepath, os.R_OK) and os.access(filepath, os.W_OK)): 368 return True 369 else: 370 return False
371