conduit r1221 - in trunk: . conduit conduit/datatypes conduit/modules conduit/modules/GConfModule scripts test/python-tests



Author: jstowers
Date: Tue Jan 15 11:07:35 2008
New Revision: 1221
URL: http://svn.gnome.org/viewvc/conduit?rev=1221&view=rev

Log:
2008-01-15  John Stowers  <john stowers gmail com>

	* conduit/DeltaProvider.py:
	* conduit/datatypes/__init__.py:
	* test/python-tests/TestCoreSyncWithConversion.py: Small fixes

	* conduit/datatypes/File.py: Split the force_new_{mtime,filename} out so
	they can be called directly
	
	* conduit/modules/GConfModule/GConfModule.py: Dont trigger an autosync if
	we were responsible for the change

	* scripts/continuous-tester.sh:
	* scripts/upload-doc.sh: Use getopt. dbus-launch optional. Misc fixes

	* conduit/modules/TestModule.py: Add TestFolderTwoWay 

	* test/python-tests/TestCoreSyncTestDataProviders.py: Test TestFolderTwoWay

	* test/python-tests/TestSyncGConfFolder.py: Add test. Illustrates bug where
	a mapping gets reversed on the 3rd modification.



Added:
   trunk/test/python-tests/TestSyncGConfFolder.py
Modified:
   trunk/ChangeLog
   trunk/conduit/DeltaProvider.py
   trunk/conduit/datatypes/File.py
   trunk/conduit/datatypes/__init__.py
   trunk/conduit/modules/GConfModule/GConfModule.py
   trunk/conduit/modules/TestModule.py
   trunk/scripts/continuous-tester.sh
   trunk/scripts/upload-doc.sh
   trunk/test/python-tests/TestCoreSyncTestDataProviders.py
   trunk/test/python-tests/TestCoreSyncWithConversion.py

Modified: trunk/conduit/DeltaProvider.py
==============================================================================
--- trunk/conduit/DeltaProvider.py	(original)
+++ trunk/conduit/DeltaProvider.py	Tue Jan 15 11:07:35 2008
@@ -28,14 +28,11 @@
         """
         @returns: added, modified, deleted
         """
-        #Copy (slice) list for in case there are other sinks to follow
-        #allItems = self.me.module.get_all()[:]
         allItems = []
         for i in self.me.module.get_all():
             #Maybe we should be unicode....
             assert type(i) in [str,unicode], "LUID Must be str not %s" % type(i)
             allItems.append(i)
-
         log.debug("Delta: Got %s items\n%s" % (len(allItems), allItems))
 
         #In order to detect deletions we need to fetch all the existing relationships.

Modified: trunk/conduit/datatypes/File.py
==============================================================================
--- trunk/conduit/datatypes/File.py	(original)
+++ trunk/conduit/datatypes/File.py	Tue Jan 15 11:07:35 2008
@@ -129,6 +129,30 @@
             return True
         else:
             return False
+
+    def _set_file_mtime(self, mtime):
+        timestamp = conduit.Utils.datetime_get_timestamp(mtime)
+        log.debug("Setting mtime of %s to %s (%s)" % (self.URI, timestamp, type(timestamp)))
+        newInfo = gnomevfs.FileInfo()
+        newInfo.mtime = timestamp
+        gnomevfs.set_file_info(self.URI,newInfo,gnomevfs.SET_FILE_INFO_TIME)
+        #close so the file info is re-read
+        self._close_file()
+
+    def _set_filename(self, filename):
+        newInfo = gnomevfs.FileInfo()
+        newInfo.name = filename
+
+        oldname = self.get_filename()
+        olduri = self._get_text_uri()
+        newuri = olduri.replace(oldname, filename)
+        
+        if filename != oldname:
+            log.debug("Trying to rename file %s (%s) -> %s (%s)" % (olduri,oldname,newuri,filename))
+            gnomevfs.set_file_info(self.URI,newInfo,gnomevfs.SET_FILE_INFO_NAME)
+            #close so the file info is re-read
+            self.URI = gnomevfs.URI(newuri)
+            self._close_file()
             
     def set_from_instance(self, f):
         """
@@ -193,19 +217,7 @@
             self._defer_rename(filename)
         else:
             try:
-                newInfo = gnomevfs.FileInfo()
-                newInfo.name = filename
-
-                oldname = self.get_filename()
-                olduri = self._get_text_uri()
-                newuri = olduri.replace(oldname, filename)
-                
-                if filename != oldname:
-                    log.debug("Trying to rename file %s (%s) -> %s (%s)" % (olduri,oldname,newuri,filename))
-                    gnomevfs.set_file_info(self.URI,newInfo,gnomevfs.SET_FILE_INFO_NAME)
-                    #close so the file info is re-read
-                    self.URI = gnomevfs.URI(newuri)
-                    self._close_file()
+                self._set_filename(filename)
             except gnomevfs.NotSupportedError:
                 #dunno what this is
                 self._defer_rename(filename)
@@ -236,13 +248,7 @@
             self._defer_new_mtime(mtime)
         else:
             try:
-                timestamp = conduit.Utils.datetime_get_timestamp(mtime)
-                log.debug("Setting mtime of %s to %s (%s)" % (self.URI, timestamp, type(timestamp)))
-                newInfo = gnomevfs.FileInfo()
-                newInfo.mtime = timestamp
-                gnomevfs.set_file_info(self.URI,newInfo,gnomevfs.SET_FILE_INFO_TIME)
-                #close so the file info is re-read
-                self._close_file()
+                self._set_file_mtime(mtime)
             except gnomevfs.NotSupportedError:
                 #dunno what this is
                 self._defer_new_mtime(mtime)
@@ -253,7 +259,6 @@
                 #file is on readonly filesystem
                 self._defer_new_mtime(mtime)
 
-
     def transfer(self, newURIString, overwrite=False, cancel_function=None):
         """
         Transfers the file to newURI. Thin wrapper around go_gnomevfs_transfer

