Package tipy :: Module drvr
[hide private]
[frames] | no frames]

Source Code for Module tipy.drvr

  1  #!/usr/bin/env python3 
  2  # -*- coding: utf-8 -*- 
  3   
  4  """The Driver class holds everything the program needs to perform prediction. 
  5   
  6  It gather instances of needed classes, implement some wrapper methods and the 
  7  very important L{drvr.Driver.predict} method which actualy compute the suggested 
  8  words. 
  9  """ 
 10   
 11  try: 
 12      from configparser import ConfigParser 
 13  except ImportError: 
 14      from ConfigParser import ConfigParser 
 15  try: 
 16      from StringIO import StringIO 
 17  except ImportError: 
 18      from io import StringIO 
 19  from tipy.clbk import Callback 
 20  from tipy.slct import Selector 
 21  from tipy.prdct import PredictorRegistry, PredictorActivator 
 22  from tipy.cntxt import ContextMonitor 
 23  from os import path 
 24  from tipy.lg import lg 
 25   
 26   
27 -class UnknownTypeCastError(Exception):
28 - def __init__(self, value):
29 self.value = value
30
31 - def __str__(self):
32 return repr('Unknown cast type "%s"' % self.value)
33 34
35 -class MissingConfigurationSection(Exception):
36 - def __init__(self, value):
37 self.value = value
38
39 - def __str__(self):
40 return repr('Section "%s" is missing from the configuration' 41 % self.value)
42 43
44 -class MissingConfigurationOption(Exception):
45 - def __init__(self, value):
46 self.value = value
47
48 - def __str__(self):
49 return repr('Section "%s" is missing from the configuration' 50 % self.value)
51 52
53 -class Configuration(ConfigParser):
54 """Copy a configuration file (ini format) in memory. 55 56 This class subclass the Configparser class. Configparser is used to read() a 57 configuration file (ini format) in memory in the form of a dictionary 58 associating sections and options. 59 This class implement a new method which allow to retrieve and cast a 60 configuration option and asserts the option do exists and can be casted. 61 The config file could be edited by the user and you know... never trust 62 user input. 63 64 G{classtree Configuration} 65 """ 66
67 - def __init__(self):
68 """Configuration creator.""" 69 super().__init__()
70
71 - def getas(self, section, option, typeCast=None):
72 """A more secure way to retrieve configuration options. 73 74 This method check if the section and the option is in the configuration 75 dictionary, else it raise an error. Also this method allow an optional 76 parameter for casting the result before returning it. Allowed type 77 casting are: 78 - bool: cast to bool 79 - int: cas to int 80 - float: cast to float 81 - list: cast to list 82 - intlist: cast to list and cast each element to int 83 - floatlist: cast to list and cast each element to float 84 The method makes sure the casting is possible. 85 86 @param section: 87 The section from which to retrieve the option. 88 @type section: str 89 @param option: 90 The option to retrieve inside the section. 91 @type option: str 92 @param typeCast: 93 Indicate how to cast the result. If no value are passed the 94 result is returned as a string. 95 96 @return: 97 The casted value of the given option found inside the given section. 98 @rtype: 99 str or int or bool or float or list (depends on "typeCast" param) 100 101 @raise MissingConfigurationSection: 102 If the given section cannot be found in the configuration 103 dictionary. 104 @raise MissingConfigurationOption: 105 If the given option cannot be found in the configuration dictionary. 106 @raise UnknownTypeCastError: 107 If the given typeCast value is not "bool", "int", "float", "list", 108 "intlist" or "floatlist". 109 """ 110 if not self.has_section(section): 111 raise MissingConfigurationSection(section) 112 if not self.has_option(section, option): 113 raise MissingConfigurationOption(option) 114 if not typeCast or typeCast == 'str': 115 return self.get(section, option) 116 if typeCast == 'bool': 117 return self.getboolean(section, option) 118 if typeCast == 'int': 119 return self.getint(section, option) 120 if typeCast == 'float': 121 return self.getfloat(section, option) 122 if typeCast == 'list': 123 return self.get(section, option).split() 124 if typeCast == 'intlist': 125 return [int(x) for x in self.get(section, option).split()] 126 if typeCast == 'floatlist': 127 return [float(x) for x in self.get(section, option).split()] 128 raise UnknownTypeCastError(typeCast)
129 130
131 -class Driver:
132 """The Driver class gather classes inctances and variables of the program. 133 134 G{classtree Driver} 135 """ 136
137 - def __init__(self, callback, configFile=''):
138 """The driver class. It hold every elements needed for the prediction. 139 140 @param callback: 141 The callback is used to access the input buffers from anywhere. 142 @type callback: L{Callback} 143 @param configFile: 144 Path of the configuration file. 145 @type configFile: str 146 """ 147 self.configFile = configFile 148 self.configuration = self.make_config() 149 self.callback = callback 150 self.predictorRegistry = PredictorRegistry(self.configuration) 151 self.contextMonitor = ContextMonitor( 152 self.configuration, self.predictorRegistry, callback) 153 self.predictorActivator = PredictorActivator( 154 self.configuration, self.predictorRegistry) 155 self.selector = Selector(self.configuration, self.contextMonitor)
156
157 - def predict(self):
158 """Request suggested words to predictors. 159 160 This method: 161 - Do the next two steps until it cannot get more suggestions. 162 - Call the L{prdct.PredictorActivator.predict} which: 163 - Call the L{prdct.Predictor.predict} method of each 164 predictors in the predictorRegistry. Each predict() method 165 should return a Prediction instance containing the suggested 166 words computed by the predictor (it may be empty). 167 - Merge the Prediction instances into a single Prediction 168 instance. 169 - Select the best suggestions in the Prediction instance and remove 170 the excess. 171 - Learn from what the user have typped. 172 - Return the selected suggestions. 173 174 @return: 175 The suggested words list. 176 @rtype: list 177 """ 178 factor = 1 179 predictions = self.predictorActivator.predict(factor) 180 result = self.selector.select(predictions) 181 182 previousPredictions = predictions 183 while len(result) < self.selector.suggestions: 184 predictions = self.predictorActivator.predict(factor) 185 if len(predictions) > len(previousPredictions): 186 factor += 1 187 result = self.selector.select(predictions) 188 previousPredictions = predictions 189 else: 190 lg.warning('WARNING: Expected number of suggestions cannot be ' 191 'reached.') 192 break 193 self.learn_from_buffers() 194 return result
195
196 - def learn_from_buffers(self):
197 """Simple ContextMonitor.update() wrapper for comprehension sake.""" 198 self.contextMonitor.update()
199
200 - def make_completion(self, suggestion):
201 """Simple ContextMonitor.make_completion() wrapper.""" 202 return self.contextMonitor.make_completion(suggestion)
203
204 - def close_databases(self):
205 """Close every opened predictors database.""" 206 self.predictorRegistry.close_database()
207
208 - def make_config(self):
209 """Initialize the config dictionary. 210 211 This method first try to read the configuration file and parse it into 212 a Configuration instance (dictionary). 213 If the config file is empty or dosen't exists, than a default config 214 dictionary is created. 215 216 @return: 217 The Configuration instance holding every settings (dictionary 218 style). 219 @rtype: L{drvr.Configuration} 220 """ 221 config = Configuration() 222 if config.read(self.configFile) == []: 223 lg.warning('Cannot open config file "%s"' % self.configFile) 224 config.readfp(StringIO( 225 """ 226 [Global] 227 language = en 228 229 [GUI] 230 font_size = 10 231 232 [MinerRegistry] 233 miners = CorpusMiner FbMiner 234 235 [CorpusMiner] 236 class = CorpusMiner 237 texts = ../txt/brown.txt 238 database = ../databases/corp.db 239 lowercase = False 240 n = 3 241 242 [DictMiner] 243 class = DictMiner 244 dictionary = /usr/share/dict/words 245 database = ../databases/dict.db 246 247 [FbMiner] 248 class = FacebookMiner 249 accesstoken = CAAUh40uO4aIBACsN37erjPUfrs0IdRZAxpbc7IhGlWpKX1REif4NPhqqD4tdZCdZBgT1J3K41ZCB3CHsjcWV78tNEDtwPwmHZBPJ3NgLV29rZCSl4vkGEqPdyEq9UNRR7OkMS1195LWO7W5jUjBrsuRYZBT7IemlZAg4FHZANrZBkaSZCwzxyrbplNYSYRB28vIdzpeLSh2s0gFZAykLoaeDQ6IKk02K9UCnK9QZD 250 database = ../databases/fb.db 251 lowercase = False 252 n = 3 253 last_update = 1433879088 254 255 [TwitterMiner] 256 257 [PredictorRegistry] 258 predictors = CorpusNgramPredictor InputNgramPredictor DictionaryPredictor 259 260 [ContextMonitor] 261 live_learning = True 262 monitored_scope = 80 263 lowercase = True 264 265 [Selector] 266 suggestions = 6 267 greedy_suggestion_threshold = 0 268 269 [PredictorActivator] 270 predict_time = 1000 271 max_partial_prediction_size = 50 272 merging_method = probabilistic 273 stoplist = ../stoplists/insanities_en.stoplist 274 275 [CorpusNgramPredictor] 276 class = WeightNgramPredictor 277 database = ../databases/corp.db 278 deltas = 0.01 0.1 0.89 279 learn = False 280 281 [InputNgramPredictor] 282 class = WeightNgramPredictor 283 database = ../databases/user.db 284 deltas = 0.01 0.1 0.89 285 learn = True 286 287 [FbNgramPredictor] 288 class = WeightNgramPredictor 289 database = ../databases/fb.db 290 deltas = 0.01 0.1 0.89 291 learn = False 292 293 [LateOccurPredictor] 294 class = LastOccurPredictor 295 lambda = 1 296 n_0 = 1 297 cutoff_threshold = 20 298 299 [MemorizePredictor] 300 class = MemorizePredictor 301 memory = ../txt/memory.txt 302 trigger = 3 303 learn = True 304 305 [DictionaryPredictor] 306 class = DictionaryPredictor 307 database = ../databases/dict.db 308 probability = 0.000001 309 """)) 310 else: 311 for section in config._sections: 312 for key, value in config._sections[section].items(): 313 config.set(section, key, value.replace( 314 '~', path.expanduser("~"))) 315 return config
316