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/02/13 06:08:08 UTC
svn commit: r1567849 [2/17] - in /bloodhound/vendor/trac: 1.0-stable/
current/ current/contrib/ current/contrib/cgi-bin/
current/contrib/workflow/ current/doc/ current/doc/utils/
current/sample-plugins/ current/sample-plugins/permissions/ current/sampl...
Modified: bloodhound/vendor/trac/current/sample-plugins/revision_links.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/sample-plugins/revision_links.py?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/sample-plugins/revision_links.py (original)
+++ bloodhound/vendor/trac/current/sample-plugins/revision_links.py Thu Feb 13 05:08:02 2014
@@ -1,3 +1,17 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2007-2013 Edgewall Software
+# Copyright (C) 2007 Christian Boos <cb...@edgewall.org>
+# All rights reserved.
+#
+# 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/.
+
"""Sample Wiki syntax extension plugin."""
from genshi.builder import tag
@@ -8,8 +22,8 @@ from trac.versioncontrol.api import NoSu
from trac.versioncontrol.web_ui import ChangesetModule
from trac.wiki.api import IWikiSyntaxProvider
-revision = "$Rev: 11490 $"
-url = "$URL: http://svn.edgewall.org/repos/trac/tags/trac-1.0.1/sample-plugins/revision_links.py $"
+revision = "$Rev: 12500 $"
+url = "$URL: https://svn.edgewall.org/repos/trac/branches/1.0-stable/sample-plugins/revision_links.py $"
class RevisionLinks(Component):
"""Adds a few more ways to refer to changesets."""
@@ -53,4 +67,3 @@ class RevisionLinks(Component):
pass
return tag.a(label, class_="missing changeset", rel="nofollow",
href=formatter.href.changeset(rev))
-
Modified: bloodhound/vendor/trac/current/sample-plugins/workflow/CodeReview.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/sample-plugins/workflow/CodeReview.py?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/sample-plugins/workflow/CodeReview.py (original)
+++ bloodhound/vendor/trac/current/sample-plugins/workflow/CodeReview.py Thu Feb 13 05:08:02 2014
@@ -1,3 +1,17 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2007-2013 Edgewall Software
+# Copyright (C) 2007 Eli Carter <re...@gmail.com>
+# All rights reserved.
+#
+# 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/.
+
from genshi.builder import tag
from trac.core import implements,Component
@@ -6,8 +20,8 @@ from trac.ticket.default_workflow import
from trac.perm import IPermissionRequestor
from trac.config import Option, ListOption
-revision = "$Rev: 11490 $"
-url = "$URL: http://svn.edgewall.org/repos/trac/tags/trac-1.0.1/sample-plugins/workflow/CodeReview.py $"
+revision = "$Rev: 12164 $"
+url = "$URL: https://svn.edgewall.org/repos/trac/branches/1.0-stable/sample-plugins/workflow/CodeReview.py $"
class CodeReviewActionController(Component):
"""Support for simple code reviews.
Modified: bloodhound/vendor/trac/current/sample-plugins/workflow/DeleteTicket.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/sample-plugins/workflow/DeleteTicket.py?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/sample-plugins/workflow/DeleteTicket.py (original)
+++ bloodhound/vendor/trac/current/sample-plugins/workflow/DeleteTicket.py Thu Feb 13 05:08:02 2014
@@ -1,11 +1,25 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2007-2013 Edgewall Software
+# Copyright (C) 2007 Eli Carter <re...@gmail.com>
+# All rights reserved.
+#
+# 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/.
+
from genshi.builder import tag
from trac.core import implements,Component
from trac.ticket.api import ITicketActionController
from trac.perm import IPermissionRequestor
-revision = "$Rev: 11490 $"
-url = "$URL: http://svn.edgewall.org/repos/trac/tags/trac-1.0.1/sample-plugins/workflow/DeleteTicket.py $"
+revision = "$Rev: 12164 $"
+url = "$URL: https://svn.edgewall.org/repos/trac/branches/1.0-stable/sample-plugins/workflow/DeleteTicket.py $"
class DeleteTicketActionController(Component):
"""Provides the admin with a way to delete a ticket.
Modified: bloodhound/vendor/trac/current/sample-plugins/workflow/MilestoneOperation.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/sample-plugins/workflow/MilestoneOperation.py?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/sample-plugins/workflow/MilestoneOperation.py (original)
+++ bloodhound/vendor/trac/current/sample-plugins/workflow/MilestoneOperation.py Thu Feb 13 05:08:02 2014
@@ -1,14 +1,16 @@
# -*- coding: utf-8 -*-
#
+# Copyright (C) 2002-2013 Edgewall Software
# Copyright (C) 2012 Franz Mayer <fr...@gefasoft.de>
+# All rights reserved.
#
-# "THE BEER-WARE LICENSE" (Revision 42):
-# <fr...@gefasoft.de> wrote this file. As long as you retain this
-# notice you can do whatever you want with this stuff. If we meet some day,
-# and you think this stuff is worth it, you can buy me a beer in return.
-# Franz Mayer
+# 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.
#
-# Author: Franz Mayer <fr...@gefasoft.de>
+# 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/.
from genshi.builder import tag
Modified: bloodhound/vendor/trac/current/sample-plugins/workflow/StatusFixer.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/sample-plugins/workflow/StatusFixer.py?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/sample-plugins/workflow/StatusFixer.py (original)
+++ bloodhound/vendor/trac/current/sample-plugins/workflow/StatusFixer.py Thu Feb 13 05:08:02 2014
@@ -1,11 +1,25 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2007-2013 Edgewall Software
+# Copyright (C) 2007 Eli Carter <re...@gmail.com>
+# All rights reserved.
+#
+# 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/.
+
from genshi.builder import tag
from trac.core import Component, implements
from trac.ticket.api import ITicketActionController, TicketSystem
from trac.perm import IPermissionRequestor
-revision = "$Rev: 11075 $"
-url = "$URL: http://svn.edgewall.org/repos/trac/tags/trac-1.0.1/sample-plugins/workflow/StatusFixer.py $"
+revision = "$Rev: 12164 $"
+url = "$URL: https://svn.edgewall.org/repos/trac/branches/1.0-stable/sample-plugins/workflow/StatusFixer.py $"
class StatusFixerActionController(Component):
"""Provides the admin with a way to correct a ticket's status.
Modified: bloodhound/vendor/trac/current/sample-plugins/workflow/VoteOperation.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/sample-plugins/workflow/VoteOperation.py?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/sample-plugins/workflow/VoteOperation.py (original)
+++ bloodhound/vendor/trac/current/sample-plugins/workflow/VoteOperation.py Thu Feb 13 05:08:02 2014
@@ -1,3 +1,17 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2007-2013 Edgewall Software
+# Copyright (C) 2007 Eli Carter <re...@gmail.com>
+# All rights reserved.
+#
+# 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/.
+
from genshi.builder import tag
from trac.core import implements,Component
@@ -6,8 +20,8 @@ from trac.ticket.default_workflow import
from trac.ticket.model import Priority, Ticket
#from trac.perm import IPermissionRequestor # (TODO)
-revision = "$Rev: 11490 $"
-url = "$URL: http://svn.edgewall.org/repos/trac/tags/trac-1.0.1/sample-plugins/workflow/VoteOperation.py $"
+revision = "$Rev: 12164 $"
+url = "$URL: https://svn.edgewall.org/repos/trac/branches/1.0-stable/sample-plugins/workflow/VoteOperation.py $"
class VoteOperation(Component):
"""Provides a simplistic vote feature.
Modified: bloodhound/vendor/trac/current/setup.cfg
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/setup.cfg?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/setup.cfg (original)
+++ bloodhound/vendor/trac/current/setup.cfg Thu Feb 13 05:08:02 2014
@@ -1,6 +1,6 @@
[egg_info]
-#tag_build = dev
-#tag_svn_revision = true
+tag_build = dev
+tag_svn_revision = true
[bdist_wininst]
bitmap = setup_wininst.bmp
Modified: bloodhound/vendor/trac/current/setup.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/setup.py?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/setup.py (original)
+++ bloodhound/vendor/trac/current/setup.py Thu Feb 13 05:08:02 2014
@@ -18,10 +18,10 @@ from setuptools import setup, find_packa
min_python = (2, 5)
if sys.version_info < min_python:
- print "Trac requires Python %d.%d or later" % min_python
+ print("Trac requires Python %d.%d or later" % min_python)
sys.exit(1)
if sys.version_info >= (3,):
- print "Trac doesn't support Python 3 (yet)"
+ print("Trac doesn't support Python 3 (yet)")
sys.exit(1)
extra = {}
@@ -49,13 +49,13 @@ except ImportError:
try:
import genshi
except ImportError:
- print "Genshi is needed by Trac setup, pre-installing"
+ print("Genshi is needed by Trac setup, pre-installing")
# give some context to the warnings we might get when installing Genshi
setup(
name = 'Trac',
- version = '1.0.1',
+ version = '1.0.2',
description = 'Integrated SCM, wiki, issue tracker and project environment',
long_description = """
Trac is a minimalistic web-based software project management and bug/issue
@@ -104,6 +104,7 @@ facilities.
],
extras_require = {
'Babel': ['Babel>=0.9.5'],
+ 'ConfigObj': ['ConfigObj'],
'Pygments': ['Pygments>=0.6'],
'reST': ['docutils>=0.3'],
'SilverCity': ['SilverCity>=0.9.4'],
@@ -149,7 +150,7 @@ facilities.
tracopt.mimeview.enscript = tracopt.mimeview.enscript
tracopt.mimeview.php = tracopt.mimeview.php
tracopt.mimeview.silvercity = tracopt.mimeview.silvercity[SilverCity]
- tracopt.perm.authz_policy = tracopt.perm.authz_policy
+ tracopt.perm.authz_policy = tracopt.perm.authz_policy[ConfigObj]
tracopt.perm.config_perm_provider = tracopt.perm.config_perm_provider
tracopt.ticket.clone = tracopt.ticket.clone
tracopt.ticket.commit_updater = tracopt.ticket.commit_updater
Modified: bloodhound/vendor/trac/current/trac/__init__.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/__init__.py?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/__init__.py (original)
+++ bloodhound/vendor/trac/current/trac/__init__.py Thu Feb 13 05:08:02 2014
@@ -16,4 +16,4 @@ from pkg_resources import DistributionNo
try:
__version__ = get_distribution('Trac').version
except DistributionNotFound:
- __version__ = '1.0.1'
+ __version__ = '1.0.2'
Modified: bloodhound/vendor/trac/current/trac/admin/api.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/admin/api.py?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/admin/api.py (original)
+++ bloodhound/vendor/trac/current/trac/admin/api.py Thu Feb 13 05:08:02 2014
@@ -11,15 +11,18 @@
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://trac.edgewall.org/log/.
+import os
import os.path
import sys
import traceback
from trac.core import *
from trac.util.text import levenshtein_distance
-from trac.util.translation import _
+from trac.util.translation import _, get_negotiated_locale, has_babel
+LANG = os.environ.get('LANG')
+
console_date_format = '%Y-%m-%d'
console_datetime_format = '%Y-%m-%d %H:%M:%S'
console_date_format_hint = 'YYYY-MM-DD'
@@ -192,3 +195,21 @@ def get_dir_list(path, dirs_only=False):
except OSError:
pass
return result
+
+
+def get_console_locale(env=None, lang=LANG):
+ """Return negotiated locale for console by LANG environment and
+ [trac] default_language."""
+ if has_babel:
+ from babel.core import Locale, UnknownLocaleError, parse_locale
+ try:
+ lang = '_'.join(filter(None, parse_locale(lang)))
+ except:
+ lang = None
+ default = env.config.get('trac', 'default_language', '') \
+ if env else None
+ try:
+ return get_negotiated_locale([lang, default]) or Locale.default()
+ except UnknownLocaleError:
+ pass
+ return None
Modified: bloodhound/vendor/trac/current/trac/admin/console.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/admin/console.py?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/admin/console.py (original)
+++ bloodhound/vendor/trac/current/trac/admin/console.py Thu Feb 13 05:08:02 2014
@@ -15,7 +15,6 @@
from __future__ import with_statement
import cmd
-import locale
import os.path
import pkg_resources
from shlex import shlex
@@ -24,7 +23,8 @@ import sys
import traceback
from trac import __version__ as VERSION
-from trac.admin import AdminCommandError, AdminCommandManager
+from trac.admin.api import AdminCommandError, AdminCommandManager, \
+ get_console_locale
from trac.core import TracError
from trac.env import Environment
from trac.ticket.model import *
@@ -33,15 +33,15 @@ from trac.util.html import html
from trac.util.text import console_print, exception_to_unicode, printout, \
printerr, raw_input, to_unicode, \
getpreferredencoding
-from trac.util.translation import _, ngettext, get_negotiated_locale, \
- has_babel, cleandoc_
+from trac.util.translation import _, ngettext, has_babel, cleandoc_
from trac.versioncontrol.api import RepositoryManager
from trac.wiki.admin import WikiAdmin
from trac.wiki.macros import WikiMacroBase
+
TRAC_VERSION = pkg_resources.get_distribution('Trac').version
rl_completion_suppress_append = None
-LANG = os.environ.get('LANG')
+
def find_readline_lib():
"""Return the name (and possibly the full path) of the readline library
@@ -67,6 +67,7 @@ class TracAdmin(cmd.Cmd):
envname = None
__env = None
needs_upgrade = None
+ cmd_mgr = None
def __init__(self, envdir=None):
cmd.Cmd.__init__(self)
@@ -146,6 +147,7 @@ Type: '?' or 'help' for help on command
self.prompt = "Trac [%s]> " % self.envname
if env is not None:
self.__env = env
+ self.cmd_mgr = AdminCommandManager(env)
def env_check(self):
if not self.__env:
@@ -168,12 +170,13 @@ Type: '?' or 'help' for help on command
def _init_env(self):
self.__env = env = Environment(self.envname)
+ negotiated = None
# fixup language according to env settings
if has_babel:
- default = env.config.get('trac', 'default_language', '')
- negotiated = get_negotiated_locale([LANG, default])
+ negotiated = get_console_locale(env)
if negotiated:
translation.activate(negotiated)
+ self.cmd_mgr = AdminCommandManager(env)
##
## Utility methods
@@ -240,9 +243,8 @@ Type: '?' or 'help' for help on command
if line and line[-1] == ' ': # Space starts new argument
args.append('')
if self.env_check():
- cmd_mgr = AdminCommandManager(self.env)
try:
- comp = cmd_mgr.complete_command(args, cmd_only)
+ comp = self.cmd_mgr.complete_command(args, cmd_only)
except Exception, e:
printerr()
printerr(_('Completion error: %(err)s',
@@ -281,8 +283,7 @@ Type: '?' or 'help' for help on command
raise TracError(_('The Trac Environment needs to be upgraded.\n\n'
'Run "trac-admin %(path)s upgrade"',
path=self.envname))
- cmd_mgr = AdminCommandManager(self.env)
- return cmd_mgr.execute_command(*args)
+ return self.cmd_mgr.execute_command(*args)
##
## Available Commands
@@ -306,15 +307,14 @@ Type: '?' or 'help' for help on command
if arg[0]:
doc = getattr(self, "_help_" + arg[0], None)
if doc is None and self.env_check():
- cmd_mgr = AdminCommandManager(self.env)
- doc = cmd_mgr.get_command_help(arg)
+ doc = self.cmd_mgr.get_command_help(arg)
if doc:
self.print_doc(doc)
else:
printerr(_("No documentation found for '%(cmd)s'."
" Use 'help' to see the list of commands.",
cmd=' '.join(arg)))
- cmds = cmd_mgr.get_similar_commands(arg[0])
+ cmds = self.cmd_mgr.get_similar_commands(arg[0])
if cmds:
printout('')
printout(ngettext("Did you mean this?",
@@ -557,14 +557,8 @@ def run(args=None):
"""Main entry point."""
if args is None:
args = sys.argv[1:]
- locale = None
if has_babel:
- import babel
- try:
- locale = get_negotiated_locale([LANG]) or babel.Locale.default()
- except babel.UnknownLocaleError:
- pass
- translation.activate(locale)
+ translation.activate(get_console_locale())
admin = TracAdmin()
if len(args) > 0:
if args[0] in ('-h', '--help', 'help'):
Modified: bloodhound/vendor/trac/current/trac/admin/templates/admin_basics.html
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/admin/templates/admin_basics.html?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/admin/templates/admin_basics.html (original)
+++ bloodhound/vendor/trac/current/trac/admin/templates/admin_basics.html Thu Feb 13 05:08:02 2014
@@ -39,15 +39,25 @@ ${project.descr}</textarea>
selected="${tzname == default_timezone or None}">${tzname}</option>
</select>
</label>
+ <span py:if="not has_pytz" class="hint">
+ Install pytz for a complete list of timezones.
+ </span>
</div>
<div class="field">
<label>Default language:<br />
- <select name="default_language">
+ <select name="default_language" disabled="${not languages or None}"
+ title="${_('Translations are currently unavailable') if not languages else None}">
<option value="">Browser's language</option>
<option py:for="locale, language in languages" value="${locale}"
selected="${locale == default_language or None}">${language}</option>
</select>
</label>
+ <span py:if="not has_babel" class="hint">
+ Install Babel for extended language support.
+ </span>
+ <span py:if="has_babel and not languages" class="hint">
+ Message catalogs have not been compiled.
+ </span>
</div>
<div class="field">
<label>Default date format:<br />
@@ -57,6 +67,9 @@ ${project.descr}</textarea>
selected="${default_date_format == 'iso8601' or None}">ISO 8601 format</option>
</select>
</label>
+ <span py:if="not has_babel" class="hint">
+ Install Babel for localized date formats.
+ </span>
</div>
</fieldset>
<div class="buttons">
Modified: bloodhound/vendor/trac/current/trac/admin/templates/admin_perms.html
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/admin/templates/admin_perms.html?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/admin/templates/admin_perms.html (original)
+++ bloodhound/vendor/trac/current/trac/admin/templates/admin_perms.html Thu Feb 13 05:08:02 2014
@@ -13,7 +13,7 @@
<body>
<h2>Manage Permissions and Groups</h2>
- <py:if test="'PERMISSION_GRANT' in perm">
+ <py:if test="'PERMISSION_GRANT' in perm('admin', 'general/perm')">
<form id="addperm" class="addnew" method="post" action="">
<fieldset>
<legend>Grant Permission:</legend>
@@ -22,13 +22,14 @@
</div>
<div class="field">
<label>Action:
- <select id="action" name="action">
- <option py:for="action in sorted(actions)">$action</option>
+ <select id="action" name="action"
+ py:with="allowed_actions = [a for a in actions if a in perm]">
+ <option py:for="action in sorted(allowed_actions)">$action</option>
</select>
</label>
</div>
<div class="buttons">
- <input type="submit" name="add" value="${_('Add')}" />
+ <input type="submit" name="add" class="trac-disable-on-submit" value="${_('Add')}" />
</div>
<p class="help">
Grant permission for an action to a subject, which can be either a user
@@ -47,7 +48,7 @@
<label>Group: <input id="sg_group" type="text" name="group" /></label>
</div>
<div class="buttons">
- <input type="submit" name="add" value="${_('Add')}"/>
+ <input type="submit" name="add" class="trac-disable-on-submit" value="${_('Add')}"/>
</div>
<p class="help">
Add a user or group to an existing permission group.
@@ -56,7 +57,7 @@
</form>
</py:if>
- <form id="revokeform" method="post" action="" py:with="can_revoke = 'PERMISSION_REVOKE' in perm">
+ <form id="revokeform" method="post" action="" py:with="can_revoke = 'PERMISSION_REVOKE' in perm('admin', 'general/perm')">
<h3>Permissions</h3>
<table class="listing" id="permlist">
<thead>
@@ -67,14 +68,18 @@
class="${'odd' if idx % 2 else 'even'}">
<td>$subject</td>
<td>
- <label py:for="subject, action in perm_group">
+ <label py:for="subject, action in perm_group"
+ py:with="invalid = action not in actions; has_perm = action in perm">
<!--! base64 makes it safe to use ':' as separator when passing
both subject and action as one query parameter -->
<input py:if="can_revoke" type="checkbox" name="sel"
+ title="${_('You don\'t have permission to revoke this action')
+ if not has_perm else None}"
value="${'%s:%s' % (unicode_to_base64(subject),
- unicode_to_base64(action))}"/>
- <span py:strip="action in actions" class="missing"
- title="Action is no longer defined">${action}</span>
+ unicode_to_base64(action))}"
+ disabled="${'disabled' if not has_perm else None}" />
+ <span class="${classes(missing=invalid)}"
+ title="${_('%(action)s is no longer defined', action=action) if invalid else action}">${action}</span>
</label>
</td>
</tr>
Modified: bloodhound/vendor/trac/current/trac/admin/templates/admin_plugins.html
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/admin/templates/admin_plugins.html?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/admin/templates/admin_plugins.html (original)
+++ bloodhound/vendor/trac/current/trac/admin/templates/admin_plugins.html Thu Feb 13 05:08:02 2014
@@ -54,7 +54,7 @@
</head>
<body>
- <h2>Manage Plugins</h2>
+ <h2>Manage Plugins <span class="trac-count">(${len(plugins)})</span></h2>
<form id="addplug" class="addnew" method="post" enctype="multipart/form-data" action="">
<fieldset>
@@ -65,8 +65,8 @@
</label>
</div>
<div class="buttons">
- <input type="submit" name="install" value="${_('Install')}"
- disabled="${readonly or None}" />
+ <input type="submit" name="install" class="trac-disable-on-submit"
+ value="${_('Install')}" disabled="${readonly or None}" />
</div>
<p class="help" py:choose="readonly">
<py:when test="True">
@@ -80,7 +80,7 @@
</fieldset>
</form>
- <form py:for="idx, plugin in enumerate(plugins)" method="post" action="">
+ <form py:for="idx, plugin in enumerate(plugins)" id="edit-plugin-${plugin.name.lower()}" method="post" action="">
<div class="plugin" id="trac-plugin-${plugin.name}">
<h3 class="foldable">${plugin.name} ${plugin.version}</h3>
<!--! FIXME: Plugin uninstall disabled as it is unreliable (#3545)
@@ -148,7 +148,7 @@
</p>
<div py:if="module.description" xml:space="preserve">${safe_wiki_to_html(context, module.description)}</div>
</td>
- <td class="sel"></td>
+ <td class="sel trac-module"></td>
</tr>
<tr py:for="component_name, component in sorted(module.components.iteritems())">
<td py:with="show_doc = show == plugin.name or show == component.full_name" id="trac-comp-${component.full_name}"
@@ -164,7 +164,7 @@
</p>
<div py:if="component.description" xml:space="preserve">${safe_wiki_to_html(context, component.description)}</div>
</td>
- <td class="sel">
+ <td class="sel trac-component">
<input py:if="not component.required" type="hidden" name="component"
value="${module_name}.${component_name}" />
<input type="checkbox" name="enable"
Modified: bloodhound/vendor/trac/current/trac/admin/tests/__init__.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/admin/tests/__init__.py?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/admin/tests/__init__.py (original)
+++ bloodhound/vendor/trac/current/trac/admin/tests/__init__.py Thu Feb 13 05:08:02 2014
@@ -1,3 +1,16 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2005-2013 Edgewall Software
+# All rights reserved.
+#
+# 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.org/wiki/TracLicense.
+#
+# 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/log/.
+
import unittest
from trac.admin.tests import console
Modified: bloodhound/vendor/trac/current/trac/admin/tests/console-tests.txt
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/admin/tests/console-tests.txt?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/admin/tests/console-tests.txt (original)
+++ bloodhound/vendor/trac/current/trac/admin/tests/console-tests.txt Thu Feb 13 05:08:02 2014
@@ -54,7 +54,7 @@ resolution remove Remove a resolution
session add Create a session for the given sid
session delete Delete the session of the specified sid
session list List the name and email for the given sids
-session purge Purge all anonymous sessions older than the given age
+session purge Purge all anonymous sessions older than the given age or date
session set Set the name or email attribute of the given sid
severity add Add a severity value option
severity change Change a severity value
@@ -87,6 +87,8 @@ wiki upgrade Upgrade default wik
Name Size Author Date Description
-------------------------------------
+===== test_attachment_add_nonexistent_resource =====
+ResourceNotFound: NonExistentPage doesn't exist, can't create attachment
===== test_config_get =====
Test project
===== test_config_set =====
@@ -357,9 +359,11 @@ Available actions:
WIKI_MODIFY, WIKI_RENAME, WIKI_VIEW
===== test_permission_remove_unknown_user =====
-Error: Cannot remove permission TICKET_VIEW for user joe.
+Error: Cannot remove permission TICKET_VIEW for user joe. The user has not been granted the permission.
===== test_permission_remove_action_not_granted =====
-Error: Cannot remove permission TICKET_CREATE for user anonymous.
+Error: Cannot remove permission TICKET_CREATE for user anonymous. The user has not been granted the permission.
+===== test_permission_remove_action_granted_through_meta_permission =====
+Error: Cannot remove permission WIKI_VIEW for user joe. The permission is granted through a meta-permission or group.
===== test_permission_export_ok =====
anonymous,BROWSER_VIEW,CHANGESET_VIEW,FILE_VIEW,LOG_VIEW,MILESTONE_VIEW,REPORT_SQL_VIEW,REPORT_VIEW,ROADMAP_VIEW,SEARCH_VIEW,TICKET_VIEW,TIMELINE_VIEW,WIKI_VIEW
authenticated,TICKET_CREATE,TICKET_MODIFY,WIKI_CREATE,WIKI_MODIFY
@@ -412,6 +416,14 @@ Name Owner
-----------------------
component1 somebody
component2 somebody
+new_component
+
+===== test_component_add_optional_owner_ok =====
+
+Name Owner
+-----------------------
+component1 somebody
+component2 somebody
new_component new_user
===== test_component_add_error_already_exists =====
@@ -720,6 +732,8 @@ milestone4
===== test_milestone_add_error_already_exists =====
IntegrityError: [...]
+===== test_milestone_add_invalid_date =====
+TracError: "<add>" is an invalid date, or the date format is not known. Try "%(hint)s" or "%(isohint)s" instead.
===== test_milestone_rename_ok =====
Name Due Completed
@@ -751,6 +765,8 @@ milestone4
===== test_milestone_due_error_bad_milestone =====
ResourceNotFound: Milestone bad_milestone does not exist.
+===== test_milestone_due_invalid_date =====
+TracError: "<due>" is an invalid date, or the date format is not known. Try "%(hint)s" or "%(isohint)s" instead.
===== test_milestone_completed_ok =====
Name Due Completed
@@ -762,6 +778,8 @@ milestone4
===== test_milestone_completed_error_bad_milestone =====
ResourceNotFound: Milestone bad_milestone does not exist.
+===== test_milestone_completed_invalid_date =====
+TracError: "<com>" is an invalid date, or the date format is not known. Try "%(hint)s" or "%(isohint)s" instead.
===== test_milestone_remove_ok =====
Name Due Completed
@@ -1013,3 +1031,5 @@ name17 0 2010-01-18 val17 val17
name18 0 2010-01-19 val18 val18
name19 0 2010-01-20 val19 val19
+===== test_session_purge_invalid_date =====
+TracError: "<purge>" is an invalid date, or the date format is not known. Try "%(hint)s" or "%(isohint)s" instead.
Modified: bloodhound/vendor/trac/current/trac/admin/tests/console.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/admin/tests/console.py?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/admin/tests/console.py (original)
+++ bloodhound/vendor/trac/current/trac/admin/tests/console.py Thu Feb 13 05:08:02 2014
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
-# Copyright (C) 2004-2009 Edgewall Software
+# Copyright (C) 2004-2013 Edgewall Software
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
@@ -42,9 +42,13 @@ import trac.search.web_ui
import trac.timeline.web_ui
import trac.wiki.web_ui
-from trac.admin import console, console_date_format
+from trac.admin import console
+from trac.admin.api import AdminCommandManager, console_date_format, \
+ get_console_locale
from trac.test import EnvironmentStub
-from trac.util.datefmt import format_date, get_date_format_hint
+from trac.util.datefmt import format_date, get_date_format_hint, \
+ get_datetime_format_hint
+from trac.util.translation import get_available_locales, has_babel
from trac.web.tests.session import _prep_session_table
STRIP_TRAILING_SPACE = re.compile(r'( +)$', re.MULTILINE)
@@ -123,8 +127,17 @@ class TracadminTestCase(unittest.TestCas
sys.stderr = _err
sys.stdout = _out
+ @property
+ def _datetime_format_hint(self):
+ return get_datetime_format_hint(get_console_locale(self.env))
+
+ def _get_command_help(self, *args):
+ docs = AdminCommandManager(self.env).get_command_help(list(args))
+ self.assertEqual(1, len(docs))
+ return docs[0][2]
+
def assertEqual(self, expected_results, output):
- if not (isinstance(expected_results, basestring) and \
+ if not (isinstance(expected_results, basestring) and
isinstance(output, basestring)):
return unittest.TestCase.assertEqual(self, expected_results, output)
def diff():
@@ -161,6 +174,61 @@ class TracadminTestCase(unittest.TestCas
self.assertEqual(0, rv)
self.assertEqual(expected_results, output)
+ # Locale test
+
+ def _test_get_console_locale_with_babel(self):
+ from babel.core import Locale, UnknownLocaleError
+ locales = get_available_locales()
+ en_US = Locale.parse('en_US')
+ de = Locale.parse('de')
+ de_DE = Locale.parse('de_DE')
+ try:
+ default = Locale.default()
+ except UnknownLocaleError:
+ default = None
+
+ language = self.env.config.get('trac', 'default_language')
+ try:
+ self.assertEqual(default, get_console_locale(None, None))
+ self.env.config.set('trac', 'default_language', '')
+ if 'de' in locales:
+ self.assertEqual(de, get_console_locale(None, 'de_DE.UTF8'))
+ self.env.config.set('trac', 'default_language', 'de')
+ self.assertEqual(de, get_console_locale(self.env, None))
+ self.assertEqual(de, get_console_locale(self.env, 'C'))
+ self.env.config.set('trac', 'default_language', 'en_US')
+ self.assertEqual(en_US, get_console_locale(self.env, None))
+ self.assertEqual(en_US, get_console_locale(self.env, 'C'))
+ self.assertEqual(de, get_console_locale(self.env,
+ 'de_DE.UTF8'))
+ if not locales: # compiled catalog is missing
+ self.assertEqual(default, get_console_locale(None,
+ 'de_DE.UTF8'))
+ self.env.config.set('trac', 'default_language', 'de')
+ self.assertEqual(default, get_console_locale(self.env, None))
+ self.assertEqual(default, get_console_locale(self.env, 'C'))
+ self.env.config.set('trac', 'default_language', 'en_US')
+ self.assertEqual(en_US, get_console_locale(self.env, None))
+ self.assertEqual(en_US, get_console_locale(self.env, 'C'))
+ self.assertEqual(en_US, get_console_locale(self.env,
+ 'de_DE.UTF8'))
+ finally:
+ self.env.config.set('trac', 'default_language', language)
+
+ def _test_get_console_locale_without_babel(self):
+ self.assertEqual(None, get_console_locale(None, 'en_US.UTF8'))
+ language = self.env.config.get('trac', 'default_language')
+ try:
+ self.env.config.set('trac', 'default_language', 'en_US')
+ self.assertEqual(None, get_console_locale(self.env, 'en_US.UTF8'))
+ finally:
+ self.env.config.set('trac', 'default_language', language)
+
+ if has_babel:
+ test_get_console_locale = _test_get_console_locale_with_babel
+ else:
+ test_get_console_locale = _test_get_console_locale_without_babel
+
# Attachment tests
def test_attachment_list_empty(self):
@@ -177,6 +245,15 @@ class TracadminTestCase(unittest.TestCas
self.assertEqual(0, rv)
self.assertEqual(self.expected_results[test_name], output)
+ def test_attachment_add_nonexistent_resource(self):
+ """Tests the 'attachment add' command in trac-admin, on a non-existent
+ resource."""
+ test_name = sys._getframe().f_code.co_name
+ rv, output = self._execute('attachment add wiki:NonExistentPage %s'
+ % __file__)
+ self.assertEqual(2, rv)
+ self.assertEqual(self.expected_results[test_name], output)
+
# Config tests
def test_config_get(self):
@@ -334,6 +411,17 @@ class TracadminTestCase(unittest.TestCas
self.assertEqual(2, rv)
self.assertEqual(self.expected_results[test_name], output)
+ def test_permission_remove_action_granted_through_meta_permission(self):
+ """
+ Tests the 'permission remove' command in trac-admin. This particular
+ test tries removing WIKI_VIEW from a user. WIKI_VIEW has been granted
+ through user anonymous."""
+ test_name = sys._getframe().f_code.co_name
+ self._execute('permission add joe TICKET_VIEW')
+ rv, output = self._execute('permission remove joe WIKI_VIEW')
+ self.assertEqual(2, rv)
+ self.assertEqual(self.expected_results[test_name], output)
+
def test_permission_export_ok(self):
"""
Tests the 'permission export' command in trac-admin. This particular
@@ -381,6 +469,18 @@ class TracadminTestCase(unittest.TestCas
test passes valid arguments and checks for success.
"""
test_name = sys._getframe().f_code.co_name
+ self._execute('component add new_component')
+ rv, output = self._execute('component list')
+ self.assertEqual(0, rv)
+ self.assertEqual(self.expected_results[test_name], output)
+
+ def test_component_add_optional_owner_ok(self):
+ """
+ Tests the 'component add' command in trac-admin with the optional
+ 'owner' argument. This particular test passes valid arguments and
+ checks for success.
+ """
+ test_name = sys._getframe().f_code.co_name
self._execute('component add new_component new_user')
rv, output = self._execute('component list')
self.assertEqual(0, rv)
@@ -449,7 +549,7 @@ class TracadminTestCase(unittest.TestCas
rv, output = self._execute('component chown bad_component changed_owner')
self.assertEqual(2, rv)
# We currently trigger a deprecation warning with py26 so we
- # can currrently only verify that the end of the output string is
+ # can currently only verify that the end of the output string is
# correct
self.assertEqual(output.endswith(self.expected_results[test_name]), True)
@@ -993,7 +1093,7 @@ class TracadminTestCase(unittest.TestCas
"""
test_name = sys._getframe().f_code.co_name
self._execute(u'milestone add \xa9tat_final "%s"' #\xc2\xa9
- % self._test_date)
+ % self._test_date)
rv, output = self._execute('milestone list')
self.assertEqual(0, rv)
self.assertEqual(self.expected_results[test_name], output)
@@ -1010,6 +1110,15 @@ class TracadminTestCase(unittest.TestCas
self.assertEqual(2, rv)
self.assertEqual(self.expected_results[test_name], output)
+ def test_milestone_add_invalid_date(self):
+ test_name = sys._getframe().f_code.co_name
+ rv, output = self._execute('milestone add new_milestone <add>')
+ self.assertEqual(2, rv)
+ self.assertEqual(self.expected_results[test_name] %
+ {'hint': self._datetime_format_hint,
+ 'isohint': get_datetime_format_hint('iso8601')},
+ output)
+
def test_milestone_rename_ok(self):
"""
Tests the 'milestone rename' command in trac-admin. This particular
@@ -1065,6 +1174,15 @@ class TracadminTestCase(unittest.TestCas
self.assertEqual(2, rv)
self.assertEqual(self.expected_results[test_name], output)
+ def test_milestone_due_invalid_date(self):
+ test_name = sys._getframe().f_code.co_name
+ rv, output = self._execute('milestone due milestone1 <due>')
+ self.assertEqual(2, rv)
+ self.assertEqual(self.expected_results[test_name] %
+ {'hint': self._datetime_format_hint,
+ 'isohint': get_datetime_format_hint('iso8601')},
+ output)
+
def test_milestone_completed_ok(self):
"""
Tests the 'milestone completed' command in trac-admin. This particular
@@ -1089,6 +1207,15 @@ class TracadminTestCase(unittest.TestCas
self.assertEqual(2, rv)
self.assertEqual(self.expected_results[test_name], output)
+ def test_milestone_completed_invalid_date(self):
+ test_name = sys._getframe().f_code.co_name
+ rv, output = self._execute('milestone completed milestone1 <com>')
+ self.assertEqual(2, rv)
+ self.assertEqual(self.expected_results[test_name] %
+ {'hint': self._datetime_format_hint,
+ 'isohint': get_datetime_format_hint('iso8601')},
+ output)
+
def test_milestone_remove_ok(self):
"""
Tests the 'milestone remove' command in trac-admin. This particular
@@ -1171,20 +1298,20 @@ class TracadminTestCase(unittest.TestCas
self.assertEqual(0, rv)
self.assertEqual(self.expected_results[test_name], output)
- def test_session_add_missing_sid(self):
+ def test_session_add_missing_sid(self):
test_name = sys._getframe().f_code.co_name
rv, output = self._execute('session add')
self.assertEqual(2, rv)
self.assertEqual(self.expected_results[test_name], output)
- def test_session_add_duplicate_sid(self):
+ def test_session_add_duplicate_sid(self):
test_name = sys._getframe().f_code.co_name
_prep_session_table(self.env)
rv, output = self._execute('session add name00')
self.assertEqual(2, rv)
self.assertEqual(self.expected_results[test_name], output)
- def test_session_add_sid_all(self):
+ def test_session_add_sid_all(self):
test_name = sys._getframe().f_code.co_name
rv, output = self._execute('session add john John john@example.org')
self.assertEqual(0, rv)
@@ -1193,7 +1320,7 @@ class TracadminTestCase(unittest.TestCas
% {'today': format_date(None, console_date_format)},
output)
- def test_session_add_sid(self):
+ def test_session_add_sid(self):
test_name = sys._getframe().f_code.co_name
rv, output = self._execute('session add john')
self.assertEqual(0, rv)
@@ -1202,7 +1329,7 @@ class TracadminTestCase(unittest.TestCas
% {'today': format_date(None, console_date_format)},
output)
- def test_session_add_sid_name(self):
+ def test_session_add_sid_name(self):
test_name = sys._getframe().f_code.co_name
rv, output = self._execute('session add john John')
self.assertEqual(0, rv)
@@ -1211,7 +1338,7 @@ class TracadminTestCase(unittest.TestCas
% {'today': format_date(None, console_date_format)},
output)
- def test_session_set_attr_name(self):
+ def test_session_set_attr_name(self):
test_name = sys._getframe().f_code.co_name
_prep_session_table(self.env)
rv, output = self._execute('session set name name00 JOHN')
@@ -1219,7 +1346,7 @@ class TracadminTestCase(unittest.TestCas
rv, output = self._execute('session list name00')
self.assertEqual(self.expected_results[test_name], output)
- def test_session_set_attr_email(self):
+ def test_session_set_attr_email(self):
test_name = sys._getframe().f_code.co_name
_prep_session_table(self.env)
rv, output = self._execute('session set email name00 JOHN@EXAMPLE.ORG')
@@ -1227,31 +1354,31 @@ class TracadminTestCase(unittest.TestCas
rv, output = self._execute('session list name00')
self.assertEqual(self.expected_results[test_name], output)
- def test_session_set_attr_missing_attr(self):
+ def test_session_set_attr_missing_attr(self):
test_name = sys._getframe().f_code.co_name
rv, output = self._execute('session set')
self.assertEqual(2, rv)
self.assertEqual(self.expected_results[test_name], output)
- def test_session_set_attr_missing_value(self):
+ def test_session_set_attr_missing_value(self):
test_name = sys._getframe().f_code.co_name
rv, output = self._execute('session set name john')
self.assertEqual(2, rv)
self.assertEqual(self.expected_results[test_name], output)
- def test_session_set_attr_missing_sid(self):
+ def test_session_set_attr_missing_sid(self):
test_name = sys._getframe().f_code.co_name
rv, output = self._execute('session set name')
self.assertEqual(2, rv)
self.assertEqual(self.expected_results[test_name], output)
- def test_session_set_attr_nonexistent_sid(self):
+ def test_session_set_attr_nonexistent_sid(self):
test_name = sys._getframe().f_code.co_name
rv, output = self._execute('session set name john foo')
self.assertEqual(2, rv)
self.assertEqual(self.expected_results[test_name], output)
- def test_session_delete_sid(self):
+ def test_session_delete_sid(self):
test_name = sys._getframe().f_code.co_name
_prep_session_table(self.env)
rv, output = self._execute('session delete name00')
@@ -1259,13 +1386,13 @@ class TracadminTestCase(unittest.TestCas
rv, output = self._execute('session list nam00')
self.assertEqual(self.expected_results[test_name], output)
- def test_session_delete_missing_params(self):
+ def test_session_delete_missing_params(self):
test_name = sys._getframe().f_code.co_name
rv, output = self._execute('session delete')
self.assertEqual(0, rv)
self.assertEqual(self.expected_results[test_name], output)
- def test_session_delete_anonymous(self):
+ def test_session_delete_anonymous(self):
test_name = sys._getframe().f_code.co_name
_prep_session_table(self.env)
rv, output = self._execute('session delete anonymous')
@@ -1282,7 +1409,7 @@ class TracadminTestCase(unittest.TestCas
rv, output = self._execute('session list *')
self.assertEqual(self.expected_results[test_name], output)
- def test_session_purge_age(self):
+ def test_session_purge_age(self):
test_name = sys._getframe().f_code.co_name
_prep_session_table(self.env, spread_visits=True)
rv, output = self._execute('session purge 20100112')
@@ -1290,9 +1417,38 @@ class TracadminTestCase(unittest.TestCas
rv, output = self._execute('session list *')
self.assertEqual(self.expected_results[test_name], output)
+ def test_session_purge_invalid_date(self):
+ test_name = sys._getframe().f_code.co_name
+ rv, output = self._execute('session purge <purge>')
+ self.assertEqual(2, rv)
+ self.assertEqual(self.expected_results[test_name] %
+ {'hint': self._datetime_format_hint,
+ 'isohint': get_datetime_format_hint('iso8601')},
+ output)
+
+ def test_help_milestone_due(self):
+ doc = self._get_command_help('milestone', 'due')
+ self.assertIn(self._datetime_format_hint, doc)
+ self.assertIn(u'"YYYY-MM-DDThh:mm:ss±hh:mm"', doc)
+
+ def test_help_milestone_completed(self):
+ doc = self._get_command_help('milestone', 'completed')
+ self.assertIn(self._datetime_format_hint, doc)
+ self.assertIn(u'"YYYY-MM-DDThh:mm:ss±hh:mm"', doc)
+
+ def test_help_version_time(self):
+ doc = self._get_command_help('version', 'time')
+ self.assertIn(self._datetime_format_hint, doc)
+ self.assertIn(u'"YYYY-MM-DDThh:mm:ss±hh:mm"', doc)
+
+ def test_help_session_purge(self):
+ doc = self._get_command_help('session', 'purge')
+ self.assertIn(u'"YYYY-MM-DDThh:mm:ss±hh:mm"', doc)
+
def suite():
- return unittest.makeSuite(TracadminTestCase, 'test')
+ return unittest.makeSuite(TracadminTestCase)
+
if __name__ == '__main__':
- unittest.main()
+ unittest.main(defaultTest='suite')
Modified: bloodhound/vendor/trac/current/trac/admin/tests/functional.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/admin/tests/functional.py?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/admin/tests/functional.py (original)
+++ bloodhound/vendor/trac/current/trac/admin/tests/functional.py Thu Feb 13 05:08:02 2014
@@ -1,7 +1,68 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2009-2013 Edgewall Software
+# All rights reserved.
+#
+# 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.org/wiki/TracLicense.
+#
+# 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/log/.
+
from trac.tests.functional import *
from trac.util.text import unicode_to_base64, unicode_from_base64
+
+class AuthorizationTestCaseSetup(FunctionalTwillTestCaseSetup):
+ def test_authorization(self, href, perms, h2_text):
+ """Check permissions required to access an administration panel. A
+ fine-grained permissions test will also be executed if ConfigObj is
+ installed.
+
+ :param href: the relative href of the administration panel
+ :param perms: list or tuple of permissions required to access
+ the administration panel
+ :param h2_text: the body of the h2 heading on the administration
+ panel"""
+ self._tester.go_to_front()
+ self._tester.logout()
+ self._tester.login('user')
+ if isinstance(perms, basestring):
+ perms = (perms, )
+
+ h2 = r'<h2>[ \t\n]*%s[ \t\n]*' \
+ r'( <span class="trac-count">\(\d+\)</span>)?[ \t\n]*</h2>'
+ try:
+ for perm in perms:
+ try:
+ tc.go(href)
+ tc.find("No administration panels available")
+ self._testenv.grant_perm('user', perm)
+ tc.go(href)
+ tc.find(h2 % h2_text)
+ finally:
+ self._testenv.revoke_perm('user', perm)
+ try:
+ tc.go(href)
+ tc.find("No administration panels available")
+ self._testenv.enable_authz_permpolicy({
+ href.strip('/').replace('/', ':', 1): {'user': perm},
+ })
+ tc.go(href)
+ tc.find(h2 % h2_text)
+ except ImportError:
+ pass
+ finally:
+ self._testenv.disable_authz_permpolicy()
+ finally:
+ self._tester.go_to_front()
+ self._tester.logout()
+ self._tester.login('admin')
+
+
class TestBasicSettings(FunctionalTwillTestCaseSetup):
def runTest(self):
"""Check basic settings."""
@@ -11,24 +72,36 @@ class TestBasicSettings(FunctionalTwillT
tc.find('https://my.example.com/something')
+class TestBasicSettingsAuthorization(AuthorizationTestCaseSetup):
+ def runTest(self):
+ """Check permissions required to access Basic Settings panel."""
+ self.test_authorization('/admin/general/basics', 'TRAC_ADMIN',
+ "Basic Settings")
+
+
class TestLoggingNone(FunctionalTwillTestCaseSetup):
def runTest(self):
"""Turn off logging."""
# For now, we just check that it shows up.
- self._tester.go_to_admin()
- tc.follow('Logging')
+ self._tester.go_to_admin("Logging")
tc.find('trac.log')
tc.formvalue('modlog', 'log_type', 'none')
tc.submit()
tc.find('selected="selected">None</option')
+class TestLoggingAuthorization(AuthorizationTestCaseSetup):
+ def runTest(self):
+ """Check permissions required to access Logging panel."""
+ self.test_authorization('/admin/general/logging', 'TRAC_ADMIN',
+ "Logging")
+
+
class TestLoggingToFile(FunctionalTwillTestCaseSetup):
def runTest(self):
"""Turn logging back on."""
# For now, we just check that it shows up.
- self._tester.go_to_admin()
- tc.follow('Logging')
+ self._tester.go_to_admin("Logging")
tc.find('trac.log')
tc.formvalue('modlog', 'log_type', 'file')
tc.formvalue('modlog', 'log_file', 'trac.log2')
@@ -43,8 +116,7 @@ class TestLoggingToFileNormal(Functional
def runTest(self):
"""Setting logging back to normal."""
# For now, we just check that it shows up.
- self._tester.go_to_admin()
- tc.follow('Logging')
+ self._tester.go_to_admin("Logging")
tc.find('trac.log')
tc.formvalue('modlog', 'log_file', 'trac.log')
tc.formvalue('modlog', 'log_level', 'DEBUG')
@@ -54,11 +126,18 @@ class TestLoggingToFileNormal(Functional
tc.find('selected="selected">DEBUG</option>')
+class TestPermissionsAuthorization(AuthorizationTestCaseSetup):
+ def runTest(self):
+ """Check permissions required to access Permissions panel."""
+ self.test_authorization('/admin/general/perm',
+ ('PERMISSION_GRANT', 'PERMISSION_REVOKE'),
+ "Manage Permissions and Groups")
+
+
class TestCreatePermissionGroup(FunctionalTwillTestCaseSetup):
def runTest(self):
"""Create a permissions group"""
- self._tester.go_to_admin()
- tc.follow('Permissions')
+ self._tester.go_to_admin("Permissions")
tc.find('Manage Permissions')
tc.formvalue('addperm', 'gp_subject', 'somegroup')
tc.formvalue('addperm', 'action', 'REPORT_CREATE')
@@ -71,8 +150,7 @@ class TestCreatePermissionGroup(Function
class TestAddUserToGroup(FunctionalTwillTestCaseSetup):
def runTest(self):
"""Add a user to a permissions group"""
- self._tester.go_to_admin()
- tc.follow('Permissions')
+ self._tester.go_to_admin("Permissions")
tc.find('Manage Permissions')
tc.formvalue('addsubj', 'sg_subject', 'authenticated')
tc.formvalue('addsubj', 'sg_group', 'somegroup')
@@ -85,8 +163,7 @@ class TestAddUserToGroup(FunctionalTwill
class TestRemoveUserFromGroup(FunctionalTwillTestCaseSetup):
def runTest(self):
"""Remove a user from a permissions group"""
- self._tester.go_to_admin()
- tc.follow('Permissions')
+ self._tester.go_to_admin("Permissions")
tc.find('Manage Permissions')
authenticated = unicode_to_base64('authenticated')
somegroup = unicode_to_base64('somegroup')
@@ -99,8 +176,7 @@ class TestRemoveUserFromGroup(Functional
class TestRemovePermissionGroup(FunctionalTwillTestCaseSetup):
def runTest(self):
"""Remove a permissions group"""
- self._tester.go_to_admin()
- tc.follow('Permissions')
+ self._tester.go_to_admin("Permissions")
tc.find('Manage Permissions')
somegroup = unicode_to_base64('somegroup')
REPORT_CREATE = unicode_to_base64('REPORT_CREATE')
@@ -114,25 +190,144 @@ class TestRemovePermissionGroup(Function
class TestPluginSettings(FunctionalTwillTestCaseSetup):
def runTest(self):
"""Check plugin settings."""
- self._tester.go_to_admin()
- tc.follow('Plugins')
+ self._tester.go_to_admin("Plugins")
tc.find('Manage Plugins')
tc.find('Install Plugin')
+class TestPluginsAuthorization(AuthorizationTestCaseSetup):
+ def runTest(self):
+ """Check permissions required to access Logging panel."""
+ self.test_authorization('/admin/general/plugin', 'TRAC_ADMIN',
+ "Manage Plugins")
+
+
+class RegressionTestTicket10752(FunctionalTwillTestCaseSetup):
+ def runTest(self):
+ """Test for regression of http://trac.edgewall.org/ticket/10752
+ Permissions on the web admin page should be greyed out when they
+ are no longer defined.
+ """
+ env = self._testenv.get_trac_environment()
+ env.db_transaction("INSERT INTO permission VALUES (%s,%s)",
+ ('anonymous', 'MISSING_PERMISSION'))
+ env.config.touch()
+
+ self._tester.go_to_admin("Permissions")
+ tc.find('<span class="missing" '
+ 'title="MISSING_PERMISSION is no longer defined">'
+ 'MISSING_PERMISSION</span>')
+
+
+class RegressionTestTicket11069(FunctionalTwillTestCaseSetup):
+ def runTest(self):
+ """Test for regression of http://trac.edgewall.org/ticket/11069
+ The permissions list should only be populated with permissions that
+ the user can grant."""
+ self._tester.go_to_front()
+ self._tester.logout()
+ self._tester.login('user')
+ self._testenv.grant_perm('user', 'PERMISSION_GRANT')
+ env = self._testenv.get_trac_environment()
+ from trac.perm import PermissionSystem
+ user_perms = PermissionSystem(env).get_user_permissions('user')
+ all_actions = PermissionSystem(env).get_actions()
+ try:
+ self._tester.go_to_admin("Permissions")
+ for action in all_actions:
+ option = r"<option>%s</option>" % action
+ if action in user_perms and user_perms[action] is True:
+ tc.find(option)
+ else:
+ tc.notfind(option)
+ finally:
+ self._testenv.revoke_perm('user', 'PERMISSION_GRANT')
+ self._tester.go_to_front()
+ self._tester.logout()
+ self._tester.login('admin')
+
+
+class RegressionTestTicket11095(FunctionalTwillTestCaseSetup):
+ """Test for regression of http://trac.edgewall.org/ticket/11095
+ The permission is truncated if it overflows the available space (CSS)
+ and the full permission name is shown in the title on hover.
+ """
+ def runTest(self):
+ self._tester.go_to_admin("Permissions")
+ tc.find('<span title="MILESTONE_VIEW">MILESTONE_VIEW</span>')
+ tc.find('<span title="WIKI_VIEW">WIKI_VIEW</span>')
+
+
+class RegressionTestTicket11117(FunctionalTwillTestCaseSetup):
+ """Test for regression of http://trac.edgewall.org/ticket/11117
+ Hint should be shown on the Basic Settings admin panel when pytz is not
+ installed.
+ """
+ def runTest(self):
+ self._tester.go_to_admin("Basic Settings")
+ pytz_hint = "Install pytz for a complete list of timezones."
+ from trac.util.datefmt import pytz
+ if pytz is None:
+ tc.find(pytz_hint)
+ else:
+ tc.notfind(pytz_hint)
+
+
+class RegressionTestTicket11257(FunctionalTwillTestCaseSetup):
+ """Test for regression of http://trac.edgewall.org/ticket/11257
+ Hints should be shown on the Basic Settings admin panel when Babel is not
+ installed.
+ """
+ def runTest(self):
+ from trac.util.translation import get_available_locales, has_babel
+
+ babel_hint_lang = "Install Babel for extended language support."
+ babel_hint_date = "Install Babel for localized date formats."
+ catalog_hint = "Message catalogs have not been compiled."
+ language_select = '<select name="default_language">'
+ disabled_language_select = \
+ '<select name="default_language" disabled="disabled" ' \
+ 'title="Translations are currently unavailable">'
+
+ self._tester.go_to_admin("Basic Settings")
+ if has_babel:
+ tc.notfind(babel_hint_lang)
+ tc.notfind(babel_hint_date)
+ if get_available_locales():
+ tc.find(language_select)
+ tc.notfind(catalog_hint)
+ else:
+ tc.find(disabled_language_select)
+ tc.find(catalog_hint)
+ else:
+ tc.find(disabled_language_select)
+ tc.find(babel_hint_lang)
+ tc.find(babel_hint_date)
+ tc.notfind(catalog_hint)
+
+
def functionalSuite(suite=None):
if not suite:
- import trac.tests.functional.testcases
- suite = trac.tests.functional.testcases.functionalSuite()
+ import trac.tests.functional
+ suite = trac.tests.functional.functionalSuite()
suite.addTest(TestBasicSettings())
+ suite.addTest(TestBasicSettingsAuthorization())
suite.addTest(TestLoggingNone())
+ suite.addTest(TestLoggingAuthorization())
suite.addTest(TestLoggingToFile())
suite.addTest(TestLoggingToFileNormal())
+ suite.addTest(TestPermissionsAuthorization())
suite.addTest(TestCreatePermissionGroup())
suite.addTest(TestAddUserToGroup())
suite.addTest(TestRemoveUserFromGroup())
suite.addTest(TestRemovePermissionGroup())
suite.addTest(TestPluginSettings())
+ suite.addTest(TestPluginsAuthorization())
+ suite.addTest(RegressionTestTicket10752())
+ suite.addTest(RegressionTestTicket11069())
+ suite.addTest(RegressionTestTicket11095())
+ suite.addTest(RegressionTestTicket11117())
+ suite.addTest(RegressionTestTicket11257())
return suite
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=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/admin/web_ui.py (original)
+++ bloodhound/vendor/trac/current/trac/admin/web_ui.py Thu Feb 13 05:08:02 2014
@@ -34,9 +34,9 @@ from trac.admin.api import IAdminPanelPr
from trac.core import *
from trac.loader import get_plugin_info, get_plugins_dir
from trac.perm import PermissionSystem, IPermissionRequestor
-from trac.util.datefmt import all_timezones
+from trac.util.datefmt import all_timezones, pytz
from trac.util.text import exception_to_unicode, \
- unicode_to_base64, unicode_from_base64
+ unicode_to_base64, unicode_from_base64
from trac.util.translation import _, get_available_locales, ngettext
from trac.web import HTTPNotFound, IRequestHandler
from trac.web.chrome import add_notice, add_stylesheet, \
@@ -111,8 +111,8 @@ class AdminModule(Component):
path_info = req.args.get('path_info')
if not panel_id:
try:
- panel_id = filter(
- lambda panel: panel[0] == cat_id, panels)[0][2]
+ panel_id = \
+ filter(lambda panel: panel[0] == cat_id, panels)[0][2]
except IndexError:
raise HTTPNotFound(_('Unknown administration panel'))
@@ -206,19 +206,19 @@ class BasicsAdminPanel(Component):
# IAdminPanelProvider methods
def get_admin_panels(self, req):
- if 'TRAC_ADMIN' in req.perm:
+ if 'TRAC_ADMIN' in req.perm('admin', 'general/basics'):
yield ('general', _('General'), 'basics', _('Basic Settings'))
def render_admin_panel(self, req, cat, page, path_info):
- req.perm.require('TRAC_ADMIN')
-
if Locale:
- locales = [Locale.parse(locale)
- for locale in get_available_locales()]
- languages = sorted((str(locale), locale.display_name)
- for locale in locales)
+ locale_ids = get_available_locales()
+ locales = [Locale.parse(locale) for locale in locale_ids]
+ # don't use str(locale) to prevent storing expanded locale
+ # identifier, see #11258
+ languages = sorted((id, locale.display_name)
+ for id, locale in zip(locale_ids, locales))
else:
- locales, languages = [], []
+ locale_ids, locales, languages = [], [], []
if req.method == 'POST':
for option in ('name', 'url', 'descr'):
@@ -230,7 +230,7 @@ class BasicsAdminPanel(Component):
self.config.set('trac', 'default_timezone', default_timezone)
default_language = req.args.get('default_language')
- if default_language not in locales:
+ if default_language not in locale_ids:
default_language = ''
self.config.set('trac', 'default_language', default_language)
@@ -249,9 +249,11 @@ class BasicsAdminPanel(Component):
data = {
'default_timezone': default_timezone,
'timezones': all_timezones,
+ 'has_pytz': pytz is not None,
'default_language': default_language.replace('-', '_'),
'languages': languages,
'default_date_format': default_date_format,
+ 'has_babel': Locale is not None,
}
Chrome(self.env).add_textarea_grips(req)
return 'admin_basics.html', data
@@ -264,7 +266,7 @@ class LoggingAdminPanel(Component):
# IAdminPanelProvider methods
def get_admin_panels(self, req):
- if 'TRAC_ADMIN' in req.perm:
+ if 'TRAC_ADMIN' in req.perm('admin', 'general/logging'):
yield ('general', _('General'), 'logging', _('Logging'))
def render_admin_panel(self, req, cat, page, path_info):
@@ -352,7 +354,8 @@ class PermissionAdminPanel(Component):
# IAdminPanelProvider methods
def get_admin_panels(self, req):
- if 'PERMISSION_GRANT' in req.perm or 'PERMISSION_REVOKE' in req.perm:
+ perm = req.perm('admin', 'general/perm')
+ if 'PERMISSION_GRANT' in perm or 'PERMISSION_REVOKE' in perm:
yield ('general', _('General'), 'perm', _('Permissions'))
def render_admin_panel(self, req, cat, page, path_info):
@@ -366,13 +369,13 @@ class PermissionAdminPanel(Component):
group = req.args.get('group', '').strip()
if subject and subject.isupper() or \
- group and group.isupper():
+ group and group.isupper():
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.require('PERMISSION_GRANT')
+ req.perm('admin', 'general/perm').require('PERMISSION_GRANT')
if action not in all_actions:
raise TracError(_('Unknown action'))
req.perm.require(action)
@@ -389,11 +392,11 @@ class PermissionAdminPanel(Component):
# Add subject to group
elif req.args.get('add') and subject and group:
- req.perm.require('PERMISSION_GRANT')
+ req.perm('admin', 'general/perm').require('PERMISSION_GRANT')
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." \
+ self.env.log.warn("Adding %s to group %s: "
+ "Permission %s unavailable, skipping perm check."
% (subject, group, action))
else:
req.perm.require(action)
@@ -410,7 +413,7 @@ class PermissionAdminPanel(Component):
# Remove permissions action
elif req.args.get('remove') and req.args.get('sel'):
- req.perm.require('PERMISSION_REVOKE')
+ req.perm('admin', 'general/perm').require('PERMISSION_REVOKE')
sel = req.args.get('sel')
sel = sel if isinstance(sel, list) else [sel]
for key in sel:
@@ -439,12 +442,10 @@ class PluginAdminPanel(Component):
# IAdminPanelProvider methods
def get_admin_panels(self, req):
- if 'TRAC_ADMIN' in req.perm:
+ if 'TRAC_ADMIN' in req.perm('admin', 'general/plugin'):
yield ('general', _('General'), 'plugin', _('Plugins'))
def render_admin_panel(self, req, cat, page, path_info):
- req.perm.require('TRAC_ADMIN')
-
if req.method == 'POST':
if 'install' in req.args:
self._do_install(req)
@@ -453,7 +454,7 @@ class PluginAdminPanel(Component):
else:
self._do_update(req)
anchor = ''
- if req.args.has_key('plugin'):
+ if 'plugin' in req.args:
anchor = '#no%d' % (int(req.args.get('plugin')) + 1)
req.redirect(req.href.admin(cat, page) + anchor)
@@ -463,7 +464,7 @@ class PluginAdminPanel(Component):
def _do_install(self, req):
"""Install a plugin."""
- if not req.args.has_key('plugin_file'):
+ if 'plugin_file' not in req.args:
raise TracError(_('No file uploaded'))
upload = req.args['plugin_file']
if isinstance(upload, unicode) or not upload.filename:
Modified: bloodhound/vendor/trac/current/trac/attachment.py
URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/attachment.py?rev=1567849&r1=1567848&r2=1567849&view=diff
==============================================================================
--- bloodhound/vendor/trac/current/trac/attachment.py (original)
+++ bloodhound/vendor/trac/current/trac/attachment.py Thu Feb 13 05:08:02 2014
@@ -38,7 +38,7 @@ from trac.mimeview import *
from trac.perm import PermissionError, IPermissionPolicy
from trac.resource import *
from trac.search import search_to_sql, shorten_result
-from trac.util import content_disposition, get_reporter_id
+from trac.util import content_disposition, create_zipinfo, get_reporter_id
from trac.util.compat import sha1
from trac.util.datefmt import format_datetime, from_utimestamp, \
to_datetime, to_utimestamp, utc
@@ -93,8 +93,9 @@ class IAttachmentManipulator(Interface):
attachment. Therefore, a return value of ``[]`` means
everything is OK."""
+
class ILegacyAttachmentPolicyDelegate(Interface):
- """Interface that can be used by plugins to seemlessly participate
+ """Interface that can be used by plugins to seamlessly participate
to the legacy way of checking for attachment permissions.
This should no longer be necessary once it becomes easier to
@@ -303,6 +304,12 @@ class Attachment(object):
t = to_datetime(t, utc)
self.date = t
+ parent_resource = self.resource.parent
+ if not resource_exists(self.env, parent_resource):
+ raise ResourceNotFound(
+ _("%(parent)s doesn't exist, can't create attachment",
+ parent=get_resource_name(self.env, parent_resource)))
+
# Make sure the path to the attachment is inside the environment
# attachments directory
attachments_dir = os.path.join(os.path.normpath(self.env.path),
@@ -333,7 +340,6 @@ class Attachment(object):
for listener in AttachmentModule(self.env).change_listeners:
listener.attachment_added(self)
-
@classmethod
def select(cls, env, parent_realm, parent_id, db=None):
"""Iterator yielding all `Attachment` instances attached to
@@ -369,7 +375,8 @@ class Attachment(object):
os.rmdir(attachment_dir)
except OSError, e:
env.log.error("Can't delete attachment directory %s: %s",
- attachment_dir, exception_to_unicode(e, traceback=True))
+ attachment_dir,
+ exception_to_unicode(e, traceback=True))
@classmethod
def reparent_all(cls, env, parent_realm, parent_id, new_realm, new_id):
@@ -385,7 +392,8 @@ class Attachment(object):
os.rmdir(attachment_dir)
except OSError, e:
env.log.error("Can't delete attachment directory %s: %s",
- attachment_dir, exception_to_unicode(e, traceback=True))
+ attachment_dir,
+ exception_to_unicode(e, traceback=True))
def open(self):
path = self.path
@@ -428,8 +436,7 @@ class AttachmentModule(Component):
CHUNK_SIZE = 4096
max_size = IntOption('attachment', 'max_size', 262144,
- """Maximum allowed file size (in bytes) for ticket and wiki
- attachments.""")
+ """Maximum allowed file size (in bytes) for attachments.""")
max_zip_size = IntOption('attachment', 'max_zip_size', 2097152,
"""Maximum allowed total size (in bytes) for an attachment list to be
@@ -491,6 +498,10 @@ class AttachmentModule(Component):
parent_id, filename = path[:last_slash], path[last_slash + 1:]
parent = parent_realm(id=parent_id)
+ if not resource_exists(self.env, parent):
+ raise ResourceNotFound(
+ _("Parent resource %(parent)s doesn't exist",
+ parent=get_resource_name(self.env, parent)))
# Link the attachment page to parent resource
parent_name = get_resource_name(self.env, parent)
@@ -682,10 +693,6 @@ class AttachmentModule(Component):
def _do_save(self, req, attachment):
req.perm(attachment.resource).require('ATTACHMENT_CREATE')
parent_resource = attachment.resource.parent
- if not resource_exists(self.env, parent_resource):
- raise ResourceNotFound(
- _("%(parent)s doesn't exist, can't create attachment",
- parent=get_resource_name(self.env, parent_resource)))
if 'cancel' in req.args:
req.redirect(get_resource_url(self.env, parent_resource, req.href))
@@ -751,7 +758,7 @@ class AttachmentModule(Component):
try:
old_attachment = Attachment(self.env,
attachment.resource(id=filename))
- if not (req.authname and req.authname != 'anonymous' \
+ if not (req.authname and req.authname != 'anonymous'
and old_attachment.author == req.authname) \
and 'ATTACHMENT_DELETE' \
not in req.perm(attachment.resource):
@@ -761,7 +768,7 @@ class AttachmentModule(Component):
"attachments requires ATTACHMENT_DELETE permission.",
name=filename))
if (not attachment.description.strip() and
- old_attachment.description):
+ old_attachment.description):
attachment.description = old_attachment.description
old_attachment.delete()
except TracError:
@@ -793,7 +800,7 @@ class AttachmentModule(Component):
def _render_form(self, req, attachment):
req.perm(attachment.resource).require('ATTACHMENT_CREATE')
return {'mode': 'new', 'author': get_reporter_id(req),
- 'attachment': attachment, 'max_size': self.max_size}
+ 'attachment': attachment, 'max_size': self.max_size}
def _download_as_zip(self, req, parent, attachments=None):
if attachments is None:
@@ -810,19 +817,14 @@ class AttachmentModule(Component):
req.send_header('Content-Disposition',
content_disposition('inline', filename))
- from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED
+ from zipfile import ZipFile, ZIP_DEFLATED
buf = StringIO()
zipfile = ZipFile(buf, 'w', ZIP_DEFLATED)
for attachment in attachments:
- zipinfo = ZipInfo()
- zipinfo.filename = attachment.filename.encode('utf-8')
- zipinfo.flag_bits |= 0x800 # filename is encoded with utf-8
- zipinfo.date_time = attachment.date.utctimetuple()[:6]
- zipinfo.compress_type = ZIP_DEFLATED
- if attachment.description:
- zipinfo.comment = attachment.description.encode('utf-8')
- zipinfo.external_attr = 0644 << 16L # needed since Python 2.5
+ zipinfo = create_zipinfo(attachment.filename,
+ mtime=attachment.date,
+ comment=attachment.description)
try:
with attachment.open() as fd:
zipfile.writestr(zipinfo, fd.read())
@@ -986,7 +988,7 @@ class LegacyAttachmentPolicy(Component):
else:
for d in self.delegates:
decision = d.check_attachment_permission(action, username,
- resource, perm)
+ resource, perm)
if decision is not None:
return decision
@@ -1100,4 +1102,3 @@ class AttachmentAdmin(Component):
finally:
if destination is not None:
output.close()
-