Skip to content

Instantly share code, notes, and snippets.

@jun66j5
Created April 17, 2012 05:54
Show Gist options
  • Save jun66j5/2403786 to your computer and use it in GitHub Desktop.
Save jun66j5/2403786 to your computer and use it in GitHub Desktop.
Patch for Trac-ja 0.11.x on TracLighting 2.x
diff --git b/python-lib/trac/trac/htdocs/css/admin.css a/python-lib/trac/trac/htdocs/css/admin.css
index f686535..6bc8d0a 100644
--- b/python-lib/trac/trac/htdocs/css/admin.css
+++ a/python-lib/trac/trac/htdocs/css/admin.css
@@ -19,32 +19,30 @@
color: #000;
}
-#tabcontent { padding: 0.4em 0 0.4em 2em; margin-left: 12em; min-height: 300px; }
+#tabcontent { padding: 0.4em 2em; margin-left: 12em; min-height: 300px; }
#tabcontent h2 { color: #333; margin-top: 0; }
-#tabcontent form { overflow: auto; padding: 0 1px; }
p.help { color: #666; font-size: 90%; margin: 1em .5em .5em; }
#enumlist tbody td { vertical-align: middle; }
-#tabcontent form.addnew { clear: right; float: right; margin: -2em 0 2em 2em; width: 33%; overflow: visible; padding: 0 }
-#tabcontent form.mod { margin-top: 1em; overflow: visible; padding: 0 }
-form.mod fieldset { margin: 0 }
+form.addnew { clear: right; float: right; margin: -2em 0 4em; width: 33% }
+form.mod { margin-top: 1em; }
form.mod .field { margin: .5em 0; }
form .field em { color: #888; font-size: smaller }
form .field .disabled em { color: #d7d7d7 }
-table.listing { clear: none; }
+table.listing { clear: none; width: 64% }
table.listing .sel, table.listing .default { text-align: center; width: 1% }
table.listing .num { text-align: right; width: 1% }
/* Plugins panel */
form#addplug { width: 35% }
.plugin { background: #f7f7f7; border: 1px solid #d7d7d7; margin: 0 0 2em;
- padding: 2px .5em; text-align: left;
+ padding: 2px .5em; text-align: left; width: 60%;
}
.plugin h3 { margin: .5em 0; color: #bb0000;}
.plugin h3 a {
- padding: 2px .5em; text-align: left;
+ padding: 2px .5em; text-align: left; width: 60%;
}
.plugin h3 a { background: url(../expanded.png) 0 50% no-repeat;
padding-left: 16px;
diff --git b/python-lib/trac/trac/htdocs/js/search.js a/python-lib/trac/trac/htdocs/js/search.js
index 5ba8e48..030b661 100644
--- b/python-lib/trac/trac/htdocs/js/search.js
+++ a/python-lib/trac/trac/htdocs/js/search.js
@@ -31,6 +31,7 @@
if (url.indexOf("?") == -1) return [];
var params = url.substr(url.indexOf("?") + 1).split("&");
for (var p in params) {
+ if (typeof(params[p])=="function") continue;
var param = params[p].split("=");
if (param.length < 2) continue;
if (param[0] == "q" || param[0] == "p") {// q= for Google, p= for Yahoo
diff --git b/python-lib/trac/trac/ticket/notification.py a/python-lib/trac/trac/ticket/notification.py
index 1b5b3a5..512e69e 100644
--- b/python-lib/trac/trac/ticket/notification.py
+++ a/python-lib/trac/trac/ticket/notification.py
@@ -17,9 +17,12 @@
#
from trac import __version__
+from trac.attachment import Attachment
from trac.core import *
from trac.config import *
+from trac.mimeview.api import Context
from trac.notification import NotifyEmail
+from trac.resource import Resource
from trac.util import md5
from trac.util.datefmt import to_timestamp
from trac.util.text import CRLF, wrap, to_unicode, obfuscate_email_address
@@ -133,16 +136,19 @@ class TicketNotifyEmail(NotifyEmail):
changes_body += ' * %s: %s%s' % (field, chg, CRLF)
if newv:
change_data[field] = {'oldvalue': old, 'newvalue': new}
-
+ else:
+ change_data.update({'author': ticket.values['reporter']})
+
self.ticket['description'] = wrap(
self.ticket.values.get('description', ''), self.COLS,
initial_indent=' ', subsequent_indent=' ', linesep=CRLF)
self.ticket['new'] = self.newticket
self.ticket['link'] = link
- subject = self.format_subj(summary)
+ subject = self.format_subj(summary, change_data)
if not self.newticket:
subject = 'Re: ' + subject
+ attachments = [attachment for attachment in Attachment.select(self.env, 'ticket', ticket.id)]
self.data.update({
'ticket_props': self.format_props(),
'ticket_body_hdr': self.format_hdr(),
@@ -150,7 +156,8 @@ class TicketNotifyEmail(NotifyEmail):
'ticket': ticket.values,
'changes_body': changes_body,
'changes_descr': changes_descr,
- 'change': change_data
+ 'change': change_data,
+ 'attachments': attachments,
})
NotifyEmail.notify(self, ticket.id, subject)
@@ -215,7 +222,7 @@ class TicketNotifyEmail(NotifyEmail):
return '#%s: %s' % (self.ticket.id, wrap(self.ticket['summary'],
self.COLS, linesep=CRLF))
- def format_subj(self, summary):
+ def format_subj(self, summary, change):
template = self.config.get('notification','ticket_subject_template')
template = TextTemplate(template.encode('utf8'))
@@ -227,6 +234,7 @@ class TicketNotifyEmail(NotifyEmail):
'prefix': prefix,
'summary': summary,
'ticket': self.ticket,
+ 'change': change,
'env': self.env,
}
diff --git b/python-lib/trac/trac/ticket/query.py a/python-lib/trac/trac/ticket/query.py
index 94ff877..26d8159 100644
--- b/python-lib/trac/trac/ticket/query.py
+++ a/python-lib/trac/trac/ticket/query.py
@@ -956,7 +956,7 @@ class QueryModule(Component):
content = StringIO()
cols = query.get_columns()
writer = csv.writer(content, delimiter=sep, quoting=csv.QUOTE_MINIMAL)
- writer.writerow([unicode(c).encode('utf-8') for c in cols])
+ writer.writerow([unicode(c).encode('cp932') for c in cols])
context = Context.from_request(req)
results = query.execute(req, self.env.get_db_cnx())
@@ -969,9 +969,9 @@ class QueryModule(Component):
if col in ('cc', 'reporter'):
value = Chrome(self.env).format_emails(context(ticket),
value)
- values.append(unicode(value).encode('utf-8'))
+ values.append(unicode(value).encode('cp932'))
writer.writerow(values)
- return (content.getvalue(), '%s;charset=utf-8' % mimetype)
+ return (content.getvalue(), '%s;charset=cp932' % mimetype)
def export_rss(self, req, query):
if 'description' not in query.rows:
diff --git b/python-lib/trac/trac/ticket/report.py a/python-lib/trac/trac/ticket/report.py
index a37713a..1b61d97 100644
--- b/python-lib/trac/trac/ticket/report.py
+++ a/python-lib/trac/trac/ticket/report.py
@@ -47,17 +47,37 @@ def cell_value(v):
return v is 0 and '0' or v and unicode(v) or ''
+class ITicketReportRenderer(Interface):
+ """Extension point interface for components that implement new report
+ writing formats."""
+
+ def get_report_format():
+ """Called to get the id for a report format, for example: .xls"""
+
+ def get_report_mimetype():
+ """Called to get the mimetype string for a report format"""
+
+ def get_report_linkname():
+ """Called to get the report link name that will appear on the UI"""
+
+ def get_report_linkclass():
+ """Called to get the class of the link that will appear on the UI"""
+
+ def render(req, cols, rows, id):
+ """Render the report, takes the request, columns and rows, report id"""
+
+
class ReportModule(Component):
implements(INavigationContributor, IPermissionRequestor, IRequestHandler,
IWikiSyntaxProvider)
items_per_page = IntOption('report', 'items_per_page', 100,
- """レポートの検索結果ページで 1 ページに表示するチケット数の
+ u"""レポートの検索結果ページで 1 ページに表示するチケット数の
デフォルト値 (''0.11 以降'')""")
items_per_page_rss = IntOption('report', 'items_per_page_rss', 0,
- """レポートの RSS フィードに掲載するチケット数
+ u"""レポートの RSS フィードに掲載するチケット数
(''0.11 以降'')""")
# INavigationContributor methods
@@ -80,7 +100,7 @@ class ReportModule(Component):
# IRequestHandler methods
def match_request(self, req):
- match = re.match(r'/report(?:/(?:([0-9]+)|-1))?$', req.path_info)
+ match = re.match(r'/report(?:/([0-9]+))?', req.path_info)
if match:
if match.group(1):
req.args['id'] = match.group(1)
@@ -133,6 +153,8 @@ class ReportModule(Component):
add_stylesheet(req, 'common/css/report.css')
return template, data, None
+ renderers = ExtensionPoint(ITicketReportRenderer)
+
# Internal methods
def _do_create(self, req, db):
@@ -301,7 +323,7 @@ class ReportModule(Component):
page = int(req.args.get('page', '1'))
limit = {'rss': self.items_per_page_rss,
- 'csv': 0, 'tab': 0}.get(format, self.items_per_page)
+ 'csv': 0, 'tab': 0, 'xls': 0}.get(format, self.items_per_page)
offset = (page - 1) * limit
user = req.args.get('USER', None)
@@ -324,11 +346,11 @@ class ReportModule(Component):
data['paginator'] = paginator
if paginator.has_next_page:
next_href = req.href.report(id, asc=asc, sort=sort_col,
- page=page + 1, **args)
+ USER=user, page=page + 1)
add_link(req, 'next', next_href, _('Next Page'))
if paginator.has_previous_page:
prev_href = req.href.report(id, asc=asc, sort=sort_col,
- page=page - 1, **args)
+ USER=user, page=page - 1)
add_link(req, 'prev', prev_href, _('Previous Page'))
pagedata = []
@@ -493,6 +515,10 @@ class ReportModule(Component):
filename=filename)
else:
if id != -1:
+ for renderer in self.renderers:
+ if renderer.get_report_format()==format:
+ renderer.render(req,cols,results,id)
+ return None
# reuse the session vars of the query module so that
# the query navigation links on the ticket can be used to
# navigate report results as well
@@ -500,10 +526,10 @@ class ReportModule(Component):
req.session['query_tickets'] = \
' '.join([str(int(row['id']))
for rg in row_groups for row in rg[1]])
+ #FIXME: I am not sure the extra args are necessary
req.session['query_href'] = \
- req.href.report(id, asc=req.args.get('asc', None),
- sort=req.args.get('sort', None),
- page=page, **args)
+ req.href.report(id, asc=not asc and '0' or None,
+ sort=sort_col, USER=user, page=page)
# Kludge: we have to clear the other query session
# variables, but only if the above succeeded
for var in ('query_constraints', 'query_time'):
@@ -514,7 +540,7 @@ class ReportModule(Component):
return 'report_view.html', data, None
def add_alternate_links(self, req, args):
- params = args.copy()
+ params = args
if 'sort' in req.args:
params['sort'] = req.args['sort']
if 'asc' in req.args:
@@ -531,6 +557,19 @@ class ReportModule(Component):
if 'REPORT_SQL_VIEW' in req.perm:
add_link(req, 'alternate', '?format=sql', _('SQL Query'),
'text/plain')
+
+ # add link for every loaded component
+ # that implements ITicketReportRenderer
+
+ for renderer in self.renderers:
+ format = renderer.get_report_format()
+ mimetype = renderer.get_report_mimetype()
+ linkname = renderer.get_report_linkname()
+ linkclass = renderer.get_report_linkclass()
+
+ add_link(req,'alternate','?format='+format+href,
+ linkname,mimetype,linkclass)
+
def execute_report(self, req, db, id, sql, args):
"""Execute given sql report (0.10 backward compatibility method)
@@ -676,16 +715,19 @@ class ReportModule(Component):
out = StringIO()
writer = csv.writer(out, delimiter=sep)
- writer.writerow([unicode(c).encode('utf-8') for c in cols])
+ #
+ writer.writerow([unicode(c).encode('cp932') for c in cols])
for row in rows:
row = list(row)
for i in xrange(len(row)):
- row[i] = converters[i](row[i]).encode('utf-8')
+ #
+ row[i] = converters[i](row[i]).encode('cp932')
writer.writerow(row)
+
data = out.getvalue()
req.send_response(200)
- req.send_header('Content-Type', mimetype + ';charset=utf-8')
+ req.send_header('Content-Type', mimetype + ';charset=cp932')
req.send_header('Content-Length', len(data))
if filename:
req.send_header('Content-Disposition', 'filename=' + filename)
diff --git b/python-lib/trac/trac/ticket/templates/ticket.html a/python-lib/trac/trac/ticket/templates/ticket.html
index 1bfc700..9ec6c97 100644
--- b/python-lib/trac/trac/ticket/templates/ticket.html
+++ a/python-lib/trac/trac/ticket/templates/ticket.html
@@ -315,7 +315,7 @@ ${comment}</textarea></p>
<tr>
<th><label for="field-description">${_('Description')}:</label></th>
<td class="fullrow" colspan="3">
- <textarea id="field-description" name="field_description" class="wikitext" rows="10" cols="68">
+ <textarea id="field-description" name="field_description" class="wikitext" rows="20" cols="75">
${ticket.description}</textarea>
</td>
</tr>
diff --git b/python-lib/trac/trac/ticket/templates/ticket_notify_email.txt a/python-lib/trac/trac/ticket/templates/ticket_notify_email.txt
index d334f16..0836e53 100644
--- b/python-lib/trac/trac/ticket/templates/ticket_notify_email.txt
+++ a/python-lib/trac/trac/ticket/templates/ticket_notify_email.txt
@@ -6,26 +6,33 @@ $ticket.description
#end
#otherwise
#if changes_body
-Changes (by $change.author):
+変更点 (by $change.author):
$changes_body
#end
#if changes_descr
#if not changes_body and not change.comment and change.author
-Description changed by $change.author:
+説明の変更 by $change.author:
#end
$changes_descr
--
#end
#if change.comment
-Comment${not changes_body and '(by %s)' % change.author or ''}:
+コメント${not changes_body and '(by %s)' % change.author or ''}:
$change.comment
#end
#end
#end
+#if attachments
+添付ファイル一覧:
+ #for attachment in attachments
+ * ${attachment.filename}
+ ${abs_url_of(attachment.resource, format='raw')}
+ #end
+#end
--
Ticket URL: <$ticket.link>
$project.name <${project.url or abs_href()}>
diff --git b/python-lib/trac/trac/versioncontrol/api.py a/python-lib/trac/trac/versioncontrol/api.py
index cb55eac..5d91687 100644
--- b/python-lib/trac/trac/versioncontrol/api.py
+++ a/python-lib/trac/trac/versioncontrol/api.py
@@ -150,6 +150,7 @@ class RepositoryManager(Component):
tid = threading._get_ident()
if tid in self._cache:
repos = self._cache[tid]
+ repos.authz.auth_name = authname
else:
rtype, rdir = self.repository_type, self.repository_dir
if not os.path.isabs(rdir):
diff --git b/python-lib/trac/trac/versioncontrol/svn_authz.py a/python-lib/trac/trac/versioncontrol/svn_authz.py
index 2f270b2..6a37789 100644
--- b/python-lib/trac/trac/versioncontrol/svn_authz.py
+++ a/python-lib/trac/trac/versioncontrol/svn_authz.py
@@ -19,9 +19,10 @@
import os.path
from trac.config import Option
+from trac.config import Configuration
from trac.core import *
from trac.versioncontrol import Authorizer
-
+from trac.util.text import to_unicode
class SvnAuthzOptions(Component):
@@ -79,14 +80,7 @@ class RealSubversionAuthorizer(Authorizer):
self.repos = repos
self.auth_name = auth_name
self.module_name = module_name
-
- from ConfigParser import ConfigParser
- self.conf_authz = ConfigParser()
- if cfg_fp:
- self.conf_authz.readfp(cfg_fp, cfg_file)
- elif cfg_file:
- self.conf_authz.read(cfg_file)
-
+ self.conf_authz = Configuration(cfg_file)
self.groups = self._groups()
def has_permission(self, path):
@@ -115,7 +109,7 @@ class RealSubversionAuthorizer(Authorizer):
# Internal API
def _groups(self):
- if not self.conf_authz.has_section('groups'):
+ if not u'groups' in self.conf_authz.sections():
return []
grp_parents = {}
@@ -145,7 +139,8 @@ class RealSubversionAuthorizer(Authorizer):
return expanded.keys()
def _get_section(self, section):
- if not self.conf_authz.has_section(section):
+ section = to_unicode(section)
+ if not (section in self.conf_authz.sections()):
return
yield self._get_permission(section, self.auth_name)
diff --git b/python-lib/trac/trac/versioncontrol/web_ui/changeset.py a/python-lib/trac/trac/versioncontrol/web_ui/changeset.py
index a24f9da..c6da78d 100644
--- b/python-lib/trac/trac/versioncontrol/web_ui/changeset.py
+++ a/python-lib/trac/trac/versioncontrol/web_ui/changeset.py
@@ -724,7 +724,7 @@ class ChangesetModule(Component):
if kind == Node.FILE and change != Changeset.DELETE:
assert new_node
zipinfo = ZipInfo()
- zipinfo.filename = new_node.path.strip('/').encode('utf-8')
+ zipinfo.filename = new_node.path.strip('/').encode('shift_jis')
# Note: unicode filenames are not supported by zipfile.
# UTF-8 is not supported by all Zip tools either,
# but as some do, I think UTF-8 is the best option here.
diff --git b/python-lib/trac/trac/web/__init__.py a/python-lib/trac/trac/web/__init__.py
index 7d6fe60..de5823a 100644
--- b/python-lib/trac/trac/web/__init__.py
+++ a/python-lib/trac/trac/web/__init__.py
@@ -11,6 +11,8 @@ if not os.path.isdir(get_distribution('genshi').location):
import sys
if 'trac.web.modpython_frontend' in sys.modules:
from trac.web.api import *
+ if 'tram.modpython_frontend' in sys.modules:
+ from trac.web.api import *
except ImportError:
from trac.web.api import *
else:
diff --git b/python-lib/trac/trac/wiki/default-pages/TracLinks a/python-lib/trac/trac/wiki/default-pages/TracLinks
index 04916ee..e1b2644 100644
--- b/python-lib/trac/trac/wiki/default-pages/TracLinks
+++ a/python-lib/trac/trac/wiki/default-pages/TracLinks
@@ -42,7 +42,7 @@ TracLinks が使えるのは:
* マイルストーン: milestone:1.0
* 添付ファイル: attachment:example.tgz(現在のページへの添付ファイル), attachment:attachment.1073.diff:ticket:944 (絶対パス)
* ファイル: source:trunk/COPYING
- * あるリビジョンのファイル: source:/trunk/COPYING#200
+ * あるリビジョンのファイル: source:/trunk/COPYING@200
* あるリビジョンのファイルのある行数: source:/trunk/COPYING@200#L25
'''Note:''' wiki:CamelCase の書式が使われることはほとんどありませんが、
diff --git b/python-lib/trac/trac/wiki/parser.py a/python-lib/trac/trac/wiki/parser.py
index 6d7468a..49fe626 100644
--- b/python-lib/trac/trac/wiki/parser.py
+++ a/python-lib/trac/trac/wiki/parser.py
@@ -149,7 +149,7 @@ class WikiParser(Component):
helper_re = re.compile(r'\?P<([a-z\d_]+)>')
for rule in syntax:
helpers += helper_re.findall(rule)[1:]
- rules = re.compile('(?:' + '|'.join(syntax) + ')', re.UNICODE)
+ rules = re.compile('(?:' + '|'.join(syntax) + ')', re.UNICODE|re.LOCALE)
self._external_handlers = handlers
self._helper_patterns = helpers
self._compiled_rules = rules
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment