def pull(self, task, onconflict=None):
        """
            Fetch updates from the peer repository and import them
            into the local database (active pull)

            @param task: the synchronization task (sync_task Row)
            @param onconflict: callback for automatic conflict resolution

            @return: tuple (error, mtime), with error=None if successful,
                     else error=message, and mtime=modification timestamp
                     of the youngest record sent
        """

        repository = self.repository
        xml = current.xml
        config = repository.config
        resource_name = task.resource_name

        current.log.debug("S3Sync: pull %s from %s" % (resource_name,
                                                       repository.url))

        # Construct the URL
        url = "%s/sync/sync.xml?resource=%s&repository=%s" % \
              (repository.url, resource_name, config.uuid)
        last_pull = task.last_pull
        if last_pull and task.update_policy not in ("THIS", "OTHER"):
            url += "&msince=%s" % s3_encode_iso_datetime(last_pull)
        url += "&include_deleted=True"

        # Send sync filters to peer
        filters = current.sync.get_filters(task.id)
        filter_string = None
        resource_name = task.resource_name
        for tablename in filters:
            prefix = "~" if not tablename or tablename == resource_name \
                            else tablename
            for k, v in filters[tablename].items():
                urlfilter = "[%s]%s=%s" % (prefix, k, v)
                url += "&%s" % urlfilter

        # Figure out the protocol from the URL
        url_split = url.split("://", 1)
        if len(url_split) == 2:
            protocol, path = url_split
        else:
            protocol, path = "http", None

        # Create the request
        req = urllib2.Request(url=url)
        handlers = []

        # Proxy handling
        proxy = repository.proxy or config.proxy or None
        if proxy:
            current.log.debug("S3Sync: pull, using proxy=%s" % proxy)
            proxy_handler = urllib2.ProxyHandler({protocol: proxy})
            handlers.append(proxy_handler)

        # Authentication handling
        username = repository.username
        password = repository.password
        if username and password:
            # Send auth data unsolicitedly (the only way with Eden instances):
            import base64
            base64string = base64.encodestring('%s:%s' %
                                               (username, password))[:-1]
            req.add_header("Authorization", "Basic %s" % base64string)
            # Just in case the peer does not accept that, add a 401 handler:
            passwd_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
            passwd_manager.add_password(realm=None,
                                        uri=url,
                                        user=username,
                                        passwd=password)
            auth_handler = urllib2.HTTPBasicAuthHandler(passwd_manager)
            handlers.append(auth_handler)

        # Install all handlers
        if handlers:
            opener = urllib2.build_opener(*handlers)
            urllib2.install_opener(opener)

        # Execute the request
        remote = False
        action = "fetch"
        response = None
        output = None

        log = repository.log
        try:
            f = urllib2.urlopen(req)
        except urllib2.HTTPError, e:
            result = log.ERROR
            remote = True # Peer error
            code = e.code
            message = e.read()
            try:
                # Sahana-Eden would send a JSON message,
                # try to extract the actual error message:
                message_json = json.loads(message)
                message = message_json.get("message", message)
            except:
                pass
            # Prefix as peer error and strip XML markup from the message
            # @todo: better method to do this?
            message = "<message>%s</message>" % message
            try:
                markup = etree.XML(message)
                message = markup.xpath(".//text()")
                if message:
                    message = " ".join(message)
                else:
                    message = ""
            except etree.XMLSyntaxError:
                pass
            output = xml.json_message(False, code, message, tree=None)
        except:
            result = log.FATAL
            code = 400
            message = sys.exc_info()[1]
            output = xml.json_message(False, code, message)
        else:
            result = log.SUCCESS
            response = f

        # Process the response
        mtime = None
        if response:

            # Get import strategy and update policy
            strategy = task.strategy
            update_policy = task.update_policy
            conflict_policy = task.conflict_policy

            success = True
            message = ""
            action = "import"

            # Import the data
            resource = current.s3db.resource(resource_name)
            if onconflict:
                onconflict_callback = lambda item: onconflict(item,
                                                              repository,
                                                              resource)
            else:
                onconflict_callback = None
            count = 0
            try:
                success = resource.import_xml(
                                response,
                                ignore_errors=True,
                                strategy=strategy,
                                update_policy=update_policy,
                                conflict_policy=conflict_policy,
                                last_sync=last_pull,
                                onconflict=onconflict_callback,
                                )
                count = resource.import_count
            except IOError, e:
                result = log.FATAL
                message = "%s" % e
                output = xml.json_message(False, 400, message)
            except Exception, e:
                # If we end up here, an uncaught error during import
                # has occured which indicates a code defect! We log it
                # and continue here, however - in order to maintain a
                # valid sync status, so that developers can restart
                # the process more easily after fixing the defect.
                result = log.FATAL
                message = "Uncaught Exception During Import: %s" % \
                          traceback.format_exc()
                output = xml.json_message(False, 500, sys.exc_info()[1])

            mtime = resource.mtime

            # Log all validation errors
            if resource.error_tree is not None:
                result = log.WARNING
                message = "%s" % resource.error
                for element in resource.error_tree.findall("resource"):
                    for field in element.findall("data[@error]"):
                        error_msg = field.get("error", None)
                        if error_msg:
                            msg = "(UID: %s) %s.%s=%s: %s" % \
                                   (element.get("uuid", None),
                                    element.get("name", None),
                                    field.get("field", None),
                                    field.get("value", field.text),
                                    field.get("error", None))
                            message = "%s, %s" % (message, msg)

            # Check for failure
            if not success:
                result = log.FATAL
                if not message:
                    message = "%s" % resource.error
                output = xml.json_message(False, 400, message)
                mtime = None

            # ...or report success
            elif not message:
                message = count % "Data imported successfully (%s records)"

        elif result == log.SUCCESS:
            # No data received from peer
            result = log.ERROR
            remote = True
            message = "No data received from peer"

        # Log the operation
        log.write(repository_id=repository.id,
                  resource_name=task.resource_name,
                  transmission=log.OUT,
                  mode=log.PULL,
                  action=action,
                  remote=remote,
                  result=result,
                  message=message)

        current.log.debug("S3Sync: import %s: %s" % (result, message))
        return (output, mtime)

    # -------------------------------------------------------------------------
dataset/ETHPy150Open sahana/eden/modules/s3/sync_adapter/eden.py/S3SyncAdapter.pull/swapped operands of `%`