diff options
Diffstat (limited to 'u1db/tests/c_backend_wrapper.pyx')
-rw-r--r-- | u1db/tests/c_backend_wrapper.pyx | 1541 |
1 files changed, 0 insertions, 1541 deletions
diff --git a/u1db/tests/c_backend_wrapper.pyx b/u1db/tests/c_backend_wrapper.pyx deleted file mode 100644 index 8a4b600d..00000000 --- a/u1db/tests/c_backend_wrapper.pyx +++ /dev/null @@ -1,1541 +0,0 @@ -# Copyright 2011-2012 Canonical Ltd. -# -# This file is part of u1db. -# -# u1db is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 -# as published by the Free Software Foundation. -# -# u1db is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with u1db. If not, see <http://www.gnu.org/licenses/>. -# -"""A Cython wrapper around the C implementation of U1DB Database backend.""" - -cdef extern from "Python.h": - object PyString_FromStringAndSize(char *s, Py_ssize_t n) - int PyString_AsStringAndSize(object o, char **buf, Py_ssize_t *length - ) except -1 - char *PyString_AsString(object) except NULL - char *PyString_AS_STRING(object) - char *strdup(char *) - void *calloc(size_t, size_t) - void free(void *) - ctypedef struct FILE: - pass - fprintf(FILE *, char *, ...) - FILE *stderr - size_t strlen(char *) - -cdef extern from "stdarg.h": - ctypedef struct va_list: - pass - void va_start(va_list, void*) - void va_start_int "va_start" (va_list, int) - void va_end(va_list) - -cdef extern from "u1db/u1db.h": - ctypedef struct u1database: - pass - ctypedef struct u1db_document: - char *doc_id - size_t doc_id_len - char *doc_rev - size_t doc_rev_len - char *json - size_t json_len - int has_conflicts - # Note: u1query is actually defined in u1db_internal.h, and in u1db.h it is - # just an opaque pointer. However, older versions of Cython don't let - # you have a forward declaration and a full declaration, so we just - # expose the whole thing here. - ctypedef struct u1query: - char *index_name - int num_fields - char **fields - cdef struct u1db_oauth_creds: - int auth_kind - char *consumer_key - char *consumer_secret - char *token_key - char *token_secret - ctypedef union u1db_creds - ctypedef u1db_creds* const_u1db_creds_ptr "const u1db_creds *" - - ctypedef char* const_char_ptr "const char*" - ctypedef int (*u1db_doc_callback)(void *context, u1db_document *doc) - ctypedef int (*u1db_key_callback)(void *context, int num_fields, - const_char_ptr *key) - ctypedef int (*u1db_doc_gen_callback)(void *context, - u1db_document *doc, int gen, const_char_ptr trans_id) - ctypedef int (*u1db_trans_info_callback)(void *context, - const_char_ptr doc_id, int gen, const_char_ptr trans_id) - - u1database * u1db_open(char *fname) - void u1db_free(u1database **) - int u1db_set_replica_uid(u1database *, char *replica_uid) - int u1db_set_document_size_limit(u1database *, int limit) - int u1db_get_replica_uid(u1database *, const_char_ptr *replica_uid) - int u1db_create_doc_from_json(u1database *db, char *json, char *doc_id, - u1db_document **doc) - int u1db_delete_doc(u1database *db, u1db_document *doc) - int u1db_get_doc(u1database *db, char *doc_id, int include_deleted, - u1db_document **doc) - int u1db_get_docs(u1database *db, int n_doc_ids, const_char_ptr *doc_ids, - int check_for_conflicts, int include_deleted, - void *context, u1db_doc_callback cb) - int u1db_get_all_docs(u1database *db, int include_deleted, int *generation, - void *context, u1db_doc_callback cb) - int u1db_put_doc(u1database *db, u1db_document *doc) - int u1db__validate_source(u1database *db, const_char_ptr replica_uid, - int replica_gen, const_char_ptr replica_trans_id) - int u1db__put_doc_if_newer(u1database *db, u1db_document *doc, - int save_conflict, char *replica_uid, - int replica_gen, char *replica_trans_id, - int *state, int *at_gen) - int u1db_resolve_doc(u1database *db, u1db_document *doc, - int n_revs, const_char_ptr *revs) - int u1db_delete_doc(u1database *db, u1db_document *doc) - int u1db_whats_changed(u1database *db, int *gen, char **trans_id, - void *context, u1db_trans_info_callback cb) - int u1db__get_transaction_log(u1database *db, void *context, - u1db_trans_info_callback cb) - int u1db_get_doc_conflicts(u1database *db, char *doc_id, void *context, - u1db_doc_callback cb) - int u1db_sync(u1database *db, const_char_ptr url, - const_u1db_creds_ptr creds, int *local_gen) nogil - int u1db_create_index_list(u1database *db, char *index_name, - int n_expressions, const_char_ptr *expressions) - int u1db_create_index(u1database *db, char *index_name, int n_expressions, - ...) - int u1db_get_from_index_list(u1database *db, u1query *query, void *context, - u1db_doc_callback cb, int n_values, - const_char_ptr *values) - int u1db_get_from_index(u1database *db, u1query *query, void *context, - u1db_doc_callback cb, int n_values, char *val0, - ...) - int u1db_get_range_from_index(u1database *db, u1query *query, - void *context, u1db_doc_callback cb, - int n_values, const_char_ptr *start_values, - const_char_ptr *end_values) - int u1db_delete_index(u1database *db, char *index_name) - int u1db_list_indexes(u1database *db, void *context, - int (*cb)(void *context, const_char_ptr index_name, - int n_expressions, const_char_ptr *expressions)) - int u1db_get_index_keys(u1database *db, char *index_name, void *context, - u1db_key_callback cb) - int u1db_simple_lookup1(u1database *db, char *index_name, char *val1, - void *context, u1db_doc_callback cb) - int u1db_query_init(u1database *db, char *index_name, u1query **query) - void u1db_free_query(u1query **query) - - int U1DB_OK - int U1DB_INVALID_PARAMETER - int U1DB_REVISION_CONFLICT - int U1DB_INVALID_DOC_ID - int U1DB_DOCUMENT_ALREADY_DELETED - int U1DB_DOCUMENT_DOES_NOT_EXIST - int U1DB_NOT_IMPLEMENTED - int U1DB_INVALID_JSON - int U1DB_DOCUMENT_TOO_BIG - int U1DB_USER_QUOTA_EXCEEDED - int U1DB_INVALID_VALUE_FOR_INDEX - int U1DB_INVALID_FIELD_SPECIFIER - int U1DB_INVALID_GLOBBING - int U1DB_BROKEN_SYNC_STREAM - int U1DB_DUPLICATE_INDEX_NAME - int U1DB_INDEX_DOES_NOT_EXIST - int U1DB_INVALID_GENERATION - int U1DB_INVALID_TRANSACTION_ID - int U1DB_INVALID_TRANSFORMATION_FUNCTION - int U1DB_UNKNOWN_OPERATION - int U1DB_INTERNAL_ERROR - int U1DB_TARGET_UNAVAILABLE - - int U1DB_INSERTED - int U1DB_SUPERSEDED - int U1DB_CONVERGED - int U1DB_CONFLICTED - - int U1DB_OAUTH_AUTH - - void u1db_free_doc(u1db_document **doc) - int u1db_doc_set_json(u1db_document *doc, char *json) - int u1db_doc_get_size(u1db_document *doc) - - -cdef extern from "u1db/u1db_internal.h": - ctypedef struct u1db_row: - u1db_row *next - int num_columns - int *column_sizes - unsigned char **columns - - ctypedef struct u1db_table: - int status - u1db_row *first_row - - ctypedef struct u1db_record: - u1db_record *next - char *doc_id - char *doc_rev - char *doc - - ctypedef struct u1db_sync_exchange: - int target_gen - int num_doc_ids - char **doc_ids_to_return - int *gen_for_doc_ids - const_char_ptr *trans_ids_for_doc_ids - - ctypedef int (*u1db__trace_callback)(void *context, const_char_ptr state) - ctypedef struct u1db_sync_target: - int (*get_sync_info)(u1db_sync_target *st, char *source_replica_uid, - const_char_ptr *st_replica_uid, int *st_gen, - char **st_trans_id, int *source_gen, - char **source_trans_id) nogil - int (*record_sync_info)(u1db_sync_target *st, - char *source_replica_uid, int source_gen, char *trans_id) nogil - int (*sync_exchange)(u1db_sync_target *st, - char *source_replica_uid, int n_docs, - u1db_document **docs, int *generations, - const_char_ptr *trans_ids, - int *target_gen, char **target_trans_id, - void *context, u1db_doc_gen_callback cb, - void *ensure_callback) nogil - int (*sync_exchange_doc_ids)(u1db_sync_target *st, - u1database *source_db, int n_doc_ids, - const_char_ptr *doc_ids, int *generations, - const_char_ptr *trans_ids, - int *target_gen, char **target_trans_id, - void *context, - u1db_doc_gen_callback cb, - void *ensure_callback) nogil - int (*get_sync_exchange)(u1db_sync_target *st, - char *source_replica_uid, - int last_known_source_gen, - u1db_sync_exchange **exchange) nogil - void (*finalize_sync_exchange)(u1db_sync_target *st, - u1db_sync_exchange **exchange) nogil - int (*_set_trace_hook)(u1db_sync_target *st, - void *context, u1db__trace_callback cb) nogil - - - void u1db__set_zero_delays() - int u1db__get_generation(u1database *, int *db_rev) - int u1db__get_document_size_limit(u1database *, int *limit) - int u1db__get_generation_info(u1database *, int *db_rev, char **trans_id) - int u1db__get_trans_id_for_gen(u1database *, int db_rev, char **trans_id) - int u1db_validate_gen_and_trans_id(u1database *, int db_rev, - const_char_ptr trans_id) - char *u1db__allocate_doc_id(u1database *) - int u1db__sql_close(u1database *) - u1database *u1db__copy(u1database *) - int u1db__sql_is_open(u1database *) - u1db_table *u1db__sql_run(u1database *, char *sql, size_t n) - void u1db__free_table(u1db_table **table) - u1db_record *u1db__create_record(char *doc_id, char *doc_rev, char *doc) - void u1db__free_records(u1db_record **) - - int u1db__allocate_document(char *doc_id, char *revision, char *content, - int has_conflicts, u1db_document **result) - int u1db__generate_hex_uuid(char *) - - int u1db__get_replica_gen_and_trans_id(u1database *db, char *replica_uid, - int *generation, char **trans_id) - int u1db__set_replica_gen_and_trans_id(u1database *db, char *replica_uid, - int generation, char *trans_id) - int u1db__sync_get_machine_info(u1database *db, char *other_replica_uid, - int *other_db_rev, char **my_replica_uid, - int *my_db_rev) - int u1db__sync_record_machine_info(u1database *db, char *replica_uid, - int db_rev) - int u1db__sync_exchange_seen_ids(u1db_sync_exchange *se, int *n_ids, - const_char_ptr **doc_ids) - int u1db__format_query(int n_fields, const_char_ptr *values, char **buf, - int *wildcard) - int u1db__get_sync_target(u1database *db, u1db_sync_target **sync_target) - int u1db__free_sync_target(u1db_sync_target **sync_target) - int u1db__sync_db_to_target(u1database *db, u1db_sync_target *target, - int *local_gen_before_sync) nogil - - int u1db__sync_exchange_insert_doc_from_source(u1db_sync_exchange *se, - u1db_document *doc, int source_gen, const_char_ptr trans_id) - int u1db__sync_exchange_find_doc_ids_to_return(u1db_sync_exchange *se) - int u1db__sync_exchange_return_docs(u1db_sync_exchange *se, void *context, - int (*cb)(void *context, - u1db_document *doc, int gen, - const_char_ptr trans_id)) - int u1db__create_http_sync_target(char *url, u1db_sync_target **target) - int u1db__create_oauth_http_sync_target(char *url, - char *consumer_key, char *consumer_secret, - char *token_key, char *token_secret, - u1db_sync_target **target) - -cdef extern from "u1db/u1db_http_internal.h": - int u1db__format_sync_url(u1db_sync_target *st, - const_char_ptr source_replica_uid, char **sync_url) - int u1db__get_oauth_authorization(u1db_sync_target *st, - char *http_method, char *url, - char **oauth_authorization) - - -cdef extern from "u1db/u1db_vectorclock.h": - ctypedef struct u1db_vectorclock_item: - char *replica_uid - int generation - - ctypedef struct u1db_vectorclock: - int num_items - u1db_vectorclock_item *items - - u1db_vectorclock *u1db__vectorclock_from_str(char *s) - void u1db__free_vectorclock(u1db_vectorclock **clock) - int u1db__vectorclock_increment(u1db_vectorclock *clock, char *replica_uid) - int u1db__vectorclock_maximize(u1db_vectorclock *clock, - u1db_vectorclock *other) - int u1db__vectorclock_as_str(u1db_vectorclock *clock, char **result) - int u1db__vectorclock_is_newer(u1db_vectorclock *maybe_newer, - u1db_vectorclock *older) - -from u1db import errors -from sqlite3 import dbapi2 - - -cdef int _append_trans_info_to_list(void *context, const_char_ptr doc_id, - int generation, - const_char_ptr trans_id) with gil: - a_list = <object>(context) - doc = doc_id - a_list.append((doc, generation, trans_id)) - return 0 - - -cdef int _append_doc_to_list(void *context, u1db_document *doc) with gil: - a_list = <object>context - pydoc = CDocument() - pydoc._doc = doc - a_list.append(pydoc) - return 0 - -cdef int _append_key_to_list(void *context, int num_fields, - const_char_ptr *key) with gil: - a_list = <object>(context) - field_list = [] - for i from 0 <= i < num_fields: - field = key[i] - field_list.append(field.decode('utf-8')) - a_list.append(tuple(field_list)) - return 0 - -cdef _list_to_array(lst, const_char_ptr **res, int *count): - cdef const_char_ptr *tmp - count[0] = len(lst) - tmp = <const_char_ptr*>calloc(sizeof(char*), count[0]) - for idx, x in enumerate(lst): - tmp[idx] = x - res[0] = tmp - -cdef _list_to_str_array(lst, const_char_ptr **res, int *count): - cdef const_char_ptr *tmp - count[0] = len(lst) - tmp = <const_char_ptr*>calloc(sizeof(char*), count[0]) - new_objs = [] - for idx, x in enumerate(lst): - if isinstance(x, unicode): - x = x.encode('utf-8') - new_objs.append(x) - tmp[idx] = x - res[0] = tmp - return new_objs - - -cdef int _append_index_definition_to_list(void *context, - const_char_ptr index_name, int n_expressions, - const_char_ptr *expressions) with gil: - cdef int i - - a_list = <object>(context) - exp_list = [] - for i from 0 <= i < n_expressions: - s = expressions[i] - exp_list.append(s.decode('utf-8')) - a_list.append((index_name, exp_list)) - return 0 - - -cdef int return_doc_cb_wrapper(void *context, u1db_document *doc, - int gen, const_char_ptr trans_id) with gil: - cdef CDocument pydoc - user_cb = <object>context - pydoc = CDocument() - pydoc._doc = doc - try: - user_cb(pydoc, gen, trans_id) - except Exception, e: - # We suppress the exception here, because intermediating through the C - # layer gets a bit crazy - return U1DB_INVALID_PARAMETER - return U1DB_OK - - -cdef int _trace_hook(void *context, const_char_ptr state) with gil: - if context == NULL: - return U1DB_INVALID_PARAMETER - ctx = <object>context - try: - ctx(state) - except: - # Note: It would be nice if we could map the Python exception into - # something in C - return U1DB_INTERNAL_ERROR - return U1DB_OK - - -cdef char *_ensure_str(object obj, object extra_objs) except NULL: - """Ensure that we have the UTF-8 representation of a parameter. - - :param obj: A Unicode or String object. - :param extra_objs: This should be a Python list. If we have to convert obj - from being a Unicode object, this will hold the PyString object so that - we know the char* lifetime will be correct. - :return: A C pointer to the UTF-8 representation. - """ - if isinstance(obj, unicode): - obj = obj.encode('utf-8') - extra_objs.append(obj) - return PyString_AsString(obj) - - -def _format_query(fields): - """Wrapper around u1db__format_query for testing.""" - cdef int status - cdef char *buf - cdef int wildcard[10] - cdef const_char_ptr *values - cdef int n_values - - # keep a reference to new_objs so that the pointers in expressions - # remain valid. - new_objs = _list_to_str_array(fields, &values, &n_values) - try: - status = u1db__format_query(n_values, values, &buf, wildcard) - finally: - free(<void*>values) - handle_status("format_query", status) - if buf == NULL: - res = None - else: - res = buf - free(buf) - w = [] - for i in range(len(fields)): - w.append(wildcard[i]) - return res, w - - -def make_document(doc_id, rev, content, has_conflicts=False): - cdef u1db_document *doc - cdef char *c_content = NULL, *c_rev = NULL, *c_doc_id = NULL - cdef int conflict - - if has_conflicts: - conflict = 1 - else: - conflict = 0 - if doc_id is None: - c_doc_id = NULL - else: - c_doc_id = doc_id - if content is None: - c_content = NULL - else: - c_content = content - if rev is None: - c_rev = NULL - else: - c_rev = rev - handle_status( - "make_document", - u1db__allocate_document(c_doc_id, c_rev, c_content, conflict, &doc)) - pydoc = CDocument() - pydoc._doc = doc - return pydoc - - -def generate_hex_uuid(): - uuid = PyString_FromStringAndSize(NULL, 32) - handle_status( - "Failed to generate uuid", - u1db__generate_hex_uuid(PyString_AS_STRING(uuid))) - return uuid - - -cdef class CDocument(object): - """A thin wrapper around the C Document struct.""" - - cdef u1db_document *_doc - - def __init__(self): - self._doc = NULL - - def __dealloc__(self): - u1db_free_doc(&self._doc) - - property doc_id: - def __get__(self): - if self._doc.doc_id == NULL: - return None - return PyString_FromStringAndSize( - self._doc.doc_id, self._doc.doc_id_len) - - property rev: - def __get__(self): - if self._doc.doc_rev == NULL: - return None - return PyString_FromStringAndSize( - self._doc.doc_rev, self._doc.doc_rev_len) - - def get_json(self): - if self._doc.json == NULL: - return None - return PyString_FromStringAndSize( - self._doc.json, self._doc.json_len) - - def set_json(self, val): - u1db_doc_set_json(self._doc, val) - - def get_size(self): - return u1db_doc_get_size(self._doc) - - property has_conflicts: - def __get__(self): - if self._doc.has_conflicts: - return True - return False - - def __repr__(self): - if self._doc.has_conflicts: - extra = ', conflicted' - else: - extra = '' - return '%s(%s, %s%s, %r)' % (self.__class__.__name__, self.doc_id, - self.rev, extra, self.get_json()) - - def __hash__(self): - raise NotImplementedError(self.__hash__) - - def __richcmp__(self, other, int t): - try: - if t == 0: # Py_LT < - return ((self.doc_id, self.rev, self.get_json()) - < (other.doc_id, other.rev, other.get_json())) - elif t == 2: # Py_EQ == - return (self.doc_id == other.doc_id - and self.rev == other.rev - and self.get_json() == other.get_json() - and self.has_conflicts == other.has_conflicts) - except AttributeError: - # Fall through to NotImplemented - pass - - return NotImplemented - - -cdef object safe_str(const_char_ptr s): - if s == NULL: - return None - return s - - -cdef class CQuery: - - cdef u1query *_query - - def __init__(self): - self._query = NULL - - def __dealloc__(self): - u1db_free_query(&self._query) - - def _check(self): - if self._query == NULL: - raise RuntimeError("No valid _query.") - - property index_name: - def __get__(self): - self._check() - return safe_str(self._query.index_name) - - property num_fields: - def __get__(self): - self._check() - return self._query.num_fields - - property fields: - def __get__(self): - cdef int i - self._check() - fields = [] - for i from 0 <= i < self._query.num_fields: - fields.append(safe_str(self._query.fields[i])) - return fields - - -cdef handle_status(context, int status): - if status == U1DB_OK: - return - if status == U1DB_REVISION_CONFLICT: - raise errors.RevisionConflict() - if status == U1DB_INVALID_DOC_ID: - raise errors.InvalidDocId() - if status == U1DB_DOCUMENT_ALREADY_DELETED: - raise errors.DocumentAlreadyDeleted() - if status == U1DB_DOCUMENT_DOES_NOT_EXIST: - raise errors.DocumentDoesNotExist() - if status == U1DB_INVALID_PARAMETER: - raise RuntimeError('Bad parameters supplied') - if status == U1DB_NOT_IMPLEMENTED: - raise NotImplementedError("Functionality not implemented yet: %s" - % (context,)) - if status == U1DB_INVALID_VALUE_FOR_INDEX: - raise errors.InvalidValueForIndex() - if status == U1DB_INVALID_GLOBBING: - raise errors.InvalidGlobbing() - if status == U1DB_INTERNAL_ERROR: - raise errors.U1DBError("internal error") - if status == U1DB_BROKEN_SYNC_STREAM: - raise errors.BrokenSyncStream() - if status == U1DB_CONFLICTED: - raise errors.ConflictedDoc() - if status == U1DB_DUPLICATE_INDEX_NAME: - raise errors.IndexNameTakenError() - if status == U1DB_INDEX_DOES_NOT_EXIST: - raise errors.IndexDoesNotExist - if status == U1DB_INVALID_GENERATION: - raise errors.InvalidGeneration - if status == U1DB_INVALID_TRANSACTION_ID: - raise errors.InvalidTransactionId - if status == U1DB_TARGET_UNAVAILABLE: - raise errors.Unavailable - if status == U1DB_INVALID_JSON: - raise errors.InvalidJSON - if status == U1DB_DOCUMENT_TOO_BIG: - raise errors.DocumentTooBig - if status == U1DB_USER_QUOTA_EXCEEDED: - raise errors.UserQuotaExceeded - if status == U1DB_INVALID_TRANSFORMATION_FUNCTION: - raise errors.IndexDefinitionParseError - if status == U1DB_UNKNOWN_OPERATION: - raise errors.IndexDefinitionParseError - if status == U1DB_INVALID_FIELD_SPECIFIER: - raise errors.IndexDefinitionParseError() - raise RuntimeError('%s (status: %s)' % (context, status)) - - -cdef class CDatabase -cdef class CSyncTarget - -cdef class CSyncExchange(object): - - cdef u1db_sync_exchange *_exchange - cdef CSyncTarget _target - - def __init__(self, CSyncTarget target, source_replica_uid, source_gen): - self._target = target - assert self._target._st.get_sync_exchange != NULL, \ - "get_sync_exchange is NULL?" - handle_status("get_sync_exchange", - self._target._st.get_sync_exchange(self._target._st, - source_replica_uid, source_gen, &self._exchange)) - - def __dealloc__(self): - if self._target is not None and self._target._st != NULL: - self._target._st.finalize_sync_exchange(self._target._st, - &self._exchange) - - def _check(self): - if self._exchange == NULL: - raise RuntimeError("self._exchange is NULL") - - property target_gen: - def __get__(self): - self._check() - return self._exchange.target_gen - - def insert_doc_from_source(self, CDocument doc, source_gen, - source_trans_id): - self._check() - handle_status("insert_doc_from_source", - u1db__sync_exchange_insert_doc_from_source(self._exchange, - doc._doc, source_gen, source_trans_id)) - - def find_doc_ids_to_return(self): - self._check() - handle_status("find_doc_ids_to_return", - u1db__sync_exchange_find_doc_ids_to_return(self._exchange)) - - def return_docs(self, return_doc_cb): - self._check() - handle_status("return_docs", - u1db__sync_exchange_return_docs(self._exchange, - <void *>return_doc_cb, &return_doc_cb_wrapper)) - - def get_seen_ids(self): - cdef const_char_ptr *seen_ids - cdef int i, n_ids - self._check() - handle_status("sync_exchange_seen_ids", - u1db__sync_exchange_seen_ids(self._exchange, &n_ids, &seen_ids)) - res = [] - for i from 0 <= i < n_ids: - res.append(seen_ids[i]) - if (seen_ids != NULL): - free(<void*>seen_ids) - return res - - def get_doc_ids_to_return(self): - self._check() - res = [] - if (self._exchange.num_doc_ids > 0 - and self._exchange.doc_ids_to_return != NULL): - for i from 0 <= i < self._exchange.num_doc_ids: - res.append( - (self._exchange.doc_ids_to_return[i], - self._exchange.gen_for_doc_ids[i], - self._exchange.trans_ids_for_doc_ids[i])) - return res - - -cdef class CSyncTarget(object): - - cdef u1db_sync_target *_st - cdef CDatabase _db - - def __init__(self): - self._db = None - self._st = NULL - u1db__set_zero_delays() - - def __dealloc__(self): - u1db__free_sync_target(&self._st) - - def _check(self): - if self._st == NULL: - raise RuntimeError("self._st is NULL") - - def get_sync_info(self, source_replica_uid): - cdef const_char_ptr st_replica_uid = NULL - cdef int st_gen = 0, source_gen = 0, status - cdef char *trans_id = NULL - cdef char *st_trans_id = NULL - cdef char *c_source_replica_uid = NULL - - self._check() - assert self._st.get_sync_info != NULL, "get_sync_info is NULL?" - c_source_replica_uid = source_replica_uid - with nogil: - status = self._st.get_sync_info(self._st, c_source_replica_uid, - &st_replica_uid, &st_gen, &st_trans_id, &source_gen, &trans_id) - handle_status("get_sync_info", status) - res_trans_id = None - res_st_trans_id = None - if trans_id != NULL: - res_trans_id = trans_id - free(trans_id) - if st_trans_id != NULL: - res_st_trans_id = st_trans_id - free(st_trans_id) - return ( - safe_str(st_replica_uid), st_gen, res_st_trans_id, source_gen, - res_trans_id) - - def record_sync_info(self, source_replica_uid, source_gen, source_trans_id): - cdef int status - cdef int c_source_gen - cdef char *c_source_replica_uid = NULL - cdef char *c_source_trans_id = NULL - - self._check() - assert self._st.record_sync_info != NULL, "record_sync_info is NULL?" - c_source_replica_uid = source_replica_uid - c_source_gen = source_gen - c_source_trans_id = source_trans_id - with nogil: - status = self._st.record_sync_info( - self._st, c_source_replica_uid, c_source_gen, - c_source_trans_id) - handle_status("record_sync_info", status) - - def _get_sync_exchange(self, source_replica_uid, source_gen): - self._check() - return CSyncExchange(self, source_replica_uid, source_gen) - - def sync_exchange_doc_ids(self, source_db, doc_id_generations, - last_known_generation, last_known_trans_id, - return_doc_cb): - cdef const_char_ptr *doc_ids - cdef int *generations - cdef int num_doc_ids - cdef int target_gen - cdef char *target_trans_id = NULL - cdef int status - cdef CDatabase sdb - - self._check() - assert self._st.sync_exchange_doc_ids != NULL, "sync_exchange_doc_ids is NULL?" - sdb = source_db - num_doc_ids = len(doc_id_generations) - doc_ids = <const_char_ptr *>calloc(num_doc_ids, sizeof(char *)) - if doc_ids == NULL: - raise MemoryError - generations = <int *>calloc(num_doc_ids, sizeof(int)) - if generations == NULL: - free(<void *>doc_ids) - raise MemoryError - trans_ids = <const_char_ptr*>calloc(num_doc_ids, sizeof(char *)) - if trans_ids == NULL: - raise MemoryError - res_trans_id = '' - try: - for i, (doc_id, gen, trans_id) in enumerate(doc_id_generations): - doc_ids[i] = PyString_AsString(doc_id) - generations[i] = gen - trans_ids[i] = trans_id - target_gen = last_known_generation - if last_known_trans_id is not None: - target_trans_id = last_known_trans_id - with nogil: - status = self._st.sync_exchange_doc_ids(self._st, sdb._db, - num_doc_ids, doc_ids, generations, trans_ids, - &target_gen, &target_trans_id, - <void*>return_doc_cb, return_doc_cb_wrapper, NULL) - handle_status("sync_exchange_doc_ids", status) - if target_trans_id != NULL: - res_trans_id = target_trans_id - finally: - if target_trans_id != NULL: - free(target_trans_id) - if doc_ids != NULL: - free(<void *>doc_ids) - if generations != NULL: - free(generations) - if trans_ids != NULL: - free(trans_ids) - return target_gen, res_trans_id - - def sync_exchange(self, docs_by_generations, source_replica_uid, - last_known_generation, last_known_trans_id, - return_doc_cb, ensure_callback=None): - cdef CDocument cur_doc - cdef u1db_document **docs = NULL - cdef int *generations = NULL - cdef const_char_ptr *trans_ids = NULL - cdef char *target_trans_id = NULL - cdef char *c_source_replica_uid = NULL - cdef int i, count, status, target_gen - assert ensure_callback is None # interface difference - - self._check() - assert self._st.sync_exchange != NULL, "sync_exchange is NULL?" - count = len(docs_by_generations) - res_trans_id = '' - try: - docs = <u1db_document **>calloc(count, sizeof(u1db_document*)) - if docs == NULL: - raise MemoryError - generations = <int*>calloc(count, sizeof(int)) - if generations == NULL: - raise MemoryError - trans_ids = <const_char_ptr*>calloc(count, sizeof(char*)) - if trans_ids == NULL: - raise MemoryError - for i from 0 <= i < count: - cur_doc = docs_by_generations[i][0] - generations[i] = docs_by_generations[i][1] - trans_ids[i] = docs_by_generations[i][2] - docs[i] = cur_doc._doc - target_gen = last_known_generation - if last_known_trans_id is not None: - target_trans_id = last_known_trans_id - c_source_replica_uid = source_replica_uid - with nogil: - status = self._st.sync_exchange( - self._st, c_source_replica_uid, count, docs, generations, - trans_ids, &target_gen, &target_trans_id, - <void *>return_doc_cb, return_doc_cb_wrapper, NULL) - handle_status("sync_exchange", status) - finally: - if docs != NULL: - free(docs) - if generations != NULL: - free(generations) - if trans_ids != NULL: - free(trans_ids) - if target_trans_id != NULL: - res_trans_id = target_trans_id - free(target_trans_id) - return target_gen, res_trans_id - - def _set_trace_hook(self, cb): - self._check() - assert self._st._set_trace_hook != NULL, "_set_trace_hook is NULL?" - handle_status("_set_trace_hook", - self._st._set_trace_hook(self._st, <void*>cb, _trace_hook)) - - _set_trace_hook_shallow = _set_trace_hook - - -cdef class CDatabase(object): - """A thin wrapper/shim to interact with the C implementation. - - Functionality should not be written here. It is only provided as a way to - expose the C API to the python test suite. - """ - - cdef public object _filename - cdef u1database *_db - cdef public object _supports_indexes - - def __init__(self, filename): - self._supports_indexes = False - self._filename = filename - self._db = u1db_open(self._filename) - - def __dealloc__(self): - u1db_free(&self._db) - - def close(self): - return u1db__sql_close(self._db) - - def _copy(self, db): - # DO NOT COPY OR REUSE THIS CODE OUTSIDE TESTS: COPYING U1DB DATABASES IS - # THE WRONG THING TO DO, THE ONLY REASON WE DO SO HERE IS TO TEST THAT WE - # CORRECTLY DETECT IT HAPPENING SO THAT WE CAN RAISE ERRORS RATHER THAN - # CORRUPT USER DATA. USE SYNC INSTEAD, OR WE WILL SEND NINJA TO YOUR - # HOUSE. - new_db = CDatabase(':memory:') - u1db_free(&new_db._db) - new_db._db = u1db__copy(self._db) - return new_db - - def _sql_is_open(self): - if self._db == NULL: - return True - return u1db__sql_is_open(self._db) - - property _replica_uid: - def __get__(self): - cdef const_char_ptr val - cdef int status - status = u1db_get_replica_uid(self._db, &val) - if status != 0: - if val != NULL: - err = str(val) - else: - err = "<unknown>" - raise RuntimeError("Failed to get_replica_uid: %d %s" - % (status, err)) - if val == NULL: - return None - return str(val) - - def _set_replica_uid(self, replica_uid): - cdef int status - status = u1db_set_replica_uid(self._db, replica_uid) - if status != 0: - raise RuntimeError('replica_uid could not be set to %s, error: %d' - % (replica_uid, status)) - - property document_size_limit: - def __get__(self): - cdef int limit - handle_status("document_size_limit", - u1db__get_document_size_limit(self._db, &limit)) - return limit - - def set_document_size_limit(self, limit): - cdef int status - status = u1db_set_document_size_limit(self._db, limit) - if status != 0: - raise RuntimeError( - "document_size_limit could not be set to %d, error: %d", - (limit, status)) - - def _allocate_doc_id(self): - cdef char *val - val = u1db__allocate_doc_id(self._db) - if val == NULL: - raise RuntimeError("Failed to allocate document id") - s = str(val) - free(val) - return s - - def _run_sql(self, sql): - cdef u1db_table *tbl - cdef u1db_row *cur_row - cdef size_t n - cdef int i - - if self._db == NULL: - raise RuntimeError("called _run_sql with a NULL pointer.") - tbl = u1db__sql_run(self._db, sql, len(sql)) - if tbl == NULL: - raise MemoryError("Failed to allocate table memory.") - try: - if tbl.status != 0: - raise RuntimeError("Status was not 0: %d" % (tbl.status,)) - # Now convert the table into python - res = [] - cur_row = tbl.first_row - while cur_row != NULL: - row = [] - for i from 0 <= i < cur_row.num_columns: - row.append(PyString_FromStringAndSize( - <char*>(cur_row.columns[i]), cur_row.column_sizes[i])) - res.append(tuple(row)) - cur_row = cur_row.next - return res - finally: - u1db__free_table(&tbl) - - def create_doc_from_json(self, json, doc_id=None): - cdef u1db_document *doc = NULL - cdef char *c_doc_id - - if doc_id is None: - c_doc_id = NULL - else: - c_doc_id = doc_id - handle_status('Failed to create_doc', - u1db_create_doc_from_json(self._db, json, c_doc_id, &doc)) - pydoc = CDocument() - pydoc._doc = doc - return pydoc - - def put_doc(self, CDocument doc): - handle_status("Failed to put_doc", - u1db_put_doc(self._db, doc._doc)) - return doc.rev - - def _validate_source(self, replica_uid, replica_gen, replica_trans_id): - cdef const_char_ptr c_uid, c_trans_id - cdef int c_gen = 0 - - c_uid = replica_uid - c_trans_id = replica_trans_id - c_gen = replica_gen - handle_status( - "invalid generation or transaction id", - u1db__validate_source(self._db, c_uid, c_gen, c_trans_id)) - - def _put_doc_if_newer(self, CDocument doc, save_conflict, replica_uid=None, - replica_gen=None, replica_trans_id=None): - cdef char *c_uid, *c_trans_id - cdef int gen, state = 0, at_gen = -1 - - if replica_uid is None: - c_uid = NULL - else: - c_uid = replica_uid - if replica_trans_id is None: - c_trans_id = NULL - else: - c_trans_id = replica_trans_id - if replica_gen is None: - gen = 0 - else: - gen = replica_gen - handle_status("Failed to _put_doc_if_newer", - u1db__put_doc_if_newer(self._db, doc._doc, save_conflict, - c_uid, gen, c_trans_id, &state, &at_gen)) - if state == U1DB_INSERTED: - return 'inserted', at_gen - elif state == U1DB_SUPERSEDED: - return 'superseded', at_gen - elif state == U1DB_CONVERGED: - return 'converged', at_gen - elif state == U1DB_CONFLICTED: - return 'conflicted', at_gen - else: - raise RuntimeError("Unknown _put_doc_if_newer state: %d" % (state,)) - - def get_doc(self, doc_id, include_deleted=False): - cdef u1db_document *doc = NULL - deleted = 1 if include_deleted else 0 - handle_status("get_doc failed", - u1db_get_doc(self._db, doc_id, deleted, &doc)) - if doc == NULL: - return None - pydoc = CDocument() - pydoc._doc = doc - return pydoc - - def get_docs(self, doc_ids, check_for_conflicts=True, - include_deleted=False): - cdef int n_doc_ids, conflicts - cdef const_char_ptr *c_doc_ids - - _list_to_array(doc_ids, &c_doc_ids, &n_doc_ids) - deleted = 1 if include_deleted else 0 - conflicts = 1 if check_for_conflicts else 0 - a_list = [] - handle_status("get_docs", - u1db_get_docs(self._db, n_doc_ids, c_doc_ids, - conflicts, deleted, <void*>a_list, _append_doc_to_list)) - free(<void*>c_doc_ids) - return a_list - - def get_all_docs(self, include_deleted=False): - cdef int c_generation - - a_list = [] - deleted = 1 if include_deleted else 0 - generation = 0 - c_generation = generation - handle_status( - "get_all_docs", u1db_get_all_docs( - self._db, deleted, &c_generation, <void*>a_list, - _append_doc_to_list)) - return (c_generation, a_list) - - def resolve_doc(self, CDocument doc, conflicted_doc_revs): - cdef const_char_ptr *revs - cdef int n_revs - - _list_to_array(conflicted_doc_revs, &revs, &n_revs) - handle_status("resolve_doc", - u1db_resolve_doc(self._db, doc._doc, n_revs, revs)) - free(<void*>revs) - - def get_doc_conflicts(self, doc_id): - conflict_docs = [] - handle_status("get_doc_conflicts", - u1db_get_doc_conflicts(self._db, doc_id, <void*>conflict_docs, - _append_doc_to_list)) - return conflict_docs - - def delete_doc(self, CDocument doc): - handle_status( - "Failed to delete %s" % (doc,), - u1db_delete_doc(self._db, doc._doc)) - - def whats_changed(self, generation=0): - cdef int c_generation - cdef int status - cdef char *trans_id = NULL - - a_list = [] - c_generation = generation - res_trans_id = '' - status = u1db_whats_changed(self._db, &c_generation, &trans_id, - <void*>a_list, _append_trans_info_to_list) - try: - handle_status("whats_changed", status) - finally: - if trans_id != NULL: - res_trans_id = trans_id - free(trans_id) - return c_generation, res_trans_id, a_list - - def _get_transaction_log(self): - a_list = [] - handle_status("_get_transaction_log", - u1db__get_transaction_log(self._db, <void*>a_list, - _append_trans_info_to_list)) - return [(doc_id, trans_id) for doc_id, gen, trans_id in a_list] - - def _get_generation(self): - cdef int generation - handle_status("get_generation", - u1db__get_generation(self._db, &generation)) - return generation - - def _get_generation_info(self): - cdef int generation - cdef char *trans_id - handle_status("get_generation_info", - u1db__get_generation_info(self._db, &generation, &trans_id)) - raw_trans_id = None - if trans_id != NULL: - raw_trans_id = trans_id - free(trans_id) - return generation, raw_trans_id - - def validate_gen_and_trans_id(self, generation, trans_id): - handle_status( - "validate_gen_and_trans_id", - u1db_validate_gen_and_trans_id(self._db, generation, trans_id)) - - def _get_trans_id_for_gen(self, generation): - cdef char *trans_id = NULL - - handle_status( - "_get_trans_id_for_gen", - u1db__get_trans_id_for_gen(self._db, generation, &trans_id)) - raw_trans_id = None - if trans_id != NULL: - raw_trans_id = trans_id - free(trans_id) - return raw_trans_id - - def _get_replica_gen_and_trans_id(self, replica_uid): - cdef int generation, status - cdef char *trans_id = NULL - - status = u1db__get_replica_gen_and_trans_id( - self._db, replica_uid, &generation, &trans_id) - handle_status("_get_replica_gen_and_trans_id", status) - raw_trans_id = None - if trans_id != NULL: - raw_trans_id = trans_id - free(trans_id) - return generation, raw_trans_id - - def _set_replica_gen_and_trans_id(self, replica_uid, generation, trans_id): - handle_status("_set_replica_gen_and_trans_id", - u1db__set_replica_gen_and_trans_id( - self._db, replica_uid, generation, trans_id)) - - def create_index_list(self, index_name, index_expressions): - cdef const_char_ptr *expressions - cdef int n_expressions - - # keep a reference to new_objs so that the pointers in expressions - # remain valid. - new_objs = _list_to_str_array( - index_expressions, &expressions, &n_expressions) - try: - status = u1db_create_index_list( - self._db, index_name, n_expressions, expressions) - finally: - free(<void*>expressions) - handle_status("create_index", status) - - def create_index(self, index_name, *index_expressions): - extra = [] - if len(index_expressions) == 0: - status = u1db_create_index(self._db, index_name, 0, NULL) - elif len(index_expressions) == 1: - status = u1db_create_index( - self._db, index_name, 1, - _ensure_str(index_expressions[0], extra)) - elif len(index_expressions) == 2: - status = u1db_create_index( - self._db, index_name, 2, - _ensure_str(index_expressions[0], extra), - _ensure_str(index_expressions[1], extra)) - elif len(index_expressions) == 3: - status = u1db_create_index( - self._db, index_name, 3, - _ensure_str(index_expressions[0], extra), - _ensure_str(index_expressions[1], extra), - _ensure_str(index_expressions[2], extra)) - elif len(index_expressions) == 4: - status = u1db_create_index( - self._db, index_name, 4, - _ensure_str(index_expressions[0], extra), - _ensure_str(index_expressions[1], extra), - _ensure_str(index_expressions[2], extra), - _ensure_str(index_expressions[3], extra)) - else: - status = U1DB_NOT_IMPLEMENTED - handle_status("create_index", status) - - def sync(self, url, creds=None): - cdef const_char_ptr c_url - cdef int local_gen = 0 - cdef u1db_oauth_creds _oauth_creds - cdef u1db_creds *_creds = NULL - c_url = url - if creds is not None: - _oauth_creds.auth_kind = U1DB_OAUTH_AUTH - _oauth_creds.consumer_key = creds['oauth']['consumer_key'] - _oauth_creds.consumer_secret = creds['oauth']['consumer_secret'] - _oauth_creds.token_key = creds['oauth']['token_key'] - _oauth_creds.token_secret = creds['oauth']['token_secret'] - _creds = <u1db_creds *>&_oauth_creds - with nogil: - status = u1db_sync(self._db, c_url, _creds, &local_gen) - handle_status("sync", status) - return local_gen - - def list_indexes(self): - a_list = [] - handle_status("list_indexes", - u1db_list_indexes(self._db, <void *>a_list, - _append_index_definition_to_list)) - return a_list - - def delete_index(self, index_name): - handle_status("delete_index", - u1db_delete_index(self._db, index_name)) - - def get_from_index_list(self, index_name, key_values): - cdef const_char_ptr *values - cdef int n_values - cdef CQuery query - - query = self._query_init(index_name) - res = [] - # keep a reference to new_objs so that the pointers in expressions - # remain valid. - new_objs = _list_to_str_array(key_values, &values, &n_values) - try: - handle_status( - "get_from_index", u1db_get_from_index_list( - self._db, query._query, <void*>res, _append_doc_to_list, - n_values, values)) - finally: - free(<void*>values) - return res - - def get_from_index(self, index_name, *key_values): - cdef CQuery query - cdef int status - - extra = [] - query = self._query_init(index_name) - res = [] - status = U1DB_OK - if len(key_values) == 0: - status = u1db_get_from_index(self._db, query._query, - <void*>res, _append_doc_to_list, 0, NULL) - elif len(key_values) == 1: - status = u1db_get_from_index(self._db, query._query, - <void*>res, _append_doc_to_list, 1, - _ensure_str(key_values[0], extra)) - elif len(key_values) == 2: - status = u1db_get_from_index(self._db, query._query, - <void*>res, _append_doc_to_list, 2, - _ensure_str(key_values[0], extra), - _ensure_str(key_values[1], extra)) - elif len(key_values) == 3: - status = u1db_get_from_index(self._db, query._query, - <void*>res, _append_doc_to_list, 3, - _ensure_str(key_values[0], extra), - _ensure_str(key_values[1], extra), - _ensure_str(key_values[2], extra)) - elif len(key_values) == 4: - status = u1db_get_from_index(self._db, query._query, - <void*>res, _append_doc_to_list, 4, - _ensure_str(key_values[0], extra), - _ensure_str(key_values[1], extra), - _ensure_str(key_values[2], extra), - _ensure_str(key_values[3], extra)) - else: - status = U1DB_NOT_IMPLEMENTED - handle_status("get_from_index", status) - return res - - def get_range_from_index(self, index_name, start_value=None, - end_value=None): - cdef CQuery query - cdef const_char_ptr *start_values - cdef int n_values - cdef const_char_ptr *end_values - - if start_value is not None: - if isinstance(start_value, basestring): - start_value = (start_value,) - new_objs_1 = _list_to_str_array( - start_value, &start_values, &n_values) - else: - n_values = 0 - start_values = NULL - if end_value is not None: - if isinstance(end_value, basestring): - end_value = (end_value,) - new_objs_2 = _list_to_str_array( - end_value, &end_values, &n_values) - else: - end_values = NULL - query = self._query_init(index_name) - res = [] - try: - handle_status("get_range_from_index", - u1db_get_range_from_index( - self._db, query._query, <void*>res, _append_doc_to_list, - n_values, start_values, end_values)) - finally: - if start_values != NULL: - free(<void*>start_values) - if end_values != NULL: - free(<void*>end_values) - return res - - def get_index_keys(self, index_name): - cdef int status - keys = [] - status = U1DB_OK - status = u1db_get_index_keys( - self._db, index_name, <void*>keys, _append_key_to_list) - handle_status("get_index_keys", status) - return keys - - def _query_init(self, index_name): - cdef CQuery query - query = CQuery() - handle_status("query_init", - u1db_query_init(self._db, index_name, &query._query)) - return query - - def get_sync_target(self): - cdef CSyncTarget target - target = CSyncTarget() - target._db = self - handle_status("get_sync_target", - u1db__get_sync_target(target._db._db, &target._st)) - return target - - -cdef class VectorClockRev: - - cdef u1db_vectorclock *_clock - - def __init__(self, s): - if s is None: - self._clock = u1db__vectorclock_from_str(NULL) - else: - self._clock = u1db__vectorclock_from_str(s) - - def __dealloc__(self): - u1db__free_vectorclock(&self._clock) - - def __repr__(self): - cdef int status - cdef char *res - if self._clock == NULL: - return '%s(None)' % (self.__class__.__name__,) - status = u1db__vectorclock_as_str(self._clock, &res) - if status != U1DB_OK: - return '%s(<failure: %d>)' % (status,) - if res == NULL: - val = '%s(NULL)' % (self.__class__.__name__,) - else: - val = '%s(%s)' % (self.__class__.__name__, res) - free(res) - return val - - def as_dict(self): - cdef u1db_vectorclock *cur - cdef int i - cdef int gen - if self._clock == NULL: - return None - res = {} - for i from 0 <= i < self._clock.num_items: - gen = self._clock.items[i].generation - res[self._clock.items[i].replica_uid] = gen - return res - - def as_str(self): - cdef int status - cdef char *res - - status = u1db__vectorclock_as_str(self._clock, &res) - if status != U1DB_OK: - raise RuntimeError("Failed to VectorClockRev.as_str(): %d" % (status,)) - if res == NULL: - s = None - else: - s = res - free(res) - return s - - def increment(self, replica_uid): - cdef int status - - status = u1db__vectorclock_increment(self._clock, replica_uid) - if status != U1DB_OK: - raise RuntimeError("Failed to increment: %d" % (status,)) - - def maximize(self, vcr): - cdef int status - cdef VectorClockRev other - - other = vcr - status = u1db__vectorclock_maximize(self._clock, other._clock) - if status != U1DB_OK: - raise RuntimeError("Failed to maximize: %d" % (status,)) - - def is_newer(self, vcr): - cdef int is_newer - cdef VectorClockRev other - - other = vcr - is_newer = u1db__vectorclock_is_newer(self._clock, other._clock) - if is_newer == 0: - return False - elif is_newer == 1: - return True - else: - raise RuntimeError("Failed to is_newer: %d" % (is_newer,)) - - -def sync_db_to_target(db, target): - """Sync the data between a CDatabase and a CSyncTarget""" - cdef CDatabase cdb - cdef CSyncTarget ctarget - cdef int local_gen = 0, status - - cdb = db - ctarget = target - with nogil: - status = u1db__sync_db_to_target(cdb._db, ctarget._st, &local_gen) - handle_status("sync_db_to_target", status) - return local_gen - - -def create_http_sync_target(url): - cdef CSyncTarget target - - target = CSyncTarget() - handle_status("create_http_sync_target", - u1db__create_http_sync_target(url, &target._st)) - return target - - -def create_oauth_http_sync_target(url, consumer_key, consumer_secret, - token_key, token_secret): - cdef CSyncTarget target - - target = CSyncTarget() - handle_status("create_http_sync_target", - u1db__create_oauth_http_sync_target(url, consumer_key, consumer_secret, - token_key, token_secret, - &target._st)) - return target - - -def _format_sync_url(target, source_replica_uid): - cdef CSyncTarget st - cdef char *sync_url = NULL - cdef object res - st = target - handle_status("format_sync_url", - u1db__format_sync_url(st._st, source_replica_uid, &sync_url)) - if sync_url == NULL: - res = None - else: - res = sync_url - free(sync_url) - return res - - -def _get_oauth_authorization(target, method, url): - cdef CSyncTarget st - cdef char *auth = NULL - - st = target - handle_status("get_oauth_authorization", - u1db__get_oauth_authorization(st._st, method, url, &auth)) - res = None - if auth != NULL: - res = auth - free(auth) - return res |