Beispiel #1
0
class SyncDaemonToolProxy(object):
    """Platform dependent proxy to syncdaemon.

    Please note that most of the methods of this class are "pre-processed"
    by overriding __getattribute__, in a way where _call_after_connection
    is called before the method itself, so every public method will return
    a deferred that will be fired when this client is connected.

    """

    _SIGNAL_MAPPING = {
        "Event": ("events", "on_event_cb"),
        "FolderCreated": ("folders", "on_folder_created_cb"),
        "FolderCreateError": ("folders", "on_folder_create_error_cb"),
        "FolderDeleted": ("folders", "on_folder_deleted_cb"),
        "FolderDeleteError": ("folders", "on_folder_delete_error_cb"),
        "FolderSubscribed": ("folders", "on_folder_subscribed_cb"),
        "FolderSubscribeError": ("folders", "on_folder_subscribe_error_cb"),
        "FolderUnSubscribed": ("folders", "on_folder_unsubscribed_cb"),
        "FolderUnSubscribeError": ("folders", "on_folder_unsubscribe_error_cb"),
        "NewShare": ("shares", "on_new_share_cb"),
        "PublicAccessChanged": ("public_files", "on_public_access_changed_cb"),
        "PublicAccessChangeError": ("public_files", "on_public_access_change_error_cb"),
        "PublicFilesList": ("public_files", "on_public_files_list_cb"),
        "PublicFilesListError": ("public_files", "on_public_files_list_error_cb"),
        "ShareAnswerResponse": ("shares", "on_share_answer_response_cb"),
        "ShareChanges": ("shares", "on_share_changed_cb"),
        "ShareCreated": ("shares", "on_share_created_cb"),
        "ShareCreateError": ("shares", "on_share_create_error_cb"),
        "ShareDeleted": ("shares", "on_share_deleted_cb"),
        "ShareDeleteError": ("shares", "on_share_delete_error_cb"),
        "ShareSubscribed": ("shares", "on_share_subscribed_cb"),
        "ShareSubscribeError": ("shares", "on_share_subscribe_error_cb"),
        "ShareUnSubscribed": ("shares", "on_share_unsubscribed_cb"),
        "ShareUnSubscribeError": ("shares", "on_share_unsubscribe_error_cb"),
        "StatusChanged": ("status", "on_status_changed_cb"),
        "VolumesChanged": ("sync_daemon", "on_volumes_changed_cb"),
    }

    # All methods and instance variables that should not be handled by
    # _call_after_connection  should be put in the list below (or start with _)

    _DONT_VERIFY_CONNECTED = ["wait_connected", "client", "last_event", "delayed_call", "log", "connected"]

    def _should_wrap(self, attr_name):
        """Check if this attribute should be wrapped."""
        return not (attr_name in SyncDaemonToolProxy._DONT_VERIFY_CONNECTED or attr_name.startswith("_"))

    def __getattribute__(self, attr_name):
        """If the attribute is not special, verify the ipc connection."""
        attr = super(SyncDaemonToolProxy, self).__getattribute__(attr_name)
        if SyncDaemonToolProxy._should_wrap(self, attr_name):
            return self._call_after_connection(attr)
        else:
            return attr

    def __init__(self, bus=None):
        self.client = UbuntuOneClient()
        self.connected = self.client.connect()

    def _call_after_connection(self, method):
        """Make sure Perspective Broker is connected before calling."""

        @defer.inlineCallbacks
        def call_after_connection_inner(*args, **kwargs):
            """Call the given method after the connection to pb is made."""
            yield self.connected
            retval = yield method(*args, **kwargs)
            defer.returnValue(retval)

        return call_after_connection_inner

    def call_method(self, client_kind, method_name, *args, **kwargs):
        """Call the 'method_name' passing 'args' and 'kwargs'."""
        client = getattr(self.client, client_kind)
        method = getattr(client, method_name)
        result = method(*args, **kwargs)
        return result

    def shutdown(self):
        """Close connections."""
        return self.client.disconnect()

    def connect_signal(self, signal_name, handler):
        """Connect 'handler' with 'signal_name'."""
        client_kind, callback = self._SIGNAL_MAPPING[signal_name]
        client = getattr(self.client, client_kind)
        setattr(client, callback, handler)
        return handler

    def disconnect_signal(self, signal_name, handler_or_match):
        """Disconnect 'handler_or_match' from 'signal_name'."""
        client_kind, callback = self._SIGNAL_MAPPING[signal_name]
        client = getattr(self.client, client_kind)
        setattr(client, callback, None)
        return handler_or_match

    def wait_connected(self):
        """Wait until syncdaemon is connected to the server."""
        return self.connected

    def start(self):
        """Start syncdaemon, should *not* be running."""
        # look in the reg to find the path of the .exe to be executed
        # to launch the sd on windows
        key = OpenKey(HKEY_LOCAL_MACHINE, U1_REG_PATH)
        path = QueryValueEx(key, SD_INSTALL_PATH)[0]
        if not os.path.exists(path):
            # either the .exe was moved of the value is wrong
            return defer.fail(WindowsError(errno.ENOENT, "Could not start syncdaemon: File not found %s" % path))
        p = subprocess.Popen([path])
        return defer.succeed(p)
Beispiel #2
0
class SyncDaemonTool(object):
    """Various utility methods to test/play with the SyncDaemon."""

    # WARNING: most of the methods of this class are "pre-processed" by
    # __getattribute__, to call _call_after_connection before the method
    # is called, so they should either be decorated with inlineCallbacks
    # or return a deferred.
    #
    # All methods and instance variables that should not be handled that way
    # should be put in the list below (or start with _):

    _DONT_VERIFY_CONNECTED = [
        "wait_connected",
        "client", "last_event", "delayed_call", "log", "connected",
    ]

    def _should_wrap(self, attr_name):
        """Check if this attribute should be wrapped."""
        return not (attr_name in SyncDaemonTool._DONT_VERIFY_CONNECTED
                    or attr_name.startswith("_"))

    def __getattribute__(self, attr_name):
        """If the attribute is not special, verify the ipc connection."""
        attr = super(SyncDaemonTool, self).__getattribute__(attr_name)
        if SyncDaemonTool._should_wrap(self, attr_name):
            return self._call_after_connection(attr)
        else:
            return attr

    def __init__(self):
        """Initialize this instance."""
        self.client = UbuntuOneClient()
        self.last_event = 0
        self.delayed_call = None
        self.log = logging.getLogger('ubuntuone.SyncDaemon.SDTool')
        self.connected = self.client.connect()

    def _call_after_connection(self, method):
        """Make sure Perspective Broker is connected before calling."""

        @defer.inlineCallbacks
        def call_after_connection_inner(*args, **kwargs):
            """Call the given method after the connection to pb is made."""
            yield self.connected
            retval = yield method(*args, **kwargs)
            defer.returnValue(retval)

        return call_after_connection_inner

    def _get_dict(self, a_dict):
        """Converts a dict returned by the IPC to a dict of strings."""
        str_dict = {}
        for key in a_dict:
            str_dict[key] = unicode(a_dict[key])
        return str_dict

    def wait_connected(self):
        """Wait until syncdaemon is connected to the server."""
        self.log.debug('wait_connected')
        d = defer.Deferred()

        def check_connection_status():
            """Check if the daemon is up and running."""
            # check if the syncdaemon is running
            # catch all errors, pylint: disable-msg=W0703
            try:
                self.client.connect()
                d.callback(True)
            except Exception, e:
                self.log.debug('Not connected: %s', e)
                d.errback()

        reactor.callLater(.5, check_connection_status)
        return d