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
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
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
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
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