Modified: trunk/conduit/datatypes/__init__.py
==============================================================================
--- trunk/conduit/datatypes/__init__.py	(original)
+++ trunk/conduit/datatypes/__init__.py	Tue Jan 15 11:07:35 2008
@@ -35,15 +35,15 @@
     def __eq__(self, other):
         if other == None:
             return False
-        log.debug("EQ: UID:%s mtime:%s hash:%s" % (self.uid != other.uid, self.mtime != other.mtime, self.hash != other.hash))
-        log.debug("EQ Types: UID:%sv%s mtime:%sv%s hash:%sv%s" % (type(self.uid),type(other.uid),type(self.mtime),type(other.mtime),type(self.hash),type(other.hash)))
+        #log.debug("EQ: UID:%s mtime:%s hash:%s" % (self.uid != other.uid, self.mtime != other.mtime, self.hash != other.hash))
+        #log.debug("EQ Types: UID:%sv%s mtime:%sv%s hash:%sv%s" % (type(self.uid),type(other.uid),type(self.mtime),type(other.mtime),type(self.hash),type(other.hash)))
         return self.uid == other.uid and self.mtime == other.mtime and self.hash == other.hash
         
     def __ne__(self, other):
         if other == None:
             return True
-        log.debug("NE: UID:%s mtime:%s hash:%s" % (self.uid != other.uid, self.mtime != other.mtime, self.hash != other.hash))
-        log.debug("NE Types: UID:%sv%s mtime:%sv%s hash:%sv%s" % (type(self.uid),type(other.uid),type(self.mtime),type(other.mtime),type(self.hash),type(other.hash)))
+        #log.debug("NE: UID:%s mtime:%s hash:%s" % (self.uid != other.uid, self.mtime != other.mtime, self.hash != other.hash))
+        #log.debug("NE Types: UID:%sv%s mtime:%sv%s hash:%sv%s" % (type(self.uid),type(other.uid),type(self.mtime),type(other.mtime),type(self.hash),type(other.hash)))
         return self.uid != other.uid or self.mtime != other.mtime or self.hash != other.hash
 
     def __hash__(self):

Modified: trunk/conduit/modules/GConfModule/GConfModule.py
==============================================================================
--- trunk/conduit/modules/GConfModule/GConfModule.py	(original)
+++ trunk/conduit/modules/GConfModule/GConfModule.py	Tue Jan 15 11:07:35 2008
@@ -27,24 +27,25 @@
     _icon_ = "preferences-desktop"
     
     DEFAULT_WHITELIST = [
-            '/apps/metacity/*',
-            '/desktop/gnome/applications/*',
-            '/desktop/gnome/background/*',
-            '/desktop/gnome/interface/*',
-            '/desktop/gnome/url-handlers/*'
-        ]
+                '/apps/metacity/*',
+                '/desktop/gnome/applications/*',
+                '/desktop/gnome/background/*',
+                '/desktop/gnome/interface/*',
+                '/desktop/gnome/url-handlers/*'
+                ]
 
     def __init__(self, *args):
         DataProvider.TwoWay.__init__(self)
         AutoSync.AutoSync.__init__(self)
 
         self.whitelist = self.DEFAULT_WHITELIST
