Package conduit :: Package modules :: Module TestModule
[hide private]

Source Code for Module conduit.modules.TestModule

  1  import gobject 
  2  import random 
  3  import datetime 
  4  import thread 
  5  import time 
  6  import os.path 
  7  import logging 
  8  log = logging.getLogger("modules.Test") 
  9   
 10  import conduit 
 11  import conduit.utils as Utils 
 12  import conduit.utils.Memstats as Memstats 
 13  import conduit.TypeConverter as TypeConverter 
 14  import conduit.dataproviders.DataProvider as DataProvider 
 15  import conduit.dataproviders.DataProviderCategory as DataProviderCategory 
 16  import conduit.dataproviders.SimpleFactory as SimpleFactory 
 17  import conduit.dataproviders.Image as Image 
 18  import conduit.dataproviders.File as FileDataProvider 
 19  import conduit.Exceptions as Exceptions 
 20  import conduit.Web as Web 
 21  from conduit.datatypes import Rid, DataType, Text, Video, Audio, File 
 22   
 23  MODULES = { 
 24      "TestSource" :              { "type": "dataprovider" }, 
 25      "TestSink" :                { "type": "dataprovider" }, 
 26      "TestWebTwoWay" :           { "type": "dataprovider" }, 
 27      "TestFileSource" :          { "type": "dataprovider" }, 
 28      "TestFileSink" :            { "type": "dataprovider" }, 
 29      "TestFileTwoWay" :          { "type": "dataprovider" }, 
 30      "TestFolderTwoWay" :        { "type": "dataprovider" }, 
 31      "TestImageSink" :           { "type": "dataprovider" }, 
 32      "TestVideoSink" :           { "type": "dataprovider" }, 
 33      "TestAudioSink" :           { "type": "dataprovider" }, 
 34      "TestConflict" :            { "type": "dataprovider" }, 
 35      "TestConversionArgs" :      { "type": "dataprovider" }, 
 36      "TestTwoWay" :              { "type": "dataprovider" }, 
 37      "TestFailRefresh" :         { "type": "dataprovider" }, 
 38      "TestSinkNeedConfigure" :   { "type": "dataprovider" }, 
 39      "TestFactory" :             { "type": "dataprovider-factory" }, 
 40  #    "TestFactoryRemoval" :      { "type": "dataprovider-factory" }, 
 41  #    "TestSimpleFactory" :       { "type": "dataprovider-factory" }, 
 42      "TestConverter" :           { "type": "converter" } 
 43  } 
 44   
 45  DEFAULT_MTIME=datetime.datetime(2003,8,16) 
 46  DEFAULT_HASH="12345" 
 47   
 48  #Test datatype is a thin wrapper around a string in the form 
 49  #"xy.." where x is an integer, and y is a string 
