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 [3/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/admin/web_ui.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/admin/web_ui.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/admin/web_ui.py (original)
+++ bloodhound/vendor/trac/current/trac/admin/web_ui.py Fri Nov 14 11:06:23 2014
@@ -22,11 +22,6 @@ import pkg_resources
import re
import shutil
-try:
- from babel.core import Locale
-except ImportError:
- Locale = None
-
from genshi import HTML
from genshi.builder import tag
@@ -37,7 +32,7 @@ from trac.perm import PermissionSystem,
from trac.util.datefmt import all_timezones, pytz
from trac.util.text import exception_to_unicode, \
unicode_to_base64, unicode_from_base64
-from trac.util.translation import _, get_available_locales, ngettext
+from trac.util.translation import _, Locale, get_available_locales, ngettext
from trac.web import HTTPNotFound, IRequestHandler
from trac.web.chrome import add_notice, add_stylesheet, \
add_warning, Chrome, INavigationContributor, \
@@ -71,8 +66,8 @@ class AdminModule(Component):
# admin panel is available
panels, providers = self._get_panels(req)
if panels:
- yield 'mainnav', 'admin', tag.a(_('Admin'), href=req.href.admin(),
- title=_('Administration'))
+ yield 'mainnav', 'admin', tag.a(_("Admin"), href=req.href.admin(),
+ title=_("Administration"))
# IRequestHandler methods
@@ -88,7 +83,7 @@ class AdminModule(Component):
def process_request(self, req):
panels, providers = self._get_panels(req)
if not panels:
- raise HTTPNotFound(_('No administration panels available'))
+ raise HTTPNotFound(_("No administration panels available"))
def _panel_order(p1, p2):
if p1[::2] == ('general', 'basics'):
@@ -114,11 +109,11 @@ class AdminModule(Component):
panel_id = \
filter(lambda panel: panel[0] == cat_id, panels)[0][2]
except IndexError:
- raise HTTPNotFound(_('Unknown administration panel'))
+ raise HTTPNotFound(_("Unknown administration panel"))
provider = providers.get((cat_id, panel_id), None)
if not provider:
- raise HTTPNotFound(_('Unknown administration panel'))
+ raise HTTPNotFound(_("Unknown administration panel"))
if hasattr(provider, 'render_admin_panel'):
template, data = provider.render_admin_panel(req, cat_id, panel_id,
@@ -189,14 +184,14 @@ def _save_config(config, req, log, notic
try:
config.save()
if notices is None:
- notices = [_('Your changes have been saved.')]
+ notices = [_("Your changes have been saved.")]
for notice in notices:
add_notice(req, notice)
except Exception, e:
- log.error('Error writing to trac.ini: %s', exception_to_unicode(e))
- add_warning(req, _('Error writing to trac.ini, make sure it is '
- 'writable by the web server. Your changes have '
- 'not been saved.'))
+ log.error("Error writing to trac.ini: %s", exception_to_unicode(e))
+ add_warning(req, _("Error writing to trac.ini, make sure it is "
+ "writable by the web server. Your changes have "
+ "not been saved."))
class BasicsAdminPanel(Component):
@@ -207,7 +202,7 @@ class BasicsAdminPanel(Component):
def get_admin_panels(self, req):
if 'TRAC_ADMIN' in req.perm('admin', 'general/basics'):
- yield ('general', _('General'), 'basics', _('Basic Settings'))
+ yield ('general', _("General"), 'basics', _("Basic Settings"))
def render_admin_panel(self, req, cat, page, path_info):
if Locale:
@@ -267,7 +262,7 @@ class LoggingAdminPanel(Component):
def get_admin_panels(self, req):
if 'TRAC_ADMIN' in req.perm('admin', 'general/logging'):
- yield ('general', _('General'), 'logging', _('Logging'))
+ yield ('general', _("General"), 'logging', _("Logging"))
def render_admin_panel(self, req, cat, page, path_info):
log_type = self.env.log_type
@@ -276,16 +271,18 @@ class LoggingAdminPanel(Component):
log_dir = os.path.join(self.env.path, 'log')
log_types = [
- dict(name='none', label=_('None'), selected=log_type == 'none', disabled=False),
- dict(name='stderr', label=_('Console'),
+ dict(name='none', label=_("None"),
+ selected=log_type == 'none', disabled=False),
+ dict(name='stderr', label=_("Console"),
selected=log_type == 'stderr', disabled=False),
- dict(name='file', label=_('File'), selected=log_type == 'file',
- disabled=False),
- dict(name='syslog', label=_('Syslog'), disabled=os.name != 'posix',
- selected=log_type in ('unix', 'syslog')),
- dict(name='eventlog', label=_('Windows event log'),
- disabled=os.name != 'nt',
- selected=log_type in ('winlog', 'eventlog', 'nteventlog')),
+ dict(name='file', label=_("File"),
+ selected=log_type == 'file', disabled=False),
+ dict(name='syslog', label=_("Syslog"),
+ selected=log_type in ('unix', 'syslog'),
+ disabled=os.name != 'posix'),
+ dict(name='eventlog', label=_("Windows event log"),
+ selected=log_type in ('winlog', 'eventlog', 'nteventlog'),
+ disabled=os.name != 'nt'),
]
log_levels = ['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG']
@@ -296,8 +293,8 @@ class LoggingAdminPanel(Component):
new_type = req.args.get('log_type')
if new_type not in [t['name'] for t in log_types]:
raise TracError(
- _('Unknown log type %(type)s', type=new_type),
- _('Invalid log type')
+ _("Unknown log type %(type)s", type=new_type),
+ _("Invalid log type")
)
if new_type != log_type:
self.config.set('logging', 'log_type', new_type)
@@ -311,8 +308,8 @@ class LoggingAdminPanel(Component):
new_level = req.args.get('log_level')
if new_level not in log_levels:
raise TracError(
- _('Unknown log level %(level)s', level=new_level),
- _('Invalid log level'))
+ _("Unknown log level %(level)s", level=new_level),
+ _("Invalid log level"))
if new_level != log_level:
self.config.set('logging', 'log_level', new_level)
changed = True
@@ -325,8 +322,8 @@ class LoggingAdminPanel(Component):
changed = True
log_file = new_file
if not log_file:
- raise TracError(_('You must specify a log file'),
- _('Missing field'))
+ raise TracError(_("You must specify a log file"),
+ _("Missing field"))
else:
self.config.remove('logging', 'log_file')
changed = True
@@ -356,7 +353,7 @@ class PermissionAdminPanel(Component):
def get_admin_panels(self, req):
perm = req.perm('admin', 'general/perm')
if 'PERMISSION_GRANT' in perm or 'PERMISSION_REVOKE' in perm:
- yield ('general', _('General'), 'perm', _('Permissions'))
+ yield ('general', _("General"), 'perm', _("Permissions"))
def render_admin_panel(self, req, cat, page, path_info):
perm = PermissionSystem(self.env)
@@ -370,24 +367,24 @@ class PermissionAdminPanel(Component):
if subject and subject.isupper() or \
group and group.isupper():
- raise TracError(_('All upper-cased tokens are reserved for '
- 'permission names'))
+ raise TracError(_("All upper-cased tokens are reserved for "
+ "permission names"))
# Grant permission to subject
if req.args.get('add') and subject and action:
req.perm('admin', 'general/perm').require('PERMISSION_GRANT')
if action not in all_actions:
- raise TracError(_('Unknown action'))
+ raise TracError(_("Unknown action"))
req.perm.require(action)
if (subject, action) not in all_permissions:
perm.grant_permission(subject, action)
- add_notice(req, _('The subject %(subject)s has been '
- 'granted the permission %(action)s.',
+ add_notice(req, _("The subject %(subject)s has been "
+ "granted the permission %(action)s.",
subject=subject, action=action))
req.redirect(req.href.admin(cat, page))
else:
- add_warning(req, _('The permission %(action)s was already '
- 'granted to %(subject)s.',
+ add_warning(req, _("The permission %(action)s was already "
+ "granted to %(subject)s.",
action=action, subject=subject))
# Add subject to group
@@ -396,19 +393,25 @@ class PermissionAdminPanel(Component):
for action in perm.get_user_permissions(group):
if not action in all_actions: # plugin disabled?
self.env.log.warn("Adding %s to group %s: "
- "Permission %s unavailable, skipping perm check."
- % (subject, group, action))
+ "Permission %s unavailable, skipping perm check.",
+ subject, group, action)
else:
- req.perm.require(action)
+ req.perm.require(action,
+ message=_("The subject %(subject)s was not added "
+ "to the group %(group)s because the "
+ "group has %(perm)s permission and "
+ "users cannot grant permissions they "
+ "don't possess.", subject=subject,
+ group=group, perm=action))
if (subject, group) not in all_permissions:
perm.grant_permission(subject, group)
- add_notice(req, _('The subject %(subject)s has been added '
- 'to the group %(group)s.',
+ add_notice(req, _("The subject %(subject)s has been added "
+ "to the group %(group)s.",
subject=subject, group=group))
req.redirect(req.href.admin(cat, page))
else:
- add_warning(req, _('The subject %(subject)s was already '
- 'added to the group %(group)s.',
+ add_warning(req, _("The subject %(subject)s was already "
+ "added to the group %(group)s.",
subject=subject, group=group))
# Remove permissions action
@@ -422,8 +425,8 @@ class PermissionAdminPanel(Component):
action = unicode_from_base64(action)
if (subject, action) in perm.get_all_permissions():
perm.revoke_permission(subject, action)
- add_notice(req, _('The selected permissions have been '
- 'revoked.'))
+ add_notice(req, _("The selected permissions have been "
+ "revoked."))
req.redirect(req.href.admin(cat, page))
perms = [perm for perm in all_permissions if perm[1].isupper()]
@@ -443,7 +446,7 @@ class PluginAdminPanel(Component):
def get_admin_panels(self, req):
if 'TRAC_ADMIN' in req.perm('admin', 'general/plugin'):
- yield ('general', _('General'), 'plugin', _('Plugins'))
+ yield ('general', _("General"), 'plugin', _("Plugins"))
def render_admin_panel(self, req, cat, page, path_info):
if req.method == 'POST':
@@ -465,25 +468,25 @@ class PluginAdminPanel(Component):
def _do_install(self, req):
"""Install a plugin."""
if 'plugin_file' not in req.args:
- raise TracError(_('No file uploaded'))
+ raise TracError(_("No file uploaded"))
upload = req.args['plugin_file']
if isinstance(upload, unicode) or not upload.filename:
- raise TracError(_('No file uploaded'))
+ raise TracError(_("No file uploaded"))
plugin_filename = upload.filename.replace('\\', '/').replace(':', '/')
plugin_filename = os.path.basename(plugin_filename)
if not plugin_filename:
- raise TracError(_('No file uploaded'))
+ raise TracError(_("No file uploaded"))
if not plugin_filename.endswith('.egg') and \
not plugin_filename.endswith('.py'):
- raise TracError(_('Uploaded file is not a Python source file or '
- 'egg'))
+ raise TracError(_("Uploaded file is not a Python source file or "
+ "egg"))
target_path = os.path.join(self.env.path, 'plugins', plugin_filename)
if os.path.isfile(target_path):
- raise TracError(_('Plugin %(name)s already installed',
+ raise TracError(_("Plugin %(name)s already installed",
name=plugin_filename))
- self.log.info('Installing plugin %s', plugin_filename)
+ self.log.info("Installing plugin %s", plugin_filename)
flags = os.O_CREAT + os.O_WRONLY + os.O_EXCL
try:
flags += os.O_BINARY
@@ -492,7 +495,7 @@ class PluginAdminPanel(Component):
pass
with os.fdopen(os.open(target_path, flags, 0666), 'w') as target_file:
shutil.copyfileobj(upload.file, target_file)
- self.log.info('Plugin %s installed to %s', plugin_filename,
+ self.log.info("Plugin %s installed to %s", plugin_filename,
target_path)
# TODO: Validate that the uploaded file is actually a valid Trac plugin
@@ -507,7 +510,7 @@ class PluginAdminPanel(Component):
plugin_path = os.path.join(self.env.path, 'plugins', plugin_filename)
if not os.path.isfile(plugin_path):
return
- self.log.info('Uninstalling plugin %s', plugin_filename)
+ self.log.info("Uninstalling plugin %s", plugin_filename)
os.remove(plugin_path)
# Make the environment reset itself on the next request
@@ -528,8 +531,8 @@ class PluginAdminPanel(Component):
if is_enabled != must_enable:
self.config.set('components', component,
'disabled' if is_enabled else 'enabled')
- self.log.info('%sabling component %s',
- 'Dis' if is_enabled else 'En', component)
+ self.log.info("%sabling component %s",
+ "Dis" if is_enabled else "En", component)
if must_enable:
added.append(component)
else:
@@ -547,13 +550,13 @@ class PluginAdminPanel(Component):
removed.sort()
notices = []
if removed:
- msg = ngettext('The following component has been disabled:',
- 'The following components have been disabled:',
+ msg = ngettext("The following component has been disabled:",
+ "The following components have been disabled:",
len(removed))
notices.append(tag(msg, make_list(removed)))
if added:
- msg = ngettext('The following component has been enabled:',
- 'The following components have been enabled:',
+ msg = ngettext("The following component has been enabled:",
+ "The following components have been enabled:",
len(added))
notices.append(tag(msg, make_list(added)))
@@ -566,7 +569,7 @@ class PluginAdminPanel(Component):
try:
return format_to_html(self.env, context, text)
except Exception, e:
- self.log.error('Unable to render component documentation: %s',
+ self.log.error("Unable to render component documentation: %s",
exception_to_unicode(e, traceback=True))
return tag.pre(text)
Modified: bloodhound/vendor/trac/current/trac/cache.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/cache.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/cache.py (original)
+++ bloodhound/vendor/trac/current/trac/cache.py Fri Nov 14 11:06:23 2014
@@ -13,6 +13,8 @@
from __future__ import with_statement
+import functools
+
from .core import Component
from .util import arity
from .util.concurrency import ThreadLocal, threading
@@ -34,12 +36,15 @@ def key_to_id(s):
return result
-class CachedPropertyBase(object):
- """Base class for cached property descriptors"""
+class CachedPropertyBase(property):
+ """Base class for cached property descriptors.
+
+ :since 1.0.2: inherits from `property`.
+ """
def __init__(self, retriever):
self.retriever = retriever
- self.__doc__ = retriever.__doc__
+ functools.update_wrapper(self, retriever)
def make_key(self, cls):
attr = self.retriever.__name__
Modified: bloodhound/vendor/trac/current/trac/db/api.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/api.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/db/api.py (original)
+++ bloodhound/vendor/trac/current/trac/db/api.py Fri Nov 14 11:06:23 2014
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
-# Copyright (C)2005-2009 Edgewall Software
+# Copyright (C)2005-2014 Edgewall Software
# Copyright (C) 2005 Christopher Lenz <cm...@gmx.de>
# All rights reserved.
#
@@ -22,6 +22,7 @@ import urllib
from trac.config import BoolOption, IntOption, Option
from trac.core import *
+from trac.db.schema import Table
from trac.util.concurrency import ThreadLocal
from trac.util.text import unicode_passwd
from trac.util.translation import _
@@ -61,9 +62,9 @@ def with_transaction(env, db=None):
:deprecated: This decorator is in turn deprecated in favor of
context managers now that python 2.4 support has been
- dropped. Use instead the new context manager,
- `QueryContextManager` and
- `TransactionContextManager`, which makes for much
+ dropped. It will be removed in Trac 1.3.1. Use instead
+ the new context managers, `QueryContextManager` and
+ `TransactionContextManager`, which make for much
simpler to write code:
>>> def api_method(p1, p2):
@@ -250,6 +251,31 @@ class DatabaseManager(Component):
args['schema'] = schema
connector.init_db(**args)
+ def create_tables(self, schema):
+ """Create the specified tables.
+
+ :param schema: an iterable of table objects.
+
+ :since: version 1.0.2
+ """
+ connector = self.get_connector()[0]
+ with self.env.db_transaction as db:
+ for table in schema:
+ for sql in connector.to_sql(table):
+ db(sql)
+
+ def drop_tables(self, schema):
+ """Drop the specified tables.
+
+ :param schema: an iterable of `Table` objects or table names.
+
+ :since: version 1.0.2
+ """
+ with self.env.db_transaction as db:
+ for table in schema:
+ table_name = table.name if isinstance(table, Table) else table
+ db.drop_table(table_name)
+
def get_connection(self, readonly=False):
"""Get a database connection from the pool.
@@ -287,7 +313,7 @@ class DatabaseManager(Component):
backup_dir = os.path.join(self.env.path, backup_dir)
db_str = self.config.get('trac', 'database')
db_name, db_path = db_str.split(":", 1)
- dest_name = '%s.%i.%d.bak' % (db_name, self.env.get_version(),
+ dest_name = '%s.%i.%d.bak' % (db_name, self.env.database_version,
int(time.time()))
dest = os.path.join(backup_dir, dest_name)
else:
Modified: bloodhound/vendor/trac/current/trac/db/mysql_backend.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/mysql_backend.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/db/mysql_backend.py (original)
+++ bloodhound/vendor/trac/current/trac/db/mysql_backend.py Fri Nov 14 11:06:23 2014
@@ -361,6 +361,7 @@ class MySQLConnection(ConnectionWrapper)
name)
cnx = MySQLdb.connect(db=path, user=user, passwd=password, host=host,
port=port, charset='utf8', **opts)
+ self.schema = path
if hasattr(cnx, 'encoders'):
# 'encoders' undocumented but present since 1.2.1 (r422)
cnx.encoders[Markup] = cnx.encoders[types.UnicodeType]
@@ -374,6 +375,24 @@ class MySQLConnection(ConnectionWrapper)
ConnectionWrapper.__init__(self, cnx, log)
self._is_closed = False
+ def cursor(self):
+ return IterableCursor(MySQLUnicodeCursor(self.cnx), self.log)
+
+ def rollback(self):
+ self.cnx.ping()
+ try:
+ self.cnx.rollback()
+ except MySQLdb.ProgrammingError:
+ self._is_closed = True
+
+ def close(self):
+ if not self._is_closed:
+ try:
+ self.cnx.close()
+ except MySQLdb.ProgrammingError:
+ pass # this error would mean it's already closed. So, ignore
+ self._is_closed = True
+
def cast(self, column, type):
if type == 'int' or type == 'int64':
type = 'signed'
@@ -384,6 +403,27 @@ class MySQLConnection(ConnectionWrapper)
def concat(self, *args):
return 'concat(%s)' % ', '.join(args)
+ def drop_table(self, table):
+ cursor = MySQLdb.cursors.Cursor(self.cnx)
+ cursor._defer_warnings = True # ignore "Warning: Unknown table ..."
+ cursor.execute("DROP TABLE IF EXISTS " + self.quote(table))
+
+ def get_column_names(self, table):
+ rows = self.execute("""
+ SELECT column_name FROM information_schema.columns
+ WHERE table_schema=%s AND table_name=%s
+ """, (self.schema, table))
+ return [row[0] for row in rows]
+
+ def get_last_id(self, cursor, table, column='id'):
+ return cursor.lastrowid
+
+ def get_table_names(self):
+ rows = self.execute("""
+ SELECT table_name FROM information_schema.tables
+ WHERE table_schema=%s""", (self.schema,))
+ return [row[0] for row in rows]
+
def like(self):
"""Return a case-insensitive LIKE clause."""
return "LIKE %%s COLLATE %s_general_ci ESCAPE '/'" % self.charset
@@ -391,31 +431,18 @@ class MySQLConnection(ConnectionWrapper)
def like_escape(self, text):
return _like_escape_re.sub(r'/\1', text)
+ def prefix_match(self):
+ """Return a case sensitive prefix-matching operator."""
+ return "LIKE %s ESCAPE '/'"
+
+ def prefix_match_value(self, prefix):
+ """Return a value for case sensitive prefix-matching operator."""
+ return self.like_escape(prefix) + '%'
+
def quote(self, identifier):
"""Return the quoted identifier."""
return "`%s`" % identifier.replace('`', '``')
- def get_last_id(self, cursor, table, column='id'):
- return cursor.lastrowid
-
def update_sequence(self, cursor, table, column='id'):
# MySQL handles sequence updates automagically
pass
-
- def rollback(self):
- self.cnx.ping()
- try:
- self.cnx.rollback()
- except MySQLdb.ProgrammingError:
- self._is_closed = True
-
- def close(self):
- if not self._is_closed:
- try:
- self.cnx.close()
- except MySQLdb.ProgrammingError:
- pass # this error would mean it's already closed. So, ignore
- self._is_closed = True
-
- def cursor(self):
- return IterableCursor(MySQLUnicodeCursor(self.cnx), self.log)
Modified: bloodhound/vendor/trac/current/trac/db/postgres_backend.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/postgres_backend.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/db/postgres_backend.py (original)
+++ bloodhound/vendor/trac/current/trac/db/postgres_backend.py Fri Nov 14 11:06:23 2014
@@ -22,7 +22,7 @@ from trac.core import *
from trac.config import Option
from trac.db.api import IDatabaseConnector, _parse_db_str
from trac.db.util import ConnectionWrapper, IterableCursor
-from trac.util import get_pkginfo
+from trac.util import get_pkginfo, lazy
from trac.util.compat import close_fds
from trac.util.text import empty, exception_to_unicode, to_unicode
from trac.util.translation import _
@@ -231,6 +231,9 @@ class PostgreSQLConnection(ConnectionWra
cnx.rollback()
ConnectionWrapper.__init__(self, cnx, log)
+ def cursor(self):
+ return IterableCursor(self.cnx.cursor(), self.log)
+
def cast(self, column, type):
# Temporary hack needed for the union of selects in the search module
return 'CAST(%s AS %s)' % (column, _type_map.get(type, type))
@@ -238,6 +241,37 @@ class PostgreSQLConnection(ConnectionWra
def concat(self, *args):
return '||'.join(args)
+ def drop_table(self, table):
+ if (self._version or '').startswith(('8.0.', '8.1.')):
+ cursor = self.cursor()
+ cursor.execute("""SELECT table_name FROM information_schema.tables
+ WHERE table_schema=current_schema()
+ AND table_name=%s""", (table,))
+ for row in cursor:
+ if row[0] == table:
+ self.execute("DROP TABLE " + self.quote(table))
+ break
+ else:
+ self.execute("DROP TABLE IF EXISTS " + self.quote(table))
+
+ def get_column_names(self, table):
+ rows = self.execute("""
+ SELECT column_name FROM information_schema.columns
+ WHERE table_schema=%s AND table_name=%s
+ """, (self.schema, table))
+ return [row[0] for row in rows]
+
+ def get_last_id(self, cursor, table, column='id'):
+ cursor.execute("SELECT CURRVAL(%s)",
+ (self.quote(self._sequence_name(table, column)),))
+ return cursor.fetchone()[0]
+
+ def get_table_names(self):
+ rows = self.execute("""
+ SELECT table_name FROM information_schema.tables
+ WHERE table_schema=%s""", (self.schema,))
+ return [row[0] for row in rows]
+
def like(self):
"""Return a case-insensitive LIKE clause."""
return "ILIKE %s ESCAPE '/'"
@@ -245,18 +279,31 @@ class PostgreSQLConnection(ConnectionWra
def like_escape(self, text):
return _like_escape_re.sub(r'/\1', text)
+ def prefix_match(self):
+ """Return a case sensitive prefix-matching operator."""
+ return "LIKE %s ESCAPE '/'"
+
+ def prefix_match_value(self, prefix):
+ """Return a value for case sensitive prefix-matching operator."""
+ return self.like_escape(prefix) + '%'
+
def quote(self, identifier):
"""Return the quoted identifier."""
return '"%s"' % identifier.replace('"', '""')
- def get_last_id(self, cursor, table, column='id'):
- cursor.execute("""SELECT CURRVAL('"%s_%s_seq"')""" % (table, column))
- return cursor.fetchone()[0]
-
def update_sequence(self, cursor, table, column='id'):
- cursor.execute("""
- SELECT setval('"%s_%s_seq"', (SELECT MAX(id) FROM %s))
- """ % (table, column, table))
-
- def cursor(self):
- return IterableCursor(self.cnx.cursor(), self.log)
+ cursor.execute("SELECT SETVAL(%%s, (SELECT MAX(%s) FROM %s))"
+ % (self.quote(column), self.quote(table)),
+ (self.quote(self._sequence_name(table, column)),))
+
+ def _sequence_name(self, table, column):
+ return '%s_%s_seq' % (table, column)
+
+ @lazy
+ def _version(self):
+ cursor = self.cursor()
+ cursor.execute('SELECT version()')
+ for version, in cursor:
+ # retrieve "8.1.23" from "PostgreSQL 8.1.23 on ...."
+ if version.startswith('PostgreSQL '):
+ return version.split(' ', 2)[1]
Modified: bloodhound/vendor/trac/current/trac/db/sqlite_backend.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/sqlite_backend.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/db/sqlite_backend.py (original)
+++ bloodhound/vendor/trac/current/trac/db/sqlite_backend.py Fri Nov 14 11:06:23 2014
@@ -27,6 +27,8 @@ from trac.util.translation import _
_like_escape_re = re.compile(r'([/_%])')
+_glob_escape_re = re.compile(r'[*?\[]')
+
try:
import pysqlite2.dbapi2 as sqlite
have_pysqlite = 2
@@ -313,6 +315,24 @@ class SQLiteConnection(ConnectionWrapper
def concat(self, *args):
return '||'.join(args)
+ def drop_table(self, table):
+ cursor = self.cursor()
+ cursor.execute("DROP TABLE IF EXISTS " + self.quote(table))
+
+ def get_column_names(self, table):
+ cursor = self.cnx.cursor()
+ rows = cursor.execute("PRAGMA table_info(%s)"
+ % self.quote(table))
+ return [row[1] for row in rows]
+
+ def get_last_id(self, cursor, table, column='id'):
+ return cursor.lastrowid
+
+ def get_table_names(self):
+ rows = self.execute("""
+ SELECT name FROM sqlite_master WHERE type='table'""")
+ return [row[0] for row in rows]
+
def like(self):
"""Return a case-insensitive LIKE clause."""
if sqlite_version >= (3, 1, 0):
@@ -326,13 +346,18 @@ class SQLiteConnection(ConnectionWrapper
else:
return text
+ def prefix_match(self):
+ """Return a case sensitive prefix-matching operator."""
+ return 'GLOB %s'
+
+ def prefix_match_value(self, prefix):
+ """Return a value for case sensitive prefix-matching operator."""
+ return _glob_escape_re.sub(lambda m: '[%s]' % m.group(0), prefix) + '*'
+
def quote(self, identifier):
"""Return the quoted identifier."""
return "`%s`" % identifier.replace('`', '``')
- def get_last_id(self, cursor, table, column='id'):
- return cursor.lastrowid
-
def update_sequence(self, cursor, table, column='id'):
# SQLite handles sequence updates automagically
# http://www.sqlite.org/autoinc.html
Modified: bloodhound/vendor/trac/current/trac/db/tests/__init__.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/tests/__init__.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/db/tests/__init__.py (original)
+++ bloodhound/vendor/trac/current/trac/db/tests/__init__.py Fri Nov 14 11:06:23 2014
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
-# Copyright (C) 2005-2013 Edgewall Software
+# Copyright (C) 2005-2014 Edgewall Software
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
@@ -14,11 +14,10 @@
import unittest
from trac.db.tests import api, mysql_test, postgres_test, util
-
from trac.db.tests.functional import functionalSuite
-def suite():
+def suite():
suite = unittest.TestSuite()
suite.addTest(api.suite())
suite.addTest(mysql_test.suite())
Modified: bloodhound/vendor/trac/current/trac/db/tests/api.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/tests/api.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/db/tests/api.py (original)
+++ bloodhound/vendor/trac/current/trac/db/tests/api.py Fri Nov 14 11:06:23 2014
@@ -16,8 +16,11 @@ from __future__ import with_statement
import os
import unittest
+import trac.tests.compat
from trac.db.api import DatabaseManager, _parse_db_str, get_column_names, \
with_transaction
+from trac.db_default import schema as default_schema
+from trac.db.schema import Column, Table
from trac.test import EnvironmentStub, Mock
from trac.util.concurrency import ThreadLocal
@@ -287,6 +290,9 @@ class StringsTestCase(unittest.TestCase)
def setUp(self):
self.env = EnvironmentStub()
+ def tearDown(self):
+ self.env.reset_db()
+
def test_insert_unicode(self):
self.env.db_transaction(
"INSERT INTO system (name,value) VALUES (%s,%s)",
@@ -318,41 +324,172 @@ class StringsTestCase(unittest.TestCase)
self.assertEqual(r'alpha\`\"\'\\beta``gamma""delta',
get_column_names(cursor)[0])
+ def test_quoted_id_with_percent(self):
+ db = self.env.get_read_db()
+ name = """%?`%s"%'%%"""
+
+ def test(db, logging=False):
+ cursor = db.cursor()
+ if logging:
+ cursor.log = self.env.log
+
+ cursor.execute('SELECT 1 AS ' + db.quote(name))
+ self.assertEqual(name, get_column_names(cursor)[0])
+ cursor.execute('SELECT %s AS ' + db.quote(name), (42,))
+ self.assertEqual(name, get_column_names(cursor)[0])
+ cursor.executemany("UPDATE system SET value=%s WHERE "
+ "1=(SELECT 0 AS " + db.quote(name) + ")",
+ [])
+ cursor.executemany("UPDATE system SET value=%s WHERE "
+ "1=(SELECT 0 AS " + db.quote(name) + ")",
+ [('42',), ('43',)])
+
+ test(db)
+ test(db, logging=True)
+
+ def test_prefix_match_case_sensitive(self):
+ @self.env.with_transaction()
+ def do_insert(db):
+ cursor = db.cursor()
+ cursor.executemany("INSERT INTO system (name,value) VALUES (%s,1)",
+ [('blahblah',), ('BlahBlah',), ('BLAHBLAH',),
+ (u'BlähBlah',), (u'BlahBläh',)])
+
+ db = self.env.get_read_db()
+ cursor = db.cursor()
+ cursor.execute("SELECT name FROM system WHERE name %s" %
+ db.prefix_match(),
+ (db.prefix_match_value('Blah'),))
+ names = sorted(name for name, in cursor)
+ self.assertEqual('BlahBlah', names[0])
+ self.assertEqual(u'BlahBläh', names[1])
+ self.assertEqual(2, len(names))
+
+ def test_prefix_match_metachars(self):
+ def do_query(prefix):
+ db = self.env.get_read_db()
+ cursor = db.cursor()
+ cursor.execute("SELECT name FROM system WHERE name %s "
+ "ORDER BY name" % db.prefix_match(),
+ (db.prefix_match_value(prefix),))
+ return [name for name, in cursor]
+
+ @self.env.with_transaction()
+ def do_insert(db):
+ values = ['foo*bar', 'foo*bar!', 'foo?bar', 'foo?bar!',
+ 'foo[bar', 'foo[bar!', 'foo]bar', 'foo]bar!',
+ 'foo%bar', 'foo%bar!', 'foo_bar', 'foo_bar!',
+ 'foo/bar', 'foo/bar!', 'fo*ob?ar[fo]ob%ar_fo/obar']
+ cursor = db.cursor()
+ cursor.executemany("INSERT INTO system (name,value) VALUES (%s,1)",
+ [(value,) for value in values])
+
+ self.assertEqual(['foo*bar', 'foo*bar!'], do_query('foo*'))
+ self.assertEqual(['foo?bar', 'foo?bar!'], do_query('foo?'))
+ self.assertEqual(['foo[bar', 'foo[bar!'], do_query('foo['))
+ self.assertEqual(['foo]bar', 'foo]bar!'], do_query('foo]'))
+ self.assertEqual(['foo%bar', 'foo%bar!'], do_query('foo%'))
+ self.assertEqual(['foo_bar', 'foo_bar!'], do_query('foo_'))
+ self.assertEqual(['foo/bar', 'foo/bar!'], do_query('foo/'))
+ self.assertEqual(['fo*ob?ar[fo]ob%ar_fo/obar'], do_query('fo*'))
+ self.assertEqual(['fo*ob?ar[fo]ob%ar_fo/obar'],
+ do_query('fo*ob?ar[fo]ob%ar_fo/obar'))
+
class ConnectionTestCase(unittest.TestCase):
def setUp(self):
self.env = EnvironmentStub()
+ self.schema = [
+ Table('HOURS', key='ID')[
+ Column('ID', auto_increment=True),
+ Column('AUTHOR')],
+ Table('blog', key='bid')[
+ Column('bid', auto_increment=True),
+ Column('author')
+ ]
+ ]
+ self.env.global_databasemanager.drop_tables(self.schema)
+ self.env.global_databasemanager.create_tables(self.schema)
def tearDown(self):
+ self.env.global_databasemanager.drop_tables(self.schema)
self.env.reset_db()
def test_get_last_id(self):
- id1 = id2 = None
q = "INSERT INTO report (author) VALUES ('anonymous')"
with self.env.db_transaction as db:
cursor = db.cursor()
cursor.execute(q)
# Row ID correct before...
id1 = db.get_last_id(cursor, 'report')
- self.assertNotEqual(0, id1)
db.commit()
cursor.execute(q)
# ... and after commit()
db.commit()
id2 = db.get_last_id(cursor, 'report')
- self.assertEqual(id1 + 1, id2)
- def test_update_sequence(self):
- self.env.db_transaction(
- "INSERT INTO report (id, author) VALUES (42, 'anonymous')")
+ self.assertNotEqual(0, id1)
+ self.assertEqual(id1 + 1, id2)
+
+ def test_update_sequence_default_column(self):
with self.env.db_transaction as db:
+ db("INSERT INTO report (id, author) VALUES (42, 'anonymous')")
cursor = db.cursor()
db.update_sequence(cursor, 'report', 'id')
+
self.env.db_transaction(
"INSERT INTO report (author) VALUES ('next-id')")
+
self.assertEqual(43, self.env.db_query(
"SELECT id FROM report WHERE author='next-id'")[0][0])
+ def test_update_sequence_nondefault_column(self):
+ with self.env.db_transaction as db:
+ cursor = db.cursor()
+ cursor.execute(
+ "INSERT INTO blog (bid, author) VALUES (42, 'anonymous')")
+ db.update_sequence(cursor, 'blog', 'bid')
+
+ self.env.db_transaction(
+ "INSERT INTO blog (author) VALUES ('next-id')")
+
+ self.assertEqual(43, self.env.db_query(
+ "SELECT bid FROM blog WHERE author='next-id'")[0][0])
+
+ def test_identifiers_need_quoting(self):
+ """Test for regression described in comment:4:ticket:11512."""
+ with self.env.db_transaction as db:
+ db("INSERT INTO %s (%s, %s) VALUES (42, 'anonymous')"
+ % (db.quote('HOURS'), db.quote('ID'), db.quote('AUTHOR')))
+ cursor = db.cursor()
+ db.update_sequence(cursor, 'HOURS', 'ID')
+
+ with self.env.db_transaction as db:
+ cursor = db.cursor()
+ cursor.execute(
+ "INSERT INTO %s (%s) VALUES ('next-id')"
+ % (db.quote('HOURS'), db.quote('AUTHOR')))
+ last_id = db.get_last_id(cursor, 'HOURS', 'ID')
+
+ self.assertEqual(43, last_id)
+
+ def test_table_names(self):
+ schema = default_schema + self.schema
+ with self.env.db_query as db:
+ db_tables = db.get_table_names()
+ self.assertEqual(len(schema), len(db_tables))
+ for table in schema:
+ self.assertIn(table.name, db_tables)
+
+ def test_get_column_names(self):
+ schema = default_schema + self.schema
+ with self.env.db_transaction as db:
+ for table in schema:
+ db_columns = db.get_column_names(table.name)
+ self.assertEqual(len(table.columns), len(db_columns))
+ for column in table.columns:
+ self.assertIn(column.name, db_columns)
+
def suite():
suite = unittest.TestSuite()
Modified: bloodhound/vendor/trac/current/trac/db/tests/mysql_test.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/tests/mysql_test.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/db/tests/mysql_test.py (original)
+++ bloodhound/vendor/trac/current/trac/db/tests/mysql_test.py Fri Nov 14 11:06:23 2014
@@ -13,10 +13,10 @@
import unittest
+import trac.tests.compat
from trac.db.mysql_backend import MySQLConnector
from trac.db.schema import Table, Column, Index
from trac.test import EnvironmentStub, Mock
-from trac.tests import compat
class MySQLTableAlterationSQLTest(unittest.TestCase):
Modified: bloodhound/vendor/trac/current/trac/db/tests/util.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/tests/util.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/db/tests/util.py (original)
+++ bloodhound/vendor/trac/current/trac/db/tests/util.py Fri Nov 14 11:06:23 2014
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
-# Copyright (C) 2010-2013 Edgewall Software
+# Copyright (C) 2010-2014 Edgewall Software
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
@@ -31,6 +31,37 @@ class SQLEscapeTestCase(unittest.TestCas
self.assertEqual("'%% %%'", sql_escape_percent("'% %'"))
self.assertEqual("'%%s %%i'", sql_escape_percent("'%s %i'"))
+ self.assertEqual("%", sql_escape_percent("%"))
+ self.assertEqual("`%%`", sql_escape_percent("`%`"))
+ self.assertEqual("``%``", sql_escape_percent("``%``"))
+ self.assertEqual("```%%```", sql_escape_percent("```%```"))
+ self.assertEqual("```%%`", sql_escape_percent("```%`"))
+ self.assertEqual("%s", sql_escape_percent("%s"))
+ self.assertEqual("% %", sql_escape_percent("% %"))
+ self.assertEqual("%s %i", sql_escape_percent("%s %i"))
+ self.assertEqual("`%%s`", sql_escape_percent("`%s`"))
+ self.assertEqual("`%% %%`", sql_escape_percent("`% %`"))
+ self.assertEqual("`%%s %%i`", sql_escape_percent("`%s %i`"))
+
+ self.assertEqual('%', sql_escape_percent('%'))
+ self.assertEqual('"%%"', sql_escape_percent('"%"'))
+ self.assertEqual('""%""', sql_escape_percent('""%""'))
+ self.assertEqual('"""%%"""', sql_escape_percent('"""%"""'))
+ self.assertEqual('"""%%"', sql_escape_percent('"""%"'))
+ self.assertEqual('%s', sql_escape_percent('%s'))
+ self.assertEqual('% %', sql_escape_percent('% %'))
+ self.assertEqual('%s %i', sql_escape_percent('%s %i'))
+ self.assertEqual('"%%s"', sql_escape_percent('"%s"'))
+ self.assertEqual('"%% %%"', sql_escape_percent('"% %"'))
+ self.assertEqual('"%%s %%i"', sql_escape_percent('"%s %i"'))
+
+ self.assertEqual("""'%%?''"%%s`%%i`%%%%"%%S'""",
+ sql_escape_percent("""'%?''"%s`%i`%%"%S'"""))
+ self.assertEqual("""`%%?``'%%s"%%i"%%%%'%%S`""",
+ sql_escape_percent("""`%?``'%s"%i"%%'%S`"""))
+ self.assertEqual('''"%%?""`%%s'%%i'%%%%`%%S"''',
+ sql_escape_percent('''"%?""`%s'%i'%%`%S"'''))
+
def suite():
suite = unittest.TestSuite()
Modified: bloodhound/vendor/trac/current/trac/db/util.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/util.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/db/util.py (original)
+++ bloodhound/vendor/trac/current/trac/db/util.py Fri Nov 14 11:06:23 2014
@@ -15,11 +15,18 @@
#
# Author: Christopher Lenz <cm...@gmx.de>
+import re
+
+_sql_escape_percent_re = re.compile("""
+ '(?:[^']+|'')*' |
+ `(?:[^`]+|``)*` |
+ "(?:[^"]+|"")*" """, re.VERBOSE)
+
def sql_escape_percent(sql):
- import re
- return re.sub("'((?:[^']|(?:''))*)'",
- lambda m: m.group(0).replace('%', '%%'), sql)
+ def repl(match):
+ return match.group(0).replace('%', '%%')
+ return _sql_escape_percent_re.sub(repl, sql)
class IterableCursor(object):
@@ -118,7 +125,7 @@ class ConnectionWrapper(object):
"""
dql = self.check_select(query)
cursor = self.cnx.cursor()
- cursor.execute(query, params)
+ cursor.execute(query, params if params is not None else [])
rows = cursor.fetchall() if dql else None
cursor.close()
return rows
Modified: bloodhound/vendor/trac/current/trac/db_default.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db_default.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/db_default.py (original)
+++ bloodhound/vendor/trac/current/trac/db_default.py Fri Nov 14 11:06:23 2014
@@ -300,8 +300,7 @@ USER dynamic variable, replaced with the
logged in user when executed.
""",
"""\
-SELECT DISTINCT
- p.value AS __color__,
+SELECT p.value AS __color__,
(CASE
WHEN owner = $USER AND status = 'accepted' THEN 'Accepted'
WHEN owner = $USER THEN 'Owned'
@@ -313,12 +312,14 @@ SELECT DISTINCT
reporter AS _reporter
FROM ticket t
LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority'
- LEFT JOIN ticket_change tc ON tc.ticket = t.id AND tc.author = $USER
- AND tc.field = 'comment'
- WHERE t.status <> 'closed'
- AND (owner = $USER OR reporter = $USER OR author = $USER)
- ORDER BY (owner = $USER AND status = 'accepted') DESC,
- owner = $USER DESC, reporter = $USER DESC,
+ WHERE t.status <> 'closed' AND
+ (owner = $USER OR reporter = $USER OR
+ EXISTS (SELECT * FROM ticket_change tc
+ WHERE tc.ticket = t.id AND tc.author = $USER AND
+ tc.field = 'comment'))
+ ORDER BY (COALESCE(owner, '') = $USER AND status = 'accepted') DESC,
+ COALESCE(owner, '') = $USER DESC,
+ COALESCE(reporter, '') = $USER DESC,
""" + db.cast('p.value', 'int') + """, milestone, t.type, t.time
"""),
#----------------------------------------------------------------------------
Modified: bloodhound/vendor/trac/current/trac/dist.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/dist.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/dist.py (original)
+++ bloodhound/vendor/trac/current/trac/dist.py Fri Nov 14 11:06:23 2014
@@ -466,6 +466,17 @@ try:
self.run_command('compile_catalog')
def run(self):
self.l10n_run()
+ # When bdist_egg is called on distribute 0.6.29 and later, the
+ # egg file includes no *.mo and *.js files which are generated
+ # in l10n_run() method.
+ # We remove build_py.data_files property to re-compute in order
+ # to avoid the issue (#11640).
+ build_py = self.get_finalized_command('build_py')
+ if 'data_files' in build_py.__dict__ and \
+ not any(any(name.endswith('.mo') for name in filenames)
+ for pkg, src_dir, build_dir, filenames
+ in build_py.data_files):
+ del build_py.__dict__['data_files']
_install_lib.run(self)
return build, install_lib
Modified: bloodhound/vendor/trac/current/trac/env.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/env.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/env.py (original)
+++ bloodhound/vendor/trac/current/trac/env.py Fri Nov 14 11:06:23 2014
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
-# Copyright (C) 2003-2011 Edgewall Software
+# Copyright (C) 2003-2014 Edgewall Software
# Copyright (C) 2003-2007 Jonas Borgström <jo...@edgewall.com>
# All rights reserved.
#
@@ -26,7 +26,8 @@ from urlparse import urlsplit
from trac import db_default
from trac.admin import AdminCommandError, IAdminCommandProvider
from trac.cache import CacheManager
-from trac.config import *
+from trac.config import BoolOption, ConfigSection, Configuration, Option, \
+ PathOption
from trac.core import Component, ComponentManager, implements, Interface, \
ExtensionPoint, TracError
from trac.db.api import (DatabaseManager, QueryContextManager,
@@ -392,7 +393,8 @@ class Environment(Component, ComponentMa
def get_db_cnx(self):
"""Return a database connection from the connection pool
- :deprecated: Use :meth:`db_transaction` or :meth:`db_query` instead
+ :deprecated: Use :meth:`db_transaction` or :meth:`db_query` instead.
+ Removed in Trac 1.1.2.
`db_transaction` for obtaining the `db` database connection
which can be used for performing any query
@@ -433,13 +435,21 @@ class Environment(Component, ComponentMa
return DatabaseManager(self).get_exceptions()
def with_transaction(self, db=None):
- """Decorator for transaction functions :deprecated:"""
+ """Decorator for transaction functions.
+
+ :deprecated: Use the query and transaction context managers instead.
+ Will be removed in Trac 1.3.1.
+ """
return with_transaction(self, db)
def get_read_db(self):
- """Return a database connection for read purposes :deprecated:
+ """Return a database connection for read purposes.
- See `trac.db.api.get_read_db` for detailed documentation."""
+ See `trac.db.api.get_read_db` for detailed documentation.
+
+ :deprecated: Use :meth:`db_query` instead.
+ Will be removed in Trac 1.3.1.
+ """
return DatabaseManager(self).get_connection(readonly=True)
@property
@@ -581,6 +591,25 @@ class Environment(Component, ComponentMa
# Create the database
DatabaseManager(self).init_db()
+ @lazy
+ def database_version(self):
+ """Returns the current version of the database.
+
+ :since 1.0.2:
+ """
+ return self.get_version()
+
+ @lazy
+ def database_initial_version(self):
+ """Returns the version of the database at the time of creation.
+
+ In practice, for database created before 0.11, this will
+ return `False` which is "older" than any db version number.
+
+ :since 1.0.2:
+ """
+ return self.get_version(initial=True)
+
def get_version(self, db=None, initial=False):
"""Return the current version of the database. If the
optional argument `initial` is set to `True`, the version of
@@ -593,6 +622,11 @@ class Environment(Component, ComponentMa
:since 1.0: deprecation warning: the `db` parameter is no
longer used and will be removed in version 1.1.1
+
+ :since 1.0.2: The lazily-evaluated attributes `database_version` and
+ `database_initial_version` should be used instead. This
+ method will be renamed to a private method in
+ release 1.3.1.
"""
rows = self.db_query("""
SELECT value FROM system WHERE name='%sdatabase_version'
@@ -711,6 +745,7 @@ class Environment(Component, ComponentMa
participant.upgrade_environment(db)
# Database schema may have changed, so close all connections
DatabaseManager(self).shutdown()
+ del self.database_version
return True
@lazy
@@ -749,7 +784,7 @@ class EnvironmentSetup(Component):
self._update_sample_config()
def environment_needs_upgrade(self, db):
- dbver = self.env.get_version()
+ dbver = self.env.database_version
if dbver == db_default.db_version:
return False
elif dbver > db_default.db_version:
@@ -763,7 +798,7 @@ class EnvironmentSetup(Component):
upgrades/dbN.py, where 'N' is the version number (int).
"""
cursor = db.cursor()
- dbver = self.env.get_version()
+ dbver = self.env.database_version
for i in range(dbver + 1, db_default.db_version + 1):
name = 'db%i' % i
try:
@@ -787,9 +822,8 @@ class EnvironmentSetup(Component):
if not os.path.isfile(filename):
return
config = Configuration(filename)
- for section, default_options in config.defaults().iteritems():
- for name, value in default_options.iteritems():
- config.set(section, name, value)
+ for (section, name), option in Option.get_registry().iteritems():
+ config.set(section, name, option.dumps(option.default))
try:
config.save()
self.log.info("Wrote sample configuration file with the new "
Modified: bloodhound/vendor/trac/current/trac/htdocs/css/admin.css
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/htdocs/css/admin.css?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/htdocs/css/admin.css (original)
+++ bloodhound/vendor/trac/current/trac/htdocs/css/admin.css Fri Nov 14 11:06:23 2014
@@ -132,4 +132,3 @@ table.trac-pluglist td { padding-left: 1
padding: 0;
white-space: nowrap;
}
-fieldset tr.field th { text-align: right; }
Modified: bloodhound/vendor/trac/current/trac/htdocs/css/report.css
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/htdocs/css/report.css?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/htdocs/css/report.css (original)
+++ bloodhound/vendor/trac/current/trac/htdocs/css/report.css Fri Nov 14 11:06:23 2014
@@ -25,7 +25,6 @@
.report div.reports { clear: both }
-
.report div.reports h2 {
/* taken from .wikipage h2 */
border-bottom: 1px solid #ddd;
@@ -81,8 +80,13 @@ h2.report-result {
}
#report-descr { margin: 0 2em; font-size: 90% }
#report-notfound { margin: 2em; font-size: 110% }
+
+/* Report edit form */
+#content.report.edit form {
+ max-width: 54em;
+}
#content.report .field { margin: 1em 0; }
-#content.report .field label { padding-bottom: .3em; }
+#content.report .field label { display: block; padding-bottom: .3em; }
#query { clear: right }
#query fieldset, #query fieldset input, #query fieldset select {
@@ -179,9 +183,9 @@ h2.report-result {
.tickets tr.color2-even { background: #ffd; border-color: #dd8; color: #880 }
.tickets tr.color3-odd { background: #fbfbfb; border-color: #ddd; color: #444 }
.tickets tr.color3-even { background: #f6f6f6; border-color: #ccc; color: #333 }
-.tickets tr.color4-odd { background: #e7ffff; border-color: #cee; color: #099 }
+.tickets tr.color4-odd { background: #e7ffff; border-color: #cee; color: #099 }
.tickets tr.color4-even { background: #dff; border-color: #bee; color: #099 }
-.tickets tr.color5-odd { background: #e7eeff; border-color: #cde; color: #469 }
+.tickets tr.color5-odd { background: #e7eeff; border-color: #cde; color: #469 }
.tickets tr.color5-even { background: #dde7ff; border-color: #cde; color: #469 }
.tickets tr.color6-odd { background: #f0f0f0; border-color: #ddd; color: #888 }
.tickets tr.color6-even { background: #f7f7f7; border-color: #ddd; color: #888 }
@@ -207,7 +211,7 @@ table.tickets tbody tr.prio1 { backgroun
table.tickets tbody tr.even.prio1 { background: #fed; border-color: #e99 }
table.tickets tbody tr.prio2 { background: #ffb; border-color: #eea }
table.tickets tbody tr.even.prio2 { background: #ffd; border-color: #dd8 }
-table.tickets tbody tr.prio3 { background: #fbfbfb; border-color: #ddd }
+table.tickets tbody tr.prio3 { background: #fbfbfb; border-color: #ddd }
table.tickets tbody tr.even.prio3 { background: #f6f6f6; border-color: #ccc }
table.tickets tbody tr.prio4 { background: #e7ffff; border-color: #cee }
table.tickets tbody tr.even.prio4 { background: #dff; border-color: #bee }
@@ -216,10 +220,10 @@ table.tickets tbody tr.even.prio5 { back
table.tickets tbody tr.prio6 { background: #f0f0f0; border-color: #ddd }
table.tickets tbody tr.even.prio6 { background: #f7f7f7 }
table.tickets tbody tr.fullrow th {
- border: none;
- vertical-align: middle;
- text-align: center;
- font-size: 85%;
+ border: none;
+ vertical-align: middle;
+ text-align: center;
+ font-size: 85%;
}
table.tickets tbody tr p:first-child { margin-top: 0 }
table.tickets tbody tr p:last-child { margin-bottom: 0 }
@@ -227,7 +231,7 @@ table.tickets tbody tr p:last-child { ma
/* Batchmod Form */
#batchmod_form { display: none; }
-#batchmod_form fieldset input#batchmod_submit { font-size: 14px; }
+#batchmod_form fieldset input#batchmod_submit { font-size: 100% }
#batchmod_form fieldset input[type="button"]{ padding: 0.1em 0.5em; }
#batchmod_form > fieldset { margin-top: 1.5em }
#batchmod_form fieldset.collapsed {
@@ -238,10 +242,8 @@ table.tickets tbody tr p:last-child { ma
.batchmod_property { width: 100%; }
.batchmod_required:before { content: " * "; }
#batchmod_form fieldset input,
-#batchmod_form fieldset select,
-.batchmod_property,
-.batchmod_label {
- font-size: 11px;
+#batchmod_form fieldset select, .batchmod_property, .batchmod_label {
+ font-size: 11px;
}
#batchmod_action { margin-top: 0; line-height: 2em; }
#batchmod_form th {
Modified: bloodhound/vendor/trac/current/trac/htdocs/css/roadmap.css
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/htdocs/css/roadmap.css?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/htdocs/css/roadmap.css (original)
+++ bloodhound/vendor/trac/current/trac/htdocs/css/roadmap.css Fri Nov 14 11:06:23 2014
@@ -95,6 +95,3 @@ p.percent {
#edit .field { margin: 0.5em 0 }
#edit label { padding-left: .2em }
#edit fieldset { margin-left: 1px; margin-right: 1px }
-#edit textarea#description { margin-left: -1px; margin-right: -1px; padding: 0; width: 100% }
-#edit .wikitoolbar { margin-left: -1px }
-#edit div.trac-resizable { width: 100% }
Modified: bloodhound/vendor/trac/current/trac/htdocs/css/ticket.css
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/htdocs/css/ticket.css?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/htdocs/css/ticket.css (original)
+++ bloodhound/vendor/trac/current/trac/htdocs/css/ticket.css Fri Nov 14 11:06:23 2014
@@ -8,7 +8,6 @@
}
#field-description-help { float: right }
-#properties div.trac-resizable, #field-description { width: 100% }
#content.ticket .trac-topnav {
float: none;
@@ -158,14 +157,7 @@ ul.children > li.child {
/* Comment editor */
#trac-comment-editor { margin-left: 2em; margin-bottom: 1em }
-#trac-comment-editor div.trac-resizable { width: 100% }
-#trac-comment-editor textarea {
- background: #ffffe0;
- margin-left: -1px;
- margin-right: -1px;
- width: 100%;
-}
-#trac-comment-editor .wikitoolbar { margin-left: -1px }
+#trac-comment-editor textarea { background: #ffffe0; }
.trac-new { border-left: 0.31em solid #c0f0c0; padding-left: 0.31em; }
.trac-loading {
@@ -208,22 +200,39 @@ button.trac-revert div { display: none;
form .field { margin-top: .75em; width: 100% }
form .field fieldset { margin-left: 1px; margin-right: 1px }
label[for=comment] { float: right }
-#comment { margin-left: -1px; margin-right: -1px; padding: 0; width: 100% }
-form .field .wikitoolbar { margin-left: -1px }
-form .field div.trac-resizable { width: 100% }
#propertyform { margin-bottom: 2em; }
#properties { white-space: nowrap; line-height: 160%; padding: .5em }
-#properties table { border-spacing: 0; width: 100%; padding: 0 .5em }
-#properties table th {
+#properties table {
+ border-spacing: 0;
+ padding: 0 .5em;
+ table-layout: fixed;
+ width: 100%;
+}
+#properties table th,
+#properties table col.th {
padding: .4em;
text-align: right;
- width: 20%;
vertical-align: top;
+ white-space: normal;
+ width: 17%;
}
#properties table th.col2 { border-left: 1px dotted #d7d7d7 }
-#properties table td { vertical-align: middle; width: 30% }
-#properties table td.fullrow { vertical-align: middle; width: 80% }
+#properties table td,
+#properties table col.td {
+ padding-right: 0.6em;
+ vertical-align: middle;
+ width: 33%
+}
+#properties table td.fullrow { width: 83% }
+#properties table td input[type="text"] {
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100%;
+}
+#properties table td.col1 label,
+#properties table td.col2 label { float: left; margin-right: 0.5em; }
+#properties table td select { max-width: 100% }
#action { line-height: 2em }
Modified: bloodhound/vendor/trac/current/trac/htdocs/css/trac.css
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/htdocs/css/trac.css?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/htdocs/css/trac.css (original)
+++ bloodhound/vendor/trac/current/trac/htdocs/css/trac.css Fri Nov 14 11:06:23 2014
@@ -82,6 +82,11 @@ span:target {
/* Forms */
input, textarea, select { margin: 2px }
+/* Avoid respect to system font settings for controls on Firefox, #11607 */
+input, select, button {
+ font-family: Arial,Verdana,'Bitstream Vera Sans',Helvetica,sans-serif;
+ font-size: 100%;
+}
/* Avoid to inherit white-space of its parent element for IE 11, #11376 */
textarea { white-space: pre-wrap }
input, select { vertical-align: middle }
@@ -178,6 +183,14 @@ input[type=button].trac-delete:hover,
input[type=submit].trac-delete:hover {
color: #e31313;
}
+textarea.trac-fullwidth, input.trac-fullwidth {
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ margin-left: 0;
+ margin-right: 0;
+ width: 100%;
+}
+textarea.trac-fullwidth { padding: 2px; }
/* Header */
#header hr { display: none }
@@ -239,7 +252,7 @@ input[type=submit].trac-delete:hover {
outline: 0;
background: transparent;
font-family: inherit;
- font-size: inherit;
+ font-size: 100%;
color: #b00;
border-bottom: 1px dotted #bbb;
cursor: pointer;
@@ -564,7 +577,6 @@ table.wiki tbody tr.odd { background-col
.wikitoolbar {
margin-top: 0.3em;
- margin-left: 2px;
border: solid #d7d7d7;
border-width: 1px 1px 1px 0;
height: 18px;
@@ -595,7 +607,7 @@ table.wiki tbody tr.odd { background-col
.wikitoolbar a#img { background-position: 0 -128px }
/* Textarea resizer */
-div.trac-resizable { display: table; width: 1px }
+div.trac-resizable { display: table; width: 100% }
div.trac-resizable > div { display: table-cell }
div.trac-resizable textarea { display: block; margin-bottom: 0 }
div.trac-grip {
Modified: bloodhound/vendor/trac/current/trac/htdocs/css/wiki.css
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/htdocs/css/wiki.css?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/htdocs/css/wiki.css (original)
+++ bloodhound/vendor/trac/current/trac/htdocs/css/wiki.css Fri Nov 14 11:06:23 2014
@@ -50,15 +50,11 @@
#edit fieldset { margin-left: 1px; margin-right: 1px }
#edit #text {
clear: both;
- margin-left: -1px;
- margin-right: -1px;
- padding: 0;
- width: 100%;
min-height: 10em;
resize: vertical;
}
-#edit .wikitoolbar { float: left; margin-left: -1px }
-#edit div.trac-resizable { clear: both; width: 100% }
+#edit .wikitoolbar { float: left }
+#edit div.trac-resizable { clear: both }
#edit + #info { margin-top: 1em }
#edit + #attachments { margin-top: 1.5em }
#changeinfo { padding: .5em }
Modified: bloodhound/vendor/trac/current/trac/htdocs/js/auto_preview.js
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/htdocs/js/auto_preview.js?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
Binary files - no diff available.
Modified: bloodhound/vendor/trac/current/trac/htdocs/js/wikitoolbar.js
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/htdocs/js/wikitoolbar.js?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
Binary files - no diff available.
Modified: bloodhound/vendor/trac/current/trac/loader.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/loader.py?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/loader.py (original)
+++ bloodhound/vendor/trac/current/trac/loader.py Fri Nov 14 11:06:23 2014
@@ -182,7 +182,10 @@ def get_plugin_info(env, include_core=Fa
version = (getattr(module, 'version', '') or
getattr(module, 'revision', ''))
# special handling for "$Rev$" strings
- version = version.replace('$', '').replace('Rev: ', 'r')
+ if version != '$Rev$':
+ version = version.replace('$', '').replace('Rev: ', 'r')
+ else: # keyword hasn't been expanded
+ version = ''
plugins[dist.project_name] = {
'name': dist.project_name, 'version': version,
'path': dist.location, 'plugin_filename': plugin_filename,
Modified: bloodhound/vendor/trac/current/trac/locale/de/LC_MESSAGES/messages.po
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/locale/de/LC_MESSAGES/messages.po?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/locale/de/LC_MESSAGES/messages.po (original)
+++ bloodhound/vendor/trac/current/trac/locale/de/LC_MESSAGES/messages.po Fri Nov 14 11:06:23 2014
@@ -4948,7 +4948,7 @@ msgstr "Repositorys"
#, python-format
msgid "You should now run %(resync)s to synchronize Trac with the repository."
msgstr ""
-"Sie sollten jetzt %(resync)s ausführen, um Trac mit dem Reposiory zu "
+"Sie sollten jetzt %(resync)s ausführen, um Trac mit dem Repository zu "
"synchronisieren."
#: trac/versioncontrol/admin.py:225
Modified: bloodhound/vendor/trac/current/trac/locale/ja/LC_MESSAGES/messages-js.po
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/locale/ja/LC_MESSAGES/messages-js.po?rev=1639602&r1=1639601&r2=1639602&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/locale/ja/LC_MESSAGES/messages-js.po (original)
+++ bloodhound/vendor/trac/current/trac/locale/ja/LC_MESSAGES/messages-js.po Fri Nov 14 11:06:23 2014
@@ -1,13 +1,13 @@
# Japanese translations for Trac.
-# Copyright (C) 2010-2013 Edgewall Software
+# Copyright (C) 2010-2014 Edgewall Software
# This file is distributed under the same license as the Trac project.
-# Jun Omae <ju...@gmail.com>, 2010-2013.
+# Jun Omae <ju...@gmail.com>, 2010-2014.
#
msgid ""
msgstr ""
-"Project-Id-Version: Trac 1.0\n"
+"Project-Id-Version: Trac 1.0.2\n"
"Report-Msgid-Bugs-To: trac-dev@googlegroups.com\n"
-"POT-Creation-Date: 2013-03-21 22:54+0100\n"
+"POT-Creation-Date: 2014-09-01 12:43+0000\n"
"PO-Revision-Date: 2010-05-25 18:45+0900\n"
"Last-Translator: Jun Omae <ju...@gmail.com>\n"
"Language-Team: ja <LL...@li.org>\n"
@@ -15,7 +15,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6dev-r0\n"
+"Generated-By: Babel 0.9.6\n"
#: trac/htdocs/js/blame.js:84
msgid "(no changeset information)"
@@ -76,7 +76,7 @@ msgstr "$yearå¹´$month"
#. TRANSLATOR: Link that closes the datepicker
#. TRANSLATOR: Link that closes the timepicker
-#: trac/htdocs/js/jquery-ui-i18n.js:7 trac/htdocs/js/jquery-ui-i18n.js:39
+#: trac/htdocs/js/jquery-ui-i18n.js:7 trac/htdocs/js/jquery-ui-i18n.js:40
msgid "Done"
msgstr "éãã"
@@ -101,34 +101,34 @@ msgid "Wk"
msgstr "é±"
#. TRANSLATOR: Heading of the standalone timepicker
-#: trac/htdocs/js/jquery-ui-i18n.js:30
+#: trac/htdocs/js/jquery-ui-i18n.js:31
msgid "Choose Time"
msgstr "æéãé¸æ"
#. TRANSLATOR: Time selector label
-#: trac/htdocs/js/jquery-ui-i18n.js:32
+#: trac/htdocs/js/jquery-ui-i18n.js:33
msgid "Time"
msgstr "æé"
#. TRANSLATOR: Time labels in the timepicker
-#: trac/htdocs/js/jquery-ui-i18n.js:34
+#: trac/htdocs/js/jquery-ui-i18n.js:35
msgid "Hour"
msgstr "æ"
-#: trac/htdocs/js/jquery-ui-i18n.js:34
+#: trac/htdocs/js/jquery-ui-i18n.js:35
msgid "Minute"
msgstr "å"
-#: trac/htdocs/js/jquery-ui-i18n.js:34
+#: trac/htdocs/js/jquery-ui-i18n.js:35
msgid "Second"
msgstr "ç§"
-#: trac/htdocs/js/jquery-ui-i18n.js:35
+#: trac/htdocs/js/jquery-ui-i18n.js:36
msgid "Time Zone"
msgstr "ã¿ã¤ã ã¾ã¼ã³"
#. TRANSLATOR: Link to pick the current time in the timepicker
-#: trac/htdocs/js/jquery-ui-i18n.js:37
+#: trac/htdocs/js/jquery-ui-i18n.js:38
msgid "Now"
msgstr "ç¾æå»"
@@ -169,7 +169,7 @@ msgstr " 追å :"
msgid "Select ticket %(id)s for modification"
msgstr "æ´æ°å¯¾è±¡ã¨ãã¦ãã±ãã %(id)s ãé¸æãã"
-#: trac/htdocs/js/query.js:387
+#: trac/htdocs/js/query.js:388
msgid "Toggle selection of all tickets shown in this group"
msgstr "ãã®ã°ã«ã¼ãã«è¡¨ç¤ºãã¦ãããã¹ã¦ã®ãã±ããã«å¯¾ããé¸æãåãæ¿ãã"
@@ -177,39 +177,39 @@ msgstr "ãã®ã°ã«ã¼ã
msgid "Link here"
msgstr "ããã«ãªã³ã¯ãã"
-#: trac/htdocs/js/wikitoolbar.js:56
+#: trac/htdocs/js/wikitoolbar.js:59
msgid "Bold text: '''Example'''"
msgstr "太å: '''ä¾'''"
-#: trac/htdocs/js/wikitoolbar.js:59
+#: trac/htdocs/js/wikitoolbar.js:62
msgid "Italic text: ''Example''"
msgstr "æä½: '''ä¾'''"
-#: trac/htdocs/js/wikitoolbar.js:62
+#: trac/htdocs/js/wikitoolbar.js:65
msgid "Heading: == Example =="
msgstr "ããã: == ä¾ =="
-#: trac/htdocs/js/wikitoolbar.js:65
+#: trac/htdocs/js/wikitoolbar.js:68
msgid "Link: [http://www.example.com/ Example]"
msgstr "ãªã³ã¯: [http://www.example.com/ ä¾]"
-#: trac/htdocs/js/wikitoolbar.js:68
+#: trac/htdocs/js/wikitoolbar.js:71
msgid "Code block: {{{ example }}}"
msgstr "ã³ã¼ããããã¯: {{{ ä¾ }}}"
-#: trac/htdocs/js/wikitoolbar.js:71
+#: trac/htdocs/js/wikitoolbar.js:74
msgid "Horizontal rule: ----"
msgstr "横罫ç·: ----"
-#: trac/htdocs/js/wikitoolbar.js:74
+#: trac/htdocs/js/wikitoolbar.js:77
msgid "New paragraph"
msgstr "段è½"
-#: trac/htdocs/js/wikitoolbar.js:77
+#: trac/htdocs/js/wikitoolbar.js:80
msgid "Line break: [[BR]]"
msgstr "æ¹è¡: [[BR]]"
-#: trac/htdocs/js/wikitoolbar.js:80
+#: trac/htdocs/js/wikitoolbar.js:83
msgid "Image: [[Image()]]"
msgstr "ç»å: [[Image()]]"