+        self.awaitingChanges = {}
 
         self.gconf = gconf.client_get_default()
         self.gconf.add_dir('/', gconf.CLIENT_PRELOAD_NONE)
-        self.gconf.notify_add('/', self.on_change)
+        self.gconf.notify_add('/', self._on_change)
 
-    def _onthelist(self, key):
+    def _in_the_list(self, key):
         for pattern in self.whitelist:
             if fnmatch.fnmatch(key, pattern):
                 return True
@@ -55,7 +56,7 @@
         for x in self.gconf.all_dirs(path):
             entries += self._get_all(x)
         for x in self.gconf.all_entries(path):
-            if self._onthelist(x.key):
+            if self._in_the_list(x.key):
                 entries.append(x.key)
         return entries
 
@@ -97,16 +98,39 @@
     def _to_gconf(self, key, value):
         t = self._gconf_type(key)
         if t == gconf.VALUE_INT:
-            self.gconf.set_int(key, int(value))
+            val = int(value)
+            func = self.gconf.set_int
         elif t == gconf.VALUE_STRING:
-            self.gconf.set_string(key, str(value))
+            val = str(value)
+            func = self.gconf.set_string
         elif t == gconf.VALUE_BOOL:
-            self.gconf.set_bool(key, bool(value))
+            val = bool(value)
+            func = self.gconf.set_bool
         elif t == gconf.VALUE_FLOAT:
-            self.gconf.set_float(key, float(value))
+            val = float(value)
+            func = self.gconf.set_float
         elif t == gconf.VALUE_LIST:
-            value = [self._from_gconf(x) for x in value]
-            self.gconf.set_list(key, eval(value))
+            val = eval([self._from_gconf(x) for x in value])
+            func = self.gconf.set_list
+        else:
+            log.warn("Unknown gconf key: %s" % key)
+            return
+
+        #We will get a notification that a key has changed.
+        #ignore it (because we made the change)
+        self.awaitingChanges[key] = val
+        #bit of a dance to ensure that we edit awaitingChanges before we
+        #make the change
+        func(key, val)
+
+    def _on_change(self, client, id, entry, data):
+        if self._in_the_list(entry.key):
+            #check to see if the change was one of ours
+            try:
+                del(self.awaitingChanges[entry.key])
+            except KeyError:
+                #the change wasnt from us
+                self.handle_modified(entry.key)
 
     def refresh(self):
         pass
@@ -144,9 +168,5 @@
     def delete(self, uid):
         self.gconf.unset(uid)
 
-    def on_change(self, client, id, entry, data):
-        if self._onthelist(entry.key):
-            self.handle_modified(entry.key)
-        
     def get_UID(self):
         return self.__class__.__name__

Modified: trunk/conduit/modules/TestModule.py
==============================================================================
--- trunk/conduit/modules/TestModule.py	(original)
+++ trunk/conduit/modules/TestModule.py	Tue Jan 15 11:07:35 2008
@@ -13,6 +13,7 @@
 import conduit.dataproviders.DataProviderCategory as DataProviderCategory
 import conduit.dataproviders.SimpleFactory as SimpleFactory
 import conduit.dataproviders.Image as Image
+import conduit.dataproviders.File as FileDataProvider
 import conduit.Exceptions as Exceptions
 import conduit.Web as Web
 from conduit.datatypes import Rid, DataType, Text, Video, Audio, File
@@ -24,6 +25,7 @@
     "TestFileSource" :          { "type": "dataprovider" },
     "TestFileSink" :            { "type": "dataprovider" },
     "TestFileTwoWay" :          { "type": "dataprovider" },
+    "TestFolderTwoWay" :        { "type": "dataprovider" },
     "TestImageSink" :           { "type": "dataprovider" },
     "TestVideoSink" :           { "type": "dataprovider" },
     "TestAudioSink" :           { "type": "dataprovider" },
@@ -347,8 +349,8 @@
     def get_all(self):
         DataProvider.DataSource.get_all(self)
         files = [
-            os.path.join(conduit.SHARED_DATA_DIR,"conduit-splash.png"),
-            __file__
+            "file://"+os.path.join(conduit.SHARED_DATA_DIR,"conduit-splash.png"),
+            "file://"+__file__
             ]
         return files
         
@@ -372,15 +374,16 @@
     def __init__(self, *args):
         _TestBase.__init__(self)
         DataProvider.DataSink.__init__(self)
