diff --git a/build/ac-macros/swig.m4 b/build/ac-macros/swig.m4 index d865689de5..c797ae69d8 100644 --- a/build/ac-macros/swig.m4 +++ b/build/ac-macros/swig.m4 @@ -154,7 +154,7 @@ AC_DEFUN(SVN_FIND_SWIG, ]) if test "$ac_cv_python_is_py3" = "yes"; then - SWIG_PY_OPTS="-python -py3" + SWIG_PY_OPTS="-python -py3 -DPY3" else SWIG_PY_OPTS="-python -classic" fi diff --git a/subversion/bindings/swig/core.i b/subversion/bindings/swig/core.i index e5a234c5e2..c309d48070 100644 --- a/subversion/bindings/swig/core.i +++ b/subversion/bindings/swig/core.i @@ -420,7 +420,7 @@ #ifdef SWIGPYTHON %typemap(argout) (char *buffer, apr_size_t *len) { - %append_output(PyStr_FromStringAndSize($1, *$2)); + %append_output(PyBytes_FromStringAndSize($1, *$2)); free($1); } #endif @@ -442,16 +442,18 @@ */ #ifdef SWIGPYTHON %typemap(in) (const char *data, apr_size_t *len) ($*2_type temp) { - if (!PyStr_Check($input)) { + char *tmpdata; + Py_ssize_t length; + if (!PyBytes_Check($input)) { PyErr_SetString(PyExc_TypeError, - "expecting a string for the buffer"); + "expecting a bytes object for the buffer"); SWIG_fail; } - /* Explicitly cast away const from PyStr_AsUTF8AndSize (in Python 3). The - swig generated argument ($1) here will be "char *", but since its only - use is to pass directly into the "const char *" argument of the wrapped - function, this is safe to do. */ - $1 = (char *)PyStr_AsUTF8AndSize($input, &temp); + if (PyBytes_AsStringAndSize($input, &tmpdata, &length) == -1) { + SWIG_fail; + } + temp = ($*2_type)length; + $1 = tmpdata; $2 = ($2_ltype)&temp; } #endif @@ -504,8 +506,8 @@ SWIG_fail; } - if (PyStr_Check($input)) { - const char *value = PyStr_AsString($input); + if (PyBytes_Check($input)) { + const char *value = PyBytes_AsString($input); $1 = apr_pstrdup(_global_pool, value); } else if (PyLong_Check($input)) { diff --git a/subversion/bindings/swig/include/svn_global.swg b/subversion/bindings/swig/include/svn_global.swg index 191bbdd531..f7364be28f 100644 --- a/subversion/bindings/swig/include/svn_global.swg +++ b/subversion/bindings/swig/include/svn_global.swg @@ -31,6 +31,12 @@ #define SVN_DEPRECATED #endif +#ifdef SWIGPYTHON +%begin %{ +#define SWIG_PYTHON_STRICT_BYTE_CHAR +%} +#endif + %include typemaps.i %include constraints.i %include exception.i @@ -136,9 +142,15 @@ static PyObject * _global_py_pool = NULL; /* Python format specifiers. Use Python instead of SWIG to parse these basic types, because Python reports better error messages (with correct argument numbers). */ +#if defined(PY3) +%typemap (in, parse="y") + char *, char const *, char * const, char const * const ""; +#else %typemap (in, parse="s") char *, char const *, char * const, char const * const ""; +#endif %typemap (in, parse="c") char ""; + %typemap (in, fragment=SWIG_As_frag(long)) long { $1 = ($1_ltype)SWIG_As(long)($input); diff --git a/subversion/bindings/swig/include/svn_string.swg b/subversion/bindings/swig/include/svn_string.swg index 8cb9b0c544..97bfb8af0c 100644 --- a/subversion/bindings/swig/include/svn_string.swg +++ b/subversion/bindings/swig/include/svn_string.swg @@ -31,15 +31,13 @@ typedef struct svn_string_t svn_string_t; because we only refer to the ->data and ->len values. */ #ifdef SWIGPYTHON - %typemap(argout) RET_STRING { PyObject *s; if (*$1 == NULL) { Py_INCREF(Py_None); s = Py_None; - } - else { - s = PyStr_FromStringAndSize((*$1)->data, (*$1)->len); + } else { + s = PyBytes_FromStringAndSize((*$1)->data, (*$1)->len); if (s == NULL) SWIG_fail; } @@ -76,13 +74,16 @@ typedef struct svn_string_t svn_string_t; #ifdef SWIGPYTHON %typemap(in) svn_stringbuf_t * { - if (!PyStr_Check($input)) { - PyErr_SetString(PyExc_TypeError, "not a string"); + if (!PyBytes_Check($input)) { + PyErr_SetString(PyExc_TypeError, "not a bytes object"); SWIG_fail; } { Py_ssize_t strBufLen; - const char *strBufChar = PyStr_AsUTF8AndSize($input, &strBufLen); + char *strBufChar; + if (-1 == PyBytes_AsStringAndSize($input, &strBufChar, &strBufLen)) { + SWIG_fail; + } $1 = svn_stringbuf_ncreate(strBufChar, strBufLen, /* ### gah... what pool to use? */ _global_pool); @@ -143,7 +144,7 @@ typedef struct svn_string_t svn_string_t; #ifdef SWIGPYTHON %typemap(out) svn_stringbuf_t * { - $result = PyStr_FromStringAndSize($1->data, $1->len); + $result = PyBytes_FromStringAndSize($1->data, (Py_ssize_t)($1->len)); } #endif @@ -179,11 +180,14 @@ typedef struct svn_string_t svn_string_t; $1 = NULL; else { Py_ssize_t pyStrLen; - if (!PyStr_Check($input)) { - PyErr_SetString(PyExc_TypeError, "not a string"); + if (!PyBytes_Check($input)) { + PyErr_SetString(PyExc_TypeError, "not a bytes object"); + SWIG_fail; + } + if (PyBytes_AsStringAndSize($input, (char **)&(value.data), + &pyStrLen) == -1) { SWIG_fail; } - value.data = PyStr_AsUTF8AndSize($input, &pyStrLen); value.len = pyStrLen; $1 = &value; } @@ -228,7 +232,7 @@ typedef struct svn_string_t svn_string_t; #ifdef SWIGPYTHON %typemap(out) svn_string_t * { - $result = PyStr_FromStringAndSize($1->data, $1->len); + $result = PyBytes_FromStringAndSize($1->data, $1->len); } #endif #ifdef SWIGPERL @@ -258,7 +262,7 @@ typedef struct svn_string_t svn_string_t; s = Py_None; } else { - s = PyStr_FromString(*$1); + s = PyBytes_FromString(*$1); if (s == NULL) SWIG_fail; } diff --git a/subversion/bindings/swig/include/svn_swigcompat.swg b/subversion/bindings/swig/include/svn_swigcompat.swg index bd29c8ac25..8edb513660 100644 --- a/subversion/bindings/swig/include/svn_swigcompat.swg +++ b/subversion/bindings/swig/include/svn_swigcompat.swg @@ -45,7 +45,7 @@ #if SWIG_VERSION <= 0x010327 #ifdef SWIGPYTHON %define %set_constant(name, value) -PyDict_SetItemString(d, name, value); +PyDict_SetItem(d, PyBytes_FromString(name), value); %enddef #endif #endif diff --git a/subversion/bindings/swig/include/svn_types.swg b/subversion/bindings/swig/include/svn_types.swg index f0f92e582f..5a018eb2bf 100644 --- a/subversion/bindings/swig/include/svn_types.swg +++ b/subversion/bindings/swig/include/svn_types.swg @@ -335,7 +335,15 @@ svn_ ## TYPE ## _swig_rb_closed(VALUE self) Create a typemap for specifying string args that may be NULL. */ #ifdef SWIGPYTHON -%typemap(in, parse="z") const char *MAY_BE_NULL ""; +%typemap(in) const char *MAY_BE_NULL +{ + if ($input == Py_None) { + $1 = NULL; + } else { + $1 = PyBytes_AsString($input); + if ($1 == NULL) SWIG_fail; + } +} #endif #ifdef SWIGPERL @@ -465,15 +473,13 @@ svn_ ## TYPE ## _swig_rb_closed(VALUE self) #ifdef SWIGPYTHON %typemap(in) (const char *PTR, apr_size_t LEN) { Py_ssize_t pyStrLen; - if (!PyStr_Check($input)) { - PyErr_SetString(PyExc_TypeError, "expecting a string"); + if (!PyBytes_Check($input)) { + PyErr_SetString(PyExc_TypeError, "expecting a bytes"); + SWIG_fail; + } + if (PyBytes_AsStringAndSize($input, &$1, &pyStrLen) == -1) { SWIG_fail; } - /* Explicitly cast away const from PyStr_AsUTF8AndSize (in Python 3). The - swig generated argument ($1) here will be "char *", but since its only - use is to pass directly into the "const char *" argument of the wrapped - function, this is safe to do. */ - $1 = (char *)PyStr_AsUTF8AndSize($input, &pyStrLen); $2 = pyStrLen; } #endif diff --git a/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c b/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c index 2301d66770..44ec8662b7 100644 --- a/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c +++ b/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c @@ -547,23 +547,23 @@ static char *make_string_from_ob(PyObject *ob, apr_pool_t *pool) { if (ob == Py_None) return NULL; - if (! PyStr_Check(ob)) + if (! PyBytes_Check(ob)) { - PyErr_SetString(PyExc_TypeError, "not a string"); + PyErr_SetString(PyExc_TypeError, "not a bytes object"); return NULL; } - return apr_pstrdup(pool, PyStr_AsString(ob)); + return apr_pstrdup(pool, PyBytes_AsString(ob)); } static svn_string_t *make_svn_string_from_ob(PyObject *ob, apr_pool_t *pool) { if (ob == Py_None) return NULL; - if (! PyStr_Check(ob)) + if (! PyBytes_Check(ob)) { - PyErr_SetString(PyExc_TypeError, "not a string"); + PyErr_SetString(PyExc_TypeError, "not a bytes object"); return NULL; } - return svn_string_create(PyStr_AsString(ob), pool); + return svn_string_create(PyBytes_AsString(ob), pool); } @@ -598,7 +598,7 @@ static PyObject *convert_hash(apr_hash_t *hash, return NULL; } /* ### gotta cast this thing cuz Python doesn't use "const" */ - if (PyDict_SetItemString(dict, (char *)key, value) == -1) + if (PyDict_SetItem(dict, PyBytes_FromString((char *)key), value) == -1) { Py_DECREF(value); Py_DECREF(dict); @@ -623,10 +623,10 @@ static PyObject *convert_svn_string_t(void *value, void *ctx, const svn_string_t *s = value; - return PyStr_FromStringAndSize(s->data, s->len); + return PyBytes_FromStringAndSize(s->data, s->len); } -/* Convert a C string into a Python String object (or a reference to +/* Convert a C string into a Python Bytes object (or a reference to Py_None if CSTRING is NULL). */ static PyObject *cstring_to_pystring(const char *cstring) { @@ -636,7 +636,7 @@ static PyObject *cstring_to_pystring(const char *cstring) Py_INCREF(Py_None); return retval; } - return PyStr_FromString(cstring); + return PyBytes_FromString(cstring); } static PyObject *convert_svn_client_commit_item3_t(void *value, void *ctx) @@ -712,7 +712,7 @@ PyObject *svn_swig_py_prophash_to_dict(apr_hash_t *hash) static PyObject *convert_string(void *value, void *ctx, PyObject *py_pool) { - return PyStr_FromString((const char *)value); + return PyBytes_FromString((const char *)value); } PyObject *svn_swig_py_stringhash_to_dict(apr_hash_t *hash) @@ -794,7 +794,7 @@ svn_swig_py_propinheriteditemarray_to_dict(const apr_array_header_t *array) apr_hash_t *prop_hash = prop_inherited_item->prop_hash; PyObject *py_key, *py_value; - py_key = PyStr_FromString(prop_inherited_item->path_or_url); + py_key = PyBytes_FromString(prop_inherited_item->path_or_url); if (py_key == NULL) goto error; @@ -838,7 +838,7 @@ PyObject *svn_swig_py_proparray_to_dict(const apr_array_header_t *array) prop = APR_ARRAY_IDX(array, i, svn_prop_t); - py_key = PyStr_FromString(prop.name); + py_key = PyBytes_FromString(prop.name); if (py_key == NULL) goto error; @@ -849,8 +849,8 @@ PyObject *svn_swig_py_proparray_to_dict(const apr_array_header_t *array) } else { - py_value = PyStr_FromStringAndSize(prop.value->data, - prop.value->len); + py_value = PyBytes_FromStringAndSize(prop.value->data, + prop.value->len); if (py_value == NULL) { Py_DECREF(py_key); @@ -900,7 +900,7 @@ PyObject *svn_swig_py_locationhash_to_dict(apr_hash_t *hash) Py_DECREF(dict); return NULL; } - value = PyStr_FromString((const char *)v); + value = PyBytes_FromString((const char *)v); if (value == NULL) { Py_DECREF(key); @@ -964,7 +964,7 @@ PyObject *svn_swig_py_c_strings_to_list(char **strings) while ((s = *strings++) != NULL) { - PyObject *ob = PyStr_FromString(s); + PyObject *ob = PyBytes_FromString(s); if (ob == NULL) goto error; @@ -1007,7 +1007,7 @@ PyObject *svn_swig_py_changed_path_hash_to_dict(apr_hash_t *hash) Py_DECREF(dict); return NULL; } - if (PyDict_SetItemString(dict, (char *)key, value) == -1) + if (PyDict_SetItem(dict, PyBytes_FromString((char *)key), value) == -1) { Py_DECREF(value); Py_DECREF(dict); @@ -1043,7 +1043,7 @@ PyObject *svn_swig_py_changed_path2_hash_to_dict(apr_hash_t *hash) Py_DECREF(dict); return NULL; } - if (PyDict_SetItemString(dict, (char *)key, value) == -1) + if (PyDict_SetItem(dict, PyBytes_FromString((char *)key), value) == -1) { Py_DECREF(value); Py_DECREF(dict); @@ -1321,7 +1321,7 @@ svn_swig_py_unwrap_string(PyObject *source, void *baton) { const char **ptr_dest = destination; - *ptr_dest = PyStr_AsString(source); + *ptr_dest = PyBytes_AsString(source); if (*ptr_dest != NULL) return 0; @@ -1440,7 +1440,7 @@ PyObject *svn_swig_py_array_to_list(const apr_array_header_t *array) for (i = 0; i < array->nelts; ++i) { PyObject *ob = - PyStr_FromString(APR_ARRAY_IDX(array, i, const char *)); + PyBytes_FromString(APR_ARRAY_IDX(array, i, const char *)); if (ob == NULL) goto error; PyList_SET_ITEM(list, i, ob); @@ -1748,7 +1748,8 @@ static svn_error_t *delete_entry(const char *path, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"delete_entry", - (char *)"slOO&", path, revision, ib->baton, + (char *)SVN_SWIG_BYTES_FMT "lOO&", + path, revision, ib->baton, make_ob_pool, pool)) == NULL) { err = callback_exception_error(); @@ -1779,7 +1780,11 @@ static svn_error_t *add_directory(const char *path, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"add_directory", +#if PY_VERSION_HEX >= 0x03000000 + (char *)"yOylO&", path, ib->baton, +#else (char *)"sOslO&", path, ib->baton, +#endif copyfrom_path, copyfrom_revision, make_ob_pool, dir_pool)) == NULL) { @@ -1810,8 +1815,8 @@ static svn_error_t *open_directory(const char *path, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"open_directory", - (char *)"sOlO&", path, ib->baton, - base_revision, + (char *)SVN_SWIG_BYTES_FMT "OlO&", + path, ib->baton, base_revision, make_ob_pool, dir_pool)) == NULL) { err = callback_exception_error(); @@ -1840,7 +1845,11 @@ static svn_error_t *change_dir_prop(void *dir_baton, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"change_dir_prop", +#if PY_VERSION_HEX >= 0x03000000 + (char *)"Oyy#O&", ib->baton, name, +#else (char *)"Oss#O&", ib->baton, name, +#endif value ? value->data : NULL, value ? value->len : 0, make_ob_pool, pool)) == NULL) @@ -1879,7 +1888,11 @@ static svn_error_t *add_file(const char *path, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"add_file", +#if PY_VERSION_HEX >= 0x03000000 + (char *)"yOylO&", path, ib->baton, +#else (char *)"sOslO&", path, ib->baton, +#endif copyfrom_path, copyfrom_revision, make_ob_pool, file_pool)) == NULL) { @@ -1911,8 +1924,8 @@ static svn_error_t *open_file(const char *path, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"open_file", - (char *)"sOlO&", path, ib->baton, - base_revision, + (char *)SVN_SWIG_BYTES_FMT "OlO&", + path, ib->baton, base_revision, make_ob_pool, file_pool)) == NULL) { err = callback_exception_error(); @@ -1985,7 +1998,11 @@ static svn_error_t *apply_textdelta(void *file_baton, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"apply_textdelta", +#if PY_VERSION_HEX >= 0x03000000 + (char *)"(Oy)", ib->baton, +#else (char *)"(Os)", ib->baton, +#endif base_checksum)) == NULL) { err = callback_exception_error(); @@ -2030,7 +2047,11 @@ static svn_error_t *change_file_prop(void *file_baton, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"change_file_prop", +#if PY_VERSION_HEX >= 0x03000000 + (char *)"Oyy#O&", ib->baton, name, +#else (char *)"Oss#O&", ib->baton, name, +#endif value ? value->data : NULL, value ? value->len : 0, make_ob_pool, pool)) == NULL) @@ -2060,7 +2081,11 @@ static svn_error_t *close_file(void *file_baton, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"close_file", +#if PY_VERSION_HEX >= 0x03000000 + (char *)"(Oy)", ib->baton, +#else (char *)"(Os)", ib->baton, +#endif text_checksum)) == NULL) { err = callback_exception_error(); @@ -2168,7 +2193,7 @@ static svn_error_t *parse_fn3_uuid_record(const char *uuid, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"uuid_record", - (char *)"sO&", uuid, + (char *)SVN_SWIG_BYTES_FMT "O&", uuid, make_ob_pool, pool)) == NULL) { err = callback_exception_error(); @@ -2257,7 +2282,11 @@ static svn_error_t *parse_fn3_set_revision_property(void *revision_baton, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"set_revision_property", +#if PY_VERSION_HEX >= 0x03000000 + (char *)"Oyy#", ib->baton, name, +#else (char *)"Oss#", ib->baton, name, +#endif value ? value->data : NULL, value ? value->len : 0)) == NULL) { @@ -2287,7 +2316,11 @@ static svn_error_t *parse_fn3_set_node_property(void *node_baton, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"set_node_property", +#if PY_VERSION_HEX >= 0x03000000 + (char *)"Oyy#", ib->baton, name, +#else (char *)"Oss#", ib->baton, name, +#endif value ? value->data : NULL, value ? value->len : 0)) == NULL) { @@ -2316,7 +2349,8 @@ static svn_error_t *parse_fn3_delete_node_property(void *node_baton, /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"delete_node_property", - (char *)"Os", ib->baton, name)) == NULL) + (char *)"O" SVN_SWIG_BYTES_FMT, + ib->baton, name)) == NULL) { err = callback_exception_error(); goto finished; @@ -2508,10 +2542,10 @@ apr_file_t *svn_swig_py_make_file(PyObject *py_file, if (py_file == NULL || py_file == Py_None) return NULL; - if (PyStr_Check(py_file)) + if (PyBytes_Check(py_file)) { /* input is a path -- just open an apr_file_t */ - const char* fname = PyStr_AsString(py_file); + const char* fname = PyBytes_AsString(py_file); apr_err = apr_file_open(&apr_file, fname, APR_CREATE | APR_READ | APR_WRITE, APR_OS_DEFAULT, pool); @@ -2731,7 +2765,11 @@ void svn_swig_py_notify_func(void *baton, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, +#if PY_VERSION_HEX >= 0x03000000 + (char *)"(yiiyiii)", +#else (char *)"(siisiii)", +#endif path, action, kind, mime_type, content_state, prop_state, @@ -2800,7 +2838,8 @@ void svn_swig_py_status_func(void *baton, return; svn_swig_py_acquire_py_lock(); - if ((result = PyObject_CallFunction(function, (char *)"sO&", path, + if ((result = PyObject_CallFunction(function, + (char *)SVN_SWIG_BYTES_FMT "O&", path, make_ob_wc_status, status)) == NULL) { err = callback_exception_error(); @@ -2839,7 +2878,12 @@ svn_error_t *svn_swig_py_delta_path_driver_cb_func(void **dir_baton, "void *", NULL); - result = PyObject_CallFunction(function, (char *)"OsO&", + result = PyObject_CallFunction(function, +#if PY_VERSION_HEX >= 0x03000000 + (char *)"OyO&", +#else + (char *)"OsO&", +#endif py_parent_baton, path, make_ob_pool, pool); @@ -2879,7 +2923,8 @@ void svn_swig_py_status_func2(void *baton, return; svn_swig_py_acquire_py_lock(); - if ((result = PyObject_CallFunction(function, (char *)"sO&", path, + if ((result = PyObject_CallFunction(function, + (char *)SVN_SWIG_BYTES_FMT "O&", path, make_ob_wc_status, status)) == NULL) { err = callback_exception_error(); @@ -2983,7 +3028,7 @@ svn_error_t *svn_swig_py_fs_lock_callback( svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(py_callback, - (char *)"sO&O&O&", + (char *)SVN_SWIG_BYTES_FMT "O&O&O&", path, make_ob_lock, lock, make_ob_error, fs_err, @@ -3053,16 +3098,16 @@ svn_error_t *svn_swig_py_get_commit_log_func(const char **log_msg, *log_msg = NULL; err = SVN_NO_ERROR; } - else if (PyStr_Check(result)) + else if (PyBytes_Check(result)) { - *log_msg = apr_pstrdup(pool, PyStr_AsString(result)); + *log_msg = apr_pstrdup(pool, PyBytes_AsString(result)); Py_DECREF(result); err = SVN_NO_ERROR; } else { Py_DECREF(result); - err = callback_bad_return_error("Not a string"); + err = callback_bad_return_error("Not a bytes object"); } finished: @@ -3104,7 +3149,11 @@ svn_error_t *svn_swig_py_repos_authz_func(svn_boolean_t *allowed, } if ((result = PyObject_CallFunction(function, +#if PY_VERSION_HEX >= 0x03000000 + (char *)"OyO", +#else (char *)"OsO", +#endif py_root, path, py_pool)) == NULL) { err = callback_exception_error(); @@ -3141,7 +3190,7 @@ svn_error_t *svn_swig_py_repos_history_func(void *baton, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, - (char *)"slO&", + (char *)SVN_SWIG_BYTES_FMT "lO&", path, revision, make_ob_pool, pool)) == NULL) { @@ -3268,7 +3317,7 @@ svn_error_t *svn_swig_py_proplist_receiver2(void *baton, } result = PyObject_CallFunction(receiver, - (char *)"sOOO", + (char *)SVN_SWIG_BYTES_FMT "OOO", path, py_props, py_iprops, py_pool); if (result == NULL) { @@ -3328,7 +3377,11 @@ svn_error_t *svn_swig_py_log_receiver(void *baton, } if ((result = PyObject_CallFunction(receiver, +#if PY_VERSION_HEX >= 0x03000000 + (char *)"OlyyyO", +#else (char *)"OlsssO", +#endif chpaths, rev, author, date, msg, py_pool)) == NULL) { @@ -3406,7 +3459,7 @@ svn_error_t *svn_swig_py_info_receiver_func(void *baton, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(receiver, - (char *)"sO&O&", + (char *)SVN_SWIG_BYTES_FMT "O&O&", path, make_ob_info, info, make_ob_pool, pool)) == NULL) { @@ -3476,7 +3529,11 @@ svn_error_t *svn_swig_py_client_blame_receiver_func(void *baton, if ((result = PyObject_CallFunction(receiver, (char *) +#if PY_VERSION_HEX >= 0x03000000 + (SVN_APR_INT64_T_PYCFMT "lyyyO&"), +#else (SVN_APR_INT64_T_PYCFMT "lsssO&"), +#endif line_no, revision, author, date, line, make_ob_pool, pool)) == NULL) { @@ -3508,7 +3565,11 @@ svn_error_t *svn_swig_py_changelist_receiver_func(void *baton, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(receiver, +#if PY_VERSION_HEX >= 0x03000000 + (char *)"yyO&", +#else (char *)"ssO&", +#endif path, changelist, make_ob_pool, pool)) == NULL) { @@ -3543,7 +3604,7 @@ svn_swig_py_auth_gnome_keyring_unlock_prompt_func(char **keyring_passwd, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, - (char *)"sO&", + (char *)SVN_SWIG_BYTES_FMT "O&", keyring_name, make_ob_pool, pool)) == NULL) { @@ -3579,7 +3640,11 @@ svn_swig_py_auth_simple_prompt_func(svn_auth_cred_simple_t **cred, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, +#if PY_VERSION_HEX >= 0x03000000 + (char *)"yylO&", +#else (char *)"sslO&", +#endif realm, username, may_save, make_ob_pool, pool)) == NULL) { @@ -3630,7 +3695,7 @@ svn_swig_py_auth_username_prompt_func(svn_auth_cred_username_t **cred, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, - (char *)"slO&", + (char *)SVN_SWIG_BYTES_FMT "lO&", realm, may_save, make_ob_pool, pool)) == NULL) { @@ -3682,7 +3747,8 @@ svn_swig_py_auth_ssl_server_trust_prompt_func( svn_swig_py_acquire_py_lock(); - if ((result = PyObject_CallFunction(function, (char *)"slO&lO&", + if ((result = PyObject_CallFunction(function, + (char *)SVN_SWIG_BYTES_FMT "lO&lO&", realm, failures, make_ob_auth_ssl_server_cert_info, cert_info, may_save, make_ob_pool, pool)) == NULL) { @@ -3733,7 +3799,7 @@ svn_swig_py_auth_ssl_client_cert_prompt_func( svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, - (char *)"slO&", + (char *)SVN_SWIG_BYTES_FMT "lO&", realm, may_save, make_ob_pool, pool)) == NULL) { @@ -3784,7 +3850,7 @@ svn_swig_py_auth_ssl_client_cert_pw_prompt_func( svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, - (char *)"slO&", + (char *)SVN_SWIG_BYTES_FMT "lO&", realm, may_save, make_ob_pool, pool)) == NULL) { @@ -3851,7 +3917,12 @@ svn_swig_py_config_auth_walk_func(svn_boolean_t *delete_cred, goto finished; } - if ((result = PyObject_CallFunction(function, (char *)"ssOO", + if ((result = PyObject_CallFunction(function, +#if PY_VERSION_HEX >= 0x03000000 + (char *)"yyOO", +#else + (char *)"ssOO", +#endif cred_kind, realmstring, py_hash, py_scratch_pool)) == NULL) { @@ -3950,7 +4021,11 @@ ra_callbacks_get_wc_prop(void *baton, } if ((result = PyObject_CallFunction(py_callback, +#if PY_VERSION_HEX >= 0x03000000 + (char *)"yyO&", path, name, +#else (char *)"ssO&", path, name, +#endif make_ob_pool, pool)) == NULL) { err = callback_exception_error(); @@ -3958,8 +4033,8 @@ ra_callbacks_get_wc_prop(void *baton, else if (result != Py_None) { Py_ssize_t len; - const char *buf = PyStr_AsUTF8AndSize(result, &len); - if (buf == NULL) + char *buf; + if (PyBytes_AsStringAndSize(result, &buf, &len) == -1) { err = callback_exception_error(); } @@ -4002,14 +4077,18 @@ ra_callbacks_push_or_set_wc_prop(const char *callback, goto finished; } - if ((py_value = PyStr_FromStringAndSize(value->data, value->len)) == NULL) + if ((py_value = PyBytes_FromStringAndSize(value->data, value->len)) == NULL) { err = callback_exception_error(); goto finished; } if ((result = PyObject_CallFunction(py_callback, +#if PY_VERSION_HEX >= 0x03000000 + (char *)"yyOO&", path, name, py_value, +#else (char *)"ssOO&", path, name, py_value, +#endif make_ob_pool, pool)) == NULL) { err = callback_exception_error(); @@ -4072,7 +4151,11 @@ ra_callbacks_invalidate_wc_props(void *baton, } if ((result = PyObject_CallFunction(py_callback, +#if PY_VERSION_HEX >= 0x03000000 + (char *)"yyO&", path, name, +#else (char *)"ssO&", path, name, +#endif make_ob_pool, pool)) == NULL) { err = callback_exception_error(); @@ -4201,7 +4284,7 @@ ra_callbacks_get_client_string(void *baton, } else if (result != Py_None) { - if ((*name = PyStr_AsString(result)) == NULL) + if ((*name = PyBytes_AsString(result)) == NULL) { err = callback_exception_error(); } @@ -4304,7 +4387,11 @@ svn_error_t *svn_swig_py_commit_callback(svn_revnum_t new_revision, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(receiver, +#if PY_VERSION_HEX >= 0x03000000 + (char *)"lyy", +#else (char *)"lss", +#endif new_revision, date, author)) == NULL) { err = callback_exception_error(); @@ -4356,7 +4443,7 @@ svn_error_t *svn_swig_py_ra_file_rev_handler_func( } if ((result = PyObject_CallFunction(handler, - (char *)"slOOO&", + (char *)SVN_SWIG_BYTES_FMT "lOOO&", path, rev, py_rev_props, py_prop_diffs, make_ob_pool, pool)) == NULL) { @@ -4402,7 +4489,7 @@ svn_error_t *svn_swig_py_ra_lock_callback( svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(py_callback, - (char *)"sbO&O&O&", + (char *)SVN_SWIG_BYTES_FMT "bO&O&O&", path, do_lock, make_ob_lock, lock, make_ob_error, ra_err, @@ -4439,7 +4526,11 @@ static svn_error_t *reporter_set_path(void *report_baton, if ((result = PyObject_CallMethod(py_reporter, (char *)"set_path", +#if PY_VERSION_HEX >= 0x03000000 + (char *)"ylbyO&", +#else (char *)"slbsO&", +#endif path, revision, start_empty, lock_token, make_ob_pool, pool)) == NULL) @@ -4472,7 +4563,7 @@ static svn_error_t *reporter_delete_path(void *report_baton, if ((result = PyObject_CallMethod(py_reporter, (char *)"delete_path", - (char *)"sO&", + (char *)SVN_SWIG_BYTES_FMT "O&", path, make_ob_pool, pool)) == NULL) { @@ -4508,7 +4599,11 @@ static svn_error_t *reporter_link_path(void *report_baton, if ((result = PyObject_CallMethod(py_reporter, (char *)"link_path", +#if PY_VERSION_HEX >= 0x03000000 + (char *)"yylbsO&", +#else (char *)"sslbsO&", +#endif path, url, revision, start_empty, lock_token, make_ob_pool, pool)) == NULL) @@ -4639,7 +4734,11 @@ wc_diff_callbacks2_file_changed_or_added(const char *callback, } result = PyObject_CallFunction(py_callback, +#if PY_VERSION_HEX >= 0x03000000 + (char *)"O&yyyllyyO&O&", +#else (char *)"O&sssllssO&O&", +#endif make_ob_wc_adm_access, adm_access, path, tmpfile1, tmpfile2, @@ -4762,7 +4861,11 @@ wc_diff_callbacks2_file_deleted(svn_wc_adm_access_t *adm_access, } result = PyObject_CallFunction(py_callback, +#if PY_VERSION_HEX >= 0x03000000 + (char *)"O&yyyyyO&", +#else (char *)"O&sssssO&", +#endif make_ob_wc_adm_access, adm_access, path, tmpfile1, tmpfile2, @@ -4816,7 +4919,11 @@ wc_diff_callbacks2_dir_added(svn_wc_adm_access_t *adm_access, } result = PyObject_CallFunction(py_callback, +#if PY_VERSION_HEX >= 0x03000000 + (char *)"O&yl", +#else (char *)"O&sl", +#endif make_ob_wc_adm_access, adm_access, path, rev); if (result == NULL) @@ -4866,7 +4973,7 @@ wc_diff_callbacks2_dir_deleted(svn_wc_adm_access_t *adm_access, } result = PyObject_CallFunction(py_callback, - (char *)"O&s", + (char *)"O&" SVN_SWIG_BYTES_FMT, make_ob_wc_adm_access, adm_access, path); if (result == NULL) { @@ -4918,7 +5025,11 @@ wc_diff_callbacks2_dir_props_changed(svn_wc_adm_access_t *adm_access, } result = PyObject_CallFunction(py_callback, +#if PY_VERSION_HEX >= 0x03000000 + (char *)"O&yO&O&", +#else (char *)"O&sO&O&", +#endif make_ob_wc_adm_access, adm_access, path, svn_swig_py_proparray_to_dict, propchanges, @@ -4974,7 +5085,11 @@ svn_swig_py_config_enumerator2(const char *name, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, +#if PY_VERSION_HEX >= 0x03000000 + (char *)"yyO&", +#else (char *)"ssO&", +#endif name, value, make_ob_pool, pool)) == NULL) @@ -5022,7 +5137,7 @@ svn_swig_py_config_section_enumerator2(const char *name, svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, - (char *)"sO&", + (char *)SVN_SWIG_BYTES_FMT "O&", name, make_ob_pool, pool)) == NULL) { diff --git a/subversion/bindings/swig/python/svn/core.py b/subversion/bindings/swig/python/svn/core.py index 11713c8def..0a77a276d5 100644 --- a/subversion/bindings/swig/python/svn/core.py +++ b/subversion/bindings/swig/python/svn/core.py @@ -155,7 +155,7 @@ def svn_path_compare_paths(path1, path2): # Common prefix was skipped above, next character is compared to # determine order - return cmp(char1, char2) + return (char1 > char2) - (char1 < char2) def svn_mergeinfo_merge(mergeinfo, changes): return _libsvncore.svn_swig_mergeinfo_merge(mergeinfo, changes) @@ -185,7 +185,7 @@ class Stream: if not data: break chunks.append(data) - return ''.join(chunks) + return b''.join(chunks) # read the amount specified return svn_stream_read(self._stream, int(amt)) diff --git a/subversion/bindings/swig/python/svn/fs.py b/subversion/bindings/swig/python/svn/fs.py index da5911b7cd..0cccb4bd22 100644 --- a/subversion/bindings/swig/python/svn/fs.py +++ b/subversion/bindings/swig/python/svn/fs.py @@ -132,16 +132,16 @@ class FileDiff: with builtins.open(self.difftemp, "wb") as fp: diffopt = _svndiff.file_options_create() - diffobj = _svndiff.file_diff_2(self.tempfile1, - self.tempfile2, + diffobj = _svndiff.file_diff_2(self.tempfile1.encode('UTF-8'), + self.tempfile2.encode('UTF-8'), diffopt) _svndiff.file_output_unified4(fp, diffobj, - self.tempfile1, - self.tempfile2, + self.tempfile1.encode('UTF-8'), + self.tempfile2.encode('UTF-8'), None, None, - "utf8", + b"utf8", None, diffopt.show_c_function, diffopt.context_size, diff --git a/subversion/bindings/swig/python/svn/ra.py b/subversion/bindings/swig/python/svn/ra.py index 035c203f68..ef9f7e8583 100644 --- a/subversion/bindings/swig/python/svn/ra.py +++ b/subversion/bindings/swig/python/svn/ra.py @@ -58,7 +58,7 @@ class Callbacks: svn.core.SVN_AUTH_PARAM_DEFAULT_PASSWORD, password) def open_tmp_file(self, pool): - path = '/'.join([self.wc, svn.wc.get_adm_dir(pool), 'tmp']) + path = b'/'.join([self.wc, svn.wc.get_adm_dir(pool), b'tmp']) (fd, fn) = tempfile.mkstemp(dir=path) os.close(fd) return fn diff --git a/subversion/bindings/swig/python/svn/repos.py b/subversion/bindings/swig/python/svn/repos.py index 6c57fee3ce..486a85026f 100644 --- a/subversion/bindings/swig/python/svn/repos.py +++ b/subversion/bindings/swig/python/svn/repos.py @@ -126,9 +126,9 @@ class ChangeCollector(_svndelta.Editor): self.notify_cb(change) def _make_base_path(self, parent_path, path): - idx = path.rfind('/') + idx = path.rfind(b'/') if parent_path: - parent_path = parent_path + '/' + parent_path = parent_path + b'/' if idx == -1: return parent_path + path return parent_path + path[idx+1:] @@ -142,7 +142,7 @@ class ChangeCollector(_svndelta.Editor): return root def open_root(self, base_revision, dir_pool=None): - return ('', '', self.base_rev) # dir_baton + return (b'', b'', self.base_rev) # dir_baton def delete_entry(self, path, revision, parent_baton, pool=None): base_path = self._make_base_path(parent_baton[1], path) @@ -281,9 +281,9 @@ class RevisionChangeCollector(ChangeCollector): ChangeCollector.__init__(self, fs_ptr, root, pool, notify_cb) def _make_base_path(self, parent_path, path): - idx = path.rfind('/') + idx = path.rfind(b'/') if idx == -1: - return parent_path + '/' + path + return parent_path + b'/' + path return parent_path + path[idx:] diff --git a/subversion/bindings/swig/python/tests/auth.py b/subversion/bindings/swig/python/tests/auth.py index ca9615b595..eec8ce13fc 100644 --- a/subversion/bindings/swig/python/tests/auth.py +++ b/subversion/bindings/swig/python/tests/auth.py @@ -31,82 +31,82 @@ class SubversionAuthTestCase(unittest.TestCase): def test_set_parameter(self): baton = core.svn_auth_open([]) - core.svn_auth_set_parameter(baton, "name", "somedata") - core.svn_auth_set_parameter(baton, "name", None) - core.svn_auth_set_parameter(baton, "name", 2) - core.svn_auth_set_parameter(baton, "name", + core.svn_auth_set_parameter(baton, b"name", b"somedata") + core.svn_auth_set_parameter(baton, b"name", None) + core.svn_auth_set_parameter(baton, b"name", 2) + core.svn_auth_set_parameter(baton, b"name", core.svn_auth_ssl_server_cert_info_t()) def test_invalid_cred_kind(self): baton = core.svn_auth_open([]) self.assertRaises(core.SubversionException, lambda: core.svn_auth_first_credentials( - "unknown", "somerealm", baton)) + b"unknown", b"somerealm", baton)) def test_credentials_get_username(self): def myfunc(realm, maysave, pool): - self.assertEqual("somerealm", realm) + self.assertEqual(b"somerealm", realm) username_cred = core.svn_auth_cred_username_t() - username_cred.username = "bar" + username_cred.username = b"bar" username_cred.may_save = False return username_cred baton = core.svn_auth_open([core.svn_auth_get_username_prompt_provider(myfunc, 1)]) creds = core.svn_auth_first_credentials( - core.SVN_AUTH_CRED_USERNAME, "somerealm", baton) + core.SVN_AUTH_CRED_USERNAME, b"somerealm", baton) self.assertTrue(creds is not None) def test_credentials_get_simple(self): def myfunc(realm, username, may_save, pool): - self.assertEqual("somerealm", realm) + self.assertEqual(b"somerealm", realm) simple_cred = core.svn_auth_cred_simple_t() - simple_cred.username = "mijnnaam" - simple_cred.password = "geheim" + simple_cred.username = b"mijnnaam" + simple_cred.password = b"geheim" simple_cred.may_save = False return simple_cred baton = core.svn_auth_open([core.svn_auth_get_simple_prompt_provider(myfunc, 1)]) creds = core.svn_auth_first_credentials( - core.SVN_AUTH_CRED_SIMPLE, "somerealm", baton) + core.SVN_AUTH_CRED_SIMPLE, b"somerealm", baton) self.assertTrue(creds is not None) def test_credentials_get_ssl_client_cert(self): def myfunc(realm, may_save, pool): - self.assertEqual("somerealm", realm) + self.assertEqual(b"somerealm", realm) ssl_cred = core.svn_auth_cred_ssl_client_cert_t() - ssl_cred.cert_file = "my-certs-file" + ssl_cred.cert_file = b"my-certs-file" ssl_cred.may_save = False return ssl_cred baton = core.svn_auth_open([core.svn_auth_get_ssl_client_cert_prompt_provider(myfunc, 1)]) creds = core.svn_auth_first_credentials( - core.SVN_AUTH_CRED_SSL_CLIENT_CERT, "somerealm", baton) + core.SVN_AUTH_CRED_SSL_CLIENT_CERT, b"somerealm", baton) self.assertTrue(creds is not None) def test_credentials_get_ssl_client_cert_pw(self): def myfunc(realm, may_save, pool): - self.assertEqual("somerealm", realm) + self.assertEqual(b"somerealm", realm) ssl_cred_pw = core.svn_auth_cred_ssl_client_cert_pw_t() - ssl_cred_pw.password = "supergeheim" + ssl_cred_pw.password = b"supergeheim" ssl_cred_pw.may_save = False return ssl_cred_pw baton = core.svn_auth_open([core.svn_auth_get_ssl_client_cert_pw_prompt_provider(myfunc, 1)]) creds = core.svn_auth_first_credentials( - core.SVN_AUTH_CRED_SSL_CLIENT_CERT_PW, "somerealm", baton) + core.SVN_AUTH_CRED_SSL_CLIENT_CERT_PW, b"somerealm", baton) self.assertTrue(creds is not None) def test_credentials_get_ssl_server_trust(self): def myfunc(realm, failures, cert_info, may_save, pool): - self.assertEqual("somerealm", realm) + self.assertEqual(b"somerealm", realm) ssl_trust = core.svn_auth_cred_ssl_server_trust_t() ssl_trust.accepted_failures = 0 ssl_trust.may_save = False return ssl_trust baton = core.svn_auth_open([core.svn_auth_get_ssl_server_trust_prompt_provider(myfunc)]) core.svn_auth_set_parameter(baton, core.SVN_AUTH_PARAM_SSL_SERVER_FAILURES, - "2") + b"2") cert_info = core.svn_auth_ssl_server_cert_info_t() core.svn_auth_set_parameter(baton, core.SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO, cert_info) creds = core.svn_auth_first_credentials( - core.SVN_AUTH_CRED_SSL_SERVER_TRUST, "somerealm", baton) + core.SVN_AUTH_CRED_SSL_SERVER_TRUST, b"somerealm", baton) self.assertTrue(creds is not None) def suite(): diff --git a/subversion/bindings/swig/python/tests/checksum.py b/subversion/bindings/swig/python/tests/checksum.py index 83da28c692..a8f3ca44e9 100644 --- a/subversion/bindings/swig/python/tests/checksum.py +++ b/subversion/bindings/swig/python/tests/checksum.py @@ -29,7 +29,7 @@ class ChecksumTestCases(unittest.TestCase): val = svn.core.svn_checksum_create(kind) check_val = svn.core.svn_checksum_to_cstring_display(val) - self.assertTrue(isinstance(check_val, str), + self.assertTrue(isinstance(check_val, bytes), "Type of digest not string") self.assertEqual(len(check_val), 2*expected_length, "Length of digest does not match kind") diff --git a/subversion/bindings/swig/python/tests/client.py b/subversion/bindings/swig/python/tests/client.py index e7cbb2862b..dcc0472c86 100644 --- a/subversion/bindings/swig/python/tests/client.py +++ b/subversion/bindings/swig/python/tests/client.py @@ -35,7 +35,7 @@ class SubversionClientTestCase(unittest.TestCase): def log_message_func(self, items, pool): """ Simple log message provider for unit tests. """ self.log_message_func_calls += 1 - return "Test log message" + return b"Test log message" def log_receiver(self, changed_paths, revision, author, date, message, pool): """ Function to receive log messages retrieved by client.log3(). """ @@ -129,8 +129,8 @@ class SubversionClientTestCase(unittest.TestCase): # We keep track of these objects in separate variables here # because you can't get a PyObject back out of a PY_AS_VOID field - test_object1 = lambda *args: "message 1" - test_object2 = lambda *args: "message 2" + test_object1 = lambda *args: b"message 1" + test_object2 = lambda *args: b"message 2" # Verify that the refcount of a Python object is incremented when # you insert it into a PY_AS_VOID field. @@ -186,7 +186,7 @@ class SubversionClientTestCase(unittest.TestCase): def test_mkdir_url(self): """Test svn_client_mkdir2 on a file:// URL""" - directory = urljoin(self.repos_uri+"/", "dir1") + directory = urljoin(self.repos_uri+b"/", b"dir1") commit_info = client.mkdir2((directory,), self.client_ctx) self.assertEqual(commit_info.revision, 13) @@ -194,28 +194,28 @@ class SubversionClientTestCase(unittest.TestCase): def test_mkdir_url_with_revprops(self): """Test svn_client_mkdir3 on a file:// URL, with added revprops""" - directory = urljoin(self.repos_uri+"/", "some/deep/subdir") + directory = urljoin(self.repos_uri+b"/", b"some/deep/subdir") - commit_info = client.mkdir3((directory,), 1, {'customprop':'value'}, + commit_info = client.mkdir3((directory,), 1, {b'customprop':b'value'}, self.client_ctx) self.assertEqual(commit_info.revision, 13) self.assertEqual(self.log_message_func_calls, 1) def test_log3_url(self): """Test svn_client_log3 on a file:// URL""" - directory = urljoin(self.repos_uri+"/", "trunk/dir1") + directory = urljoin(self.repos_uri+b"/", b"trunk/dir1") start = core.svn_opt_revision_t() end = core.svn_opt_revision_t() - core.svn_opt_parse_revision(start, end, "4:0") + core.svn_opt_parse_revision(start, end, b"4:0") client.log3((directory,), start, start, end, 1, True, False, self.log_receiver, self.client_ctx) - self.assertEqual(self.change_author, "john") - self.assertEqual(self.log_message, "More directories.") + self.assertEqual(self.change_author, b"john") + self.assertEqual(self.log_message, b"More directories.") self.assertEqual(len(self.changed_paths), 3) - for dir in ('/trunk/dir1', '/trunk/dir2', '/trunk/dir3'): + for dir in (b'/trunk/dir1', b'/trunk/dir2', b'/trunk/dir3'): self.assertTrue(dir in self.changed_paths) - self.assertEqual(self.changed_paths[dir].action, 'A') + self.assertEqual(self.changed_paths[dir].action, b'A') def test_log5(self): """Test svn_client_log5.""" @@ -242,7 +242,7 @@ class SubversionClientTestCase(unittest.TestCase): """Test svn_client_uuid_from_url on a file:// URL""" self.assertTrue(isinstance( client.uuid_from_url(self.repos_uri, self.client_ctx), - str)) + bytes)) def test_url_from_path(self): """Test svn_client_url_from_path for a file:// URL""" @@ -274,7 +274,7 @@ class SubversionClientTestCase(unittest.TestCase): client.uuid_from_url(self.repos_uri, self.client_ctx)) self.assertTrue(isinstance(client.uuid_from_path(path, wc_adm, - self.client_ctx), str)) + self.client_ctx), bytes)) def test_open_ra_session(self): """Test svn_client_open_ra_session().""" @@ -297,8 +297,8 @@ class SubversionClientTestCase(unittest.TestCase): try: # Test 1: Run info -r BASE. We expect the size value to be filled in. rev.kind = core.svn_opt_revision_base - readme_path = '%s/trunk/README.txt' % wc_path - readme_url = '%s/trunk/README.txt' % self.repos_uri + readme_path = b'%s/trunk/README.txt' % wc_path + readme_url = b'%s/trunk/README.txt' % self.repos_uri client.info(readme_path, rev, rev, self.info_receiver, False, self.client_ctx) @@ -344,8 +344,8 @@ class SubversionClientTestCase(unittest.TestCase): True, False, self.client_ctx) # Let's try to backport a change from the v1x branch - trunk_path = core.svn_dirent_join(wc_path, 'trunk') - v1x_path = core.svn_dirent_join(wc_path, 'branches/v1x') + trunk_path = core.svn_dirent_join(wc_path, b'trunk') + v1x_path = core.svn_dirent_join(wc_path, b'branches/v1x') start = core.svn_opt_revision_t() start.kind = core.svn_opt_revision_number @@ -365,14 +365,14 @@ class SubversionClientTestCase(unittest.TestCase): # Did it take effect? readme_path_native = core.svn_dirent_local_style( - core.svn_dirent_join(trunk_path, 'README.txt') + core.svn_dirent_join(trunk_path, b'README.txt') ) - readme = open(readme_path_native, 'r') + readme = open(readme_path_native, 'rb') readme_text = readme.read() readme.close() - self.assertEqual(readme_text, 'This is a test.\n') + self.assertEqual(readme_text, b'This is a test.\n') def test_platform_providers(self): providers = core.svn_auth_get_platform_specific_client_providers(None, None) @@ -391,38 +391,38 @@ class SubversionClientTestCase(unittest.TestCase): # just test if this doesn't error out, there's not even a return # value to test. def prompt_func(realm_string, pool): - return "Foo" + return b"Foo" core.svn_auth_set_gnome_keyring_unlock_prompt_func(self.client_ctx.auth_baton, prompt_func) def proplist_receiver_trunk(self, path, props, iprops, pool): - self.assertEqual(props['svn:global-ignores'], '*.q\n') + self.assertEqual(props[b'svn:global-ignores'], b'*.q\n') self.proplist_receiver_trunk_calls += 1 def proplist_receiver_dir1(self, path, props, iprops, pool): self.assertEqual(iprops[self.proplist_receiver_dir1_key], - {'svn:global-ignores':'*.q\n'}) + {b'svn:global-ignores':b'*.q\n'}) self.proplist_receiver_dir1_calls += 1 def test_inherited_props(self): """Test inherited props""" - trunk_url = self.repos_uri + '/trunk' - client.propset_remote('svn:global-ignores', '*.q', trunk_url, + trunk_url = self.repos_uri + b'/trunk' + client.propset_remote(b'svn:global-ignores', b'*.q', trunk_url, False, 12, {}, None, self.client_ctx) head = core.svn_opt_revision_t() head.kind = core.svn_opt_revision_head - props, iprops, rev = client.propget5('svn:global-ignores', trunk_url, + props, iprops, rev = client.propget5(b'svn:global-ignores', trunk_url, head, head, core.svn_depth_infinity, None, self.client_ctx) - self.assertEqual(props[trunk_url], '*.q\n') + self.assertEqual(props[trunk_url], b'*.q\n') - dir1_url = trunk_url + '/dir1' - props, iprops, rev = client.propget5('svn:global-ignores', dir1_url, + dir1_url = trunk_url + b'/dir1' + props, iprops, rev = client.propget5(b'svn:global-ignores', dir1_url, head, head, core.svn_depth_infinity, None, self.client_ctx) - self.assertEqual(iprops[trunk_url], {'svn:global-ignores':'*.q\n'}) + self.assertEqual(iprops[trunk_url], {b'svn:global-ignores':b'*.q\n'}) self.proplist_receiver_trunk_calls = 0 client.proplist4(trunk_url, head, head, core.svn_depth_empty, None, True, @@ -462,15 +462,15 @@ class SubversionClientTestCase(unittest.TestCase): False, False, self.client_ctx) expected_paths = [ path, - os.path.join(path, 'branches'), - os.path.join(path, 'tags'), - os.path.join(path, 'trunk'), + os.path.join(path, b'branches'), + os.path.join(path, b'tags'), + os.path.join(path, b'trunk'), path, path ] # All normal subversion apis process paths in Subversion's canonical format, # which isn't the platform specific format - expected_paths = [x.replace(os.path.sep, '/') for x in expected_paths] + expected_paths = [x.replace(os.path.sep.encode('UTF-8'), b'/') for x in expected_paths] self.notified_paths.sort() expected_paths.sort() @@ -485,12 +485,12 @@ class SubversionClientTestCase(unittest.TestCase): self.notified_paths = [] expected_paths = [ path, - os.path.join(path, 'trunk', 'README.txt'), - os.path.join(path, 'trunk'), + os.path.join(path, b'trunk', b'README.txt'), + os.path.join(path, b'trunk'), path, path ] - expected_paths = [x.replace(os.path.sep, '/') for x in expected_paths] + expected_paths = [x.replace(os.path.sep.encode('UTF-8'), b'/') for x in expected_paths] client.update4((path,), rev, core.svn_depth_unknown, True, False, False, False, False, self.client_ctx) self.notified_paths.sort() diff --git a/subversion/bindings/swig/python/tests/core.py b/subversion/bindings/swig/python/tests/core.py index b41654357c..f7e4eff26f 100644 --- a/subversion/bindings/swig/python/tests/core.py +++ b/subversion/bindings/swig/python/tests/core.py @@ -19,6 +19,8 @@ # # import unittest +import os +import tempfile import svn.core, svn.client import utils @@ -40,13 +42,13 @@ class SubversionCoreTestCase(unittest.TestCase): 'error message') def test_mime_type_is_binary(self): - self.assertEqual(0, svn.core.svn_mime_type_is_binary("text/plain")) - self.assertEqual(1, svn.core.svn_mime_type_is_binary("image/png")) + self.assertEqual(0, svn.core.svn_mime_type_is_binary(b"text/plain")) + self.assertEqual(1, svn.core.svn_mime_type_is_binary(b"image/png")) def test_mime_type_validate(self): self.assertRaises(svn.core.SubversionException, - svn.core.svn_mime_type_validate, "this\nis\ninvalid\n") - svn.core.svn_mime_type_validate("unknown/but-valid; charset=utf8") + svn.core.svn_mime_type_validate, b"this\nis\ninvalid\n") + svn.core.svn_mime_type_validate(b"unknown/but-valid; charset=utf8") def test_exception_interoperability(self): """Test if SubversionException is correctly converted into svn_error_t @@ -109,20 +111,20 @@ class SubversionCoreTestCase(unittest.TestCase): def test_config_enumerate2(self): cfg = svn.core.svn_config_create(False) entries = { - 'one': 'one-value', - 'two': 'two-value', - 'three': 'three-value' + b'one': b'one-value', + b'two': b'two-value', + b'three': b'three-value' } for (name, value) in entries.items(): - svn.core.svn_config_set(cfg, "section", name, value) + svn.core.svn_config_set(cfg, b"section", name, value) received_entries = {} def enumerator(name, value, pool): received_entries[name] = value return len(received_entries) < 2 - svn.core.svn_config_enumerate2(cfg, "section", enumerator) + svn.core.svn_config_enumerate2(cfg, b"section", enumerator) self.assertEqual(len(received_entries), 2) for (name, value) in received_entries.items(): @@ -131,22 +133,22 @@ class SubversionCoreTestCase(unittest.TestCase): def test_config_enumerate2_exception(self): cfg = svn.core.svn_config_create(False) - svn.core.svn_config_set(cfg, "section", "one", "one-value") - svn.core.svn_config_set(cfg, "section", "two", "two-value") + svn.core.svn_config_set(cfg, b"section", b"one", b"one-value") + svn.core.svn_config_set(cfg, b"section", b"two", b"two-value") def enumerator(name, value, pool): raise Exception # the exception will be swallowed, but enumeration must be stopped self.assertEqual( - svn.core.svn_config_enumerate2(cfg, "section", enumerator), 1) + svn.core.svn_config_enumerate2(cfg, b"section", enumerator), 1) def test_config_enumerate_sections2(self): cfg = svn.core.svn_config_create(False) - sections = ['section-one', 'section-two', 'section-three'] + sections = [b'section-one', b'section-two', b'section-three'] for section in sections: - svn.core.svn_config_set(cfg, section, "name", "value") + svn.core.svn_config_set(cfg, section, b"name", b"value") received_sections = [] def enumerator(section, pool): @@ -161,8 +163,8 @@ class SubversionCoreTestCase(unittest.TestCase): def test_config_enumerate_sections2_exception(self): cfg = svn.core.svn_config_create(False) - svn.core.svn_config_set(cfg, "section-one", "name", "value") - svn.core.svn_config_set(cfg, "section-two", "name", "value") + svn.core.svn_config_set(cfg, b"section-one", b"name", b"value") + svn.core.svn_config_set(cfg, b"section-two", b"name", b"value") def enumerator(section, pool): raise Exception @@ -171,6 +173,120 @@ class SubversionCoreTestCase(unittest.TestCase): self.assertEqual( svn.core.svn_config_enumerate_sections2(cfg, enumerator), 1) + def test_stream_from_stringbuf(self): + stream = svn.core.svn_stream_from_stringbuf(b'') + svn.core.svn_stream_close(stream) + with self.assertRaises(TypeError): + stream = svn.core.svn_stream_from_stringbuf(b''.decode()) + svn.core.svn_stream_close(stream) + + def test_stream_read_full(self): + in_str = (b'Python\x00' + b'\xa4\xd1\xa4\xa4\xa4\xbd\xa4\xf3\r\n' + b'Subversion\x00' + b'\xa4\xb5\xa4\xd6\xa4\xd0\xa1\xbc\xa4\xb8\xa4\xe7\xa4\xf3\n' + b'swig\x00' + b'\xa4\xb9\xa4\xa6\xa4\xa3\xa4\xb0\r' + b'end') + stream = svn.core.svn_stream_from_stringbuf(in_str) + self.assertEqual(svn.core.svn_stream_read_full(stream, 4096), in_str) + svn.core.svn_stream_seek(stream, None) + self.assertEqual(svn.core.svn_stream_read_full(stream, 10), in_str[0:10]) + svn.core.svn_stream_seek(stream, None) + svn.core.svn_stream_skip(stream, 20) + self.assertEqual(svn.core.svn_stream_read_full(stream, 4096), in_str[20:]) + self.assertEqual(svn.core.svn_stream_read_full(stream, 4096), b'') + svn.core.svn_stream_close(stream) + + def test_stream_read2(self): + # as we can't create non block stream by using swig-py API directly, + # we only test svn_stream_read2() behaves just same as + # svn_stream_read_full() + in_str = (b'Python\x00' + b'\xa4\xd1\xa4\xa4\xa4\xbd\xa4\xf3\r\n' + b'Subversion\x00' + b'\xa4\xb5\xa4\xd6\xa4\xd0\xa1\xbc\xa4\xb8\xa4\xe7\xa4\xf3\n' + b'swig\x00' + b'\xa4\xb9\xa4\xa6\xa4\xa3\xa4\xb0\r' + b'end') + stream = svn.core.svn_stream_from_stringbuf(in_str) + self.assertEqual(svn.core.svn_stream_read2(stream, 4096), in_str) + svn.core.svn_stream_seek(stream, None) + self.assertEqual(svn.core.svn_stream_read2(stream, 10), in_str[0:10]) + svn.core.svn_stream_seek(stream, None) + svn.core.svn_stream_skip(stream, 20) + self.assertEqual(svn.core.svn_stream_read2(stream, 4096), in_str[20:]) + self.assertEqual(svn.core.svn_stream_read2(stream, 4096), b'') + svn.core.svn_stream_close(stream) + + def test_stream_write_exception(self): + ostr_unicode = b'Python'.decode() + stream = svn.core.svn_stream_empty() + with self.assertRaises(TypeError): + svn.core.svn_stream_write(stream, ostr_unicode) + svn.core.svn_stream_close(stream) + + def test_stream_write(self): + o1_str = b'Python\x00\xa4\xd1\xa4\xa4\xa4\xbd\xa4\xf3\r\n' + o2_str = (b'subVersioN\x00' + b'\xa4\xb5\xa4\xd6\xa4\xd0\xa1\xbc\xa4\xb8\xa4\xe7\xa4\xf3\n') + o3_str = b'swig\x00\xa4\xb9\xa4\xa6\xa4\xa3\xa4\xb0\rend' + out_str = o1_str + o2_str + o3_str + rewrite_str = b'Subversion' + fd, fname = tempfile.mkstemp() + os.close(fd) + try: + stream = svn.core.svn_stream_from_aprfile2(fname.encode('UTF-8'), False) + self.assertEqual(svn.core.svn_stream_write(stream, out_str), + len(out_str)) + svn.core.svn_stream_seek(stream, None) + self.assertEqual(svn.core.svn_stream_read_full(stream, 4096), out_str) + svn.core.svn_stream_seek(stream, None) + svn.core.svn_stream_skip(stream, len(o1_str)) + self.assertEqual(svn.core.svn_stream_write(stream, rewrite_str), + len(rewrite_str)) + svn.core.svn_stream_seek(stream, None) + self.assertEqual( + svn.core.svn_stream_read_full(stream, 4096), + o1_str + rewrite_str + o2_str[len(rewrite_str):] + o3_str) + svn.core.svn_stream_close(stream) + finally: + try: + os.remove(fname) + except OSError: + pass + + def test_stream_readline(self): + o1_str = b'Python\t\xa4\xd1\xa4\xa4\xa4\xbd\xa4\xf3\r\n' + o2_str = (b'Subversion\t' + b'\xa4\xb5\xa4\xd6\xa4\xd0\xa1\xbc\xa4\xb8\xa4\xe7\xa4\xf3\n') + o3_str = b'swig\t\xa4\xb9\xa4\xa6\xa4\xa3\xa4\xb0\rend' + in_str = o1_str + o2_str + o3_str + stream = svn.core.svn_stream_from_stringbuf(in_str) + self.assertEqual(svn.core.svn_stream_readline(stream, b'\n'), + [o1_str[:-1], 0]) + self.assertEqual(svn.core.svn_stream_readline(stream, b'\n'), + [o2_str[:-1], 0]) + self.assertEqual(svn.core.svn_stream_readline(stream, b'\n'), + [o3_str, 1]) + self.assertEqual(svn.core.svn_stream_readline(stream, b'\n'), + [b'', 1]) + svn.core.svn_stream_seek(stream, None) + self.assertEqual(svn.core.svn_stream_readline(stream, b'\r\n'), + [o1_str[:-2], 0]) + self.assertEqual(svn.core.svn_stream_readline(stream, b'\r\n'), + [o2_str + o3_str, 1]) + svn.core.svn_stream_write(stream, b'\r\n') + svn.core.svn_stream_seek(stream, None) + self.assertEqual(svn.core.svn_stream_readline(stream, b'\r\n'), + [o1_str[:-2], 0]) + self.assertEqual(svn.core.svn_stream_readline(stream, b'\r\n'), + [o2_str + o3_str, 0]) + self.assertEqual(svn.core.svn_stream_readline(stream, b'\r\n'), + [b'', 1]) + svn.core.svn_stream_close(stream) + + def suite(): return unittest.defaultTestLoader.loadTestsFromTestCase( SubversionCoreTestCase) diff --git a/subversion/bindings/swig/python/tests/delta.py b/subversion/bindings/swig/python/tests/delta.py index 3d7dd07442..690ade5da5 100644 --- a/subversion/bindings/swig/python/tests/delta.py +++ b/subversion/bindings/swig/python/tests/delta.py @@ -47,14 +47,15 @@ class DeltaTestCase(unittest.TestCase): def testTxWindowHandler_stream_IF(self): """Test tx_invoke_window_handler, with svn.core.svn_stream_t object""" pool = svn.core.Pool() - in_str = "hello world" + in_str = b"hello world" src_stream = svn.core.svn_stream_from_stringbuf(in_str) - content_str = "bye world" + content_str = b"bye world" content_stream = svn.core.svn_stream_from_stringbuf(content_str) fd, fname = tempfile.mkstemp() os.close(fd) try: - target_stream = svn.core.svn_stream_from_aprfile2(fname, False) + target_stream = svn.core.svn_stream_from_aprfile2(fname.encode('UTF-8'), + False) window_handler, baton = \ svn.delta.tx_apply(src_stream, target_stream, None) svn.delta.tx_send_stream(content_stream, window_handler, baton, pool) @@ -72,17 +73,18 @@ class DeltaTestCase(unittest.TestCase): def testTxWindowHandler_Stream_IF(self): """Test tx_invoke_window_handler, with svn.core.Stream object""" pool = svn.core.Pool() - in_str = "hello world" + in_str = b"hello world" src_stream = svn.core.Stream( svn.core.svn_stream_from_stringbuf(in_str)) - content_str = "bye world" + content_str = b"bye world" content_stream = svn.core.Stream( svn.core.svn_stream_from_stringbuf(content_str)) fd, fname = tempfile.mkstemp() os.close(fd) try: target_stream = svn.core.Stream( - svn.core.svn_stream_from_aprfile2(fname, False)) + svn.core.svn_stream_from_aprfile2(fname.encode('UTF-8'), + False)) window_handler, baton = \ svn.delta.tx_apply(src_stream, target_stream, None) svn.delta.tx_send_stream(content_stream, window_handler, baton, None) diff --git a/subversion/bindings/swig/python/tests/fs.py b/subversion/bindings/swig/python/tests/fs.py index b1e2538d0a..8cadce6c63 100644 --- a/subversion/bindings/swig/python/tests/fs.py +++ b/subversion/bindings/swig/python/tests/fs.py @@ -37,7 +37,7 @@ class SubversionFSTestCase(unittest.TestCase): def log_message_func(self, items, pool): """ Simple log message provider for unit tests. """ - return "Test unicode log message" + return b"Test unicode log message" def setUp(self): """Load a Subversion repository""" @@ -68,8 +68,8 @@ class SubversionFSTestCase(unittest.TestCase): clientctx.auth_baton = core.svn_auth_open(providers) - commitinfo = client.import2(self.tmpfile, - urljoin(self.repos_uri +"/", "trunk/UniTest.txt"), + commitinfo = client.import2(self.tmpfile.encode('UTF-8'), + urljoin(self.repos_uri + b"/", b"trunk/UniTest.txt"), True, True, clientctx) @@ -87,7 +87,7 @@ class SubversionFSTestCase(unittest.TestCase): """Test diffing of a repository path using the internal diff.""" # Test standard internal diff - fdiff = fs.FileDiff(fs.revision_root(self.fs, self.commitedrev), "/trunk/UniTest.txt", + fdiff = fs.FileDiff(fs.revision_root(self.fs, self.commitedrev), b"/trunk/UniTest.txt", None, None, diffoptions=None) diffp = fdiff.get_pipe() @@ -108,7 +108,7 @@ class SubversionFSTestCase(unittest.TestCase): else: raise err - fdiff = fs.FileDiff(fs.revision_root(self.fs, self.commitedrev), "/trunk/UniTest.txt", + fdiff = fs.FileDiff(fs.revision_root(self.fs, self.commitedrev), b"/trunk/UniTest.txt", None, None, diffoptions=[]) diffp = fdiff.get_pipe() diffoutput = diffp.read().decode('utf8') diff --git a/subversion/bindings/swig/python/tests/mergeinfo.py b/subversion/bindings/swig/python/tests/mergeinfo.py index b54b150d8a..873fc52be7 100644 --- a/subversion/bindings/swig/python/tests/mergeinfo.py +++ b/subversion/bindings/swig/python/tests/mergeinfo.py @@ -42,11 +42,11 @@ class SubversionMergeinfoTestCase(unittest.TestCase): """Test cases for mergeinfo""" # Some textual mergeinfo. - TEXT_MERGEINFO1 = "/trunk:3-9,27,42*" - TEXT_MERGEINFO2 = "/trunk:27-29,41-43*" + TEXT_MERGEINFO1 = b"/trunk:3-9,27,42*" + TEXT_MERGEINFO2 = b"/trunk:27-29,41-43*" # Meta data used in conjunction with this mergeinfo. - MERGEINFO_SRC = "/trunk" + MERGEINFO_SRC = b"/trunk" MERGEINFO_NBR_REV_RANGES = 3 def setUp(self): @@ -113,15 +113,15 @@ class SubversionMergeinfoTestCase(unittest.TestCase): self.MERGEINFO_NBR_REV_RANGES) def test_mergeinfo_get(self): - mergeinfo = repos.fs_get_mergeinfo(self.repos, ['/trunk'], self.rev, + mergeinfo = repos.fs_get_mergeinfo(self.repos, [b'/trunk'], self.rev, core.svn_mergeinfo_inherited, False, None, None) expected_mergeinfo = \ - { '/trunk' : - { '/branches/a' : [RevRange(2, 11)], - '/branches/b' : [RevRange(9, 13)], - '/branches/c' : [RevRange(2, 16)], - '/trunk' : [RevRange(1, 9)], }, + { b'/trunk' : + { b'/branches/a' : [RevRange(2, 11)], + b'/branches/b' : [RevRange(9, 13)], + b'/branches/c' : [RevRange(2, 16)], + b'/trunk' : [RevRange(1, 9)], }, } self.compare_mergeinfo_catalogs(mergeinfo, expected_mergeinfo) diff --git a/subversion/bindings/swig/python/tests/ra.py b/subversion/bindings/swig/python/tests/ra.py index 858ceaa66f..3d00b2c2ae 100644 --- a/subversion/bindings/swig/python/tests/ra.py +++ b/subversion/bindings/swig/python/tests/ra.py @@ -53,16 +53,16 @@ class SubversionRepositoryAccessTestCase(unittest.TestCase): def test_get_file(self): # Test getting the properties of a file fs_revnum = fs.youngest_rev(self.fs) - rev, properties = ra.get_file(self.ra_ctx, "trunk/README2.txt", + rev, properties = ra.get_file(self.ra_ctx, b"trunk/README2.txt", core.SVN_INVALID_REVNUM, None) self.assertEqual(rev, fs_revnum) - self.assertEqual(properties["svn:mime-type"], "text/plain") + self.assertEqual(properties[b"svn:mime-type"], b"text/plain") # Test getting the contents of a file filestream = BytesIO() - rev, properties = ra.get_file(self.ra_ctx, "trunk/README2.txt", + rev, properties = ra.get_file(self.ra_ctx, b"trunk/README2.txt", fs_revnum, filestream) - self.assertEqual("A test.\n", filestream.getvalue().decode('UTF-8')) + self.assertEqual(b"A test.\n", filestream.getvalue()) def test_get_repos_root(self): root = ra.get_repos_root(self.ra_ctx) @@ -79,53 +79,53 @@ class SubversionRepositoryAccessTestCase(unittest.TestCase): self.assertEqual(ra_revnum, fs_revnum) def test_get_dir2(self): - (dirents, _, props) = ra.get_dir2(self.ra_ctx, '', 1, core.SVN_DIRENT_KIND) - self.assertTrue('trunk' in dirents) - self.assertTrue('branches' in dirents) - self.assertTrue('tags' in dirents) - self.assertEqual(dirents['trunk'].kind, core.svn_node_dir) - self.assertEqual(dirents['branches'].kind, core.svn_node_dir) - self.assertEqual(dirents['tags'].kind, core.svn_node_dir) + (dirents, _, props) = ra.get_dir2(self.ra_ctx, b'', 1, core.SVN_DIRENT_KIND) + self.assertTrue(b'trunk' in dirents) + self.assertTrue(b'branches' in dirents) + self.assertTrue(b'tags' in dirents) + self.assertEqual(dirents[b'trunk'].kind, core.svn_node_dir) + self.assertEqual(dirents[b'branches'].kind, core.svn_node_dir) + self.assertEqual(dirents[b'tags'].kind, core.svn_node_dir) self.assertTrue(core.SVN_PROP_ENTRY_UUID in props) self.assertTrue(core.SVN_PROP_ENTRY_LAST_AUTHOR in props) - (dirents, _, _) = ra.get_dir2(self.ra_ctx, 'trunk', 1, core.SVN_DIRENT_KIND) + (dirents, _, _) = ra.get_dir2(self.ra_ctx, b'trunk', 1, core.SVN_DIRENT_KIND) self.assertEqual(dirents, {}) - (dirents, _, _) = ra.get_dir2(self.ra_ctx, 'trunk', 10, + (dirents, _, _) = ra.get_dir2(self.ra_ctx, b'trunk', 10, core.SVN_DIRENT_KIND) - self.assertTrue('README2.txt' in dirents) - self.assertEqual(dirents['README2.txt'].kind, core.svn_node_file) + self.assertTrue(b'README2.txt' in dirents) + self.assertEqual(dirents[b'README2.txt'].kind, core.svn_node_file) def test_commit3(self): commit_info = [] def my_callback(info, pool): commit_info.append(info) - revprops = {"svn:log": "foobar", "testprop": ""} + revprops = {b"svn:log": b"foobar", b"testprop": b""} editor, edit_baton = ra.get_commit_editor3(self.ra_ctx, revprops, my_callback, None, False) root = editor.open_root(edit_baton, 4) self.assertNotEqual(root, None) - child = editor.add_directory("bla3", root, None, 0) + child = editor.add_directory(b"bla3", root, None, 0) self.assertNotEqual(child, None) editor.close_edit(edit_baton) info = commit_info[0] self.assertEqual(info.revision, fs.youngest_rev(self.fs)) - revprops['svn:author'] = info.author - revprops['svn:date'] = info.date + revprops[b'svn:author'] = info.author + revprops[b'svn:date'] = info.date self.assertEqual(ra.rev_proplist(self.ra_ctx, info.revision), revprops) def test_commit2(self): def my_callback(info, pool): self.assertEqual(info.revision, fs.youngest_rev(self.fs)) - editor, edit_baton = ra.get_commit_editor2(self.ra_ctx, "foobar", my_callback, None, False) + editor, edit_baton = ra.get_commit_editor2(self.ra_ctx, b"foobar", my_callback, None, False) root = editor.open_root(edit_baton, 4) self.assertNotEqual(root, None) - child = editor.add_directory("bla", root, None, 0) + child = editor.add_directory(b"bla", root, None, 0) self.assertNotEqual(child, None) editor.close_edit(edit_baton) @@ -133,18 +133,18 @@ class SubversionRepositoryAccessTestCase(unittest.TestCase): def my_callback(revision, date, author): self.assertEqual(revision, fs.youngest_rev(self.fs)) - editor, edit_baton = ra.get_commit_editor(self.ra_ctx, "foobar", my_callback, None, False) + editor, edit_baton = ra.get_commit_editor(self.ra_ctx, b"foobar", my_callback, None, False) root = editor.open_root(edit_baton, 4) - child = editor.add_directory("blah", root, None, 0) + child = editor.add_directory(b"blah", root, None, 0) editor.close_edit(edit_baton) def test_delta_driver_commit(self): # Setup paths we'll commit in this test. - to_delete = ['trunk/README.txt', 'trunk/dir1/dir2'] - to_mkdir = ['test_delta_driver_commit.d', 'test_delta_driver_commit2.d'] - to_add = ['test_delta_driver_commit', 'test_delta_driver_commit2'] - to_dir_prop = ['trunk/dir1/dir3', 'test_delta_driver_commit2.d'] - to_file_prop = ['trunk/README2.txt', 'test_delta_driver_commit2'] + to_delete = [b'trunk/README.txt', b'trunk/dir1/dir2'] + to_mkdir = [b'test_delta_driver_commit.d', b'test_delta_driver_commit2.d'] + to_add = [b'test_delta_driver_commit', b'test_delta_driver_commit2'] + to_dir_prop = [b'trunk/dir1/dir3', b'test_delta_driver_commit2.d'] + to_file_prop = [b'trunk/README2.txt', b'test_delta_driver_commit2'] all_paths = {} for i in to_delete + to_mkdir + to_add + to_dir_prop + to_file_prop: all_paths[i] = True @@ -154,7 +154,7 @@ class SubversionRepositoryAccessTestCase(unittest.TestCase): commit_info = [] def commit_cb(info, pool): commit_info.append(info) - revprops = {"svn:log": "foobar", "testprop": ""} + revprops = {b"svn:log": b"foobar", b"testprop": b""} (editor, edit_baton) = ra.get_commit_editor3(self.ra_ctx, revprops, commit_cb, None, False) try: @@ -177,12 +177,12 @@ class SubversionRepositoryAccessTestCase(unittest.TestCase): if dir_baton is None: dir_baton = editor.open_directory(path, parent, revision, pool) editor.change_dir_prop(dir_baton, - 'test_delta_driver_commit', 'foo', pool) + b'test_delta_driver_commit', b'foo', pool) elif path in to_file_prop: if file_baton is None: file_baton = editor.open_file(path, parent, revision, pool) editor.change_file_prop(file_baton, - 'test_delta_driver_commit', 'foo', pool) + b'test_delta_driver_commit', b'foo', pool) if file_baton is not None: editor.close_file(file_baton, None, pool) return dir_baton @@ -199,8 +199,8 @@ class SubversionRepositoryAccessTestCase(unittest.TestCase): info = commit_info[0] if info.author is not None: - revprops['svn:author'] = info.author - revprops['svn:date'] = info.date + revprops[b'svn:author'] = info.author + revprops[b'svn:date'] = info.date self.assertEqual(ra.rev_proplist(self.ra_ctx, info.revision), revprops) receiver_called = [False] @@ -209,17 +209,17 @@ class SubversionRepositoryAccessTestCase(unittest.TestCase): self.assertEqual(revision, info.revision) self.assertEqual(author, info.author) self.assertEqual(date, info.date) - self.assertEqual(message, revprops['svn:log']) + self.assertEqual(message, revprops[b'svn:log']) for (path, change) in core._as_list(changed_paths.items()): - path = path.lstrip('/') + path = path.lstrip(b'/') self.assertTrue(path in all_paths) if path in to_delete: - self.assertEqual(change.action, 'D') + self.assertEqual(change.action, b'D') elif path in to_mkdir or path in to_add: - self.assertEqual(change.action, 'A') + self.assertEqual(change.action, b'A') elif path in to_dir_prop or path in to_file_prop: - self.assertEqual(change.action, 'M') - ra.get_log(self.ra_ctx, [''], info.revision, info.revision, + self.assertEqual(change.action, b'M') + ra.get_log(self.ra_ctx, [b''], info.revision, info.revision, 0, # limit True, # discover_changed_paths True, # strict_node_history @@ -246,26 +246,26 @@ class SubversionRepositoryAccessTestCase(unittest.TestCase): sess_url = ra.get_session_url(self.ra_ctx) try: - ra.reparent(self.ra_ctx, self.repos_uri+"/trunk") + ra.reparent(self.ra_ctx, self.repos_uri+b"/trunk") reporter, reporter_baton = ra.do_diff2(self.ra_ctx, fs_revnum, - "README.txt", 0, 0, 1, + b"README.txt", 0, 0, 1, self.repos_uri - +"/trunk/README.txt", + +b"/trunk/README.txt", e_ptr, e_baton) - reporter.set_path(reporter_baton, "", 0, True, None) + reporter.set_path(reporter_baton, b"", 0, True, None) reporter.finish_report(reporter_baton) finally: ra.reparent(self.ra_ctx, sess_url) - self.assertEqual("A test.\n", editor.textdeltas[0].new_data) + self.assertEqual(b"A test.\n", editor.textdeltas[0].new_data) self.assertEqual(1, len(editor.textdeltas)) def test_get_locations(self): - locations = ra.get_locations(self.ra_ctx, "trunk/README.txt", 2, list(range(1, 5))) + locations = ra.get_locations(self.ra_ctx, b"trunk/README.txt", 2, list(range(1, 5))) self.assertEqual(locations, { - 2: '/trunk/README.txt', - 3: '/trunk/README.txt', - 4: '/trunk/README.txt'}) + 2: b'/trunk/README.txt', + 3: b'/trunk/README.txt', + 4: b'/trunk/README.txt'}) def test_has_capability(self): self.assertEqual(True, ra.has_capability(self.ra_ctx, @@ -274,23 +274,23 @@ class SubversionRepositoryAccessTestCase(unittest.TestCase): def test_get_file_revs(self): def rev_handler(path, rev, rev_props, prop_diffs, pool): self.assertTrue(rev == 2 or rev == 3) - self.assertEqual(path, "/trunk/README.txt") + self.assertEqual(path, b"/trunk/README.txt") if rev == 2: self.assertEqual(rev_props, { - 'svn:log': 'Added README.', - 'svn:author': 'john', - 'svn:date': '2005-04-01T13:12:18.216267Z' + b'svn:log': b'Added README.', + b'svn:author': b'john', + b'svn:date': b'2005-04-01T13:12:18.216267Z' }) self.assertEqual(prop_diffs, {}) elif rev == 3: self.assertEqual(rev_props, { - 'svn:log': 'Fixed README.\n', - 'svn:author': 'kate', - 'svn:date': '2005-04-01T13:24:58.234643Z' + b'svn:log': b'Fixed README.\n', + b'svn:author': b'kate', + b'svn:date': b'2005-04-01T13:24:58.234643Z' }) - self.assertEqual(prop_diffs, {'svn:mime-type': 'text/plain', 'svn:eol-style': 'native'}) + self.assertEqual(prop_diffs, {b'svn:mime-type': b'text/plain', b'svn:eol-style': b'native'}) - ra.get_file_revs(self.ra_ctx, "trunk/README.txt", 0, 10, rev_handler) + ra.get_file_revs(self.ra_ctx, b"trunk/README.txt", 0, 10, rev_handler) def test_lock(self): @@ -299,9 +299,9 @@ class SubversionRepositoryAccessTestCase(unittest.TestCase): self.errors = 0 def callback(path, do_lock, lock, ra_err, pool): self.calls += 1 - self.assertEqual(path, "trunk/README2.txt") + self.assertEqual(path, b"trunk/README2.txt") if lock: - self.assertEqual(lock.owner, "jrandom") + self.assertEqual(lock.owner, b"jrandom") self.locks += 1 if ra_err: self.assertTrue(ra_err.apr_err == core.SVN_ERR_FS_PATH_ALREADY_LOCKED @@ -312,31 +312,31 @@ class SubversionRepositoryAccessTestCase(unittest.TestCase): self.callbacks.auth_baton = core.svn_auth_open(providers) core.svn_auth_set_parameter(self.callbacks.auth_baton, core.SVN_AUTH_PARAM_DEFAULT_USERNAME, - "jrandom") + b"jrandom") self.ra_ctx = ra.open2(self.repos_uri, self.callbacks, {}) rev = fs.youngest_rev(self.fs) - ra.lock(self.ra_ctx, {"trunk/README2.txt":rev}, "sleutel", False, callback) + ra.lock(self.ra_ctx, {b"trunk/README2.txt":rev}, b"sleutel", False, callback) self.assertEqual(self.calls, 1) self.assertEqual(self.locks, 1) self.assertEqual(self.errors, 0) self.calls = 0 self.locks = 0 - ra.lock(self.ra_ctx, {"trunk/README2.txt":rev}, "sleutel", False, callback) + ra.lock(self.ra_ctx, {b"trunk/README2.txt":rev}, b"sleutel", False, callback) self.assertEqual(self.calls, 1) self.assertEqual(self.locks, 0) self.assertEqual(self.errors, 1) self.calls = 0 self.errors = 0 - the_lock = fs.get_lock(self.fs, "/trunk/README2.txt") - ra.unlock(self.ra_ctx, {"trunk/README2.txt":the_lock.token}, False, callback) + the_lock = fs.get_lock(self.fs, b"/trunk/README2.txt") + ra.unlock(self.ra_ctx, {b"trunk/README2.txt":the_lock.token}, False, callback) self.assertEqual(self.calls, 1) self.assertEqual(self.locks, 0) self.assertEqual(self.errors, 0) self.calls = 0 - ra.unlock(self.ra_ctx, {"trunk/README2.txt":the_lock.token}, False, callback) + ra.unlock(self.ra_ctx, {b"trunk/README2.txt":the_lock.token}, False, callback) self.assertEqual(self.calls, 1) self.assertEqual(self.locks, 0) self.assertEqual(self.errors, 1) @@ -346,16 +346,16 @@ class SubversionRepositoryAccessTestCase(unittest.TestCase): self.test_commit3() rev = fs.youngest_rev(self.fs) revprops = ra.rev_proplist(self.ra_ctx, rev) - self.assertTrue("svn:log" in revprops) - self.assertTrue("testprop" in revprops) + self.assertTrue(b"svn:log" in revprops) + self.assertTrue(b"testprop" in revprops) def receiver(log_entry, pool): called[0] = True self.assertEqual(log_entry.revision, rev) if discover_changed_paths: - self.assertEqual(core._as_list(log_entry.changed_paths.keys()), ['/bla3']) - changed_path = log_entry.changed_paths['/bla3'] - self.assertTrue(changed_path.action in ['A', 'D', 'R', 'M']) + self.assertEqual(core._as_list(log_entry.changed_paths.keys()), [b'/bla3']) + changed_path = log_entry.changed_paths[b'/bla3'] + self.assertTrue(changed_path.action in [b'A', b'D', b'R', b'M']) self.assertEqual(changed_path.copyfrom_path, None) self.assertEqual(changed_path.copyfrom_rev, -1) else: @@ -376,9 +376,9 @@ class SubversionRepositoryAccessTestCase(unittest.TestCase): for log_revprops in ( # Retrieve the standard three. - ["svn:author", "svn:date", "svn:log"], + [b"svn:author", b"svn:date", b"svn:log"], # Retrieve just testprop. - ["testprop"], + [b"testprop"], # Retrieve all. None, # Retrieve none. @@ -386,7 +386,7 @@ class SubversionRepositoryAccessTestCase(unittest.TestCase): ): for discover_changed_paths in [True, False]: called = [False] - ra.get_log2(self.ra_ctx, [""], + ra.get_log2(self.ra_ctx, [b""], rev, rev, # start, end 1, # limit discover_changed_paths, @@ -403,22 +403,22 @@ class SubversionRepositoryAccessTestCase(unittest.TestCase): e_ptr, e_baton = delta.make_editor(editor) - reporter, reporter_baton = ra.do_update(self.ra_ctx, 10, "", True, e_ptr, e_baton) + reporter, reporter_baton = ra.do_update(self.ra_ctx, 10, b"", True, e_ptr, e_baton) - reporter.set_path(reporter_baton, "", 0, True, None) + reporter.set_path(reporter_baton, b"", 0, True, None) reporter.finish_report(reporter_baton) def test_namestring(self): # Only ra-{svn,serf} support this right now. uri = self.repos_uri - if uri.startswith('http') or uri.startswith('svn'): + if uri.startswith(b'http') or uri.startswith(b'svn'): called = [False] def cb(pool): called[0] = True - return 'namestring_test' + return b'namestring_test' self.callbacks.get_client_string = cb - ra.stat(self.ra_ctx, "", 1) + ra.stat(self.ra_ctx, b"", 1) self.assertTrue(called[0]) def suite(): diff --git a/subversion/bindings/swig/python/tests/repository.py b/subversion/bindings/swig/python/tests/repository.py index 8e60e3e98e..034e3ed1c8 100644 --- a/subversion/bindings/swig/python/tests/repository.py +++ b/subversion/bindings/swig/python/tests/repository.py @@ -44,34 +44,34 @@ class DumpStreamParser(repos.ParseFns3): repos.ParseFns3.__init__(self) self.ops = [] def magic_header_record(self, version, pool=None): - self.ops.append(("magic-header", version)) + self.ops.append((b"magic-header", version)) def uuid_record(self, uuid, pool=None): - self.ops.append(("uuid", uuid)) + self.ops.append((b"uuid", uuid)) def new_revision_record(self, headers, pool=None): rev = int(headers[repos.DUMPFILE_REVISION_NUMBER]) - self.ops.append(("new-revision", rev)) + self.ops.append((b"new-revision", rev)) return rev def close_revision(self, revision_baton): - self.ops.append(("close-revision", revision_baton)) + self.ops.append((b"close-revision", revision_baton)) def new_node_record(self, headers, revision_baton, pool=None): node = headers[repos.DUMPFILE_NODE_PATH] - self.ops.append(("new-node", revision_baton, node)) + self.ops.append((b"new-node", revision_baton, node)) return (revision_baton, node) def close_node(self, node_baton): - self.ops.append(("close-node", node_baton[0], node_baton[1])) + self.ops.append((b"close-node", node_baton[0], node_baton[1])) def set_revision_property(self, revision_baton, name, value): - self.ops.append(("set-revision-prop", revision_baton, name, value)) + self.ops.append((b"set-revision-prop", revision_baton, name, value)) def set_node_property(self, node_baton, name, value): - self.ops.append(("set-node-prop", node_baton[0], node_baton[1], name, value)) + self.ops.append((b"set-node-prop", node_baton[0], node_baton[1], name, value)) def remove_node_props(self, node_baton): - self.ops.append(("remove-node-props", node_baton[0], node_baton[1])) + self.ops.append((b"remove-node-props", node_baton[0], node_baton[1])) def delete_node_property(self, node_baton, name): - self.ops.append(("delete-node-prop", node_baton[0], node_baton[1], name)) + self.ops.append((b"delete-node-prop", node_baton[0], node_baton[1], name)) def apply_textdelta(self, node_baton): - self.ops.append(("apply-textdelta", node_baton[0], node_baton[1])) + self.ops.append((b"apply-textdelta", node_baton[0], node_baton[1])) return None def set_fulltext(self, node_baton): - self.ops.append(("set-fulltext", node_baton[0], node_baton[1])) + self.ops.append((b"set-fulltext", node_baton[0], node_baton[1])) return None @@ -104,17 +104,17 @@ class SubversionRepositoryTestCase(unittest.TestCase): raise core.SubversionException(apr_err=core.SVN_ERR_CEASE_INVOCATION, message="Hi from history_lookup") - repos.history2(self.fs, '/trunk/README2.txt', history_lookup, None, 0, + repos.history2(self.fs, b'/trunk/README2.txt', history_lookup, None, 0, self.rev, True) self.assertEqual(len(revs), 1) def test_create(self): """Make sure that repos.create doesn't segfault when we set fs-type using a config hash""" - fs_config = { "fs-type": "fsfs" } + fs_config = { b"fs-type": b"fsfs" } for i in range(5): path = self.temper.alloc_empty_dir(suffix='-repository-create%d' % i) - repos.create(path, "", "", None, fs_config) + repos.create(path, b"", b"", None, fs_config) def test_dump_fs2(self): """Test the dump_fs2 function""" @@ -131,10 +131,10 @@ class SubversionRepositoryTestCase(unittest.TestCase): is_cancelled) # Check that we can dump stuff - dump = dumpstream.getvalue().decode("UTF-8") - feedback = feedbackstream.getvalue().decode("UTF-8") - expected_feedback = "* Dumped revision " + str(self.rev) - self.assertEqual(dump.count("Node-path: trunk/README.txt"), 2) + dump = dumpstream.getvalue() + feedback = feedbackstream.getvalue() + expected_feedback = b"* Dumped revision " + str(self.rev).encode('utf-8') + self.assertEqual(dump.count(b"Node-path: trunk/README.txt"), 2) self.assertEqual(feedback.count(expected_feedback), 1) self.assertEqual(self.callback_calls, 13) @@ -154,13 +154,13 @@ class SubversionRepositoryTestCase(unittest.TestCase): # Check that we can grab the feedback stream, but not the dumpstream repos.dump_fs2(self.repos, None, feedbackstream, 0, self.rev, 0, 0, None) - feedback = feedbackstream.getvalue().decode('UTF-8') + feedback = feedbackstream.getvalue() self.assertEqual(feedback.count(expected_feedback), 1) # Check that we can grab the dumpstream, but not the feedbackstream repos.dump_fs2(self.repos, dumpstream, None, 0, self.rev, 0, 0, None) - dump = dumpstream.getvalue().decode('UTF-8') - self.assertEqual(dump.count("Node-path: trunk/README.txt"), 2) + dump = dumpstream.getvalue() + self.assertEqual(dump.count(b"Node-path: trunk/README.txt"), 2) # Check that we can ignore both the dumpstream and the feedbackstream repos.dump_fs2(self.repos, dumpstream, None, 0, self.rev, 0, 0, None) @@ -184,43 +184,43 @@ class SubversionRepositoryTestCase(unittest.TestCase): stream.close() self.assertEqual(self.cancel_calls, 76) expected_list = [ - ("magic-header", 2), - ('uuid', '92ea810a-adf3-0310-b540-bef912dcf5ba'), - ('new-revision', 0), - ('set-revision-prop', 0, 'svn:date', '2005-04-01T09:57:41.312767Z'), - ('close-revision', 0), - ('new-revision', 1), - ('set-revision-prop', 1, 'svn:log', 'Initial directory layout.'), - ('set-revision-prop', 1, 'svn:author', 'john'), - ('set-revision-prop', 1, 'svn:date', '2005-04-01T10:00:52.353248Z'), - ('new-node', 1, 'branches'), - ('remove-node-props', 1, 'branches'), - ('close-node', 1, 'branches'), - ('new-node', 1, 'tags'), - ('remove-node-props', 1, 'tags'), - ('close-node', 1, 'tags'), - ('new-node', 1, 'trunk'), - ('remove-node-props', 1, 'trunk'), - ('close-node', 1, 'trunk'), - ('close-revision', 1), - ('new-revision', 2), - ('set-revision-prop', 2, 'svn:log', 'Added README.'), - ('set-revision-prop', 2, 'svn:author', 'john'), - ('set-revision-prop', 2, 'svn:date', '2005-04-01T13:12:18.216267Z'), - ('new-node', 2, 'trunk/README.txt'), - ('remove-node-props', 2, 'trunk/README.txt'), - ('set-fulltext', 2, 'trunk/README.txt'), - ('close-node', 2, 'trunk/README.txt'), - ('close-revision', 2), ('new-revision', 3), - ('set-revision-prop', 3, 'svn:log', 'Fixed README.\n'), - ('set-revision-prop', 3, 'svn:author', 'kate'), - ('set-revision-prop', 3, 'svn:date', '2005-04-01T13:24:58.234643Z'), - ('new-node', 3, 'trunk/README.txt'), - ('remove-node-props', 3, 'trunk/README.txt'), - ('set-node-prop', 3, 'trunk/README.txt', 'svn:mime-type', 'text/plain'), - ('set-node-prop', 3, 'trunk/README.txt', 'svn:eol-style', 'native'), - ('set-fulltext', 3, 'trunk/README.txt'), - ('close-node', 3, 'trunk/README.txt'), ('close-revision', 3), + (b"magic-header", 2), + (b'uuid', b'92ea810a-adf3-0310-b540-bef912dcf5ba'), + (b'new-revision', 0), + (b'set-revision-prop', 0, b'svn:date', b'2005-04-01T09:57:41.312767Z'), + (b'close-revision', 0), + (b'new-revision', 1), + (b'set-revision-prop', 1, b'svn:log', b'Initial directory layout.'), + (b'set-revision-prop', 1, b'svn:author', b'john'), + (b'set-revision-prop', 1, b'svn:date', b'2005-04-01T10:00:52.353248Z'), + (b'new-node', 1, b'branches'), + (b'remove-node-props', 1, b'branches'), + (b'close-node', 1, b'branches'), + (b'new-node', 1, b'tags'), + (b'remove-node-props', 1, b'tags'), + (b'close-node', 1, b'tags'), + (b'new-node', 1, b'trunk'), + (b'remove-node-props', 1, b'trunk'), + (b'close-node', 1, b'trunk'), + (b'close-revision', 1), + (b'new-revision', 2), + (b'set-revision-prop', 2, b'svn:log', b'Added README.'), + (b'set-revision-prop', 2, b'svn:author', b'john'), + (b'set-revision-prop', 2, b'svn:date', b'2005-04-01T13:12:18.216267Z'), + (b'new-node', 2, b'trunk/README.txt'), + (b'remove-node-props', 2, b'trunk/README.txt'), + (b'set-fulltext', 2, b'trunk/README.txt'), + (b'close-node', 2, b'trunk/README.txt'), + (b'close-revision', 2), (b'new-revision', 3), + (b'set-revision-prop', 3, b'svn:log', b'Fixed README.\n'), + (b'set-revision-prop', 3, b'svn:author', b'kate'), + (b'set-revision-prop', 3, b'svn:date', b'2005-04-01T13:24:58.234643Z'), + (b'new-node', 3, b'trunk/README.txt'), + (b'remove-node-props', 3, b'trunk/README.txt'), + (b'set-node-prop', 3, b'trunk/README.txt', b'svn:mime-type', b'text/plain'), + (b'set-node-prop', 3, b'trunk/README.txt', b'svn:eol-style', b'native'), + (b'set-fulltext', 3, b'trunk/README.txt'), + (b'close-node', 3, b'trunk/README.txt'), (b'close-revision', 3), ] # Compare only the first X nodes described in the expected list - otherwise # the comparison list gets too long. @@ -232,7 +232,7 @@ class SubversionRepositoryTestCase(unittest.TestCase): DumpStreamParser.set_fulltext(self, node_baton) return 42 stream = open(os.path.join(os.path.dirname(sys.argv[0]), - "trac/versioncontrol/tests/svnrepos.dump")) + "trac/versioncontrol/tests/svnrepos.dump"), "rb") try: dsp = DumpStreamParserSubclass() ptr, baton = repos.make_parse_fns3(dsp) @@ -249,7 +249,7 @@ class SubversionRepositoryTestCase(unittest.TestCase): logs.append(paths) # Run get_logs - repos.get_logs(self.repos, ['/'], self.rev, 0, True, 0, addLog) + repos.get_logs(self.repos, [b'/'], self.rev, 0, True, 0, addLog) # Count and verify changes change_count = 0 @@ -257,8 +257,8 @@ class SubversionRepositoryTestCase(unittest.TestCase): for path_changed in core._as_list(log.values()): change_count += 1 path_changed.assert_valid() - self.assertEqual(logs[2]["/tags/v1.1"].action, "A") - self.assertEqual(logs[2]["/tags/v1.1"].copyfrom_path, "/branches/v1x") + self.assertEqual(logs[2][b"/tags/v1.1"].action, b"A") + self.assertEqual(logs[2][b"/tags/v1.1"].copyfrom_path, b"/branches/v1x") self.assertEqual(len(logs), 12) self.assertEqual(change_count, 19) @@ -269,14 +269,14 @@ class SubversionRepositoryTestCase(unittest.TestCase): prev_root = fs.revision_root(self.fs, self.rev-1) editor = ChangeReceiver(this_root, prev_root) e_ptr, e_baton = delta.make_editor(editor) - repos.dir_delta(prev_root, '', '', this_root, '', e_ptr, e_baton, + repos.dir_delta(prev_root, b'', b'', this_root, b'', e_ptr, e_baton, _authz_callback, 1, 1, 0, 0) # Check results. # Ignore the order in which the editor delivers the two sibling files. self.assertEqual(set([editor.textdeltas[0].new_data, editor.textdeltas[1].new_data]), - set(["This is a test.\n", "A test.\n"])) + set([b"This is a test.\n", b"A test.\n"])) self.assertEqual(len(editor.textdeltas), 2) def test_unnamed_editor(self): @@ -287,29 +287,29 @@ class SubversionRepositoryTestCase(unittest.TestCase): this_root = fs.revision_root(self.fs, self.rev) prev_root = fs.revision_root(self.fs, self.rev-1) e_ptr, e_baton = delta.make_editor(ChangeReceiver(this_root, prev_root)) - repos.dir_delta(prev_root, '', '', this_root, '', e_ptr, e_baton, + repos.dir_delta(prev_root, b'', b'', this_root, b'', e_ptr, e_baton, _authz_callback, 1, 1, 0, 0) def test_retrieve_and_change_rev_prop(self): """Test playing with revprops""" - self.assertEqual(repos.fs_revision_prop(self.repos, self.rev, "svn:log", + self.assertEqual(repos.fs_revision_prop(self.repos, self.rev, b"svn:log", _authz_callback), - "''(a few years later)'' Argh... v1.1 was buggy, " - "after all") + b"''(a few years later)'' Argh... v1.1 was buggy, " + b"after all") # We expect this to complain because we have no pre-revprop-change # hook script for the repository. self.assertRaises(SubversionException, repos.fs_change_rev_prop3, - self.repos, self.rev, "jrandom", "svn:log", - "Youngest revision", True, True, _authz_callback) + self.repos, self.rev, b"jrandom", b"svn:log", + b"Youngest revision", True, True, _authz_callback) - repos.fs_change_rev_prop3(self.repos, self.rev, "jrandom", "svn:log", - "Youngest revision", False, False, + repos.fs_change_rev_prop3(self.repos, self.rev, b"jrandom", b"svn:log", + b"Youngest revision", False, False, _authz_callback) - self.assertEqual(repos.fs_revision_prop(self.repos, self.rev, "svn:log", + self.assertEqual(repos.fs_revision_prop(self.repos, self.rev, b"svn:log", _authz_callback), - "Youngest revision") + b"Youngest revision") def freeze_body(self, pool): self.freeze_invoked += 1 @@ -324,42 +324,42 @@ class SubversionRepositoryTestCase(unittest.TestCase): def test_lock_unlock(self): """Basic lock/unlock""" - access = fs.create_access('jrandom') + access = fs.create_access(b'jrandom') fs.set_access(self.fs, access) - fs.lock(self.fs, '/trunk/README.txt', None, None, 0, 0, self.rev, False) + fs.lock(self.fs, b'/trunk/README.txt', None, None, 0, 0, self.rev, False) try: - fs.lock(self.fs, '/trunk/README.txt', None, None, 0, 0, self.rev, False) + fs.lock(self.fs, b'/trunk/README.txt', None, None, 0, 0, self.rev, False) except core.SubversionException as exc: self.assertEqual(exc.apr_err, core.SVN_ERR_FS_PATH_ALREADY_LOCKED) - fs.lock(self.fs, '/trunk/README.txt', None, None, 0, 0, self.rev, True) + fs.lock(self.fs, b'/trunk/README.txt', None, None, 0, 0, self.rev, True) self.calls = 0 self.errors = 0 def unlock_callback(path, lock, err, pool): - self.assertEqual(path, '/trunk/README.txt') + self.assertEqual(path, b'/trunk/README.txt') self.assertEqual(lock, None) self.calls += 1 if err != None: self.assertEqual(err.apr_err, core.SVN_ERR_FS_NO_SUCH_LOCK) self.errors += 1 - the_lock = fs.get_lock(self.fs, '/trunk/README.txt') - fs.unlock_many(self.fs, {'/trunk/README.txt':the_lock.token}, False, + the_lock = fs.get_lock(self.fs, b'/trunk/README.txt') + fs.unlock_many(self.fs, {b'/trunk/README.txt':the_lock.token}, False, unlock_callback) self.assertEqual(self.calls, 1) self.assertEqual(self.errors, 0) self.calls = 0 - fs.unlock_many(self.fs, {'/trunk/README.txt':the_lock.token}, False, + fs.unlock_many(self.fs, {b'/trunk/README.txt':the_lock.token}, False, unlock_callback) self.assertEqual(self.calls, 1) self.assertEqual(self.errors, 1) self.locks = 0 def lock_callback(path, lock, err, pool): - self.assertEqual(path, '/trunk/README.txt') + self.assertEqual(path, b'/trunk/README.txt') if lock != None: - self.assertEqual(lock.owner, 'jrandom') + self.assertEqual(lock.owner, b'jrandom') self.locks += 1 self.calls += 1 if err != None: @@ -369,7 +369,7 @@ class SubversionRepositoryTestCase(unittest.TestCase): self.calls = 0 self.errors = 0 target = fs.lock_target_create(None, self.rev) - fs.lock_many(self.fs, {'trunk/README.txt':target}, + fs.lock_many(self.fs, {b'trunk/README.txt':target}, None, False, 0, False, lock_callback) self.assertEqual(self.calls, 1) self.assertEqual(self.locks, 1) @@ -377,7 +377,7 @@ class SubversionRepositoryTestCase(unittest.TestCase): self.calls = 0 self.locks = 0 - fs.lock_many(self.fs, {'trunk/README.txt':target}, + fs.lock_many(self.fs, {b'trunk/README.txt':target}, None, False, 0, False, lock_callback) self.assertEqual(self.calls, 1) self.assertEqual(self.locks, 0) @@ -385,21 +385,21 @@ class SubversionRepositoryTestCase(unittest.TestCase): self.calls = 0 self.errors = 0 - the_lock = fs.get_lock(self.fs, '/trunk/README.txt') - repos.fs_unlock_many(self.repos, {'trunk/README.txt':the_lock.token}, + the_lock = fs.get_lock(self.fs, b'/trunk/README.txt') + repos.fs_unlock_many(self.repos, {b'trunk/README.txt':the_lock.token}, False, unlock_callback) self.assertEqual(self.calls, 1) self.assertEqual(self.errors, 0) self.calls = 0 - repos.fs_unlock_many(self.repos, {'trunk/README.txt':the_lock.token}, + repos.fs_unlock_many(self.repos, {b'trunk/README.txt':the_lock.token}, False, unlock_callback) self.assertEqual(self.calls, 1) self.assertEqual(self.errors, 1) self.calls = 0 self.errors = 0 - repos.fs_lock_many(self.repos, {'trunk/README.txt':target}, + repos.fs_lock_many(self.repos, {b'trunk/README.txt':target}, None, False, 0, False, lock_callback) self.assertEqual(self.calls, 1) self.assertEqual(self.locks, 1) @@ -407,7 +407,7 @@ class SubversionRepositoryTestCase(unittest.TestCase): self.calls = 0 self.locks = 0 - repos.fs_lock_many(self.repos, {'trunk/README.txt':target}, + repos.fs_lock_many(self.repos, {b'trunk/README.txt':target}, None, False, 0, False, lock_callback) self.assertEqual(self.calls, 1) self.assertEqual(self.locks, 0) diff --git a/subversion/bindings/swig/python/tests/trac/versioncontrol/main.py b/subversion/bindings/swig/python/tests/trac/versioncontrol/main.py index 1b8a87c3f4..0d5d0618de 100644 --- a/subversion/bindings/swig/python/tests/trac/versioncontrol/main.py +++ b/subversion/bindings/swig/python/tests/trac/versioncontrol/main.py @@ -154,12 +154,12 @@ class Node(object): Represents a directory or file in the repository. """ - DIRECTORY = "dir" - FILE = "file" + DIRECTORY = b"dir" + FILE = b"file" def __init__(self, path, rev, kind): assert kind in (Node.DIRECTORY, Node.FILE), "Unknown node kind %s" % kind - self.path = str(path) + self.path = path self.rev = rev self.kind = kind @@ -217,7 +217,7 @@ class Node(object): content_type = property(lambda x: x.get_content_type()) def get_name(self): - return self.path.split('/')[-1] + return self.path.split(b'/')[-1] name = property(lambda x: x.get_name()) def get_last_modified(self): @@ -233,11 +233,11 @@ class Changeset(object): Represents a set of changes of a repository. """ - ADD = 'add' - COPY = 'copy' - DELETE = 'delete' - EDIT = 'edit' - MOVE = 'move' + ADD = b'add' + COPY = b'copy' + DELETE = b'delete' + EDIT = b'edit' + MOVE = b'move' def __init__(self, rev, message, author, date): self.rev = rev diff --git a/subversion/bindings/swig/python/tests/trac/versioncontrol/svn_fs.py b/subversion/bindings/swig/python/tests/trac/versioncontrol/svn_fs.py index e0aef2df0d..fe92bb70b7 100644 --- a/subversion/bindings/swig/python/tests/trac/versioncontrol/svn_fs.py +++ b/subversion/bindings/swig/python/tests/trac/versioncontrol/svn_fs.py @@ -55,9 +55,12 @@ import os.path import time import weakref import posixpath +import sys from svn import fs, repos, core, delta +IS_PY3 = sys.version_info[0] >= 3 + _kindmap = {core.svn_node_dir: Node.DIRECTORY, core.svn_node_file: Node.FILE} @@ -107,17 +110,17 @@ class SubversionRepository(Repository): raise TracError("%s does not appear to be a Subversion repository." % (path, )) if self.path != path: self.scope = path[len(self.path):] - if not self.scope[-1] == '/': - self.scope += '/' + if not self.scope[-1:] == b'/': + self.scope += b'/' else: - self.scope = '/' + self.scope = b'/' self.repos = repos.svn_repos_open(self.path) self.fs_ptr = repos.svn_repos_fs(self.repos) self.rev = fs.youngest_rev(self.fs_ptr) self.history = None - if self.scope != '/': + if self.scope != b'/': self.history = [] for path,rev in _get_history(self.scope[1:], self.authz, self.fs_ptr, 0, self.rev): @@ -132,7 +135,7 @@ class SubversionRepository(Repository): return node_type in _kindmap def normalize_path(self, path): - return path == '/' and path or path and path.strip('/') or '' + return path == b'/' and path or path and path.strip(b'/') or b'' def normalize_rev(self, rev): try: @@ -157,7 +160,7 @@ class SubversionRepository(Repository): def get_node(self, path, rev=None): self.authz.assert_permission(self.scope + path) - if path and path[-1] == '/': + if path and path[-1] == b'/': path = path[:-1] rev = self.normalize_rev(rev) @@ -166,13 +169,13 @@ class SubversionRepository(Repository): def get_oldest_rev(self): rev = 0 - if self.scope == '/': + if self.scope == b'/': return rev return self.history[-1] def get_youngest_rev(self): rev = self.rev - if self.scope == '/': + if self.scope == b'/': return rev return self.history[0] @@ -180,7 +183,7 @@ class SubversionRepository(Repository): rev = int(rev) if rev == 0: return None - if self.scope == '/': + if self.scope == b'/': return rev - 1 idx = self.history.index(rev) if idx + 1 < len(self.history): @@ -191,7 +194,7 @@ class SubversionRepository(Repository): rev = int(rev) if rev == self.rev: return None - if self.scope == '/': + if self.scope == b'/': return rev + 1 if rev == 0: return self.oldest_rev @@ -224,7 +227,7 @@ class SubversionRepository(Repository): else: # the path changed: 'newer' was a copy rev = self.previous_rev(newer[1]) # restart before the copy op yield newer[0], newer[1], Changeset.COPY - older = (older[0], older[1], 'unknown') + older = (older[0], older[1], b'unknown') break newer = older if older: # either a real ADD or the source of a COPY @@ -262,7 +265,7 @@ class SubversionRepository(Repository): def authz_cb(root, path, pool): return 1 text_deltas = 0 # as this is anyway re-done in Diff.py... entry_props = 0 # ("... typically used only for working copy updates") - repos.svn_repos_dir_delta(old_root, old_path, '', + repos.svn_repos_dir_delta(old_root, old_path, b'', new_root, new_path, e_ptr, e_baton, authz_cb, text_deltas, @@ -290,7 +293,7 @@ class SubversionNode(Node): def __init__(self, path, rev, authz, scope, fs_ptr): self.authz = authz self.scope = scope - if scope != '/': + if scope != b'/': self.scoped_path = scope + path else: self.scoped_path = path @@ -300,7 +303,11 @@ class SubversionNode(Node): self.root = fs.revision_root(fs_ptr, rev) node_type = fs.check_path(self.root, self.scoped_path) if not node_type in _kindmap: - raise TracError("No node at %s in revision %s" % (path, rev)) + if IS_PY3: + raise TracError("No node at %s in revision %s" + % (path.decode('UTF-8'), rev)) + else: + raise TracError("No node at %s in revision %s" % (path, rev)) self.created_rev = fs.node_created_rev(self.root, self.scoped_path) self.created_path = fs.node_created_path(self.root, self.scoped_path) # Note: 'created_path' differs from 'path' if the last change was a copy, @@ -323,7 +330,7 @@ class SubversionNode(Node): return entries = fs.dir_entries(self.root, self.scoped_path) for item in entries: - path = '/'.join((self.path, item)) + path = b'/'.join((self.path, item)) if not self.authz.has_permission(path): continue yield SubversionNode(path, self._requested_rev, self.authz, @@ -350,7 +357,7 @@ class SubversionNode(Node): def get_properties(self): props = fs.node_proplist(self.root, self.scoped_path) for name,value in core._as_list(props.items()): - props[name] = str(value) # Make sure the value is a proper string + props[name] = value return props def get_content_length(self): @@ -461,7 +468,7 @@ class DiffChangeEditor(delta.Editor): # -- svn.delta.Editor callbacks def open_root(self, base_revision, dir_pool): - return ('/', Changeset.EDIT) + return (b'/', Changeset.EDIT) def add_directory(self, path, dir_baton, copyfrom_path, copyfrom_rev, dir_pool): self.deltas.append((path, Node.DIRECTORY, Changeset.ADD)) diff --git a/subversion/bindings/swig/python/tests/trac/versioncontrol/tests/svn_fs.py b/subversion/bindings/swig/python/tests/trac/versioncontrol/tests/svn_fs.py index a4c39c2783..edbefd012c 100644 --- a/subversion/bindings/swig/python/tests/trac/versioncontrol/tests/svn_fs.py +++ b/subversion/bindings/swig/python/tests/trac/versioncontrol/tests/svn_fs.py @@ -68,19 +68,19 @@ from trac.test import TestSetup from trac.versioncontrol import Changeset, Node from trac.versioncontrol.svn_fs import SubversionRepository -temp_path = tempfile.mktemp("-trac-svnrepos") +temp_path = tempfile.mktemp("-trac-svnrepos").encode('UTF-8') REPOS_PATH = core.svn_dirent_internal_style(temp_path) -REPOS_URL = pathname2url(temp_path) +REPOS_URL = pathname2url(temp_path).encode('UTF-8') del temp_path -if REPOS_URL.startswith("///"): +if REPOS_URL.startswith(b"///"): # Don't add extra slashes if they're already present. # (This is important for Windows compatibility). - REPOS_URL = "file:" + REPOS_URL + REPOS_URL = b"file:" + REPOS_URL else: # If the URL simply starts with '/', we need to add two # extra slashes to make it a valid 'file://' URL - REPOS_URL = "file://" + REPOS_URL + REPOS_URL = b"file://" + REPOS_URL REPOS_URL = core.svn_uri_canonicalize(REPOS_URL) @@ -93,9 +93,9 @@ class SubversionRepositoryTestSetup(TestSetup): # ensure a fresh start. self.tearDown() - r = repos.svn_repos_create(REPOS_PATH, '', '', None, None) + r = repos.svn_repos_create(REPOS_PATH, b'', b'', None, None) repos.svn_repos_load_fs2(r, dumpfile, BytesIO(), - repos.svn_repos_load_uuid_ignore, '', + repos.svn_repos_load_uuid_ignore, b'', 0, 0, None) def tearDown(self): @@ -122,111 +122,111 @@ class SubversionRepositoryTestCase(unittest.TestCase): self.assertEqual(None, self.repos.next_rev(12)) def test_get_node(self): - node = self.repos.get_node('/trunk') - self.assertEqual('trunk', node.name) - self.assertEqual('/trunk', node.path) + node = self.repos.get_node(b'/trunk') + self.assertEqual(b'trunk', node.name) + self.assertEqual(b'/trunk', node.path) self.assertEqual(Node.DIRECTORY, node.kind) self.assertEqual(6, node.rev) self.assertEqual(1112381806, node.last_modified) - node = self.repos.get_node('/trunk/README.txt') - self.assertEqual('README.txt', node.name) - self.assertEqual('/trunk/README.txt', node.path) + node = self.repos.get_node(b'/trunk/README.txt') + self.assertEqual(b'README.txt', node.name) + self.assertEqual(b'/trunk/README.txt', node.path) self.assertEqual(Node.FILE, node.kind) self.assertEqual(3, node.rev) self.assertEqual(1112361898, node.last_modified) def test_get_node_specific_rev(self): - node = self.repos.get_node('/trunk', 1) - self.assertEqual('trunk', node.name) - self.assertEqual('/trunk', node.path) + node = self.repos.get_node(b'/trunk', 1) + self.assertEqual(b'trunk', node.name) + self.assertEqual(b'/trunk', node.path) self.assertEqual(Node.DIRECTORY, node.kind) self.assertEqual(1, node.rev) self.assertEqual(1112349652, node.last_modified) - node = self.repos.get_node('/trunk/README.txt', 2) - self.assertEqual('README.txt', node.name) - self.assertEqual('/trunk/README.txt', node.path) + node = self.repos.get_node(b'/trunk/README.txt', 2) + self.assertEqual(b'README.txt', node.name) + self.assertEqual(b'/trunk/README.txt', node.path) self.assertEqual(Node.FILE, node.kind) self.assertEqual(2, node.rev) self.assertEqual(1112361138, node.last_modified) def test_get_dir_entries(self): - node = self.repos.get_node('/trunk') + node = self.repos.get_node(b'/trunk') entries = node.get_entries() self.assertSequenceEqual(sorted([entry.name for entry in entries]), - sorted(['README2.txt', - 'dir1', - 'README.txt'])) + sorted([b'README2.txt', + b'dir1', + b'README.txt'])) def test_get_file_entries(self): - node = self.repos.get_node('/trunk/README.txt') + node = self.repos.get_node(b'/trunk/README.txt') entries = node.get_entries() self.assertSequenceEqual([entry.name for entry in entries], []) def test_get_dir_content(self): - node = self.repos.get_node('/trunk') + node = self.repos.get_node(b'/trunk') self.assertEqual(None, node.content_length) self.assertEqual(None, node.content_type) self.assertEqual(None, node.get_content()) def test_get_file_content(self): - node = self.repos.get_node('/trunk/README.txt') + node = self.repos.get_node(b'/trunk/README.txt') self.assertEqual(8, node.content_length) - self.assertEqual('text/plain', node.content_type) - self.assertEqual('A test.\n', node.get_content().read()) + self.assertEqual(b'text/plain', node.content_type) + self.assertEqual(b'A test.\n', node.get_content().read()) def test_get_dir_properties(self): - f = self.repos.get_node('/trunk') + f = self.repos.get_node(b'/trunk') props = f.get_properties() self.assertEqual(0, len(props)) def test_get_file_properties(self): - f = self.repos.get_node('/trunk/README.txt') + f = self.repos.get_node(b'/trunk/README.txt') props = f.get_properties() - self.assertEqual('native', props['svn:eol-style']) - self.assertEqual('text/plain', props['svn:mime-type']) + self.assertEqual(b'native', props[b'svn:eol-style']) + self.assertEqual(b'text/plain', props[b'svn:mime-type']) # Revision Log / node history def test_get_node_history(self): - node = self.repos.get_node('/trunk/README2.txt') + node = self.repos.get_node(b'/trunk/README2.txt') history = node.get_history() self.assertSequenceEqual([x for x in history], - [('trunk/README2.txt', 6, 'copy'), - ('trunk/README.txt', 3, 'edit'), - ('trunk/README.txt', 2, 'add')]) + [(b'trunk/README2.txt', 6, b'copy'), + (b'trunk/README.txt', 3, b'edit'), + (b'trunk/README.txt', 2, b'add')]) def test_get_node_history_follow_copy(self): - node = self.repos.get_node('/tags/v1/README.txt') + node = self.repos.get_node(b'/tags/v1/README.txt') history = node.get_history() self.assertSequenceEqual([x for x in history], - [('tags/v1/README.txt', 7, 'copy'), - ('trunk/README.txt', 3, 'edit'), - ('trunk/README.txt', 2, 'add')]) + [(b'tags/v1/README.txt', 7, b'copy'), + (b'trunk/README.txt', 3, b'edit'), + (b'trunk/README.txt', 2, b'add')]) # Revision Log / path history def test_get_path_history(self): - history = self.repos.get_path_history('/trunk/README2.txt', None) + history = self.repos.get_path_history(b'/trunk/README2.txt', None) self.assertSequenceEqual([x for x in history], - [('trunk/README2.txt', 6, 'copy'), - ('trunk/README.txt', 3, 'unknown')]) + [(b'trunk/README2.txt', 6, b'copy'), + (b'trunk/README.txt', 3, b'unknown')]) def test_get_path_history_copied_file(self): - history = self.repos.get_path_history('/tags/v1/README.txt', None) + history = self.repos.get_path_history(b'/tags/v1/README.txt', None) self.assertSequenceEqual([x for x in history], - [('tags/v1/README.txt', 7, 'copy'), - ('trunk/README.txt', 3, 'unknown')]) + [(b'tags/v1/README.txt', 7, b'copy'), + (b'trunk/README.txt', 3, b'unknown')]) def test_get_path_history_copied_dir(self): - history = self.repos.get_path_history('/branches/v1x', None) + history = self.repos.get_path_history(b'/branches/v1x', None) self.assertSequenceEqual([x for x in history], - [('branches/v1x', 12, 'copy'), - ('tags/v1.1', 10, 'unknown'), - ('branches/v1x', 11, 'delete'), - ('branches/v1x', 9, 'edit'), - ('branches/v1x', 8, 'copy'), - ('tags/v1', 7, 'unknown')]) + [(b'branches/v1x', 12, b'copy'), + (b'tags/v1.1', 10, b'unknown'), + (b'branches/v1x', 11, b'delete'), + (b'branches/v1x', 9, b'edit'), + (b'branches/v1x', 8, b'copy'), + (b'tags/v1', 7, b'unknown')]) # Diffs @@ -240,37 +240,37 @@ class SubversionRepositoryTestCase(unittest.TestCase): self.assertEqual(expected[2], (got[2], got[3])) def test_diff_file_different_revs(self): - diffs = self.repos.get_deltas('trunk/README.txt', 2, 'trunk/README.txt', 3) - self._cmp_diff((('trunk/README.txt', 2), - ('trunk/README.txt', 3), + diffs = self.repos.get_deltas(b'trunk/README.txt', 2, b'trunk/README.txt', 3) + self._cmp_diff(((b'trunk/README.txt', 2), + (b'trunk/README.txt', 3), (Node.FILE, Changeset.EDIT)), next(diffs)) self.assertRaises(StopIteration, lambda: next(diffs)) def test_diff_file_different_files(self): - diffs = self.repos.get_deltas('branches/v1x/README.txt', 12, - 'branches/v1x/README2.txt', 12) - self._cmp_diff((('branches/v1x/README.txt', 12), - ('branches/v1x/README2.txt', 12), + diffs = self.repos.get_deltas(b'branches/v1x/README.txt', 12, + b'branches/v1x/README2.txt', 12) + self._cmp_diff(((b'branches/v1x/README.txt', 12), + (b'branches/v1x/README2.txt', 12), (Node.FILE, Changeset.EDIT)), next(diffs)) self.assertRaises(StopIteration, lambda: next(diffs)) def test_diff_file_no_change(self): - diffs = self.repos.get_deltas('trunk/README.txt', 7, - 'tags/v1/README.txt', 7) + diffs = self.repos.get_deltas(b'trunk/README.txt', 7, + b'tags/v1/README.txt', 7) self.assertRaises(StopIteration, lambda: next(diffs)) def test_diff_dir_different_revs(self): - diffs = self.repos.get_deltas('trunk', 4, 'trunk', 8) + diffs = self.repos.get_deltas(b'trunk', 4, b'trunk', 8) expected = [ - (None, ('trunk/README2.txt', 6), + (None, (b'trunk/README2.txt', 6), (Node.FILE, Changeset.ADD)), - (None, ('trunk/dir1/dir2', 8), + (None, (b'trunk/dir1/dir2', 8), (Node.DIRECTORY, Changeset.ADD)), - (None, ('trunk/dir1/dir3', 8), + (None, (b'trunk/dir1/dir3', 8), (Node.DIRECTORY, Changeset.ADD)), - (('trunk/dir2', 4), None, + ((b'trunk/dir2', 4), None, (Node.DIRECTORY, Changeset.DELETE)), - (('trunk/dir3', 4), None, + ((b'trunk/dir3', 4), None, (Node.DIRECTORY, Changeset.DELETE)), ] actual = [next(diffs) for i in range(5)] @@ -283,17 +283,17 @@ class SubversionRepositoryTestCase(unittest.TestCase): self.assertRaises(StopIteration, lambda: next(diffs)) def test_diff_dir_different_dirs(self): - diffs = self.repos.get_deltas('trunk', 1, 'branches/v1x', 12) + diffs = self.repos.get_deltas(b'trunk', 1, b'branches/v1x', 12) expected = [ - (None, ('branches/v1x/README.txt', 12), + (None, (b'branches/v1x/README.txt', 12), (Node.FILE, Changeset.ADD)), - (None, ('branches/v1x/README2.txt', 12), + (None, (b'branches/v1x/README2.txt', 12), (Node.FILE, Changeset.ADD)), - (None, ('branches/v1x/dir1', 12), + (None, (b'branches/v1x/dir1', 12), (Node.DIRECTORY, Changeset.ADD)), - (None, ('branches/v1x/dir1/dir2', 12), + (None, (b'branches/v1x/dir1/dir2', 12), (Node.DIRECTORY, Changeset.ADD)), - (None, ('branches/v1x/dir1/dir3', 12), + (None, (b'branches/v1x/dir1/dir3', 12), (Node.DIRECTORY, Changeset.ADD)), ] actual = [next(diffs) for i in range(5)] @@ -308,8 +308,8 @@ class SubversionRepositoryTestCase(unittest.TestCase): self.assertRaises(StopIteration, lambda: next(diffs)) def test_diff_dir_no_change(self): - diffs = self.repos.get_deltas('trunk', 7, - 'tags/v1', 7) + diffs = self.repos.get_deltas(b'trunk', 7, + b'tags/v1', 7) self.assertRaises(StopIteration, lambda: next(diffs)) # Changesets @@ -325,52 +325,52 @@ class SubversionRepositoryTestCase(unittest.TestCase): def test_changeset_added_dirs(self): chgset = self.repos.get_changeset(1) self.assertEqual(1, chgset.rev) - self.assertEqual('Initial directory layout.', chgset.message) - self.assertEqual('john', chgset.author) + self.assertEqual(b'Initial directory layout.', chgset.message) + self.assertEqual(b'john', chgset.author) self.assertEqual(1112349652, chgset.date) changes = chgset.get_changes() self.assertSequenceEqual(sorted([x for x in changes]), - sorted([('trunk', Node.DIRECTORY, Changeset.ADD, None, -1), - ('branches', Node.DIRECTORY, Changeset.ADD, None, -1), - ('tags', Node.DIRECTORY, Changeset.ADD, None, -1)])) + sorted([(b'trunk', Node.DIRECTORY, Changeset.ADD, None, -1), + (b'branches', Node.DIRECTORY, Changeset.ADD, None, -1), + (b'tags', Node.DIRECTORY, Changeset.ADD, None, -1)])) def test_changeset_file_edit(self): chgset = self.repos.get_changeset(3) self.assertEqual(3, chgset.rev) - self.assertEqual('Fixed README.\n', chgset.message) - self.assertEqual('kate', chgset.author) + self.assertEqual(b'Fixed README.\n', chgset.message) + self.assertEqual(b'kate', chgset.author) self.assertEqual(1112361898, chgset.date) changes = chgset.get_changes() self.assertSequenceEqual(sorted([x for x in changes]), - sorted([('trunk/README.txt', Node.FILE, Changeset.EDIT, - 'trunk/README.txt', 2)])) + sorted([(b'trunk/README.txt', Node.FILE, Changeset.EDIT, + b'trunk/README.txt', 2)])) def test_changeset_dir_moves(self): chgset = self.repos.get_changeset(5) self.assertEqual(5, chgset.rev) - self.assertEqual('Moved directories.', chgset.message) - self.assertEqual('kate', chgset.author) + self.assertEqual(b'Moved directories.', chgset.message) + self.assertEqual(b'kate', chgset.author) self.assertEqual(1112372739, chgset.date) changes = chgset.get_changes() self.assertSequenceEqual(sorted([x for x in changes]), sorted([ - ('trunk/dir1/dir2', Node.DIRECTORY, Changeset.MOVE, 'trunk/dir2', 4), - ('trunk/dir1/dir3', Node.DIRECTORY, Changeset.MOVE, 'trunk/dir3', 4)])) + (b'trunk/dir1/dir2', Node.DIRECTORY, Changeset.MOVE, b'trunk/dir2', 4), + (b'trunk/dir1/dir3', Node.DIRECTORY, Changeset.MOVE, b'trunk/dir3', 4)])) def test_changeset_file_copy(self): chgset = self.repos.get_changeset(6) self.assertEqual(6, chgset.rev) - self.assertEqual('More things to read', chgset.message) - self.assertEqual('john', chgset.author) + self.assertEqual(b'More things to read', chgset.message) + self.assertEqual(b'john', chgset.author) self.assertEqual(1112381806, chgset.date) changes = chgset.get_changes() self.assertSequenceEqual(sorted([x for x in changes]), - sorted([('trunk/README2.txt', Node.FILE, Changeset.COPY, - 'trunk/README.txt', 3)])) + sorted([(b'trunk/README2.txt', Node.FILE, Changeset.COPY, + b'trunk/README.txt', 3)])) def suite(): diff --git a/subversion/bindings/swig/python/tests/utils.py b/subversion/bindings/swig/python/tests/utils.py index 48881177ac..01cacc4fc6 100644 --- a/subversion/bindings/swig/python/tests/utils.py +++ b/subversion/bindings/swig/python/tests/utils.py @@ -47,14 +47,14 @@ class Temper(object): def alloc_empty_dir(self, suffix = ""): """Create an empty temporary directory. Returns its full path in canonical internal form.""" - temp_dir_name = core.svn_dirent_internal_style(tempfile.mkdtemp(suffix)) + temp_dir_name = core.svn_dirent_internal_style(tempfile.mkdtemp(suffix).encode('UTF-8')) self._cleanup_list.append((temp_dir_name, core.svn_io_remove_dir)) return temp_dir_name def alloc_empty_repo(self, suffix = ""): """Create an empty repository. Returns a tuple of its handle, path and file: URI in canonical internal form.""" - temp_path = tempfile.mkdtemp(suffix) + temp_path = tempfile.mkdtemp(suffix).encode('UTF-8') repo_path = core.svn_dirent_internal_style(temp_path) repo_uri = core.svn_uri_canonicalize(file_uri_for_path(temp_path)) handle = repos.create(repo_path, None, None, None, None) @@ -74,9 +74,9 @@ class Temper(object): def file_uri_for_path(path): """Return the file: URI corresponding to the given path.""" - uri_path = pathname2url(path) + uri_path = pathname2url(path).encode('UTF-8') # pathname2url claims to return the path part of the URI, but on Windows # it returns both the authority and path parts for no reason, which # means we have to trim the leading slashes to "normalize" the result. - return 'file:///' + uri_path.lstrip('/') + return b'file:///' + uri_path.lstrip(b'/') diff --git a/subversion/bindings/swig/python/tests/wc.py b/subversion/bindings/swig/python/tests/wc.py index b27da85866..721ec2d78e 100644 --- a/subversion/bindings/swig/python/tests/wc.py +++ b/subversion/bindings/swig/python/tests/wc.py @@ -56,10 +56,10 @@ class SubversionWorkingCopyTestCase(unittest.TestCase): wc.entry(self.path, self.wc, True) def test_lock(self): - readme_path = '%s/trunk/README.txt' % self.path + readme_path = b'%s/trunk/README.txt' % self.path lock = core.svn_lock_create(core.Pool()) - lock.token = 'http://svnbook.org/nightly/en/svn.advanced.locking.html' + lock.token = b'http://svnbook.org/nightly/en/svn.advanced.locking.html' wc.add_lock(readme_path, lock, self.wc) self.assertEqual(True, wc.adm_locked(self.wc)) @@ -73,23 +73,23 @@ class SubversionWorkingCopyTestCase(unittest.TestCase): self.assertEqual(self.path, wc.adm_access_path(self.wc)) def test_is_adm_dir(self): - self.assertTrue(wc.is_adm_dir(".svn")) - self.assertFalse(wc.is_adm_dir(".foosvn")) + self.assertTrue(wc.is_adm_dir(b".svn")) + self.assertFalse(wc.is_adm_dir(b".foosvn")) def test_get_adm_dir(self): - self.assertTrue(isinstance(wc.get_adm_dir(), str)) + self.assertTrue(isinstance(wc.get_adm_dir(), bytes)) def test_set_adm_dir(self): - self.assertRaises(SubversionException, wc.set_adm_dir, ".foobar") - self.assertTrue(wc.is_adm_dir(".svn")) - self.assertFalse(wc.is_adm_dir("_svn")) - self.assertFalse(wc.is_adm_dir(".foobar")) - wc.set_adm_dir("_svn") - self.assertTrue(wc.is_adm_dir("_svn")) - self.assertEqual("_svn", wc.get_adm_dir()) - wc.set_adm_dir(".svn") - self.assertFalse(wc.is_adm_dir("_svn")) - self.assertEqual(".svn", wc.get_adm_dir()) + self.assertRaises(SubversionException, wc.set_adm_dir, b".foobar") + self.assertTrue(wc.is_adm_dir(b".svn")) + self.assertFalse(wc.is_adm_dir(b"_svn")) + self.assertFalse(wc.is_adm_dir(b".foobar")) + wc.set_adm_dir(b"_svn") + self.assertTrue(wc.is_adm_dir(b"_svn")) + self.assertEqual(b"_svn", wc.get_adm_dir()) + wc.set_adm_dir(b".svn") + self.assertFalse(wc.is_adm_dir(b"_svn")) + self.assertEqual(b".svn", wc.get_adm_dir()) def test_init_traversal_info(self): wc.init_traversal_info() @@ -122,7 +122,7 @@ class SubversionWorkingCopyTestCase(unittest.TestCase): pass # Remove trunk/README.txt - readme_path = '%s/trunk/README.txt' % self.path + readme_path = b'%s/trunk/README.txt' % self.path self.assertTrue(os.path.exists(readme_path)) os.remove(readme_path) @@ -134,7 +134,7 @@ class SubversionWorkingCopyTestCase(unittest.TestCase): # Check that the report finished self.assertTrue(reporter.finished_report) - self.assertEqual([''], set_paths) + self.assertEqual([b''], set_paths) self.assertEqual(1, len(infos)) # Check content of infos object @@ -179,42 +179,42 @@ class SubversionWorkingCopyTestCase(unittest.TestCase): self.assertTrue(len(paths) > 0) def test_is_normal_prop(self): - self.assertFalse(wc.is_normal_prop('svn:wc:foo:bar')) - self.assertFalse(wc.is_normal_prop('svn:entry:foo:bar')) - self.assertTrue(wc.is_normal_prop('svn:foo:bar')) - self.assertTrue(wc.is_normal_prop('foreign:foo:bar')) + self.assertFalse(wc.is_normal_prop(b'svn:wc:foo:bar')) + self.assertFalse(wc.is_normal_prop(b'svn:entry:foo:bar')) + self.assertTrue(wc.is_normal_prop(b'svn:foo:bar')) + self.assertTrue(wc.is_normal_prop(b'foreign:foo:bar')) def test_is_wc_prop(self): - self.assertTrue(wc.is_wc_prop('svn:wc:foo:bar')) - self.assertFalse(wc.is_wc_prop('svn:entry:foo:bar')) - self.assertFalse(wc.is_wc_prop('svn:foo:bar')) - self.assertFalse(wc.is_wc_prop('foreign:foo:bar')) + self.assertTrue(wc.is_wc_prop(b'svn:wc:foo:bar')) + self.assertFalse(wc.is_wc_prop(b'svn:entry:foo:bar')) + self.assertFalse(wc.is_wc_prop(b'svn:foo:bar')) + self.assertFalse(wc.is_wc_prop(b'foreign:foo:bar')) def test_is_entry_prop(self): - self.assertTrue(wc.is_entry_prop('svn:entry:foo:bar')) - self.assertFalse(wc.is_entry_prop('svn:wc:foo:bar')) - self.assertFalse(wc.is_entry_prop('svn:foo:bar')) - self.assertFalse(wc.is_entry_prop('foreign:foo:bar')) + self.assertTrue(wc.is_entry_prop(b'svn:entry:foo:bar')) + self.assertFalse(wc.is_entry_prop(b'svn:wc:foo:bar')) + self.assertFalse(wc.is_entry_prop(b'svn:foo:bar')) + self.assertFalse(wc.is_entry_prop(b'foreign:foo:bar')) def test_get_prop_diffs(self): - wc.prop_set("foreign:foo", "bla", self.path, self.wc) - self.assertEqual([{"foreign:foo": "bla"}, {}], + wc.prop_set(b"foreign:foo", b"bla", self.path, self.wc) + self.assertEqual([{b"foreign:foo": b"bla"}, {}], wc.get_prop_diffs(self.path, self.wc)) def test_get_pristine_copy_path(self): - path_to_file = '%s/trunk/README.txt' % self.path + path_to_file = b'%s/trunk/README.txt' % self.path path_to_text_base = wc.get_pristine_copy_path(path_to_file) - with open(path_to_text_base) as fp: + with open(path_to_text_base, 'rb') as fp: text_base = fp.read() # TODO: This test should modify the working file first, to ensure the # path isn't just the path to the working file. - self.assertEqual(text_base, 'A test.\n') + self.assertEqual(text_base, b'A test.\n') def test_entries_read(self): entries = wc.entries_read(self.wc, True) keys = core._as_list(entries.keys()) keys.sort() - self.assertEqual(['', 'branches', 'tags', 'trunk'], keys) + self.assertEqual([b'', b'branches', b'tags', b'trunk'], keys) def test_get_ignores(self): self.assertTrue(isinstance(wc.get_ignores(None, self.wc), list)) @@ -222,9 +222,9 @@ class SubversionWorkingCopyTestCase(unittest.TestCase): def test_commit(self): # Replace README.txt's contents, using binary mode so we know the # exact contents even on Windows, and therefore the MD5 checksum. - readme_path = '%s/trunk/README.txt' % self.path + readme_path = b'%s/trunk/README.txt' % self.path fp = open(readme_path, 'wb') - fp.write('hello\n'.encode('UTF-8')) + fp.write(b'hello\n') fp.close() # Setup ra_ctx. @@ -236,7 +236,7 @@ class SubversionWorkingCopyTestCase(unittest.TestCase): commit_info = [None] def commit_cb(_commit_info, pool): commit_info[0] = _commit_info - (editor, edit_baton) = ra.get_commit_editor2(ra_ctx, 'log message', + (editor, edit_baton) = ra.get_commit_editor2(ra_ctx, b'log message', commit_cb, None, False) @@ -250,7 +250,7 @@ class SubversionWorkingCopyTestCase(unittest.TestCase): False, editor, baton, pool) return baton try: - delta.path_driver(editor, edit_baton, -1, ['trunk/README.txt'], + delta.path_driver(editor, edit_baton, -1, [b'trunk/README.txt'], driver_cb) editor.close_edit(edit_baton) except: @@ -265,8 +265,8 @@ class SubversionWorkingCopyTestCase(unittest.TestCase): (commit_info,) = commit_info # Assert the commit. - self.assertEqual(binascii.b2a_hex(checksum).decode('UTF-8'), - 'b1946ac92492d2347c6235b4d2611184') + self.assertEqual(binascii.b2a_hex(checksum), + b'b1946ac92492d2347c6235b4d2611184') self.assertEqual(commit_info.revision, 13) # Bump working copy state. @@ -290,14 +290,14 @@ class SubversionWorkingCopyTestCase(unittest.TestCase): url = self.repos_uri # cause file_changed: Replace README.txt's contents. - readme_path = '%s/trunk/README.txt' % self.path - fp = open(readme_path, 'w') - fp.write('hello\n') + readme_path = b'%s/trunk/README.txt' % self.path + fp = open(readme_path, 'wb') + fp.write(b'hello\n') fp.close() # cause file_added: Create readme3. - readme3_path = '%s/trunk/readme3' % self.path - fp = open(readme3_path, 'w') - fp.write('hello\n') + readme3_path = b'%s/trunk/readme3' % self.path + fp = open(readme3_path, 'wb') + fp.write(b'hello\n') fp.close() wc.add2(readme3_path, wc.adm_probe_retrieve(self.wc, @@ -307,7 +307,7 @@ class SubversionWorkingCopyTestCase(unittest.TestCase): None, # notify_func pool) # cause file_deleted: Delete README2.txt. - readme2_path = '%s/trunk/README2.txt' % self.path + readme2_path = b'%s/trunk/README2.txt' % self.path wc.delete3(readme2_path, wc.adm_probe_retrieve(self.wc, os.path.dirname(readme2_path), pool), @@ -316,8 +316,8 @@ class SubversionWorkingCopyTestCase(unittest.TestCase): False, # keep_local pool) # cause dir_props_changed: ps testprop testval dir1/dir2 - dir2_path = '%s/trunk/dir1/dir2' % self.path - wc.prop_set2('testprop', 'testval', dir2_path, + dir2_path = b'%s/trunk/dir1/dir2' % self.path + wc.prop_set2(b'testprop', b'testval', dir2_path, wc.adm_probe_retrieve(self.wc, os.path.dirname(dir2_path), pool), False, # skip_checks @@ -338,8 +338,8 @@ class SubversionWorkingCopyTestCase(unittest.TestCase): def write_diff(path, left, right): options = svn.diff.file_options_create() diff = svn.diff.file_diff_2(left, right, options, pool) - original_header = modified_header = '' - encoding = 'utf8' + original_header = modified_header = b'' + encoding = b'utf8' relative_to_dir = None bio = BytesIO() svn.diff.file_output_unified3(bio, diff, @@ -347,7 +347,7 @@ class SubversionWorkingCopyTestCase(unittest.TestCase): original_header, modified_header, encoding, relative_to_dir, options.show_c_function, pool) - got_diffs[path[len(self.path) + 1:]] = bio.getvalue().decode('UTF-8').splitlines() + got_diffs[path[len(self.path) + 1:]] = bio.getvalue().splitlines() # Diff callbacks that call props_changed and write_diff. contentstate = propstate = state = wc.notify_state_unknown @@ -379,7 +379,7 @@ class SubversionWorkingCopyTestCase(unittest.TestCase): # Setup wc diff editor. (editor, edit_baton) = wc.get_diff_editor4( - self.wc, '', diff_callbacks, depth, + self.wc, b'', diff_callbacks, depth, False, # ignore_ancestry False, # use_text_base False, # reverse_order @@ -396,39 +396,39 @@ class SubversionWorkingCopyTestCase(unittest.TestCase): (reporter, report_baton) = ra.do_diff3( ra_ctx, head, # versus_url revision - '', # diff_target + b'', # diff_target depth, False, # ignore_ancestry True, # text_deltas url, # versus_url editor, edit_baton, pool) # Report wc state (pretty plain). - reporter.set_path(report_baton, '', head, depth, + reporter.set_path(report_baton, b'', head, depth, False, # start_empty None, # lock_token pool) reporter.finish_report(report_baton, pool) # Assert we got the right diff. - expected_prop_changes = [('trunk/dir1/dir2', - 'testprop', 'testval')] + expected_prop_changes = [(b'trunk/dir1/dir2', + b'testprop', b'testval')] expected_diffs = { - 'trunk/readme3': - ['--- ', - '+++ ', - '@@ -0,0 +1 @@', - '+hello'], - 'trunk/README.txt': - ['--- ', - '+++ ', - '@@ -1 +1 @@', - '-A test.', - '+hello'], - 'trunk/README2.txt': - ['--- ', - '+++ ', - '@@ -1 +0,0 @@', - '-A test.'], + b'trunk/readme3': + [b'--- ', + b'+++ ', + b'@@ -0,0 +1 @@', + b'+hello'], + b'trunk/README.txt': + [b'--- ', + b'+++ ', + b'@@ -1 +1 @@', + b'-A test.', + b'+hello'], + b'trunk/README2.txt': + [b'--- ', + b'+++ ', + b'@@ -1 +0,0 @@', + b'-A test.'], } self.assertEqual(got_prop_changes, expected_prop_changes) self.assertEqual(got_diffs, expected_diffs) diff --git a/subversion/bindings/swig/svn_client.i b/subversion/bindings/swig/svn_client.i index ea226876b0..07cdd67a49 100644 --- a/subversion/bindings/swig/svn_client.i +++ b/subversion/bindings/swig/svn_client.i @@ -119,7 +119,7 @@ ppitem = (svn_client_proplist_item_t **)(*$1)->elts; for (i = 0; i < nelts; ++i, ++ppitem) { PyObject *item = PyTuple_New(2); - PyObject *name = PyStr_FromStringAndSize((*ppitem)->node_name->data, + PyObject *name = PyBytes_FromStringAndSize((*ppitem)->node_name->data, (*ppitem)->node_name->len); PyObject *hash = svn_swig_py_prophash_to_dict((*ppitem)->prop_hash);