50 -class TestDataType(DataType.DataType):
51 _name_ = "test_type"
52 - def __init__(self, Integer, mtime=DEFAULT_MTIME, hash=DEFAULT_HASH):
53 DataType.DataType.__init__(self) 54 self.Integer = int(Integer) 55 self.myHash = hash 56 57 #WARNING: Datatypes should not call these function from within 58 #their constructor - that is the dataproviders responsability. Consider 59 #this a special case for testing 60 self.set_UID(str(Integer)) 61 self.set_open_URI("file:///home/") 62 self.set_mtime(mtime)
63
64 - def __str__(self):
65 return "testData %s" % self.Integer
66
67 - def __getstate__(self):
68 data = DataType.DataType.__getstate__(self) 69 data['Integer'] = self.Integer 70 data['myHash'] = self.myHash 71 return data
72
73 - def __setstate__(self, data):
74 self.Integer = data['Integer'] 75 self.myHash = data['myHash'] 76 DataType.DataType.__setstate__(self, data)
77
78 - def get_hash(self):
79 return self.myHash
80
81 - def get_snippet(self):
82 return str(self) + "\nI am a piece of test data"
83 84 #The strings are numerically compared. If A < B then it is older 85 #If A is larger than B then it is newer.
86 - def compare(self, B):
87 a = self.Integer 88 b = B.Integer 89 if a < b: 90 return conduit.datatypes.COMPARISON_OLDER 91 elif a > b: 92 return conduit.datatypes.COMPARISON_NEWER 93 elif a == b: 94 return conduit.datatypes.COMPARISON_EQUAL 95 else: 96 return conduit.datatypes.COMPARISON_UNKNOWN
97
98 -class _TestBase(DataProvider.DataProviderBase):
99 _configurable_ = True
100 - def __init__(self):
101 DataProvider.DataProviderBase.__init__(self) 102 #Through an error on the nth time through 103 self.errorAfter = 999 104 self.errorFatal = False 105 self.newHash = False 106 self.newMtime = False 107 self.slow = False 108 self.UID = Utils.random_string() 109 self.numData = 5 110 #Variables to test the config fuctions 111 self.aString = "" 112 self.aInt = 0 113 self.aBool = False 114 self.aList = [] 115 self.count = 0
116
117 - def _change_detected(self, *args):
118 gobject.timeout_add(3000, self.emit_change_detected)
119
120 - def initialize(self):
121 return True
122
123 - def configure(self, window):
124 import gtk 125 import conduit.gtkui.SimpleConfigurator as SimpleConfigurator 126 127 def setError(param): 128 self.errorAfter = int(param)
129 def setErrorFatal(param): 130 self.errorFatal = bool(param)
131 def setSlow(param): 132 self.slow = bool(param) 133 def setNewHash(param): 134 self.newHash = bool(param) 135 def setNewMtime(param): 136 self.newMtime = bool(param) 137 def setUID(param): 138 self.UID = str(param) 139 def setNumData(param): 140 self.numData = int(param) 141 items = [ 142 { 143 "Name" : "Error At:", 144 "Widget" : gtk.Entry, 145 "Callback" : setError, 146 "InitialValue" : self.errorAfter 147 }, 148 { 149 "Name" : "Error is Fatal?", 150 "Widget" : gtk.CheckButton, 151 "Callback" : setErrorFatal, 152 "InitialValue" : self.errorFatal 153 }, 154 { 155 "Name" : "Take a Long Time?", 156 "Widget" : gtk.CheckButton, 157 "Callback" : setSlow, 158 "InitialValue" : self.slow 159 }, 160 { 161 "Name" : "Data gets a New Hash", 162 "Widget" : gtk.CheckButton, 163 "Callback" : setNewHash, 164 "InitialValue" : self.newHash 165 }, 166 { 167 "Name" : "Data gets a New Mtime", 168 "Widget" : gtk.CheckButton, 169 "Callback" : setNewMtime, 170 "InitialValue" : self.newMtime 171 }, 172 { 173 "Name" : "UID", 174 "Widget" : gtk.Entry, 175 "Callback" : setUID, 176 "InitialValue" : self.UID 177 }, 178 { 179 "Name" : "Num Data", 180 "Widget" : gtk.Entry, 181 "Callback" : setNumData, 182 "InitialValue" : self.numData 183 }, 184 { 185 "Name" : "Emit Change Detected", 186 "Widget" : gtk.CheckButton, 187 "Callback" : self._change_detected, 188 "InitialValue" : False 189 } 190 ] 191 dialog = SimpleConfigurator.SimpleConfigurator(window, self._name_, items) 192 dialog.run() 193
194 - def get_UID(self):
195 return self.UID
196
197 - def get_configuration(self):
198 return { 199 "errorAfter" : self.errorAfter, 200 "errorFatal" : self.errorFatal, 201 "slow" : self.slow, 202 "newHash" : self.newHash, 203 "newMtime" : self.newMtime, 204 "UID" : self.UID, 205 "aString" : "im a string", 206 "aInt" : 5, 207 "aBool" : True, 208 "aList" : ["ListItem1", "ListItem2"] 209 }
210
211 -class _TestConversionBase(DataProvider.DataSink):
212 _configurable_ = True
213 - def __init__(self, *args):
214 DataProvider.DataSink.__init__(self) 215 self.encodings = {} 216 self.encoding = "unchanged"
217
218 - def configure(self, window):
219 import gtk 220 import conduit.gtkui.SimpleConfigurator as SimpleConfigurator 221 222 def setEnc(param): 223 self.encoding = str(param)
224 225 encodings = self.encodings.keys()+["unchanged"] 226 items = [ 227 { 228 "Name" : "Format (%s)" % ",".join(encodings), 229 "Widget" : gtk.Entry, 230 "Callback" : setEnc, 231 "InitialValue" : self.encoding 232 } 233 ] 234 dialog = SimpleConfigurator.SimpleConfigurator(window, self._name_, items) 235 dialog.run()
236
237 - def get_input_conversion_args(self):
238 try: 239 return self.encodings[self.encoding] 240 except KeyError: 241 #HACK: Any conversion arg is allowed for test data type... 242 if self._in_type_ == "test_type": 243 return {"arg":self.encoding} 244 else: 245 return {}
246
247 - def get_configuration(self):
248 return {'encoding':self.encoding}
249
250 - def get_UID(self):
251 return Utils.random_string()
252
253 -class TestSource(_TestBase, DataProvider.DataSource):
254 255 _name_ = "Test Source" 256 _description_ = "Emits TestDataTypes" 257 _category_ = conduit.dataproviders.CATEGORY_TEST 258 _module_type_ = "source" 259 _in_type_ = "test_type" 260 _out_type_ = "test_type" 261 _icon_ = "go-next" 262 263 DEFAULT_NUM_DATA = 10 264
265 - def __init__(self, *args):
266 _TestBase.__init__(self) 267 DataProvider.DataSource.__init__(self) 268 self.data = [] 269 self.numData = self.DEFAULT_NUM_DATA
270
271 - def refresh(self):
272 DataProvider.DataSource.refresh(self) 273 self.data = [] 274 #Assemble a random array of data 275 for i in range(0, random.randint(1, self.numData)): 276 self.data.append(str(i))
277
278 - def get_all(self):
279 DataProvider.DataSource.get_all(self) 280 data = [] 281 for i in range(0,self.numData): 282 data.append(str(i)) 283 return data
284
285 - def get(self, LUID):
286 DataProvider.DataSource.get(self, LUID) 287 if self.slow: 288 time.sleep(1) 289 290 index = int(LUID) 291 if index >= self.errorAfter: 292 if self.errorFatal: 293 raise Exceptions.SyncronizeFatalError("Error After:%s Count:%s" % (self.errorAfter, index)) 294 else: 295 raise Exceptions.SyncronizeError("Error After:%s Count:%s" % (self.errorAfter, index)) 296 297 mtime = DEFAULT_MTIME 298 if self.newMtime: 299 mtime = datetime.datetime.now() 300 301 hash = DEFAULT_HASH 302 if self.newHash: 303 hash = Utils.random_string() 304 305 data = TestDataType(LUID, mtime, hash) 306 return data
307
308 - def add(self, LUID):
309 return True
310
311 - def finish(self, aborted, error, conflict):
312 DataProvider.DataSource.finish(self) 313 self.data = []
314
315 -class TestSink(_TestBase, DataProvider.DataSink):
316 317 _name_ = "Test Sink" 318 _description_ = "Consumes TestDataTypes" 319 _category_ = conduit.dataproviders.CATEGORY_TEST 320 _module_type_ = "sink" 321 _in_type_ = "test_type" 322 _out_type_ = "test_type" 323 _icon_ = "edit-redo" 324
325 - def __init__(self, *args):
328
329 - def put(self, data, overwrite, LUID=None):
330 DataProvider.DataSink.put(self, data, overwrite, LUID) 331 if self.slow: 332 time.sleep(1) 333 if self.count >= self.errorAfter: 334 if self.errorFatal: 335 raise Exceptions.SyncronizeFatalError("Error After:%s Count:%s" % (self.errorAfter, self.count)) 336 else: 337 raise Exceptions.SyncronizeError("Error After:%s Count:%s" % (self.errorAfter, self.count)) 338 self.count += 1 339 newData = TestDataType(data.get_UID()) 340 return newData.get_rid()
341
342 -class TestTwoWay(TestSource, TestSink):
343 344 _name_ = "Test Two Way" 345 _description_ = "Sync TestDataTypes" 346 _category_ = conduit.dataproviders.CATEGORY_TEST 347 _module_type_ = "twoway" 348 _in_type_ = "test_type" 349 _out_type_ = "test_type" 350 _icon_ = "view-refresh" 351
352 - def __init__(self, *args):
353 TestSource.__init__(self) 354 TestSink.__init__(self)
355
356 -class TestFileSource(_TestBase, DataProvider.DataSource):
357 358 _name_ = "Test File Source" 359 _description_ = "Emits Files" 360 _category_ = conduit.dataproviders.CATEGORY_TEST 361 _module_type_ = "source" 362 _in_type_ = "file" 363 _out_type_ = "file" 364 _icon_ = "text-x-generic" 365
366 - def __init__(self, *args):
367 _TestBase.__init__(self) 368 DataProvider.DataSource.__init__(self) 369 self.UID = Utils.random_string()
370
371 - def get_all(self):
372 DataProvider.DataSource.get_all(self) 373 files = [ 374 "file://"+os.path.join(conduit.SHARED_DATA_DIR,"conduit-splash.png"), 375 "file://"+__file__ 376 ] 377 return files
378
379 - def get(self, LUID):
380 DataProvider.DataSource.get(self, LUID) 381 f = File.File(URI=LUID) 382 f.set_open_URI(LUID) 383 f.set_UID(LUID) 384 return f
385
386 -class TestFileSink(_TestBase, DataProvider.DataSink):
387 388 _name_ = "Test File Sink" 389 _description_ = "Consumes Files" 390 _category_ = conduit.dataproviders.CATEGORY_TEST 391 _module_type_ = "sink" 392 _in_type_ = "file" 393 _out_type_ = "file" 394 _icon_ = "text-x-generic" 395
396 - def __init__(self, *args):
397 _TestBase.__init__(self) 398 DataProvider.DataSink.__init__(self) 399 self.folder = "file://"+Utils.new_tempdir()
400
401 - def put(self, data, overwrite, LUID=None):
402 log.debug("Putting file: %s" % data._get_text_uri()) 403 DataProvider.DataSink.put(self, data, overwrite, LUID) 404 if LUID == None: 405 LUID = self.folder+os.sep+data.get_filename() 406 data.transfer(LUID,overwrite) 407 data.set_UID(LUID) 408 return data.get_rid()
409
410 -class TestFileTwoWay(TestFileSource, TestFileSink):
411 412 _name_ = "Test File Two Way" 413 _description_ = "Sync Files" 414 _category_ = conduit.dataproviders.CATEGORY_TEST 415 _module_type_ = "twoway" 416 _in_type_ = "file" 417 _out_type_ = "file" 418 _icon_ = "text-x-generic" 419
420 - def __init__(self, *args):
423
424 -class TestFolderTwoWay(FileDataProvider.FolderTwoWay):
425 426 _name_ = "Test Folder Two Way" 427 _description_ = "Sync Folders" 428 _category_ = conduit.dataproviders.CATEGORY_TEST 429 _module_type_ = "twoway" 430 _in_type_ = "file" 431 _out_type_ = "file" 432 _icon_ = "text-x-generic" 433
434 - def __init__(self, *args):
435 #Put a single tempfile into a tempdir 436 FileDataProvider.FolderTwoWay.__init__( 437 self, 438 folder= "file://"+Utils.new_tempdir(), 439 folderGroupName="Test", 440 includeHidden=False, 441 compareIgnoreMtime=False, 442 followSymlinks=False 443 )
444
445 - def get_UID(self):
446 return self.folder
447
448 - def add(self, LUID):
449 #Add a temp file to folder 450 tmpfile = Utils.new_tempfile(Utils.random_string()) 451 self.put(tmpfile,True,None)
452
453 -class TestImageSink(_TestBase, Image.ImageSink):
454 455 _name_ = "Test Image Sink" 456