+        self.folder = "file://"+Utils.new_tempdir()
 
     def put(self, data, overwrite, LUID=None):
         log.debug("Putting file: %s" % data._get_text_uri())
         DataProvider.DataSink.put(self, data, overwrite, LUID)
         if LUID == None:
-            LUID = data.get_UID()
-        f = File.File(URI=LUID)
-        f.set_UID(LUID)
-        return f.get_rid()
+            LUID = self.folder+os.sep+data.get_filename()
+        data.transfer(LUID,overwrite)
+        data.set_UID(LUID)
+        return data.get_rid()
         
 class TestFileTwoWay(TestFileSource, TestFileSink):
 
@@ -396,6 +399,35 @@
         TestFileSource.__init__(self)
         TestFileSink.__init__(self)
 
+class TestFolderTwoWay(FileDataProvider.FolderTwoWay):
+
+    _name_ = "Test Folder Two Way"
+    _description_ = "Sync Folders"
+    _category_ = conduit.dataproviders.CATEGORY_TEST
+    _module_type_ = "twoway"
+    _in_type_ = "file"
+    _out_type_ = "file"
+    _icon_ = "text-x-generic"
+
+    def __init__(self, *args):
+        #Put a single tempfile into a tempdir
+        FileDataProvider.FolderTwoWay.__init__(
+                            self,
+                            folder= "file://"+Utils.new_tempdir(),
+                            folderGroupName="Test",
+                            includeHidden=False,
+                            compareIgnoreMtime=False
+                            )
+        self.need_configuration(False)
+
+    def get_UID(self):
+        return self.folder
+
+    def add(self, LUID):
+        #Add a temp file to folder
+        tmpfile = Utils.new_tempfile(Utils.random_string())
+        self.put(tmpfile,True,None)
+
 class TestImageSink(_TestBase, Image.ImageSink):
 
     _name_ = "Test Image Sink"

Modified: trunk/scripts/continuous-tester.sh
==============================================================================
--- trunk/scripts/continuous-tester.sh	(original)
+++ trunk/scripts/continuous-tester.sh	Tue Jan 15 11:07:35 2008
@@ -1,7 +1,7 @@
 #!/bin/sh
 #Continuously builds and tests conduit from GNOME svn
-TEST_DIR='/tmp/conduittestdir'
-LOGFILE='/home/john/Desktop/conduit-test.log'
+TEST_DIR='/home/john/testing/conduit'
+LOGFILE='/home/john/testing/conduit-test.log'
 SVN_REPO='http://svn.gnome.org/svn/conduit/trunk'
 TEST_OPTIONS='cu'
 SLEEP_TIME='1h'
@@ -13,31 +13,30 @@
 Runs the conduit test suite and uploads the results. Defaults to only running\n\
 if the remote repository has changed\n\n\
 Options:\n\
-\t-f, --force\t\tRun the tests even if the repository has not changed\n\
-\t-d, --disable-docs\tDisable buliding of documentation\n\
-\t-l, --loop\t\tRuns in a never ending loop"
+\t-f\t\tRun the tests even if the repository has not changed\n\
+\t-d\t\tDisable buliding of documentation\n\
+\t-l\t\tRun in a never ending loop\n\
+\t-b\t\tRun with dbus-launch\n\
+\t-h\t\tShow this help message\n"
 
 FORCE=no
 DOCS=yes
 CNT=-1
 LOOP=no
-#Check the arguments.
-for option in "$@"; do
-  case "$option" in
-    -h | --help)
-      echo $USAGE
-      exit 0 ;;
-    -f | --force)
-      FORCE=yes ;;
-    -d | --disable-docs)
-      DOCS=no ;;
-    -l | --loop)
-      CNT=1
-      LOOP=yes ;;
-    -*)
-      echo "Unrecognized option: $option\n\n$USAGE"
-      exit 1 ;;
-  esac
+DBUS_LAUNCH=''
+while getopts "fdlbh" options
+do
+    case $options in
+        f )     FORCE=yes;;
+        d )     DOCS=no;;
+        l )     LOOP=yes
+                CNT=1;;
+        b )     DBUS_LAUNCH=dbus-launch;;
+        h )     echo $USAGE
+                exit 0;;
+        * )     echo $USAGE
+                exit 1;;
+    esac
 done
 
 if [ ! -d $TEST_DIR ]; then
@@ -60,7 +59,7 @@
         #being run from a VT
         svn up . 
         echo "`date` Running Test (Revision $RVERSION)" | tee -a $LOGFILE
