예제 #1
0
def register(registry_url, extra_data=None,
             encode=None, decode=None, headers=None, timeout=None,
             session=None):
    """
    Request a node registry from the server.

    If there is already a node registered in the local database, it
    won't be used for the following operations. Additional data can be
    passed to the request by giving *extra_data*, a dictionary of
    values.

    By default, the *encode* function is ``json.dumps``, the *decode*
    function is ``json.loads``, and the *headers* are appropriate HTTP
    headers for JSON.
    """
    assert isinstance(registry_url, basestring), "registry url must be a string"
    assert bool(registry_url), "registry url can't be empty"
    if extra_data is not None:
        assert isinstance(extra_data, dict), "extra data must be a dictionary"

    code, reason, response = post_request(
        registry_url, extra_data or {}, encode, decode, headers, timeout)

    if (code // 100 != 2) or response is None:
        raise RegisterRejected(code, reason, response)

    message = RegisterMessage(response)
    session.add(message.node)
    return response
예제 #2
0
def request_push(
    push_url, extra_data=None, encode=None, decode=None, headers=None, timeout=None, extensions=True, session=None
):
    message = PushMessage()
    message.latest_version_id = core.get_latest_version_id(session=session)
    compress(session=session)
    message.add_unversioned_operations(session=session, include_extensions=extensions)
    message.set_node(session.query(Node).order_by(Node.node_id.desc()).first())

    data = message.to_json()
    data.update({"extra_data": extra_data or {}})

    code, reason, response = post_request(push_url, data, encode, decode, headers, timeout)

    if (code // 100 != 2) or response is None:
        if suggests_pull is not None and suggests_pull(code, reason, response):
            raise PullSuggested(code, reason, response)
        raise PushRejected(code, reason, response)
    new_version_id = response.get("new_version_id")
    if new_version_id is None:
        raise PushRejected(code, reason, {"error": "server didn't respond with new version id", "response": response})
    # Who should set the dates? Maybe send a complete Version from the
    # server. For now the field is ignored, so it doesn't matter.
    session.add(Version(version_id=new_version_id, created=datetime.datetime.now()))
    for op in message.operations:
        op.version_id = new_version_id
    # return the response for the programmer to do what she wants
    # afterwards
    return response
예제 #3
0
def request_push(push_url: str,
                 extra_data=None,
                 encode=None,
                 decode=None,
                 headers=None,
                 timeout=None,
                 extensions=True,
                 session=None) -> Dict[str, Any]:
    message = PushMessage()
    message.latest_version_id = core.get_latest_version_id(session=session)
    compress(session=session)
    message.add_unversioned_operations(session=session,
                                       include_extensions=extensions)

    if not message.operations:
        return {}

    message.set_node(session.query(Node).order_by(Node.node_id.desc()).first())

    data = message.to_json()
    data.update({'extra_data': extra_data or {}})

    code, reason, response = post_request(push_url, data, encode, decode,
                                          headers, timeout)

    if (code // 100 != 2) or response is None:
        if suggests_pull is not None and suggests_pull(code, reason, response):
            raise PullSuggested(code, reason, response)
        raise PushRejected(code, reason, response)
    new_version_id = response.get('new_version_id')
    if new_version_id is None:
        raise PushRejected(
            code, reason, {
                'error': "server didn't respond with new version id",
                'response': response
            })
    # Who should set the dates? Maybe send a complete Version from the
    # server. For now the field is ignored, so it doesn't matter.
    session.add(
        Version(version_id=new_version_id, created=datetime.datetime.now()))
    for op in message.operations:
        op.version_id = new_version_id
    # return the response for the programmer to do what she wants
    # afterwards
    return response
예제 #4
0
def pull(pull_url,
         extra_data=None,
         encode=None,
         decode=None,
         headers=None,
         monitor=None,
         timeout=None,
         include_extensions=True):
    """
    Attempts a pull from the server. Returns the response body.

    Additional data can be passed to the request by giving
    *extra_data*, a dictionary of values.

    If not interrupted, the pull will perform a local merge. If the
    response from the server isn't appropriate, it will raise a
    dbysnc.client.pull.BadResponseError.

    By default, the *encode* function is ``json.dumps``, the *decode*
    function is ``json.loads``, and the *headers* are appropriate HTTP
    headers for JSON.

    *monitor* should be a routine that receives a dictionary with
    information of the state of the request and merge procedure.

    *include_extensions* dictates whether the extension functions will
    be called during the merge or not. Default is ``True``.
    """
    assert isinstance(pull_url, basestring), "pull url must be a string"
    assert bool(pull_url), "pull url can't be empty"
    if extra_data is not None:
        assert isinstance(extra_data, dict), "extra data must be a dictionary"
    request_message = PullRequestMessage()
    for op in compress():
        request_message.add_operation(op)
    data = request_message.to_json()
    data.update({'extra_data': extra_data or {}})

    code, reason, response = post_request(pull_url, data, encode, decode,
                                          headers, timeout, monitor)
    if (code // 100 != 2):
        if monitor:
            monitor({'status': "error", 'reason': reason.lower()})
        raise BadResponseError(code, reason, response)
    if response is None:
        if monitor:
            monitor({'status': "error", 'reason': "invalid response format"})
        raise BadResponseError(code, reason, response)
    message = None
    try:
        message = PullMessage(response)
    except KeyError:
        if monitor:
            monitor({'status': "error", 'reason': "invalid message format"})
        raise BadResponseError("response object isn't a valid PullMessage",
                               response)

    if monitor:
        monitor({'status': "merging", 'operations': len(message.operations)})
    merge(message, include_extensions=include_extensions)
    if monitor:
        monitor({'status': "done"})
    # return the response for the programmer to do what she wants
    # afterwards
    return response
예제 #5
0
def pull(pull_url, extra_data=None,
         encode=None, decode=None, headers=None, monitor=None, timeout=None,
         include_extensions=True):
    """
    Attempts a pull from the server. Returns the response body.

    Additional data can be passed to the request by giving
    *extra_data*, a dictionary of values.

    If not interrupted, the pull will perform a local merge. If the
    response from the server isn't appropriate, it will raise a
    dbysnc.client.pull.BadResponseError.

    By default, the *encode* function is ``json.dumps``, the *decode*
    function is ``json.loads``, and the *headers* are appropriate HTTP
    headers for JSON.

    *monitor* should be a routine that receives a dictionary with
    information of the state of the request and merge procedure.

    *include_extensions* dictates whether the extension functions will
    be called during the merge or not. Default is ``True``.
    """
    assert isinstance(pull_url, basestring), "pull url must be a string"
    assert bool(pull_url), "pull url can't be empty"
    if extra_data is not None:
        assert isinstance(extra_data, dict), "extra data must be a dictionary"
    request_message = PullRequestMessage()
    for op in compress(): request_message.add_operation(op)
    data = request_message.to_json()
    data.update({'extra_data': extra_data or {}})

    code, reason, response = post_request(
        pull_url, data, encode, decode, headers, timeout, monitor)
    if (code // 100 != 2):
        if monitor:
            monitor({'status': "error", 'reason': reason.lower()})
        raise BadResponseError(code, reason, response)
    if response is None:
        if monitor:
            monitor({
                'status': "error",
                'reason': "invalid response format"})
        raise BadResponseError(code, reason, response)
    message = None
    try:
        message = PullMessage(response)
    except KeyError:
        if monitor:
            monitor({
                'status': "error",
                'reason': "invalid message format"})
        raise BadResponseError(
            "response object isn't a valid PullMessage", response)

    if monitor:
        monitor({
            'status': "merging",
            'operations': len(message.operations)})
    merge(message, include_extensions=include_extensions)
    if monitor:
        monitor({'status': "done"})
    # return the response for the programmer to do what she wants
    # afterwards
    return response