You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bloodhound.apache.org by rj...@apache.org on 2014/11/14 12:06:31 UTC
svn commit: r1639602 [8/14] - in /bloodhound/vendor/trac/current: ./
contrib/workflow/ doc/dev/ sample-plugins/ sample-plugins/permissions/
sample-plugins/workflow/ trac/ trac/admin/ trac/admin/templates/
trac/admin/tests/ trac/db/ trac/db/tests/ trac/...
Modified: bloodhound/vendor/trac/current/trac/templates/error.html
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/templates/error.html?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/templates/error.html (original)
+++ bloodhound/vendor/trac/current/trac/templates/error.html Fri Nov 14 11:06:23 2014
@@ -1,3 +1,13 @@
+<!--! Copyright (C) 2006-2014 Edgewall Software
+
+ This software is licensed as described in the file COPYING, which
+ you should have received as part of this distribution. The terms
+ are also available at http://trac.edgewall.com/license.html.
+
+ This software consists of voluntary contributions made by many
+ individuals. For the exact contribution history, see the revision
+ history and logs, available at http://trac.edgewall.org/.
+-->
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
@@ -39,7 +49,9 @@
$("#traceback pre").hide();
$("#tbtoggle").parent().show();
- $("#systeminfo").append("<tr><th>jQuery</th><td>" + $().jquery + "</td></tr>");
+ $("#systeminfo").append("<tr><th>jQuery</th><td>"+$().jquery+"</td></tr>" +
+ "<tr><th>jQuery UI</th><td>"+$.ui.version+"</td></tr>" +
+ "<tr><th>jQuery Timepicker</th><td>"+$.timepicker.version+"</td></tr>");
$("#systeminfo").before("<p>User Agent: <tt>" + navigator.userAgent + "</tt></p>");
});
/*]]>*/</script>
@@ -48,7 +60,9 @@
$("form.newticket textarea").each(function() {
$(this).val($(this).val()
.replace(/#USER_AGENT#/m, navigator.userAgent)
- .replace(/#JQUERY#/m, $().jquery));
+ .replace(/#JQUERY#/m, $().jquery)
+ .replace(/#JQUERYUI#/m, $.ui.version)
+ .replace(/#JQUERYTP#/m, $.timepicker.version));
});
});
/*]]>*/</script>
@@ -98,13 +112,17 @@ ${description_en if url else description
<p>The action that triggered the error was:</p>
<pre>${req.method}: ${req.path_info}</pre>
</py:when>
- <py:otherwise>
- <form class="newticket" method="get" action="${project.admin_href.newticket()}#">
+ <py:otherwise py:choose="">
+ <p py:when="not project.admin_href or project.admin_trac_url == '.'">
+ This is probably a local installation issue.
+ </p>
+ <form py:otherwise=""
+ class="newticket" method="get" action="${project.admin_href.newticket()}#">
<p>This is probably a local installation issue.
- <py:if test="project.admin_href and project.admin_trac_url != '.'"><i18n:msg params="create">
+ <i18n:msg params="create">
You should ${create_ticket()} a ticket at the admin Trac to report
the issue.
- </i18n:msg></py:if>
+ </i18n:msg>
</p>
</form>
<h2>Found a bug in Trac?</h2>
@@ -140,7 +158,7 @@ ${description_en if url else description
<li class="frame" py:for="idx, frame in enumerate(frames)">
<a href="#frame${idx}" id="frame${idx}"><span i18n:msg="file, line, function" py:strip="">
<span class="file">File "${frame.filename}",
- line <b>${frame.lineno + 1}</b>, in</span>
+ line <strong>${frame.lineno + 1}</strong>, in</span>
<var>${frame.function}</var></span>
</a>
<div py:if="frame.line" class="source" style="display: none">
Modified: bloodhound/vendor/trac/current/trac/templates/history_view.html
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/templates/history_view.html?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/templates/history_view.html (original)
+++ bloodhound/vendor/trac/current/trac/templates/history_view.html Fri Nov 14 11:06:23 2014
@@ -1,3 +1,13 @@
+<!--! Copyright (C) 2006-2014 Edgewall Software
+
+ This software is licensed as described in the file COPYING, which
+ you should have received as part of this distribution. The terms
+ are also available at http://trac.edgewall.com/license.html.
+
+ This software consists of voluntary contributions made by many
+ individuals. For the exact contribution history, see the revision
+ history and logs, available at http://trac.edgewall.org/.
+-->
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
@@ -15,7 +25,7 @@
<div id="content" class="ticket">
<h1 i18n:msg="name">Change History for <a href="${url or url_of(resource)}">${name or name_of(resource)}</a></h1>
- <form py:if="history" class="printableform" method="get" action="">
+ <form py:if="history" id="history" class="printableform" method="get" action="">
<div class="buttons">
<input type="hidden" name="action" value="${diff_action or 'diff'}" />
<input py:for="k, v in diff_args or []" type="hidden" name="$k" value="$v"/>
Modified: bloodhound/vendor/trac/current/trac/templates/index.html
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/templates/index.html?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/templates/index.html (original)
+++ bloodhound/vendor/trac/current/trac/templates/index.html Fri Nov 14 11:06:23 2014
@@ -1,3 +1,13 @@
+<!--! Copyright (C) 2006-2014 Edgewall Software
+
+ This software is licensed as described in the file COPYING, which
+ you should have received as part of this distribution. The terms
+ are also available at http://trac.edgewall.com/license.html.
+
+ This software consists of voluntary contributions made by many
+ individuals. For the exact contribution history, see the revision
+ history and logs, available at http://trac.edgewall.org/.
+-->
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
Modified: bloodhound/vendor/trac/current/trac/templates/layout.html
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/templates/layout.html?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/templates/layout.html (original)
+++ bloodhound/vendor/trac/current/trac/templates/layout.html Fri Nov 14 11:06:23 2014
@@ -1,3 +1,13 @@
+<!--! Copyright (C) 2006-2014 Edgewall Software
+
+ This software is licensed as described in the file COPYING, which
+ you should have received as part of this distribution. The terms
+ are also available at http://trac.edgewall.com/license.html.
+
+ This software consists of voluntary contributions made by many
+ individuals. For the exact contribution history, see the revision
+ history and logs, available at http://trac.edgewall.org/.
+-->
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
Modified: bloodhound/vendor/trac/current/trac/templates/list_of_attachments.html
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/templates/list_of_attachments.html?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/templates/list_of_attachments.html (original)
+++ bloodhound/vendor/trac/current/trac/templates/list_of_attachments.html Fri Nov 14 11:06:23 2014
@@ -1,4 +1,13 @@
-<!--!
+<!--! Copyright (C) 2010-2014 Edgewall Software
+
+ This software is licensed as described in the file COPYING, which
+ you should have received as part of this distribution. The terms
+ are also available at http://trac.edgewall.com/license.html.
+
+ This software consists of voluntary contributions made by many
+ individuals. For the exact contribution history, see the revision
+ history and logs, available at http://trac.edgewall.org/.
+
Display a list of attachments.
Arguments:
Modified: bloodhound/vendor/trac/current/trac/templates/macros.html
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/templates/macros.html?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/templates/macros.html (original)
+++ bloodhound/vendor/trac/current/trac/templates/macros.html Fri Nov 14 11:06:23 2014
@@ -1,3 +1,13 @@
+<!--! Copyright (C) 2006-2014 Edgewall Software
+
+ This software is licensed as described in the file COPYING, which
+ you should have received as part of this distribution. The terms
+ are also available at http://trac.edgewall.com/license.html.
+
+ This software consists of voluntary contributions made by many
+ individuals. For the exact contribution history, see the revision
+ history and logs, available at http://trac.edgewall.org/.
+-->
<div xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/"
xmlns:xi="http://www.w3.org/2001/XInclude"
Modified: bloodhound/vendor/trac/current/trac/templates/page_index.html
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/templates/page_index.html?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/templates/page_index.html (original)
+++ bloodhound/vendor/trac/current/trac/templates/page_index.html Fri Nov 14 11:06:23 2014
@@ -1,6 +1,17 @@
-<!--! Display a page index.
+<!--! Copyright (C) 2008-2014 Edgewall Software
- `paginator` must be a trac.util.presentation.Paginator instance
+ This software is licensed as described in the file COPYING, which
+ you should have received as part of this distribution. The terms
+ are also available at http://trac.edgewall.com/license.html.
+
+ This software consists of voluntary contributions made by many
+ individuals. For the exact contribution history, see the revision
+ history and logs, available at http://trac.edgewall.org/.
+
+Display a page index.
+
+Arguments:
+ - `paginator` must be a trac.util.presentation.Paginator instance
-->
<div xmlns="http://www.w3.org/1999/xhtml"
Modified: bloodhound/vendor/trac/current/trac/templates/preview_file.html
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/templates/preview_file.html?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/templates/preview_file.html (original)
+++ bloodhound/vendor/trac/current/trac/templates/preview_file.html Fri Nov 14 11:06:23 2014
@@ -1,4 +1,13 @@
-<!--!
+<!--! Copyright (C) 2010-2014 Edgewall Software
+
+ This software is licensed as described in the file COPYING, which
+ you should have received as part of this distribution. The terms
+ are also available at http://trac.edgewall.com/license.html.
+
+ This software consists of voluntary contributions made by many
+ individuals. For the exact contribution history, see the revision
+ history and logs, available at http://trac.edgewall.org/.
+
Display a div for visualizing a preview of a file content.
Arguments:
Modified: bloodhound/vendor/trac/current/trac/templates/progress_bar.html
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/templates/progress_bar.html?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/templates/progress_bar.html (original)
+++ bloodhound/vendor/trac/current/trac/templates/progress_bar.html Fri Nov 14 11:06:23 2014
@@ -1,4 +1,13 @@
-<!--!
+<!--! Copyright (C) 2010-2014 Edgewall Software
+
+ This software is licensed as described in the file COPYING, which
+ you should have received as part of this distribution. The terms
+ are also available at http://trac.edgewall.com/license.html.
+
+ This software consists of voluntary contributions made by many
+ individuals. For the exact contribution history, see the revision
+ history and logs, available at http://trac.edgewall.org/.
+
Display groups of tickets in a progress bar.
Arguments:
Modified: bloodhound/vendor/trac/current/trac/templates/progress_bar_grouped.html
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/templates/progress_bar_grouped.html?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/templates/progress_bar_grouped.html (original)
+++ bloodhound/vendor/trac/current/trac/templates/progress_bar_grouped.html Fri Nov 14 11:06:23 2014
@@ -1,4 +1,13 @@
-<!--!
+<!--! Copyright (C) 2011-2014 Edgewall Software
+
+ This software is licensed as described in the file COPYING, which
+ you should have received as part of this distribution. The terms
+ are also available at http://trac.edgewall.com/license.html.
+
+ This software consists of voluntary contributions made by many
+ individuals. For the exact contribution history, see the revision
+ history and logs, available at http://trac.edgewall.org/.
+
Display a table of progress bars for ticket groups
Arguments:
Modified: bloodhound/vendor/trac/current/trac/templates/theme.html
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/templates/theme.html?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/templates/theme.html (original)
+++ bloodhound/vendor/trac/current/trac/templates/theme.html Fri Nov 14 11:06:23 2014
@@ -1,3 +1,13 @@
+<!--! Copyright (C) 2006-2014 Edgewall Software
+
+ This software is licensed as described in the file COPYING, which
+ you should have received as part of this distribution. The terms
+ are also available at http://trac.edgewall.com/license.html.
+
+ This software consists of voluntary contributions made by many
+ individuals. For the exact contribution history, see the revision
+ history and logs, available at http://trac.edgewall.org/.
+-->
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
Modified: bloodhound/vendor/trac/current/trac/test.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/test.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/test.py (original)
+++ bloodhound/vendor/trac/current/trac/test.py Fri Nov 14 11:06:23 2014
@@ -144,7 +144,8 @@ class TestSetup(unittest.TestSuite):
return result
def _wrapped_run(self, *args, **kwargs):
- "Python 2.7 / unittest2 compatibility - there must be a better way..."
+ """Python 2.7 / unittest2 compatibility - there must be a better
+ way..."""
self.setUp()
if hasattr(self, 'fixture'):
for test in self._tests:
@@ -153,6 +154,7 @@ class TestSetup(unittest.TestSuite):
unittest.TestSuite._wrapped_run(self, *args, **kwargs)
self.tearDown()
+
class TestCaseSetup(unittest.TestCase):
def setFixture(self, fixture):
self.fixture = fixture
@@ -164,7 +166,7 @@ def get_dburi():
dburi = os.environ.get('TRAC_TEST_DB_URI')
if dburi:
scheme, db_prop = _parse_db_str(dburi)
- # Assume the schema 'tractest' for Postgres
+ # Assume the schema 'tractest' for PostgreSQL
if scheme == 'postgres' and \
not db_prop.get('params', {}).get('schema'):
if '?' in dburi:
@@ -176,9 +178,8 @@ def get_dburi():
def reset_sqlite_db(env, db_prop):
- dbname = os.path.basename(db_prop['path'])
with env.db_transaction as db:
- tables = db("SELECT name FROM sqlite_master WHERE type='table'")
+ tables = db.get_table_names()
for table in tables:
db("DELETE FROM %s" % table)
return tables
@@ -189,24 +190,24 @@ def reset_postgres_db(env, db_prop):
dbname = db.schema
if dbname:
# reset sequences
- # information_schema.sequences view is available in PostgreSQL 8.2+
- # however Trac supports PostgreSQL 8.0+, uses
+ # information_schema.sequences view is available in
+ # PostgreSQL 8.2+ however Trac supports PostgreSQL 8.0+, uses
# pg_get_serial_sequence()
- for seq in db("""
- SELECT sequence_name FROM (
- SELECT pg_get_serial_sequence(%s||table_name,
- column_name)
- AS sequence_name
- FROM information_schema.columns
- WHERE table_schema=%s) AS tab
- WHERE sequence_name IS NOT NULL""",
- (dbname + '.', dbname)):
+ seqs = [seq for seq, in db("""
+ SELECT sequence_name
+ FROM (
+ SELECT pg_get_serial_sequence(
+ quote_ident(table_schema) || '.' ||
+ quote_ident(table_name), column_name) AS sequence_name
+ FROM information_schema.columns
+ WHERE table_schema=%s) AS tab
+ WHERE sequence_name IS NOT NULL""", (dbname,))]
+ for seq in seqs:
db("ALTER SEQUENCE %s RESTART WITH 1" % seq)
# clear tables
- tables = db("""SELECT table_name FROM information_schema.tables
- WHERE table_schema=%s""", (dbname,))
+ tables = db.get_table_names()
for table in tables:
- db("DELETE FROM %s" % table)
+ db("DELETE FROM %s" % db.quote(table))
# PostgreSQL supports TRUNCATE TABLE as well
# (see http://www.postgresql.org/docs/8.1/static/sql-truncate.html)
# but on the small tables used here, DELETE is actually much faster
@@ -217,12 +218,18 @@ def reset_mysql_db(env, db_prop):
dbname = os.path.basename(db_prop['path'])
if dbname:
with env.db_transaction as db:
- tables = db("""SELECT table_name FROM information_schema.tables
+ tables = db("""SELECT table_name, auto_increment
+ FROM information_schema.tables
WHERE table_schema=%s""", (dbname,))
- for table in tables:
- # TRUNCATE TABLE is prefered to DELETE FROM, as we need to reset
- # the auto_increment in MySQL.
- db("TRUNCATE TABLE %s" % table)
+ for table, auto_increment in tables:
+ if auto_increment is None or auto_increment == 1:
+ # DELETE FROM is preferred to TRUNCATE TABLE, as the
+ # auto_increment is not used or it is 1.
+ db("DELETE FROM %s" % table)
+ else:
+ # TRUNCATE TABLE is preferred to DELETE FROM, as we
+ # need to reset the auto_increment in MySQL.
+ db("TRUNCATE TABLE %s" % table)
return tables
@@ -245,6 +252,12 @@ class EnvironmentStub(Environment):
activate in the stub environment.
:param disable: A list of component classes or name globs to
deactivate in the stub environment.
+ :param path: The location of the environment in the file system.
+ No files or directories are created when specifying
+ this parameter.
+ :param destroying: If True, the database will not be reset. This is
+ useful for cases when the object is being
+ constructed in order to call `destroy_db`.
"""
if enable is not None and not isinstance(enable, (list, tuple)):
raise TypeError('Keyword argument "enable" must be a list')
@@ -323,28 +336,26 @@ class EnvironmentStub(Environment):
remove_sqlite_db = False
try:
with self.db_transaction as db:
- db.rollback() # make sure there's no transaction in progress
+ db.rollback() # make sure there's no transaction in progress
# check the database version
- database_version = db(
- "SELECT value FROM system WHERE name='database_version'")
- if database_version:
- database_version = int(database_version[0][0])
- if database_version == db_default.db_version:
- # same version, simply clear the tables (faster)
- m = sys.modules[__name__]
- reset_fn = 'reset_%s_db' % scheme
- if hasattr(m, reset_fn):
- tables = getattr(m, reset_fn)(self, db_prop)
- else:
- # different version or version unknown, drop the tables
- remove_sqlite_db = True
- self.destroy_db(scheme, db_prop)
- except Exception, e:
+ database_version = self.get_version()
+ except Exception:
# "Database not found ...",
# "OperationalError: no such table: system" or the like
pass
+ else:
+ if database_version == db_default.db_version:
+ # same version, simply clear the tables (faster)
+ m = sys.modules[__name__]
+ reset_fn = 'reset_%s_db' % scheme
+ if hasattr(m, reset_fn):
+ tables = getattr(m, reset_fn)(self, db_prop)
+ else:
+ # different version or version unknown, drop the tables
+ remove_sqlite_db = True
+ self.destroy_db(scheme, db_prop)
- db = None # as we might shutdown the pool FIXME no longer needed!
+ db = None # as we might shutdown the pool FIXME no longer needed!
if scheme == 'sqlite' and remove_sqlite_db:
path = db_prop['path']
@@ -362,12 +373,14 @@ class EnvironmentStub(Environment):
self.global_databasemanager.shutdown()
with self.db_transaction as db:
+ if scheme == 'sqlite':
+ # Speed-up tests with SQLite database
+ db("PRAGMA synchronous = OFF")
if default_data:
for table, cols, vals in db_default.get_data(db):
db.executemany("INSERT INTO %s (%s) VALUES (%s)"
% (table, ','.join(cols),
- ','.join(['%s' for c in cols])),
- vals)
+ ','.join(['%s'] * len(cols))), vals)
else:
db("INSERT INTO system (name, value) VALUES (%s, %s)",
('database_version', str(db_default.db_version)))
@@ -378,12 +391,9 @@ class EnvironmentStub(Environment):
try:
with self.db_transaction as db:
if scheme == 'postgres' and db.schema:
- db('DROP SCHEMA "%s" CASCADE' % db.schema)
+ db('DROP SCHEMA %s CASCADE' % db.quote(db.schema))
elif scheme == 'mysql':
- dbname = os.path.basename(db_prop['path'])
- for table in db("""
- SELECT table_name FROM information_schema.tables
- WHERE table_schema=%s""", (dbname,)):
+ for table in db.get_table_names():
db("DROP TABLE IF EXISTS `%s`" % table)
except Exception:
# "TracError: Database not found...",
@@ -391,7 +401,7 @@ class EnvironmentStub(Environment):
pass
return False
- # overriden
+ # overridden
def is_component_enabled(self, cls):
if self._component_name(cls).startswith('__main__.'):
@@ -418,6 +428,7 @@ def locate(fn):
INCLUDE_FUNCTIONAL_TESTS = True
+
def suite():
import trac.tests
import trac.admin.tests
Modified: bloodhound/vendor/trac/current/trac/tests/config.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/tests/config.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/tests/config.py (original)
+++ bloodhound/vendor/trac/current/trac/tests/config.py Fri Nov 14 11:06:23 2014
@@ -19,10 +19,10 @@ import tempfile
import time
import unittest
+import trac.tests.compat
from trac.config import *
from trac.core import Component, Interface, implements
from trac.test import Configuration, EnvironmentStub
-from trac.tests import compat
from trac.util import create_file
Modified: bloodhound/vendor/trac/current/trac/tests/core.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/tests/core.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/tests/core.py (original)
+++ bloodhound/vendor/trac/current/trac/tests/core.py Fri Nov 14 11:06:23 2014
@@ -14,9 +14,9 @@
#
# Author: Christopher Lenz <cm...@gmx.de>
+import trac.tests.compat
from trac.core import *
from trac.core import ComponentManager
-from trac.tests import compat
import unittest
Modified: bloodhound/vendor/trac/current/trac/tests/env.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/tests/env.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/tests/env.py (original)
+++ bloodhound/vendor/trac/current/trac/tests/env.py Fri Nov 14 11:06:23 2014
@@ -13,11 +13,12 @@
from __future__ import with_statement
+from ConfigParser import RawConfigParser
import shutil
import tempfile
import unittest
-from trac.tests import compat
+import trac.tests.compat
from trac import db_default
from trac.core import ComponentManager
from trac.env import Environment
@@ -85,6 +86,8 @@ class EnvironmentTestCase(unittest.TestC
def test_get_version(self):
"""Testing env.get_version"""
self.assertEqual(db_default.db_version, self.env.get_version())
+ self.assertEqual(db_default.db_version, self.env.database_version)
+ self.assertEqual(db_default.db_version, self.env.database_initial_version)
def test_get_known_users(self):
"""Testing env.get_known_users"""
@@ -112,6 +115,24 @@ class EnvironmentTestCase(unittest.TestC
self.assertEqual(False, EnvironmentStub.required)
self.assertEqual(None, self.env.is_component_enabled(EnvironmentStub))
+ def test_dumped_values_in_tracini(self):
+ parser = RawConfigParser()
+ filename = self.env.config.filename
+ self.assertEqual([filename], parser.read(filename))
+ self.assertEqual('#cc0,#0c0,#0cc,#00c,#c0c,#c00',
+ parser.get('revisionlog', 'graph_colors'))
+ self.assertEqual('disabled', parser.get('trac', 'secure_cookies'))
+
+ def test_dumped_values_in_tracini_sample(self):
+ parser = RawConfigParser()
+ filename = self.env.config.filename + '.sample'
+ self.assertEqual([filename], parser.read(filename))
+ self.assertEqual('#cc0,#0c0,#0cc,#00c,#c0c,#c00',
+ parser.get('revisionlog', 'graph_colors'))
+ self.assertEqual('disabled', parser.get('trac', 'secure_cookies'))
+ self.assertTrue(parser.has_option('logging', 'log_format'))
+ self.assertEqual('', parser.get('logging', 'log_format'))
+
def suite():
suite = unittest.TestSuite()
Modified: bloodhound/vendor/trac/current/trac/tests/functional/__init__.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/tests/functional/__init__.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/tests/functional/__init__.py (original)
+++ bloodhound/vendor/trac/current/trac/tests/functional/__init__.py Fri Nov 14 11:06:23 2014
@@ -123,22 +123,33 @@ if twill:
else:
env_class = FunctionalTestEnvironment
+ tester_class = FunctionalTester
+
def setUp(self, port=None):
"""If no port is specified, use a semi-random port and subdirectory
'testenv'; but if a port is specified, use that port and
subdirectory 'testenv<portnum>'.
"""
if port is None:
- port = 8000 + os.getpid() % 1000
- dirname = "testenv"
+ try:
+ port = int(os.getenv('TRAC_TEST_PORT'))
+ except (TypeError, ValueError):
+ pass
+
+ env_path = os.getenv('TRAC_TEST_ENV_PATH')
+ if not env_path:
+ env_name = 'testenv%s' % (port or '')
+ env_path = os.path.join(trac_source_tree, env_name)
else:
- dirname = "testenv%s" % port
- dirname = os.path.join(trac_source_tree, dirname)
+ env_path += str(port or '')
+
+ if port is None:
+ port = 8000 + os.getpid() % 1000
baseurl = "http://127.0.0.1:%s" % port
- self._testenv = self.env_class(dirname, port, baseurl)
+ self._testenv = self.env_class(env_path, port, baseurl)
self._testenv.start()
- self._tester = FunctionalTester(baseurl)
+ self._tester = self.tester_class(baseurl)
self.fixture = (self._testenv, self._tester)
def tearDown(self):
Modified: bloodhound/vendor/trac/current/trac/tests/functional/better_twill.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/tests/functional/better_twill.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/tests/functional/better_twill.py (original)
+++ bloodhound/vendor/trac/current/trac/tests/functional/better_twill.py Fri Nov 14 11:06:23 2014
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
-# Copyright (C) 2008-2013 Edgewall Software
+# Copyright (C) 2008-2014 Edgewall Software
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
@@ -17,8 +17,10 @@ It also handles twill's absense.
"""
import os
-from os.path import abspath, dirname, join
import sys
+import urllib
+import urlparse
+from os.path import abspath, dirname, join
from pkg_resources import parse_version as pv
try:
from cStringIO import StringIO
@@ -160,7 +162,7 @@ if twill:
html_file.write(b.get_html())
html_file.close()
- return filename
+ return urlparse.urljoin('file:', urllib.pathname2url(filename))
# Twill isn't as helpful with errors as I'd like it to be, so we replace
# the formvalue function. This would be better done as a patch to Twill.
@@ -170,8 +172,8 @@ if twill:
except (twill.errors.TwillAssertionError,
twill.utils.ClientForm.ItemNotFoundError), e:
filename = twill_write_html()
- args = e.args + (filename,)
- raise twill.errors.TwillAssertionError(*args)
+ raise twill.errors.TwillAssertionError('%s at %s' %
+ (unicode(e), filename))
tc.formvalue = better_formvalue
tc.fv = better_formvalue
@@ -221,8 +223,8 @@ if twill:
tcfind(what, flags)
except twill.errors.TwillAssertionError, e:
filename = twill_write_html()
- args = e.args + (filename,)
- raise twill.errors.TwillAssertionError(*args)
+ raise twill.errors.TwillAssertionError('%s at %s' %
+ (unicode(e), filename))
tc.find = better_find
def better_notfind(what, flags='', tcnotfind=tc.notfind):
@@ -230,8 +232,8 @@ if twill:
tcnotfind(what, flags)
except twill.errors.TwillAssertionError, e:
filename = twill_write_html()
- args = e.args + (filename,)
- raise twill.errors.TwillAssertionError(*args)
+ raise twill.errors.TwillAssertionError('%s at %s' %
+ (unicode(e), filename))
tc.notfind = better_notfind
# Same for tc.url - no hint about what went wrong!
@@ -240,8 +242,8 @@ if twill:
tcurl(should_be)
except twill.errors.TwillAssertionError, e:
filename = twill_write_html()
- args = e.args + (filename,)
- raise twill.errors.TwillAssertionError(*args)
+ raise twill.errors.TwillAssertionError('%s at %s' %
+ (unicode(e), filename))
tc.url = better_url
else:
b = tc = None
Modified: bloodhound/vendor/trac/current/trac/tests/functional/compat.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/tests/functional/compat.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/tests/functional/compat.py (original)
+++ bloodhound/vendor/trac/current/trac/tests/functional/compat.py Fri Nov 14 11:06:23 2014
@@ -11,5 +11,5 @@
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://trac.edgewall.org/log/.
-from trac.util.compat import close_fds
from trac.tests.compat import rmtree
+from trac.util.compat import close_fds
Modified: bloodhound/vendor/trac/current/trac/tests/functional/svntestenv.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/tests/functional/svntestenv.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/tests/functional/svntestenv.py (original)
+++ bloodhound/vendor/trac/current/trac/tests/functional/svntestenv.py Fri Nov 14 11:06:23 2014
@@ -24,16 +24,17 @@ class SvnFunctionalTestEnvironment(Funct
def work_dir(self):
return os.path.join(self.dirname, 'workdir')
+ def repo_path(self, filename):
+ return os.path.join(self.dirname, filename)
+
def repo_path_for_initenv(self):
- return os.path.join(self.dirname, 'repo')
+ return self.repo_path('repo')
def create_repo(self):
"""
Initialize a repo of the type :attr:`self.repotype`.
"""
- if call(["svnadmin", "create", self.repo_path_for_initenv()],
- stdout=logfile, stderr=logfile, close_fds=close_fds):
- raise Exception('unable to create subversion repository')
+ self.svnadmin_create()
if call(['svn', 'co', self.repo_url(), self.work_dir()],
stdout=logfile, stderr=logfile, close_fds=close_fds):
raise Exception('Checkout from %s failed.' % self.repo_url())
@@ -53,6 +54,18 @@ class SvnFunctionalTestEnvironment(Funct
else:
return 'file://' + repodir
+ def svnadmin_create(self, filename=None):
+ """Subversion helper to create a new repository."""
+ if filename is None:
+ path = self.repo_path_for_initenv()
+ else:
+ path = self.repo_path(filename)
+ if call(["svnadmin", "create", path],
+ stdout=logfile, stderr=logfile, close_fds=close_fds):
+ raise Exception('unable to create subversion repository: %r' %
+ path)
+ return path
+
def svn_mkdir(self, paths, msg, username='admin'):
"""Subversion helper to create a new directory within the main
repository. Operates directly on the repository url, so a working
Modified: bloodhound/vendor/trac/current/trac/tests/functional/testcases.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/tests/functional/testcases.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/tests/functional/testcases.py (original)
+++ bloodhound/vendor/trac/current/trac/tests/functional/testcases.py Fri Nov 14 11:06:23 2014
@@ -32,11 +32,61 @@ class TestAttachmentNonexistentParent(Fu
'Parent resource NonexistentPage doesn\'t exist</p>')
+class TestErrorPage(FunctionalTwillTestCaseSetup):
+ """Validate the error page.
+ Defects reported to trac-hacks should use the Component defined in the
+ plugin's URL (#11434).
+ """
+ def runTest(self):
+ env = self._testenv.get_trac_environment()
+ env.config.set('components', 'RaiseExceptionPlugin.*', 'enabled')
+ env.config.save()
+ create_file(os.path.join(env.path, 'plugins',
+ 'RaiseExceptionPlugin.py'),
+"""\
+from trac.core import Component, implements
+from trac.web.api import IRequestHandler
+
+url = None
+
+class RaiseExceptionPlugin(Component):
+ implements(IRequestHandler)
+
+ def match_request(self, req):
+ if req.path_info.startswith('/raise-exception'):
+ return True
+
+ def process_request(self, req):
+ print 'maybe?'
+ if req.args.get('report') == 'tho':
+ global url
+ url = 'http://trac-hacks.org/wiki/HelloWorldMacro'
+ raise Exception
+
+""")
+ self._testenv.restart()
+
+ try:
+ tc.go(self._tester.url + '/raise-exception')
+ tc.find(internal_error)
+ tc.find('<form class="newticket" method="get" '
+ 'action="http://trac.edgewall.org/newticket">')
+
+ tc.go(self._tester.url + '/raise-exception?report=tho')
+ tc.find(internal_error)
+ tc.find('<form class="newticket" method="get" '
+ 'action="http://trac-hacks.org/newticket">')
+ tc.find('<input type="hidden" name="component" '
+ 'value="HelloWorldMacro" />')
+ finally:
+ env.config.set('components', 'RaiseExceptionPlugin.*', 'disabled')
+
+
class RegressionTestRev6017(FunctionalTwillTestCaseSetup):
def runTest(self):
"""Test for regression of the plugin reload fix in r6017"""
# Setup the DeleteTicket plugin
- plugin = open(os.path.join(self._testenv.command_cwd,
+ plugin = open(os.path.join(self._testenv.trac_src,
'sample-plugins', 'workflow',
'DeleteTicket.py')).read()
open(os.path.join(self._testenv.tracdir, 'plugins',
@@ -198,17 +248,6 @@ See also http://bugs.python.org/issue155
""")
-class ErrorPageValidation(FunctionalTwillTestCaseSetup):
- def runTest(self):
- """Validate the error page"""
- url = self._tester.url + '/wiki/WikiStart'
- tc.go(url + '?version=bug')
- tc.url(url)
- tc.find(internal_error)
- tc.find('<form class="newticket" method="get" '
- 'action="http://trac.edgewall.org/newticket">')
-
-
class RegressionTestTicket3663(FunctionalTwillTestCaseSetup):
def runTest(self):
"""Regression test for non-UTF-8 PATH_INFO (#3663)
@@ -297,6 +336,7 @@ def functionalSuite(suite=None):
import trac.tests.functional
suite = trac.tests.functional.functionalSuite()
suite.addTest(TestAttachmentNonexistentParent())
+ suite.addTest(TestErrorPage())
suite.addTest(RegressionTestRev6017())
suite.addTest(RegressionTestTicket3833a())
suite.addTest(RegressionTestTicket3833b())
@@ -304,7 +344,6 @@ def functionalSuite(suite=None):
suite.addTest(RegressionTestTicket5572())
suite.addTest(RegressionTestTicket7209())
suite.addTest(RegressionTestTicket9880())
- suite.addTest(ErrorPageValidation())
suite.addTest(RegressionTestTicket3663())
suite.addTest(RegressionTestTicket6318())
suite.addTest(RegressionTestTicket11434())
Modified: bloodhound/vendor/trac/current/trac/tests/functional/testenv.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/tests/functional/testenv.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/tests/functional/testenv.py (original)
+++ bloodhound/vendor/trac/current/trac/tests/functional/testenv.py Fri Nov 14 11:06:23 2014
@@ -25,7 +25,7 @@ from subprocess import call, Popen, PIPE
from trac.env import open_environment
from trac.test import EnvironmentStub, get_dburi
from trac.tests.compat import rmtree
-from trac.tests.functional import logfile
+from trac.tests.functional import logfile, trac_source_tree
from trac.tests.functional.better_twill import tc, ConnectError
from trac.util import terminate
from trac.util.compat import close_fds, wait_for_file_mtime_change
@@ -64,6 +64,7 @@ class FunctionalTestEnvironment(object):
def __init__(self, dirname, port, url):
"""Create a :class:`FunctionalTestEnvironment`, see the class itself
for parameter information."""
+ self.trac_src = trac_source_tree
self.url = url
self.command_cwd = os.path.normpath(os.path.join(dirname, '..'))
self.dirname = os.path.abspath(dirname)
@@ -77,8 +78,6 @@ class FunctionalTestEnvironment(object):
self.create()
locale.setlocale(locale.LC_ALL, '')
- trac_src = '.'
-
@property
def dburi(self):
dburi = get_dburi()
@@ -114,11 +113,13 @@ class FunctionalTestEnvironment(object):
def post_create(self, env):
"""Hook for modifying the environment after creation. For example, to
- set configuration like::
+ set configuration like:
+ ::
def post_create(self, env):
env.config.set('git', 'path', '/usr/bin/git')
env.config.save()
+
"""
pass
@@ -310,21 +311,24 @@ class FunctionalTestEnvironment(object):
def enable_authz_permpolicy(self, authz_content, filename=None):
"""Enables the Authz permissions policy. The `authz_content` will
be written to `filename`, and may be specified in a triple-quoted
- string.
- '''
- [wiki:WikiStart@*]
- * = WIKI_VIEW
- [wiki:PrivatePage@*]
- john = WIKI_VIEW
- * = !WIKI_VIEW
- '''
+ string.::
+
+ [wiki:WikiStart@*]
+ * = WIKI_VIEW
+ [wiki:PrivatePage@*]
+ john = WIKI_VIEW
+ * = !WIKI_VIEW
+
`authz_content` may also be a dictionary of dictionaries specifying
the sections and key/value pairs of each section, however this form
should only be used when the order of the entries in the file is not
- important, as the order cannot be known.
- {'wiki:WikiStart@*': {'*': 'WIKI_VIEW'},
- 'wiki:PrivatePage@*': {'john': 'WIKI_VIEW', '*': '!WIKI_VIEW'},
- }
+ important, as the order cannot be known.::
+
+ {
+ 'wiki:WikiStart@*': {'*': 'WIKI_VIEW'},
+ 'wiki:PrivatePage@*': {'john': 'WIKI_VIEW', '*': '!WIKI_VIEW'},
+ }
+
The `filename` parameter is optional, and if omitted a filename will
be generated by computing a hash of `authz_content`, prefixed with
"authz-".
Modified: bloodhound/vendor/trac/current/trac/tests/functional/tester.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/tests/functional/tester.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/tests/functional/tester.py (original)
+++ bloodhound/vendor/trac/current/trac/tests/functional/tester.py Fri Nov 14 11:06:23 2014
@@ -20,7 +20,7 @@ import re
from trac.tests.functional import internal_error
from trac.tests.functional.better_twill import tc, b
from trac.tests.contentgen import random_page, random_sentence, random_word, \
- random_unique_camel
+ random_unique_camel
from trac.util.text import to_utf8, unicode_quote
try:
Modified: bloodhound/vendor/trac/current/trac/tests/perm.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/tests/perm.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/tests/perm.py (original)
+++ bloodhound/vendor/trac/current/trac/tests/perm.py Fri Nov 14 11:06:23 2014
@@ -11,18 +11,20 @@
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://trac.edgewall.org/log/.
+import unittest
+
from trac import perm
from trac.core import *
+from trac.resource import Resource
from trac.test import EnvironmentStub
-import unittest
-
class DefaultPermissionStoreTestCase(unittest.TestCase):
def setUp(self):
- self.env = EnvironmentStub(enable=[perm.DefaultPermissionStore,
- perm.DefaultPermissionGroupProvider])
+ self.env = \
+ EnvironmentStub(enable=[perm.DefaultPermissionStore,
+ perm.DefaultPermissionGroupProvider])
self.store = perm.DefaultPermissionStore(self.env)
def tearDown(self):
@@ -102,6 +104,48 @@ class TestPermissionRequestor(Component)
('TEST_ADMIN', ['TEST_MODIFY'])]
+class PermissionErrorTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.env = EnvironmentStub()
+
+ def test_default_message(self):
+ permission_error = perm.PermissionError()
+ self.assertEqual(None, permission_error.action)
+ self.assertEqual(None, permission_error.resource)
+ self.assertEqual(None, permission_error.env)
+ self.assertEqual("Insufficient privileges to perform this operation.",
+ unicode(permission_error))
+ self.assertEqual("Forbidden", permission_error.title)
+ self.assertEqual(unicode(permission_error), permission_error.msg)
+
+ def test_message_specified(self):
+ message = "The message."
+ permission_error = perm.PermissionError(msg=message)
+ self.assertEqual(message, unicode(permission_error))
+
+ def test_message_from_action(self):
+ action = 'WIKI_VIEW'
+ permission_error = perm.PermissionError(action)
+ self.assertEqual(action, permission_error.action)
+ self.assertEqual(None, permission_error.resource)
+ self.assertEqual(None, permission_error.env)
+ self.assertEqual("WIKI_VIEW privileges are required to perform this "
+ "operation. You don't have the required "
+ "permissions.", unicode(permission_error))
+
+ def test_message_from_action_and_resource(self):
+ action = 'WIKI_VIEW'
+ resource = Resource('wiki', 'WikiStart')
+ permission_error = perm.PermissionError(action, resource, self.env)
+ self.assertEqual(action, permission_error.action)
+ self.assertEqual(resource, permission_error.resource)
+ self.assertEqual(self.env, permission_error.env)
+ self.assertEqual("WIKI_VIEW privileges are required to perform this "
+ "operation on WikiStart. You don't have the "
+ "required permissions.", unicode(permission_error))
+
+
class PermissionSystemTestCase(unittest.TestCase):
def setUp(self):
@@ -184,7 +228,8 @@ class PermissionCacheTestCase(unittest.T
def test_require(self):
self.perm.require('TEST_MODIFY')
self.perm.require('TEST_ADMIN')
- self.assertRaises(perm.PermissionError, self.perm.require, 'TRAC_ADMIN')
+ self.assertRaises(perm.PermissionError,
+ self.perm.require, 'TRAC_ADMIN')
def test_assert_permission(self):
self.perm.assert_permission('TEST_MODIFY')
@@ -231,12 +276,14 @@ class TestPermissionPolicy(Component):
class PermissionPolicyTestCase(unittest.TestCase):
+
def setUp(self):
self.env = EnvironmentStub(enable=[perm.DefaultPermissionStore,
perm.DefaultPermissionPolicy,
TestPermissionPolicy,
TestPermissionRequestor])
- self.env.config.set('trac', 'permission_policies', 'TestPermissionPolicy')
+ self.env.config.set('trac', 'permission_policies',
+ 'TestPermissionPolicy')
self.policy = TestPermissionPolicy(self.env)
self.perm = perm.PermissionCache(self.env, 'testuser')
@@ -261,7 +308,8 @@ class PermissionPolicyTestCase(unittest.
('testuser', 'TEST_ADMIN'): True})
def test_policy_chaining(self):
- self.env.config.set('trac', 'permission_policies', 'TestPermissionPolicy,DefaultPermissionPolicy')
+ self.env.config.set('trac', 'permission_policies',
+ 'TestPermissionPolicy,DefaultPermissionPolicy')
self.policy.grant('testuser', ['TEST_MODIFY'])
system = perm.PermissionSystem(self.env)
system.grant_permission('testuser', 'TEST_ADMIN')
@@ -279,6 +327,7 @@ class PermissionPolicyTestCase(unittest.
def suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(DefaultPermissionStoreTestCase))
+ suite.addTest(unittest.makeSuite(PermissionErrorTestCase))
suite.addTest(unittest.makeSuite(PermissionSystemTestCase))
suite.addTest(unittest.makeSuite(PermissionCacheTestCase))
suite.addTest(unittest.makeSuite(PermissionPolicyTestCase))
Modified: bloodhound/vendor/trac/current/trac/tests/wikisyntax.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/tests/wikisyntax.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/tests/wikisyntax.py (original)
+++ bloodhound/vendor/trac/current/trac/tests/wikisyntax.py Fri Nov 14 11:06:23 2014
@@ -25,6 +25,7 @@ from trac.test import MockPerm
from trac.web.href import Href
from trac.wiki.tests import formatter
+
SEARCH_TEST_CASES = u"""
============================== search: link resolver
search:foo
Modified: bloodhound/vendor/trac/current/trac/ticket/admin.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/ticket/admin.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/ticket/admin.py (original)
+++ bloodhound/vendor/trac/current/trac/ticket/admin.py Fri Nov 14 11:06:23 2014
@@ -395,10 +395,11 @@ class MilestoneAdminPanel(TicketAdminPan
return self.get_milestone_list()
def _do_list(self):
- print_table([(m.name, m.due and
- format_date(m.due, console_date_format),
- m.completed and
- format_datetime(m.completed, console_datetime_format))
+ print_table([(m.name,
+ format_date(m.due, console_date_format)
+ if m.due else None,
+ format_datetime(m.completed, console_datetime_format)
+ if m.completed else None)
for m in model.Milestone.select(self.env)],
[_("Name"), _("Due"), _("Completed")])
@@ -417,15 +418,16 @@ class MilestoneAdminPanel(TicketAdminPan
def _do_due(self, name, due):
milestone = model.Milestone(self.env, name)
- milestone.due = due and parse_date(due, hint='datetime',
- locale=get_console_locale(self.env))
+ milestone.due = parse_date(due, hint='datetime',
+ locale=get_console_locale(self.env)) \
+ if due else None
milestone.update()
def _do_completed(self, name, completed):
milestone = model.Milestone(self.env, name)
- milestone.completed = completed and \
- parse_date(completed, hint='datetime',
- locale=get_console_locale(self.env))
+ milestone.completed = parse_date(completed, hint='datetime',
+ locale=get_console_locale(self.env)) \
+ if completed else None
milestone.update()
def _do_remove(self, name):
@@ -566,17 +568,18 @@ class VersionAdminPanel(TicketAdminPanel
def _do_list(self):
print_table([(v.name,
- v.time and format_date(v.time, console_date_format))
- for v in model.Version.select(self.env)],
+ format_date(v.time, console_date_format)
+ if v.time else None)
+ for v in model.Version.select(self.env)],
[_("Name"), _("Time")])
def _do_add(self, name, time=None):
version = model.Version(self.env)
version.name = name
if time is not None:
- version.time = time and \
- parse_date(time, hint='datetime',
- locale=get_console_locale(self.env))
+ version.time = parse_date(time, hint='datetime',
+ locale=get_console_locale(self.env)) \
+ if time else None
version.insert()
def _do_rename(self, name, newname):
@@ -586,9 +589,9 @@ class VersionAdminPanel(TicketAdminPanel
def _do_time(self, name, time):
version = model.Version(self.env, name)
- version.time = time and \
- parse_date(time, hint='datetime',
- locale=get_console_locale(self.env))
+ version.time = parse_date(time, hint='datetime',
+ locale=get_console_locale(self.env)) \
+ if time else None
version.update()
def _do_remove(self, name):
Modified: bloodhound/vendor/trac/current/trac/ticket/api.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/ticket/api.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/ticket/api.py (original)
+++ bloodhound/vendor/trac/current/trac/ticket/api.py Fri Nov 14 11:06:23 2014
@@ -122,6 +122,15 @@ class ITicketChangeListener(Interface):
def ticket_deleted(ticket):
"""Called when a ticket is deleted."""
+ def ticket_comment_modified(ticket, cdate, author, comment, old_comment):
+ """Called when a ticket comment is modified."""
+
+ def ticket_change_deleted(ticket, cdate, changes):
+ """Called when a ticket change is deleted.
+
+ `changes` is a dictionary of tuple `(oldvalue, newvalue)`
+ containing the ticket change of the fields that have changed."""
+
class ITicketManipulator(Interface):
"""Miscellaneous manipulation of ticket workflow features."""
Modified: bloodhound/vendor/trac/current/trac/ticket/batch.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/ticket/batch.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/ticket/batch.py (original)
+++ bloodhound/vendor/trac/current/trac/ticket/batch.py Fri Nov 14 11:06:23 2014
@@ -29,6 +29,7 @@ from trac.util.translation import _, tag
from trac.web import IRequestHandler
from trac.web.chrome import add_warning, add_script_data
+
class BatchModifyModule(Component):
"""Ticket batch modification module.
Modified: bloodhound/vendor/trac/current/trac/ticket/default_workflow.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/ticket/default_workflow.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/ticket/default_workflow.py (original)
+++ bloodhound/vendor/trac/current/trac/ticket/default_workflow.py Fri Nov 14 11:06:23 2014
@@ -20,6 +20,7 @@ import pkg_resources
from ConfigParser import RawConfigParser
from StringIO import StringIO
+from functools import partial
from genshi.builder import tag
@@ -98,10 +99,12 @@ class ConfigurableTicketWorkflow(Compone
"""Ticket action controller which provides actions according to a
workflow defined in trac.ini.
- The workflow is idefined in the `[ticket-workflow]` section of the
+ The workflow is defined in the `[ticket-workflow]` section of the
[wiki:TracIni#ticket-workflow-section trac.ini] configuration file.
"""
+ implements(IEnvironmentSetupParticipant, ITicketActionController)
+
ticket_workflow_section = ConfigSection('ticket-workflow',
"""The workflow for tickets is controlled by plugins. By default,
there's only a `ConfigurableTicketWorkflow` component in charge.
@@ -129,7 +132,6 @@ class ConfigurableTicketWorkflow(Compone
self.log.warning("Ticket workflow action '%s' doesn't define "
"any transitions", name)
- implements(ITicketActionController, IEnvironmentSetupParticipant)
# IEnvironmentSetupParticipant methods
@@ -226,19 +228,14 @@ Read TracWorkflow for more information (
this_action = self.actions[action]
status = this_action['newstate']
operations = this_action['operations']
- current_owner_or_empty = ticket._old.get('owner', ticket['owner'])
- current_owner = current_owner_or_empty or '(none)'
- if not (Chrome(self.env).show_email_addresses
- or 'EMAIL_VIEW' in req.perm(ticket.resource)):
- format_user = obfuscate_email_address
- else:
- format_user = lambda address: address
- current_owner = format_user(current_owner)
+ current_owner = ticket._old.get('owner', ticket['owner'])
+ format_author = partial(Chrome(self.env).format_author, req)
+ formatted_current_owner = format_author(current_owner or _("(none)"))
control = [] # default to nothing
hints = []
if 'reset_workflow' in operations:
- control.append(tag("from invalid state "))
+ control.append(_("from invalid state"))
hints.append(_("Current state no longer exists"))
if 'del_owner' in operations:
hints.append(_("The ticket will be disowned"))
@@ -256,39 +253,40 @@ Read TracWorkflow for more information (
else:
owners = None
- if owners == None:
+ if owners is None:
owner = req.args.get(id, req.authname)
- control.append(tag_('to %(owner)s',
+ control.append(tag_("to %(owner)s",
owner=tag.input(type='text', id=id,
name=id, value=owner)))
hints.append(_("The owner will be changed from "
"%(current_owner)s to the specified user",
- current_owner=current_owner))
+ current_owner=formatted_current_owner))
elif len(owners) == 1:
owner = tag.input(type='hidden', id=id, name=id,
value=owners[0])
- formatted_owner = format_user(owners[0])
- control.append(tag_('to %(owner)s ',
- owner=tag(formatted_owner, owner)))
+ formatted_new_owner = format_author(owners[0])
+ control.append(tag_("to %(owner)s",
+ owner=tag(formatted_new_owner, owner)))
if ticket['owner'] != owners[0]:
hints.append(_("The owner will be changed from "
"%(current_owner)s to %(selected_owner)s",
- current_owner=current_owner,
- selected_owner=formatted_owner))
+ current_owner=formatted_current_owner,
+ selected_owner=formatted_new_owner))
else:
- control.append(tag_('to %(owner)s', owner=tag.select(
+ control.append(tag_("to %(owner)s", owner=tag.select(
[tag.option(x, value=x,
selected=(x == selected_owner or None))
for x in owners],
id=id, name=id)))
hints.append(_("The owner will be changed from "
"%(current_owner)s to the selected user",
- current_owner=current_owner))
+ current_owner=formatted_current_owner))
elif 'set_owner_to_self' in operations and \
ticket._old.get('owner', ticket['owner']) != req.authname:
hints.append(_("The owner will be changed from %(current_owner)s "
- "to %(authname)s", current_owner=current_owner,
- authname=req.authname))
+ "to %(authname)s",
+ current_owner=formatted_current_owner,
+ authname=format_author(req.authname)))
if 'set_resolution' in operations:
if 'set_resolution' in this_action:
resolutions = [x.strip() for x in
@@ -303,7 +301,7 @@ Read TracWorkflow for more information (
if len(resolutions) == 1:
resolution = tag.input(type='hidden', id=id, name=id,
value=resolutions[0])
- control.append(tag_('as %(resolution)s',
+ control.append(tag_("as %(resolution)s",
resolution=tag(resolutions[0],
resolution)))
hints.append(_("The resolution will be set to %(name)s",
@@ -311,7 +309,7 @@ Read TracWorkflow for more information (
else:
selected_option = req.args.get(id,
TicketSystem(self.env).default_resolution)
- control.append(tag_('as %(resolution)s',
+ control.append(tag_("as %(resolution)s",
resolution=tag.select(
[tag.option(x, value=x,
selected=(x == selected_option or None))
@@ -321,19 +319,20 @@ Read TracWorkflow for more information (
if 'del_resolution' in operations:
hints.append(_("The resolution will be deleted"))
if 'leave_status' in operations:
- control.append(_('as %(status)s ',
+ control.append(_("as %(status)s",
status= ticket._old.get('status',
ticket['status'])))
if len(operations) == 1:
hints.append(_("The owner will remain %(current_owner)s",
- current_owner=current_owner)
- if current_owner_or_empty else
+ current_owner=formatted_current_owner)
+ if current_owner else
_("The ticket will remain with no owner"))
else:
if status != '*':
hints.append(_("Next status will be '%(name)s'", name=status))
- return (this_action['name'], tag(*control), '. '.join(hints) + '.'
- if hints else '')
+ return (this_action['name'],
+ tag((' ' if i else None, c) for i, c in enumerate(control)),
+ '. '.join(hints) + '.' if hints else '')
def get_ticket_changes(self, req, ticket, action):
this_action = self.actions[action]
Modified: bloodhound/vendor/trac/current/trac/ticket/model.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/ticket/model.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/ticket/model.py (original)
+++ bloodhound/vendor/trac/current/trac/ticket/model.py Fri Nov 14 11:06:23 2014
@@ -507,6 +507,12 @@ class Ticket(object):
self._fetch_ticket(self.id)
+ changes = dict((field, (oldvalue, newvalue))
+ for field, oldvalue, newvalue in fields)
+ for listener in TicketSystem(self.env).change_listeners:
+ if hasattr(listener, 'ticket_change_deleted'):
+ listener.ticket_change_deleted(self, cdate, changes)
+
def modify_comment(self, cdate, author, comment, when=None):
"""Modify a ticket comment specified by its date, while keeping a
history of edits.
@@ -531,8 +537,8 @@ class Ticket(object):
# Find the next edit number
fields = db("""SELECT field FROM ticket_change
WHERE ticket=%%s AND time=%%s AND field %s
- """ % db.like(),
- (self.id, ts, db.like_escape('_comment') + '%'))
+ """ % db.prefix_match(),
+ (self.id, ts, db.prefix_match_value('_comment')))
rev = max(int(field[8:]) for field, in fields) + 1 if fields else 0
db("""INSERT INTO ticket_change
(ticket,time,author,field,oldvalue,newvalue)
@@ -546,8 +552,8 @@ class Ticket(object):
for old_author, in db("""
SELECT author FROM ticket_change
WHERE ticket=%%s AND time=%%s AND NOT field %s LIMIT 1
- """ % db.like(),
- (self.id, ts, db.like_escape('_') + '%')):
+ """ % db.prefix_match(),
+ (self.id, ts, db.prefix_match_value('_'))):
db("""INSERT INTO ticket_change
(ticket,time,author,field,oldvalue,newvalue)
VALUES (%s,%s,%s,'comment','',%s)
@@ -563,6 +569,12 @@ class Ticket(object):
self.values['changetime'] = when
+ old_comment = old_comment or ''
+ for listener in TicketSystem(self.env).change_listeners:
+ if hasattr(listener, 'ticket_comment_modified'):
+ listener.ticket_comment_modified(self, cdate, author, comment,
+ old_comment)
+
def get_comment_history(self, cnum=None, cdate=None, db=None):
"""Retrieve the edit history of a comment identified by its number or
date.
@@ -590,8 +602,8 @@ class Ticket(object):
for author0, last_comment in db("""
SELECT author, newvalue FROM ticket_change
WHERE ticket=%%s AND time=%%s AND NOT field %s LIMIT 1
- """ % db.like(),
- (self.id, ts0, db.like_escape('_') + '%')):
+ """ % db.prefix_match(),
+ (self.id, ts0, db.prefix_match_value('_'))):
break
else:
return
@@ -600,8 +612,8 @@ class Ticket(object):
rows = db("""SELECT field, author, oldvalue, newvalue
FROM ticket_change
WHERE ticket=%%s AND time=%%s AND field %s
- """ % db.like(),
- (self.id, ts0, db.like_escape('_comment') + '%'))
+ """ % db.prefix_match(),
+ (self.id, ts0, db.prefix_match_value('_comment')))
rows = sorted((int(field[8:]), author, old, new)
for field, author, old, new in rows)
history = []
@@ -653,8 +665,8 @@ class Ticket(object):
for author, in db("""
SELECT author FROM ticket_change
WHERE ticket=%%s AND time=%%s AND NOT field %s LIMIT 1
- """ % db.like(),
- (self.id, ts, db.like_escape('_') + '%')):
+ """ % db.prefix_match(),
+ (self.id, ts, db.prefix_match_value('_'))):
break
return (ts, author, comment)
@@ -1003,11 +1015,10 @@ class Milestone(object):
def delete(self, retarget_to=None, author=None, db=None):
"""Delete the milestone.
- :param author: the author of the change
-
- :since 1.0.2: the `retarget_to` parameter is deprecated and tickets
- should moved to another milestone by calling `move_tickets` before
- `delete`.
+ :since 1.0.2: the `retarget_to` and `author` parameters are
+ deprecated and will be removed in Trac 1.3.1. Tickets
+ should be moved to another milestone by calling
+ `move_tickets` before `delete`.
:since 1.0: the `db` parameter is no longer needed and will be removed
in version 1.1.1
@@ -1015,6 +1026,7 @@ class Milestone(object):
with self.env.db_transaction as db:
self.env.log.info("Deleting milestone %s", self.name)
db("DELETE FROM milestone WHERE name=%s", (self.name,))
+ Attachment.delete_all(self.env, 'milestone', self.name)
# Don't translate ticket comment (comment:40:ticket:5658)
self.move_tickets(retarget_to, author, "Milestone deleted")
self._old['name'] = None
Modified: bloodhound/vendor/trac/current/trac/ticket/notification.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/ticket/notification.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/ticket/notification.py (original)
+++ bloodhound/vendor/trac/current/trac/ticket/notification.py Fri Nov 14 11:06:23 2014
@@ -26,6 +26,7 @@ from trac.core import *
from trac.config import *
from trac.notification import NotifyEmail
from trac.ticket.api import TicketSystem
+from trac.ticket.model import Ticket
from trac.util.datefmt import to_utimestamp
from trac.util.text import obfuscate_email_address, shorten_line, \
text_width, wrap
@@ -75,65 +76,69 @@ class TicketNotificationSystem(Component
0.12.2)''""")
-def get_ticket_notification_recipients(env, config, tktid, prev_cc):
- """Returns the notifications recipients.
+def get_ticket_notification_recipients(env, config, tktid, prev_cc=None,
+ modtime=None):
+ """Returns notifications recipients.
- :since 1.0.3: the `config` parameter is no longer used.
+ :since 1.0.2: the `config` parameter is no longer used.
+ :since 1.0.2: the `prev_cc` parameter is deprecated.
"""
section = env.config['notification']
- notify_reporter = section.getbool('always_notify_reporter')
- notify_owner = section.getbool('always_notify_owner')
- notify_updater = section.getbool('always_notify_updater')
-
- ccrecipients = prev_cc
- torecipients = []
- with env.db_query as db:
- # Harvest email addresses from the cc, reporter, and owner fields
- for row in db("SELECT cc, reporter, owner FROM ticket WHERE id=%s",
- (tktid,)):
- if row[0]:
- ccrecipients += row[0].replace(',', ' ').split()
- reporter = row[1]
- owner = row[2]
- if notify_reporter:
- torecipients.append(row[1])
- if notify_owner:
- torecipients.append(row[2])
- break
-
- # Harvest email addresses from the author field of ticket_change(s)
- if notify_updater:
- for author, ticket in db("""
- SELECT DISTINCT author, ticket FROM ticket_change
- WHERE ticket=%s
- """, (tktid,)):
- torecipients.append(author)
-
- # Suppress the updater from the recipients
- updater = None
- for updater, in db("""
- SELECT author FROM ticket_change WHERE ticket=%s
- ORDER BY time DESC LIMIT 1
- """, (tktid,)):
- break
- else:
- for updater, in db("SELECT reporter FROM ticket WHERE id=%s",
- (tktid,)):
- break
-
- if not notify_updater:
- filter_out = True
- if notify_reporter and (updater == reporter):
- filter_out = False
- if notify_owner and (updater == owner):
- filter_out = False
- if filter_out:
- torecipients = [r for r in torecipients
- if r and r != updater]
- elif updater:
- torecipients.append(updater)
+ always_notify_reporter = section.getbool('always_notify_reporter')
+ always_notify_owner = section.getbool('always_notify_owner')
+ always_notify_updater = section.getbool('always_notify_updater')
+
+ cc_recipients = set(prev_cc or [])
+ to_recipients = set()
+ tkt = Ticket(env, tktid)
+
+ # CC field is stored as comma-separated string. Parse to list.
+ to_list = lambda cc: cc.replace(',', ' ').split()
+
+ # Backward compatibility
+ if not modtime:
+ modtime = tkt['changetime']
+
+ # Harvest email addresses from the cc, reporter, and owner fields
+ if tkt['cc']:
+ cc_recipients.update(to_list(tkt['cc']))
+ if always_notify_reporter:
+ to_recipients.add(tkt['reporter'])
+ if always_notify_owner:
+ to_recipients.add(tkt['owner'])
+
+ # Harvest email addresses from the author field of ticket_change(s)
+ if always_notify_updater:
+ for author, ticket in env.db_query("""
+ SELECT DISTINCT author, ticket FROM ticket_change
+ WHERE ticket=%s
+ """, (tktid, )):
+ to_recipients.add(author)
+
+ # Harvest previous owner and cc list
+ author = None
+ for changelog in tkt.get_changelog(modtime):
+ author, field, old = changelog[1:4]
+ if field == 'owner' and always_notify_owner:
+ to_recipients.add(old)
+ elif field == 'cc':
+ cc_recipients.update(to_list(old))
+
+ # Suppress the updater from the recipients if necessary
+ updater = author or tkt['reporter']
+ if not always_notify_updater:
+ filter_out = True
+ if always_notify_reporter and updater == tkt['reporter']:
+ filter_out = False
+ if always_notify_owner and updater == tkt['owner']:
+ filter_out = False
+ if filter_out:
+ to_recipients.discard(updater)
+ elif updater:
+ to_recipients.add(updater)
- return (torecipients, ccrecipients, reporter, owner)
+ return list(to_recipients), list(cc_recipients), \
+ tkt['reporter'], tkt['owner']
class TicketNotifyEmail(NotifyEmail):
@@ -148,7 +153,6 @@ class TicketNotifyEmail(NotifyEmail):
def __init__(self, env):
NotifyEmail.__init__(self, env)
- self.prev_cc = []
ambiguous_char_width = env.config.get('notification',
'ambiguous_char_width',
'single')
@@ -226,7 +230,6 @@ class TicketNotifyEmail(NotifyEmail):
self.ambiwidth) + '\n'
if chgcc:
changes_body += chgcc
- self.prev_cc += self.parse_cc(old) if old else []
else:
if field in ['owner', 'reporter']:
old = self.obfuscate_email(old)
@@ -411,9 +414,9 @@ class TicketNotifyEmail(NotifyEmail):
return template.generate(**data).render('text', encoding=None).strip()
def get_recipients(self, tktid):
- (torecipients, ccrecipients, reporter, owner) = \
- get_ticket_notification_recipients(self.env, self.config,
- tktid, self.prev_cc)
+ torecipients, ccrecipients, reporter, owner = \
+ get_ticket_notification_recipients(self.env, self.config, tktid,
+ modtime=self.modtime)
self.reporter = reporter
self.owner = owner
return (torecipients, ccrecipients)
@@ -507,12 +510,11 @@ class BatchTicketNotifyEmail(NotifyEmail
return shorten_line(subj)
def get_recipients(self, tktids):
- alltorecipients = []
- allccrecipients = []
+ alltorecipients = set()
+ allccrecipients = set()
for t in tktids:
- (torecipients, ccrecipients, reporter, owner) = \
- get_ticket_notification_recipients(self.env, self.config,
- t, [])
- alltorecipients.extend(torecipients)
- allccrecipients.extend(ccrecipients)
- return (list(set(alltorecipients)), list(set(allccrecipients)))
+ torecipients, ccrecipients, reporter, owner = \
+ get_ticket_notification_recipients(self.env, self.config, t)
+ alltorecipients.update(torecipients)
+ allccrecipients.update(ccrecipients)
+ return list(alltorecipients), list(allccrecipients)
Modified: bloodhound/vendor/trac/current/trac/ticket/query.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/ticket/query.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/ticket/query.py (original)
+++ bloodhound/vendor/trac/current/trac/ticket/query.py Fri Nov 14 11:06:23 2014
@@ -32,14 +32,14 @@ from trac.db import get_column_names
from trac.mimeview.api import IContentConverter, Mimeview
from trac.resource import Resource
from trac.ticket.api import TicketSystem
-from trac.ticket.model import Milestone, group_milestones, Ticket
+from trac.ticket.model import Milestone, group_milestones
from trac.util import Ranges, as_bool
from trac.util.compat import any
from trac.util.datefmt import format_datetime, from_utimestamp, parse_date, \
to_timestamp, to_utimestamp, utc, user_time
from trac.util.presentation import Paginator
from trac.util.text import empty, shorten_line, quote_query_string
-from trac.util.translation import _, tag_, cleandoc_
+from trac.util.translation import _, tag_, cleandoc_, ngettext
from trac.web import arg_list_to_args, parse_arg_list, IRequestHandler
from trac.web.href import Href
from trac.web.chrome import (INavigationContributor, Chrome,
@@ -1165,7 +1165,7 @@ class QueryModule(Component):
values = []
for col in cols:
value = result[col]
- if col in ('cc', 'reporter'):
+ if col in ('cc', 'owner', 'reporter'):
value = Chrome(self.env).format_emails(
context.child(ticket), value)
elif col in query.time_fields:
@@ -1267,6 +1267,9 @@ class TicketQueryMacro(WikiMacroBase):
The `rows` parameter can be used to specify which field(s) should
be viewed as a row, e.g. `rows=description|summary`
+ The `col` parameter can be used to specify which fields should
+ be viewed as columns. For '''table''' format only.
+
For compatibility with Trac 0.10, if there's a last positional parameter
given to the macro, it will be used to specify the `format`.
Also, using "&" as a field separator still works (except for `order`)
@@ -1327,8 +1330,10 @@ class TicketQueryMacro(WikiMacroBase):
if format == 'count':
cnt = query.count(req)
- return tag.span(cnt, title='%d tickets for which %s' %
- (cnt, query_string), class_='query_count')
+ title = ngettext("%(num)d ticket for which %(query)s",
+ "%(num)d tickets for which %(query)s",
+ cnt, query=query_string)
+ return tag.span(cnt, title=title, class_='query_count')
tickets = query.execute(req)
@@ -1350,14 +1355,21 @@ class TicketQueryMacro(WikiMacroBase):
add_stylesheet(req, 'common/css/roadmap.css')
def query_href(extra_args, group_value = None):
- q = Query.from_string(self.env, query_string)
+ q = query_string + ''.join('&%s=%s' % (kw, v)
+ for kw in extra_args
+ if kw not in ['group', 'status']
+ for v in extra_args[kw])
+ q = Query.from_string(self.env, q)
+ args = {}
if q.group:
- extra_args[q.group] = group_value
- q.group = None
+ args[q.group] = group_value
+ q.group = extra_args.get('group')
+ if 'status' in extra_args:
+ args['status'] = extra_args['status']
for constraint in q.constraints:
- constraint.update(extra_args)
+ constraint.update(args)
if not q.constraints:
- q.constraints.append(extra_args)
+ q.constraints.append(args)
return q.get_href(formatter.context)
chrome = Chrome(self.env)
tickets = apply_ticket_permissions(self.env, req, tickets)
Modified: bloodhound/vendor/trac/current/trac/ticket/report.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/ticket/report.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/ticket/report.py (original)
+++ bloodhound/vendor/trac/current/trac/ticket/report.py Fri Nov 14 11:06:23 2014
@@ -186,17 +186,19 @@ class ReportModule(Component):
if content_type: # i.e. alternate format
return template, data, content_type
+ from trac.ticket.query import QueryModule
+ show_query_link = 'TICKET_VIEW' in req.perm and \
+ self.env.is_component_enabled(QueryModule)
+
if id != -1 or action == 'new':
add_ctxtnav(req, _('Available Reports'), href=req.href.report())
add_link(req, 'up', req.href.report(), _('Available Reports'))
- else:
+ elif show_query_link:
add_ctxtnav(req, _('Available Reports'))
# Kludge: only show link to custom query if the query module
# is actually enabled
- from trac.ticket.query import QueryModule
- if 'TICKET_VIEW' in req.perm and \
- self.env.is_component_enabled(QueryModule):
+ if show_query_link:
add_ctxtnav(req, _('Custom Query'), href=req.href.query())
data['query_href'] = req.href.query()
data['saved_query_href'] = req.session.get('query_href')
@@ -680,6 +682,9 @@ class ReportModule(Component):
try:
cursor.execute(count_sql, args)
except Exception, e:
+ self.log.warn('Exception caught while executing report: %r, '
+ 'args %r%s', count_sql, args,
+ exception_to_unicode(e, traceback=True))
return e, count_sql
num_items = cursor.fetchone()[0]
@@ -689,6 +694,9 @@ class ReportModule(Component):
try:
cursor.execute(colnames_sql, args)
except Exception, e:
+ self.log.warn('Exception caught while executing report: %r, '
+ 'args %r%s', colnames_sql, args,
+ exception_to_unicode(e, traceback=True))
return e, colnames_sql
cols = get_column_names(cursor)
@@ -740,6 +748,9 @@ class ReportModule(Component):
try:
cursor.execute(sql, args)
except Exception, e:
+ self.log.warn('Exception caught while executing report: %r, args '
+ '%r%s',
+ sql, args, exception_to_unicode(e, traceback=True))
if order_by or limit_offset:
add_notice(req, _("Hint: if the report failed due to automatic"
" modification of the ORDER BY clause or the"
@@ -755,14 +766,18 @@ class ReportModule(Component):
return cols, rows, num_items, missing_args, limit_offset
def get_report(self, id):
- for title, description, sql in self.env.db_query("""
- SELECT title, description, query from report WHERE id=%s
- """, (id,)):
- break
+ try:
+ number = int(id)
+ except (ValueError, TypeError):
+ pass
else:
- raise ResourceNotFound(_("Report {%(num)s} does not exist.",
- num=id), _("Invalid Report Number"))
- return title, description, sql
+ for title, description, sql in self.env.db_query("""
+ SELECT title, description, query from report WHERE id=%s
+ """, (number,)):
+ return title, description, sql
+
+ raise ResourceNotFound(_("Report {%(num)s} does not exist.", num=id),
+ _("Invalid Report Number"))
def get_var_args(self, req):
# reuse somehow for #9574 (wiki vars)