Index: trunk/contrib/make_status.py =================================================================== --- trunk/contrib/make_status.py (revision 17537) +++ trunk/contrib/make_status.py (revision 17560) @@ -22,7 +22,5 @@ return '%d.%d.%d' % version + str(core.SVN_VER_TAG, 'utf-8') - def _pytidylib_version(): - import pkg_resources version = pkg_resources.get_distribution('pytidylib').version try: @@ -42,4 +40,7 @@ return '%s (%s)' % (version, info) if info else version +def _pysqlite3_version(): + return pkg_resources.get_distribution('pysqlite3').version + PACKAGES = [ @@ -52,6 +53,6 @@ ("sqlite3", ('sqlite3.version', 'sqlite3.sqlite_version')), - ("PySqlite", ('pysqlite2.dbapi2.version', - 'pysqlite2.dbapi2.sqlite_version')), + ("PySqlite3", ('__main__._pysqlite3_version()', + 'pysqlite3.dbapi2.sqlite_version')), ("PyMySQL", 'pymysql.__version__'), ("Psycopg2", 'psycopg2.__version__'), Index: trunk/contrib/trac-pre-commit-hook =================================================================== --- trunk/contrib/trac-pre-commit-hook (revision 17537) +++ trunk/contrib/trac-pre-commit-hook (revision 17560) @@ -26,6 +26,4 @@ # /usr/bin/python /some/path/trac-pre-commit-hook "$TRAC_ENV" "$LOG" || exit 1 # - -from __future__ import print_function import os Index: trunk/setup.cfg =================================================================== Index: trunk/trac/__init__.py =================================================================== --- trunk/trac/__init__.py (revision 17537) +++ trunk/trac/__init__.py (revision 17560) @@ -17,3 +17,3 @@ __version__ = get_distribution('Trac').version except DistributionNotFound: - __version__ = '1.5.3' + __version__ = '1.5.4' Index: trunk/trac/db/sqlite_backend.py =================================================================== --- trunk/trac/db/sqlite_backend.py (revision 17537) +++ trunk/trac/db/sqlite_backend.py (revision 17560) @@ -35,5 +35,5 @@ try: - import pysqlite2.dbapi2 as sqlite + import pysqlite3.dbapi2 as sqlite except ImportError: import sqlite3 as sqlite @@ -46,5 +46,4 @@ % pysqlite_version) min_sqlite_version = (3, 0, 0) -min_pysqlite_version = (2, 6, 0) # version provided by Python 2.7 @@ -171,7 +170,4 @@ version=sqlite_version_string, min_version='%d.%d.%d' % min_sqlite_version) - elif pysqlite_version < min_pysqlite_version: - self.error = _("Need at least PySqlite %(version)s or higher", - version='%d.%d.%d' % min_pysqlite_version) yield 'sqlite', -1 if self.error else 1 Index: trunk/trac/htdocs/js/wiki.js =================================================================== --- trunk/trac/htdocs/js/wiki.js (revision 17537) +++ trunk/trac/htdocs/js/wiki.js (revision 17560) @@ -5,4 +5,6 @@ window.wikiColumn = function($wikipage) { + if ($wikipage.length === 0) + return; var $content = $("#content"); $("").on("click", function () { Index: trunk/trac/ticket/templates/report_view.html =================================================================== --- trunk/trac/ticket/templates/report_view.html (revision 17537) +++ trunk/trac/ticket/templates/report_view.html (revision 17560) @@ -163,4 +163,5 @@ # if loop.first: + # set header_group, header = None, None # set column_headers # for header_group in header_groups: Index: trunk/trac/util/html.py =================================================================== --- trunk/trac/util/html.py (revision 17537) +++ trunk/trac/util/html.py (revision 17560) @@ -25,5 +25,5 @@ from html.parser import HTMLParser -from markupsafe import Markup, escape as escape_quotes +from markupsafe import Markup, escape as escape_quotes, soft_unicode try: Index: trunk/trac/util/presentation.py =================================================================== --- trunk/trac/util/presentation.py (revision 17537) +++ trunk/trac/util/presentation.py (revision 17560) @@ -22,11 +22,11 @@ import re -from jinja2 import Markup, Undefined, contextfilter, evalcontextfilter +from jinja2 import Undefined, contextfilter, evalcontextfilter from jinja2.filters import make_attrgetter -from jinja2.utils import soft_unicode from trac.core import TracError from .datefmt import to_utimestamp, utc -from .html import Fragment, classes, html_attribute, styles, tag +from .html import (Fragment, Markup, classes, html_attribute, soft_unicode, + styles, tag) from .text import javascript_quote Index: trunk/trac/util/text.py =================================================================== --- trunk/trac/util/text.py (revision 17537) +++ trunk/trac/util/text.py (revision 17560) @@ -23,4 +23,5 @@ import locale import os +import pkg_resources import re import sys @@ -43,4 +44,9 @@ # -- Jinja2 + +_jinja2_ver = pkg_resources.parse_version(jinja2.__version__) +_jinja2_exts = ['jinja2.ext.do', 'jinja2.ext.i18n'] +if _jinja2_ver < pkg_resources.parse_version('3'): + _jinja2_exts.append('jinja2.ext.with_') def jinja2env(**kwargs): @@ -66,5 +72,5 @@ trim_blocks=True, lstrip_blocks=True, - extensions=['jinja2.ext.do', 'jinja2.ext.i18n', 'jinja2.ext.with_'], + extensions=list(_jinja2_exts), finalize=filterout_none, autoescape=autoescape_extensions, Index: trunk/trac/web/_fcgi.py =================================================================== --- trunk/trac/web/_fcgi.py (revision 17537) +++ trunk/trac/web/_fcgi.py (revision 17560) @@ -40,26 +40,16 @@ __version__ = '$Revision: 2025 $' +import _thread +import codecs +import errno import io +import os +import select +import signal +import socket +import struct import sys -import os -import signal -import struct -import select -import socket -import errno +import threading import traceback - -try: - import thread - import threading - thread_available = True -except ImportError: - import dummy_thread as thread - import dummy_threading as threading - thread_available = False - -# Apparently 2.3 doesn't define SHUT_WR? Assume it is 1 in this case. -if not hasattr(socket, 'SHUT_WR'): - socket.SHUT_WR = 1 __all__ = ['WSGIServer'] @@ -138,5 +128,5 @@ self._shrinkThreshold = conn.server.inputStreamShrinkThreshold - self._buf = '' + self._buf = b'' self._bufList = [] self._pos = 0 # Current read position. @@ -160,5 +150,5 @@ def read(self, n=-1): if self._pos == self._avail and self._eof: - return '' + return b'' while True: if n < 0 or (self._avail - self._pos) < n: @@ -177,5 +167,5 @@ # Merge buffer list, if necessary. if self._bufList: - self._buf += ''.join(self._bufList) + self._buf += _bytes_join(self._bufList) self._bufList = [] r = self._buf[self._pos:newPos] @@ -186,9 +176,9 @@ def readline(self, length=None): if self._pos == self._avail and self._eof: - return '' + return b'' while True: # Unfortunately, we need to merge the buffer list early. if self._bufList: - self._buf += ''.join(self._bufList) + self._buf += _bytes_join(self._bufList) self._bufList = [] # Find newline. @@ -317,4 +307,5 @@ def write(self, data): assert not self.closed + assert type(data) is bytes if not data: @@ -337,5 +328,5 @@ # Only need to flush if this OutputStream is actually buffered. if self._buffered: - data = ''.join(self._bufList) + data = _bytes_join(self._bufList) self._bufList = [] self._write(data) @@ -397,22 +388,22 @@ are returned. """ - nameLength = ord(s[pos]) - if nameLength & 128: - nameLength = struct.unpack('!L', s[pos:pos+4])[0] & 0x7fffffff + namelen = s[pos] + if namelen & 128: + namelen = struct.unpack('!L', s[pos:pos+4])[0] & 0x7fffffff pos += 4 else: pos += 1 - valueLength = ord(s[pos]) - if valueLength & 128: - valueLength = struct.unpack('!L', s[pos:pos+4])[0] & 0x7fffffff + valuelen = s[pos] + if valuelen & 128: + valuelen = struct.unpack('!L', s[pos:pos+4])[0] & 0x7fffffff pos += 4 else: pos += 1 - name = s[pos:pos+nameLength] - pos += nameLength - value = s[pos:pos+valueLength] - pos += valueLength + name = str(s[pos:pos+namelen], 'iso-8859-1') + pos += namelen + value = str(s[pos:pos+valuelen], 'iso-8859-1') + pos += valuelen return pos, (name, value) @@ -424,17 +415,25 @@ The encoded string is returned. """ - nameLength = len(name) - if nameLength < 128: - s = chr(nameLength) + name = name.encode('iso-8859-1') + value = value.encode('iso-8859-1') + + namelen = len(name) + if namelen < 128: + namelen = _code2bytes(namelen) else: - s = struct.pack('!L', nameLength | 0x80000000) - - valueLength = len(value) - if valueLength < 128: - s += chr(valueLength) + namelen = struct.pack('!L', namelen | 0x80000000) + + valuelen = len(value) + if valuelen < 128: + valuelen = _code2bytes(valuelen) else: - s += struct.pack('!L', valueLength | 0x80000000) - - return s + name + value + valuelen = struct.pack('!L', valuelen | 0x80000000) + + return namelen + valuelen + name + value + +_bytes_join = b''.join +_str_join = ''.join +_code2bytes = lambda code: b'%c' % code +_utf8_writer = lambda f: codecs.getwriter('utf-8')(f) class Record(object): @@ -450,5 +449,5 @@ self.contentLength = 0 self.paddingLength = 0 - self.contentData = '' + self.contentData = b'' @staticmethod @@ -464,5 +463,5 @@ data = sock.recv(length) except socket.error as e: - if e[0] == errno.EAGAIN: + if e.errno == errno.EAGAIN: select.select([sock], [], []) continue @@ -475,5 +474,5 @@ recvLen += dataLen length -= dataLen - return ''.join(dataList), recvLen + return _bytes_join(dataList), recvLen def read(self, sock): @@ -516,4 +515,5 @@ Writes data to a socket and does not return until all the data is sent. """ + assert type(data) is bytes length = len(data) while length: @@ -521,5 +521,5 @@ sent = sock.send(data) except socket.error as e: - if e[0] == errno.EAGAIN: + if e.errno == errno.EAGAIN: select.select([], [sock], []) continue @@ -545,5 +545,5 @@ self._sendall(sock, self.contentData) if self.paddingLength: - self._sendall(sock, '\x00'*self.paddingLength) + self._sendall(sock, b'\x00' * self.paddingLength) class Request(object): @@ -563,5 +563,6 @@ self.stdin = inputStreamClass(conn) self.stdout = OutputStream(conn, self, FCGI_STDOUT) - self.stderr = OutputStream(conn, self, FCGI_STDERR, buffered=True) + self.stderr = _utf8_writer(OutputStream(conn, self, FCGI_STDERR, + buffered=True)) self.data = inputStreamClass(conn) @@ -585,5 +586,5 @@ self._end(appStatus, protocolStatus) except socket.error as e: - if e[0] != errno.EPIPE: + if e.errno != errno.EPIPE: raise @@ -645,6 +646,6 @@ try: while True: - r, w, e = select.select([self._sock], [], []) - if not r or not self._sock.recv(1024): + rlist, wlist, xlist = select.select([self._sock], [], []) + if not rlist or not self._sock.recv(1024): break except: @@ -660,6 +661,6 @@ except EOFError: break - except (select.error, socket.error) as e: - if e[0] == errno.EBADF: # Socket was closed by Request. + except select.error as e: + if e.errno == errno.EBADF: # Socket was closed by Request. break raise @@ -675,10 +676,10 @@ while self._keepGoing: try: - r, w, e = select.select([self._sock], [], [], 1.0) + rlist, wlist, xlist = select.select([self._sock], [], [], 1.0) except ValueError: # Sigh. ValueError gets thrown sometimes when passing select # a closed socket. raise EOFError - if r: break + if rlist: break if not self._keepGoing: return @@ -876,5 +877,5 @@ def _start_request(self, req): - thread.start_new_thread(req.run, ()) + _thread.start_new_thread(req.run, ()) def _do_params(self, inrec): @@ -948,31 +949,22 @@ self.handler = handler self.maxwrite = maxwrite - if thread_available: - try: - import resource - # Attempt to glean the maximum number of connections - # from the OS. - maxConns = resource.getrlimit(resource.RLIMIT_NOFILE)[0] - except (ImportError, AttributeError): - maxConns = 100 # Just some made up number. - maxReqs = maxConns - if multiplexed: - self._connectionClass = MultiplexedConnection - maxReqs *= 5 # Another made up number. - else: - self._connectionClass = Connection - self.capability = { - FCGI_MAX_CONNS: maxConns, - FCGI_MAX_REQS: maxReqs, - FCGI_MPXS_CONNS: multiplexed and 1 or 0 - } + try: + import resource + # Attempt to glean the maximum number of connections + # from the OS. + maxConns = resource.getrlimit(resource.RLIMIT_NOFILE)[0] + except (ImportError, AttributeError): + maxConns = 100 # Just some made up number. + maxReqs = maxConns + if multiplexed: + self._connectionClass = MultiplexedConnection + maxReqs *= 5 # Another made up number. else: self._connectionClass = Connection - self.capability = { - # If threads aren't available, these are pretty much correct. - FCGI_MAX_CONNS: 1, - FCGI_MAX_REQS: 1, - FCGI_MPXS_CONNS: 0 - } + self.capability = { + FCGI_MAX_CONNS: maxConns, + FCGI_MAX_REQS: maxReqs, + FCGI_MPXS_CONNS: 1 if multiplexed else 0, + } self._bindAddress = bindAddress self._umask = umask @@ -987,8 +979,8 @@ sock.getpeername() except socket.error as e: - if e[0] == errno.ENOTSOCK: + if e.errno == errno.ENOTSOCK: # Not a socket, assume CGI context. isFCGI = False - elif e[0] != errno.ENOTCONN: + elif e.errno != errno.ENOTCONN: raise @@ -1072,15 +1064,15 @@ while self._keepGoing: try: - r, w, e = select.select([sock], [], [], timeout) + rlist, wlist, xlist = select.select([sock], [], [], timeout) except select.error as e: - if e[0] == errno.EINTR: + if e.errno == errno.EINTR: continue raise - if r: + if rlist: try: clientSock, addr = sock.accept() except socket.error as e: - if e[0] in (errno.EINTR, errno.EAGAIN): + if e.errno in (errno.EINTR, errno.EAGAIN): continue raise @@ -1094,5 +1086,5 @@ # messages (either in a new thread or this thread). conn = self._connectionClass(clientSock, addr, self) - thread.start_new_thread(conn.run, ()) + _thread.start_new_thread(conn.run, ()) self._mainloopPeriodic() @@ -1134,7 +1126,8 @@ should be overridden. """ - import cgitb - req.stdout.write('Content-Type: text/html\r\n\r\n' + - cgitb.html(sys.exc_info())) + out = _utf8_writer(req.stdout) + out.write('Content-Type: text/plain; charset=utf-8\r\n\r\n') + traceback.print_exc(file=out) + out.flush() class WSGIServer(Server): @@ -1164,5 +1157,5 @@ # Used to force single-threadedness - self._app_lock = thread.allocate_lock() + self._app_lock = _thread.allocate_lock() def handler(self, req): @@ -1175,5 +1168,5 @@ environ.update(self.environ) - environ['wsgi.version'] = (1,0) + environ['wsgi.version'] = (1, 0) environ['wsgi.input'] = req.stdin if self._bindAddress is None: @@ -1183,5 +1176,5 @@ environ['wsgi.errors'] = stderr environ['wsgi.multithread'] = not isinstance(req, CGIRequest) and \ - thread_available and self.multithreaded + self.multithreaded # Rationale for the following: If started by the web server # (self._bindAddress is None) in either FastCGI or CGI mode, the @@ -1207,26 +1200,15 @@ def write(data): - assert type(data) is str, 'write() argument must be string' + assert type(data) is bytes, 'write() argument must be bytes' assert headers_set, 'write() before start_response()' if not headers_sent: - status, responseHeaders = headers_sent[:] = headers_set - found = False - for header,value in responseHeaders: - if header.lower() == 'content-length': - found = True - break - if not found and result is not None: - try: - if len(result) == 1: - responseHeaders.append(('Content-Length', - str(len(data)))) - except: - pass - s = 'Status: %s\r\n' % status - for header in responseHeaders: - s += '%s: %s\r\n' % header - s += '\r\n' - req.stdout.write(s) + status, headers = headers_sent[:] = headers_set + def generator(): + yield 'Status: %s\r\n' % status + for header in headers: + yield '%s: %s\r\n' % header + yield '\r\n' + req.stdout.write(_str_join(generator()).encode('iso-8859-1')) req.stdout.write(data) @@ -1266,11 +1248,11 @@ write(data) if not headers_sent: - write('') # in case body was empty + write(b'') # in case body was empty finally: if hasattr(result, 'close'): result.close() except socket.error as e: - if e[0] != errno.EPIPE: - raise # Don't let EPIPE propagate beyond server + if e.errno != errno.EPIPE: + raise # Don't let EPIPE propagate beyond server finally: if not self.multithreaded: Index: trunk/trac/web/fcgi_frontend.py =================================================================== --- trunk/trac/web/fcgi_frontend.py (revision 17537) +++ trunk/trac/web/fcgi_frontend.py (revision 17560) @@ -27,5 +27,4 @@ use_flup = False - class FlupMiddleware(object): """Flup doesn't URL unquote the PATH_INFO, so we need to do it.""" @@ -43,8 +42,9 @@ try: from flup.server.fcgi import WSGIServer + except ImportError: + use_flup = False + else: params['maxThreads'] = 15 dispatch_request = FlupMiddleware(dispatch_request) - except ImportError: - use_flup = False if not use_flup: Index: trunk/trac/web/standalone.py =================================================================== --- trunk/trac/web/standalone.py (revision 17537) +++ trunk/trac/web/standalone.py (revision 17560) @@ -345,4 +345,5 @@ certfile=args.certfile, keyfile=args.keyfile) + httpd.environ['HTTPS'] = 'yes' httpd.serve_forever() elif args.protocol in ('scgi', 'ajp', 'fcgi'): Index: trunk/trac/web/templates/deploy_trac.cgi =================================================================== --- trunk/trac/web/templates/deploy_trac.cgi (revision 17537) +++ trunk/trac/web/templates/deploy_trac.cgi (revision 17560) @@ -15,6 +15,4 @@ {##}# {##}# Author: Jonas Borgström - -from __future__ import print_function try: Index: trunk/trac/web/templates/deploy_trac.fcgi =================================================================== --- trunk/trac/web/templates/deploy_trac.fcgi (revision 17537) +++ trunk/trac/web/templates/deploy_trac.fcgi (revision 17560) @@ -15,6 +15,4 @@ {##}# {##}# Author: Jonas Borgström - -from __future__ import print_function try: @@ -36,14 +34,12 @@ raise except Exception as e: - print("Content-Type: text/plain\r\n\r\n", end=' ') + print("Content-Type: text/plain", end="\r\n") + print("", end="\r\n") print("Oops...") - print() + print("") print("Trac detected an internal error:") - print() + print("") print(e) - print() + print("", flush=True) import traceback - import io - tb = io.Bytes() - traceback.print_exc(file=tb) - print(tb.getvalue()) + traceback.print_exc(file=sys.stdout) Index: trunk/trac/wiki/tests/functional.py =================================================================== --- trunk/trac/wiki/tests/functional.py (revision 17537) +++ trunk/trac/wiki/tests/functional.py (revision 17560) @@ -234,4 +234,6 @@ self._tester.go_to_wiki(page_name) tc.submit(formname='modifypage') + tc.url('%s/wiki/%s?action=edit' % (self._tester.url, page_name), + regexp=False) tc.find(readonly_checkbox) tc.formvalue('edit', 'readonly', True) Index: trunk/tracopt/versioncontrol/git/PyGIT.py =================================================================== --- trunk/tracopt/versioncontrol/git/PyGIT.py (revision 17537) +++ trunk/tracopt/versioncontrol/git/PyGIT.py (revision 17560) @@ -27,5 +27,5 @@ from trac.core import TracBaseError -from trac.util import terminate +from trac.util import as_int, terminate from trac.util.compat import close_fds from trac.util.datefmt import time_now @@ -333,34 +333,25 @@ def git_version(git_bin='git'): GIT_VERSION_MIN_REQUIRED = (1, 5, 6) - try: - g = GitCore(git_bin=git_bin) - [v] = g.version().splitlines() - version = v.strip().split()[2] - # 'version' has usually at least 3 numeric version - # components, e.g.:: - # 1.5.4.2 - # 1.5.4.3.230.g2db511 - # 1.5.4.GIT - - def try_int(s): - try: - return int(s) - except ValueError: - return s - - split_version = tuple(map(try_int, version.split(b'.'))) - - result = {} - result['v_str'] = version - result['v_tuple'] = split_version - result['v_min_tuple'] = GIT_VERSION_MIN_REQUIRED - result['v_min_str'] = ".".join(map(str, GIT_VERSION_MIN_REQUIRED)) - result['v_compatible'] = split_version >= GIT_VERSION_MIN_REQUIRED - return result - - except Exception as e: - raise GitError("Could not retrieve GIT version (tried to " - "execute/parse '%s --version' but got %s)" - % (git_bin, repr(e))) + version = str(GitCore(git_bin=git_bin).version(), 'utf-8') + # 'version' should have at least 3 numeric version components: + # 1.5.6 + # 1.5.6.windows.1 + # 1.5.6.2 + # 1.5.6.3.230.g2db511 + # 1.5.6.GIT + m = re.match('git version (.*)\n$', version) + if not m: + raise GitError("Could not retrieve GIT version. " + "'%s --version' returned %s" + % (git_bin, repr(version))) + version_str = m.group(1) + version_tuple = tuple(as_int(s, s) for s in version_str.split('.')) + return { + 'v_str': version_str, + 'v_tuple': version_tuple, + 'v_min_str': '.'.join(map(str, GIT_VERSION_MIN_REQUIRED)), + 'v_min_tuple': GIT_VERSION_MIN_REQUIRED, + 'v_compatible': version_tuple >= GIT_VERSION_MIN_REQUIRED, + } def __init__(self, git_dir, log, git_bin='git', git_fs_encoding=None, Index: trunk/tracopt/versioncontrol/git/tests/PyGIT.py =================================================================== --- trunk/tracopt/versioncontrol/git/tests/PyGIT.py (revision 17537) +++ trunk/tracopt/versioncontrol/git/tests/PyGIT.py (revision 17560) @@ -38,6 +38,11 @@ def test_git_version(self): v = Storage.git_version() - self.assertTrue(v) + self.assertIsInstance(v, dict) self.assertTrue(v['v_compatible']) + self.assertIsInstance(v['v_str'], str) + self.assertGreaterEqual(len(v['v_tuple']), 3) + self.assertIsInstance(v['v_tuple'][0], int) + self.assertIsInstance(v['v_tuple'][1], int) + self.assertIsInstance(v['v_tuple'][2], int) Index: trunk/tracopt/versioncontrol/svn/svn_fs.py =================================================================== --- trunk/tracopt/versioncontrol/svn/svn_fs.py (revision 17537) +++ trunk/tracopt/versioncontrol/svn/svn_fs.py (revision 17560) @@ -276,5 +276,5 @@ self.fs_ptr = repos.svn_repos_fs(self.repos) - self.uuid = fs.get_uuid(self.fs_ptr, self.pool) + self.uuid = _from_svn(fs.get_uuid(self.fs_ptr, self.pool)) self.base = 'svn:%s:%s' % (self.uuid, root_path) name = 'svn:%s:%s' % (self.uuid, path) Index: trunk/tracopt/versioncontrol/svn/tests/svn_fs.py =================================================================== --- trunk/tracopt/versioncontrol/svn/tests/svn_fs.py (revision 17537) +++ trunk/tracopt/versioncontrol/svn/tests/svn_fs.py (revision 17560) @@ -43,4 +43,5 @@ REPOS_PATH = None REPOS_NAME = 'repo' +REPOS_UUID = '92ea810a-adf3-0310-b540-bef912dcf5ba' URL = 'svn://test' @@ -151,4 +152,10 @@ if td: return td + + def test_repos_properties(self): + self.assertEqual(REPOS_UUID, self.repos.uuid) + self.assertEqual('svn:%s:%s' % (REPOS_UUID, REPOS_PATH), + self.repos.base) + self.assertEqual(self.repos.name, self.repos.base) def test_invalid_path_raises(self): @@ -1104,4 +1111,11 @@ class ScopedTests(object): + def test_repos_properties(self): + self.assertEqual(REPOS_UUID, self.repos.uuid) + self.assertEqual('svn:%s:%s' % (REPOS_UUID, REPOS_PATH), + self.repos.base) + self.assertEqual('svn:%s:%s/tête' % (REPOS_UUID, REPOS_PATH), + self.repos.name) + def test_repos_normalize_path(self): self.assertEqual('/', self.repos.normalize_path('/')) @@ -1591,7 +1605,9 @@ skipped = { 'SvnCachedRepositoryNormalTests': [ + 'test_repos_properties', 'test_changeset_repos_creation', ], 'SvnCachedRepositoryScopedTests': [ + 'test_repos_properties', 'test_changeset_repos_creation', 'test_rev_navigation',