-        dbus-launch $TEST_DIR/scripts/run-tests.sh -$TEST_OPTIONS 
+        $DBUS_LAUNCH $TEST_DIR/scripts/run-tests.sh -$TEST_OPTIONS 
         
         #Build packages
         #./autogen.sh && make && make dist &>/dev/null

Modified: trunk/scripts/upload-doc.sh
==============================================================================
--- trunk/scripts/upload-doc.sh	(original)
+++ trunk/scripts/upload-doc.sh	Tue Jan 15 11:07:35 2008
@@ -6,4 +6,4 @@
     exit 1
 fi
 
-rsync -qtz --delete doc/*.{html,gif,png,py,js,css} root greenbirdsystems com:/var/www/conduit-project.org/doc/conduit
+rsync -qtz doc/*.{html,gif,png,py,js,css} root greenbirdsystems com:/var/www/conduit-project.org/doc/conduit

Modified: trunk/test/python-tests/TestCoreSyncTestDataProviders.py
==============================================================================
--- trunk/test/python-tests/TestCoreSyncTestDataProviders.py	(original)
+++ trunk/test/python-tests/TestCoreSyncTestDataProviders.py	Tue Jan 15 11:07:35 2008
@@ -161,4 +161,23 @@
 aborted,errored,conflicted = test.get_sync_result()
 ok("Sync completed without conflicts", aborted == False and errored == False and conflicted == False)
 
+
+###
+#Test folder sink
+###
+ok("---- TWO WAY: TEST FILE", True)
+test = SimpleSyncTest()
+test.set_two_way_policy({"conflict":"ask","deleted":"ask"})
+
+#add a file to source and sink
+source = test.get_dataprovider("TestFolderTwoWay")
+source.module.add(None)
+sink = test.get_dataprovider("TestFolderTwoWay")
+sink.module.add(None)
+test.prepare(source, sink)
+test.set_two_way_sync(True)
+test.sync(debug=False)
+aborted,errored,conflicted = test.get_sync_result()
+ok("Sync completed without conflicts", aborted == False and errored == False and conflicted == False)
+
 finished()

Modified: trunk/test/python-tests/TestCoreSyncWithConversion.py
==============================================================================
--- trunk/test/python-tests/TestCoreSyncWithConversion.py	(original)
+++ trunk/test/python-tests/TestCoreSyncWithConversion.py	Tue Jan 15 11:07:35 2008
@@ -109,8 +109,6 @@
 so,sk = test.sync(debug=DB_DEBUG)
 ok("Sync'd data", so == 2 and sk == 2)
 
-
-
 #Modify t
 sink.mtime=datetime.datetime(2007,2,24)
 test.sync(debug=DB_DEBUG)
@@ -119,7 +117,7 @@
                             sourceUID=sink.get_UID(),
                             sinkUID=source.get_UID()
                             )
-print maps
-#ok("MappingDB saved all relationships
+
+test.sync(debug=DB_DEBUG)
 
 finished()

Added: trunk/test/python-tests/TestSyncGConfFolder.py
==============================================================================
--- (empty file)
+++ trunk/test/python-tests/TestSyncGConfFolder.py	Tue Jan 15 11:07:35 2008
@@ -0,0 +1,34 @@
+#common sets up the conduit environment
+from common import *
+
+#setup test
+test = SimpleSyncTest()
+
+#Setup the key to sync
+gconf = test.get_dataprovider("GConfTwoWay")
+gconf.module.whitelist = ['/apps/metacity/general/num_workspaces']
+folder = test.get_dataprovider("TestFolderTwoWay")
+
+test.prepare(gconf, folder)
+test.set_two_way_policy({"conflict":"ask","deleted":"ask"})
+test.set_two_way_sync(True)
+
+a = test.get_source_count()
+b = test.get_sink_count()
+ok("Got items to sync (%s,%s)" % (a,b), a == 1 and b == 0)
+
+for i in (1,2,3,4):
+    if i > 1:
+        #Now modify the file
+        f = folder.module.get(
+                folder.module.get_all()[0]
+                )
+        f._set_file_mtime(datetime.datetime(2008,1,i))
+
+    a,b = test.sync()
+    aborted,errored,conflicted = test.get_sync_result()
+    ok("Sync #%s: Completed without conflicts" % i, aborted == False and errored == False and conflicted == False)
+    ok("Sync #%s: All items (%s,%s)" % (i,a,b), a == b and a == 1)
+
+finished()
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]