incubator-bloodhound-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From g..@apache.org
Subject svn commit: r1398858 [27/33] - in /incubator/bloodhound/vendor/trac/current: ./ contrib/ doc/ doc/api/ doc/utils/ sample-plugins/ sample-plugins/permissions/ sample-plugins/workflow/ trac/ trac/admin/ trac/admin/templates/ trac/admin/tests/ trac/db/ tr...
Date Tue, 16 Oct 2012 15:55:11 GMT
Modified: incubator/bloodhound/vendor/trac/current/trac/ticket/templates/query_results.html
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/ticket/templates/query_results.html?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/ticket/templates/query_results.html (original)
+++ incubator/bloodhound/vendor/trac/current/trac/ticket/templates/query_results.html Tue Oct 16 15:55:00 2012
@@ -42,14 +42,15 @@
     </tr>
   </py:def>
   ${group_heading(*groups[0]) if groups else None}
-  <table class="listing tickets">
+  <table class="listing tickets"
+         py:with="num_cols = len(headers) + int(batch_modify or 0)">
     <thead py:strip="group_index">
       ${column_headers()}
     </thead>
     <py:for each="group_index, (groupname, results) in enumerate(groups)">
       <tbody py:if="group_index">
         <tr py:if="groupname is not None" class="trac-group">
-          <th colspan="${len(headers)}">
+          <th colspan="$num_cols">
             ${group_heading(groupname, results)}
           </th>
         </tr>
@@ -57,7 +58,7 @@
       </tbody>
       <tbody>
         <tr py:if="not results" class="even">
-          <td colspan="${len(headers)}">
+          <td colspan="$num_cols">
             No tickets found
           </td>
         </tr>
@@ -90,13 +91,13 @@
               <py:with vars="result_rows = [t for t in row if result[t]]">
                 <py:choose>
                   <tr py:when="ticket_context.resource in context" class="fullrow">
-                    <td colspan="${len(headers)}">
+                    <td colspan="$num_cols">
                       <p class="meta"><em>(this ticket)</em></p>
                     </td>
                   </tr>
                   <tr py:otherwise="" py:for="r in result_rows" class="fullrow">
                     <th class="meta">${fields.get(r, {'label': r or 'none'}).label}</th>
-                    <td colspan="${len(headers)-1}" xml:space="preserve">
+                    <td colspan="${num_cols - 1}" xml:space="preserve">
                       ${wiki_to_html(ticket_context, result[r])}
                     </td>
                   </tr>
@@ -106,7 +107,7 @@
           </py:with>
         </py:for>
         <tr py:if="group_index == len(groups)-1 and last_group_is_partial">
-          <td colspan="${len(headers)}">
+          <td colspan="$num_cols">
             <i>(more results for this group on next page)</i>
           </td>
         </tr>

Modified: incubator/bloodhound/vendor/trac/current/trac/ticket/templates/report_list.html
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/ticket/templates/report_list.html?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/ticket/templates/report_list.html (original)
+++ incubator/bloodhound/vendor/trac/current/trac/ticket/templates/report_list.html Tue Oct 16 15:55:00 2012
@@ -40,11 +40,12 @@
         <div py:if="saved_query_href">
           <form method="get" action="${href.report()}">
             <div class="inlinebuttons">
+
               <input type="hidden" name="action" value="clear" />
-              <input type="submit" class="inlinebutton" title="Forget last query" value="${_('Clear')}" />
+              <input type="submit" value="${captioned_button('x', _('Clear'))}" title="Forget last query" class="trac-delete" />
             </div>
           </form>
-          <h2><a href="$saved_query_href"><em>Return to Last Query</em></a></h2>
+          <h3><a href="$saved_query_href"><em>Return to Last Query</em></a></h3>
           <span class="foldable" />
           <div class="description">
             <p>Continue browsing through the current list of results,
@@ -53,7 +54,7 @@
         </div>
 
         <div py:if="query_href">
-          <h2><a href="$query_href"><em>Custom Query</em></a></h2>
+          <h3><a href="$query_href"><em>Custom Query</em></a></h3>
           <span class="foldable" />
           <div class="description">
             <p>Compose a new ticket query by selecting filters and columns to display.</p>
@@ -78,16 +79,21 @@
             <form py:if="can_delete" method="get" action="${href.report(id)}">
               <div class="inlinebuttons">
                 <input type="hidden" name="action" value="delete" />
-                <input type="submit" class="inlinebutton" title="Delete report" value="${_('Delete')}" />
+                <input type="submit" value="${captioned_button('–', _('Delete'))}"
+                     title="Delete report" class="trac-delete" />
               </div>
             </form>
             <form py:if="can_edit" method="get" action="${href.report(id)}">
               <div class="inlinebuttons">
                 <input type="hidden" name="action" value="edit" />
-                <input type="submit" class="inlinebutton" title="Edit report" value="${_('Edit')}" />
+                <input type="submit" value="${captioned_button('✎', _('Edit'))}"
+                     title="Edit report" />
               </div>
             </form>
-            <h2><a title="View report" href="${href.report(id)}">{$id} <em>$title</em></a></h2>
+            <h3><a title="View report" href="${href.report(id)}" py:choose="sort">
+              <py:when test="'title'">$title <em>{$id}</em></py:when>
+              <py:otherwise><em>{$id}</em> $title</py:otherwise>
+              </a></h3>
             <span class="foldable" />
             <div py:if="description" class="description" xml:space="preserve">
               ${wiki_to_html(context, description)}

Modified: incubator/bloodhound/vendor/trac/current/trac/ticket/templates/report_view.html
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/ticket/templates/report_view.html?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/ticket/templates/report_view.html (original)
+++ incubator/bloodhound/vendor/trac/current/trac/ticket/templates/report_view.html Tue Oct 16 15:55:00 2012
@@ -84,8 +84,7 @@
           <th py:for="header in header_group" py:if="not header.hidden" py:with="fullrow = header is header_group[-1]"
               colspan="${'100' if fullrow else None}"
               class="${'asc' if header.asc else 'desc' if header.asc is not None else None}">
-            <a py:strip="not sorting_enabled"
-              href="${report_href(sort=header.col, asc=not header.asc)}">
+            <a href="${report_href(sort=header.col, asc=not header.asc)}">
               $header.title
             </a>
           </th>

Modified: incubator/bloodhound/vendor/trac/current/trac/ticket/templates/roadmap.html
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/ticket/templates/roadmap.html?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/ticket/templates/roadmap.html (original)
+++ incubator/bloodhound/vendor/trac/current/trac/ticket/templates/roadmap.html Tue Oct 16 15:55:00 2012
@@ -12,7 +12,6 @@
 
   <body>
     <div id="content" class="roadmap">
-      <h1>Roadmap</h1>
 
       <form id="prefs" method="get" action="">
         <div>
@@ -30,6 +29,8 @@
         </div>
       </form>
 
+      <h1>Roadmap</h1>
+
       <div class="milestones">
         <div py:for="idx, milestone in enumerate(milestones)" class="milestone">
 

Modified: incubator/bloodhound/vendor/trac/current/trac/ticket/templates/ticket.html
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/ticket/templates/ticket.html?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/ticket/templates/ticket.html (original)
+++ incubator/bloodhound/vendor/trac/current/trac/ticket/templates/ticket.html Tue Oct 16 15:55:00 2012
@@ -19,8 +19,12 @@
         $("div.description").find("h1,h2,h3,h4,h5,h6").addAnchor(_("Link to this section"));
         $(".foldable").enableFolding(false, true);
       <py:when test="ticket.exists">/*<![CDATA[*/
+        $("#attachments").toggleClass("collapsed");
+        $("#trac-up-attachments").click(function () {
+          $("#attachments").removeClass("collapsed");
+          return true;
+        });
         $("#modify").parent().toggleClass("collapsed");
-        $(".trac-topnav a").click(function() { $("#modify").parent().removeClass("collapsed"); });
 
         /* only enable control elements for the currently selected action */
         var actions = $("#action input[name='action']");
@@ -34,6 +38,30 @@
         actions.click(updateActionFields);
         updateActionFields();
 
+        function setRevertHandler() {
+          $("button.trac-revert").click(function() {
+            var div = $("div", this);
+            var field_name = div[0].id.substr(7);
+            var field_value = div.text();
+            var input = $("#propertyform *[name=field_" + field_name + "]");
+            if (input.length > 0) {
+              if (input.filter("input[type=radio]").length > 0) {
+                input.val([field_value]);
+              } else if (input.filter("input[type=checkbox]").length > 0) {
+                input.val(field_value == "1" ? [field_value] : []);
+              } else {
+                input.val(field_value);
+              }
+            } else { // Special case for CC checkbox
+              input = $("#propertyform input[name=cc_update]").val([]);
+            }
+            input.change();
+            $(this).closest("li").remove();
+            return false;
+          });
+        }
+        setRevertHandler();
+
         var comment_focused = false;
         $("#comment").focus(function() { comment_focused = true; })
                      .blur(function() { comment_focused = false; });
@@ -45,6 +73,8 @@
           if (!$('#trac-comments-oldest').checked())
             $('#trac-comments-oldest').click().change();
           $("#changelog").replaceWith(items.filter("#changelog"));
+          if ($('#trac-comments-only-toggle').attr('checked'))
+            $('#trac-comments-only-toggle').click().attr('checked', true);
           // Show warning
           var new_changes = $("#changelog .trac-new");
           $("#trac-edit-warning").toggle(new_changes.length != 0);
@@ -56,6 +86,7 @@
           var preview = $("#ticketchange").html(items.filter('#preview').children());
           var show_preview = preview.children().length != 0;
           $("#ticketchange").toggle(show_preview);
+          setRevertHandler();
           // Collapse property form if comment editor has focus
           if (show_preview && comment_focused)
             $("#modify").parent().addClass("collapsed");
@@ -66,7 +97,6 @@
         }, "#changelog .trac-loading");
         /*]]>*/
         <py:if test="preview_mode">
-        $("#attachments").toggleClass("collapsed");
         $("#trac-add-comment").scrollToTop();
         </py:if>
       </py:when>
@@ -96,30 +126,10 @@
                   has_edit_comment = 'TICKET_EDIT_COMMENT' in perm(ticket.resource);
                   has_property_editor = not version and version != 0 and not cnum_edit
                                         and (can_append or can_modify or can_edit or can_create)">
-      <div class="trac-topnav" py:if="ticket.exists and has_property_editor">
-        <a href="#propertyform" title="Go to the ticket editor">Modify</a> &darr;
-      </div>
-      <h1 id="trac-ticket-title" py:choose="">
-        <py:when test="ticket.exists">
-          <a href="${href.ticket(ticket.id)}" i18n:msg="id">Ticket #${ticket.id}</a>
-          <span class="status">(${ticket.status}<py:if
-              test="ticket.type"> ${ticket.type}</py:if><py:if
-              test="ticket.resolution">: ${ticket.resolution}</py:if>)</span>
-          <py:choose test="">
-            <py:when test="version is None" />
-            <py:when test="version == 0">
-              &mdash; <i18n:msg>at <a href="#comment:description">Initial Version</a></i18n:msg>
-            </py:when>
-            <py:otherwise>
-              &mdash; <i18n:msg params="version">at <a href="#comment:$version">Version $version</a></i18n:msg>
-            </py:otherwise>
-          </py:choose>
-        </py:when>
-        <py:otherwise>
-          Create New Ticket <span py:if="preview_mode and ticket.type" class="status">(${ticket.type})</span>
-        </py:otherwise>
-      </h1>
 
+      <h1 py:if="not ticket.exists">
+        Create New Ticket <span py:if="preview_mode and ticket.type" class="status">(${ticket.type})</span>
+      </h1>
 
       <py:if test="ticket.exists">
         <xi:include href="ticket_box.html" py:with="preview_mode = change_preview.fields"/>
@@ -150,7 +160,7 @@
             </form>
           </div>
 
-          <h2 class="foldable">Change History</h2>
+          <h3 class="foldable">Change History <span class="trac-count">(${len(changes)})</span></h3>
 
           <div id="changelog">
             <py:for each="change in changes">
@@ -169,33 +179,30 @@
                       else href.newticket() + '#ticket'}">
         <!--! Add comment -->
         <div py:if="ticket.exists and can_append" id="trac-add-comment" class="field">
-          <div class="trac-nav">
-            <a href="#content" title="View ticket fields and description">View</a> &uarr;
-          </div>
-          <h2>
-            <a id="edit" onfocus="$('#comment').get(0).focus()">Add a comment</a>
-          </h2>
-          <div id="trac-edit-warning" class="warning system-message"
-               style="${'display: none' if start_time == ticket['changetime'] else None}"
-               i18n:msg="">
-            This ticket has been modified since you started editing. You should review the
-            <em class="trac-new">other modifications</em> which have been appended above,
-            and any <em class="trac-conflict">conflicts</em> shown in the preview below.
-            You can nevertheless proceed and submit your changes if you wish so.
-          </div>
-          <!--! Comment field -->
-          <fieldset class="iefix">
-            <label for="comment" i18n:msg="">You may use
-              <a tabindex="42" href="${href.wiki('WikiFormatting')}">WikiFormatting</a>
-              here.
-            </label>
-            <textarea id="comment" name="comment" class="wikitext trac-resizable" rows="10" cols="78">
+          <h3 class="foldable" id="edit">Add Comment</h3>
+          <div>
+            <div id="trac-edit-warning" class="warning system-message"
+                 style="${'display: none' if start_time == ticket['changetime'] else None}"
+                 i18n:msg="">
+              This ticket has been modified since you started editing. You should review the
+              <em class="trac-new">other modifications</em> which have been appended above,
+              and any <em class="trac-conflict">conflicts</em> shown in the preview below.
+              You can nevertheless proceed and submit your changes if you wish so.
+            </div>
+            <!--! Comment field -->
+            <fieldset>
+              <label for="comment" i18n:msg="">You may use
+                <a tabindex="42" href="${href.wiki('WikiFormatting')}">WikiFormatting</a>
+                here.
+              </label>
+              <textarea id="comment" name="comment" class="wikitext trac-resizable" rows="10" cols="78">
 ${comment}</textarea>
-          </fieldset>
+            </fieldset>
+          </div>
         </div>
 
         <div>
-          <h2 py:if="ticket.exists" class="foldable">Modify Ticket</h2>
+          <h3 py:if="ticket.exists" class="foldable">Modify Ticket</h3>
           <div id="modify">
             <!--! Properties -->
             <fieldset id="properties" py:if="can_modify or can_edit or can_create"
@@ -225,7 +232,7 @@ ${comment}</textarea>
                   <tr>
                     <th><label for="field-description">Description:</label></th>
                     <td class="fullrow" colspan="3">
-                      <fieldset class="iefix">
+                      <fieldset>
                         <label for="field-description" id="field-description-help" i18n:msg="">You may use
                           <a tabindex="42" href="${href.wiki('WikiFormatting')}">WikiFormatting</a> here.
                         </label>
@@ -364,7 +371,7 @@ ${value}</textarea>
         </p>
 
         <div py:if="ticket.exists" class="trac-nav">
-          <a href="#attachments" title="Go to the list of attachments">Attachments</a> &uarr;
+          <a href="#attachments" id="trac-up-attachments" title="Go to the list of attachments">Attachments</a> &uarr;
         </div>
         <div class="buttons">
           <py:if test="ticket.exists">
@@ -378,7 +385,8 @@ ${value}</textarea>
 
       </form>
 
-      <xi:include href="ticket_box.html" py:if="not ticket.exists" py:with="preview_mode = True"/>
+      <xi:include href="ticket_box.html" py:if="not ticket.exists"
+                  py:with="hide = not preview_mode; preview_mode = True"/>
 
       <div id="help" i18n:msg="">
         <strong>Note:</strong> See

Modified: incubator/bloodhound/vendor/trac/current/trac/ticket/templates/ticket_box.html
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/ticket/templates/ticket_box.html?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/ticket/templates/ticket_box.html (original)
+++ incubator/bloodhound/vendor/trac/current/trac/ticket/templates/ticket_box.html Tue Oct 16 15:55:00 2012
@@ -7,6 +7,7 @@ Arguments:
  - description_change: metadata about changes in the description
  - can_append: True if the user is allowed to append to tickets
  - preview_mode: if True, show the "draft" background
+ - hide=False: if True, hide the box
  - reporter_link=None: rendered link for the reporter field
  - owner_link=None: rendered link for the owner field
 -->
@@ -14,32 +15,63 @@ Arguments:
      xmlns:py="http://genshi.edgewall.org/"
      xmlns:xi="http://www.w3.org/2001/XInclude"
      xmlns:i18n="http://genshi.edgewall.org/i18n"
-     id="ticket" class="${'ticketdraft' if preview_mode else None}">
+     id="ticket" class="trac-content ${'ticketdraft' if preview_mode else None}"
+     style="${'display: none' if value_of('hide', False) else None}">
+
   <div class="date">
     <p i18n:msg="created" py:if="ticket.exists">Opened ${pretty_dateinfo(ticket.time)}</p>
-    <p i18n:msg="modified" py:if="ticket.changetime != ticket.time">Last modified ${pretty_dateinfo(ticket.changetime)}</p>
+    <p i18n:msg="closed" py:if="closetime">Closed ${pretty_dateinfo(closetime)}</p>
+    <p i18n:msg="modified" py:if="ticket.changetime != ticket.time and ticket.changetime != closetime">
+      Last modified ${pretty_dateinfo(ticket.changetime)}</p>
     <p py:if="not ticket.exists"><span class="trac-loading"/><i>(ticket not yet created)</i></p>
   </div>
   <!--! use a placeholder if it's a new ticket -->
-  <h2 class="summary searchable">$ticket.summary</h2>
+
+  <h2>
+    <a href="${href.ticket(ticket.id)}" class="trac-id">#${ticket.id}</a>
+    <span class="trac-status">
+      ${'status' in fields_map and fields[fields_map['status']].rendered or ticket.status}
+    </span>
+    <span class="trac-type" py:if="ticket.type">
+      ${'type' in fields_map and fields[fields_map['type']].rendered or ticket.type}
+    </span>
+    <span class="trac-resolution" py:if="ticket.resolution">
+      (${'resolution' in fields_map and fields[fields_map['resolution']].rendered or ticket.resolution})
+    </span>
+  </h2>
+
+  <h1 id="trac-ticket-title" class="searchable">
+    <span class="summary">$ticket.summary</span>
+    <py:choose test="">
+      <py:when test="version is None" />
+      <py:when test="version == 0">
+        &mdash; <i18n:msg>at <a href="#comment:description">Initial Version</a></i18n:msg>
+      </py:when>
+      <py:otherwise>
+        &mdash; <i18n:msg params="version">at <a href="#comment:$version">Version $version</a></i18n:msg>
+      </py:otherwise>
+    </py:choose>
+  </h1>
 
   <table class="properties"
          py:with="fields = [f for f in fields if not f.skip and f.name not in ('type', 'owner')]">
-    <tr>
-      <th id="h_reporter">Reported by:</th>
-      <td headers="h_reporter" class="searchable">
-        ${reporter_link if defined('reporter_link') else authorinfo(ticket.reporter)}
-      </td>
-      <th id="h_owner">Owned by:</th>
-      <td headers="h_owner">
-        ${(owner_link if defined('owner_link') else authorinfo(ticket.owner)) if ticket.owner else ''}
-      </td>
+    <tr py:with="
+      v_reporter = reporter_link if defined('reporter_link') else authorinfo(ticket.reporter);
+      v_owner = (owner_link if defined('owner_link') else authorinfo(ticket.owner)) if ticket.owner else ''
+      ">
+      <th id="h_reporter" class="${classes(missing=not v_reporter)}">Reported by:</th>
+      <td headers="h_reporter" class="searchable">$v_reporter</td>
+      <th id="h_owner" class="${classes(missing=not v_owner)}">Owned by:</th>
+      <td headers="h_owner">$v_owner</td>
     </tr>
     <tr py:for="row in group(fields, 2, lambda f: f.type != 'textarea')"
       py:with="fullrow = len(row) == 1">
       <py:for each="idx, field in enumerate(row)">
         <th py:if="idx == 0 or not fullrow"
-            id="${'h_' + field.name if field else None}">
+            id="${'h_' + field.name if field else None}"
+            class="${classes(missing=not field or
+                              ('rendered' in field and not field.rendered) or
+                               not ticket[field.name])}" >
           <py:if test="field"><i18n:msg params="field">${field.label or field.name}:</i18n:msg></py:if>
         </th>
         <td py:if="idx == 0 or not fullrow"
@@ -59,10 +91,10 @@ Arguments:
   <div class="description">
     <h3 id="comment:description">
       Description
-      <span py:if="description_change" class="lastmod" title="$description_change.date">
+      <a href="${href.ticket(ticket.id, action='diff', version=description_change.cnum)}"
+         py:if="description_change" class="lastmod trac-diff" title="$description_change.date">
         <i18n:msg params="author">(last modified by ${authorinfo(description_change.author)})</i18n:msg>
-        (<a href="${href.ticket(ticket.id, action='diff', version=description_change.cnum)}">diff</a>)
-      </span>
+      </a>
     </h3>
 
     <!--! Quote the description (only for existing tickets) -->
@@ -70,7 +102,7 @@ Arguments:
           id="addreply" method="get" action="#comment">
       <div class="inlinebuttons">
         <input type="hidden" name="replyto" value="description" />
-        <input type="submit" name="reply" value="${_('Reply')}" title="Reply, quoting this description" />
+        <input type="submit" name="reply" value="${captioned_button('↳', _('Reply'))}" title="Reply, quoting this description" />
       </div>
     </form>
     <div py:if="ticket.description" class="searchable" xml:space="preserve">

Modified: incubator/bloodhound/vendor/trac/current/trac/ticket/templates/ticket_change.html
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/ticket/templates/ticket_change.html?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/ticket/templates/ticket_change.html (original)
+++ incubator/bloodhound/vendor/trac/current/trac/ticket/templates/ticket_change.html Tue Oct 16 15:55:00 2012
@@ -62,21 +62,21 @@ Arguments:
     <form py:if="'cnum' in change and can_edit_comment" method="get" action="#comment:${cnum}">
       <div class="inlinebuttons">
         <input type="hidden" name="cnum_edit" value="${cnum}"/>
-        <input type="submit" value="${_('Edit')}" title="${_('Edit comment %(cnum)s', cnum=cnum)}"/>
+        <input type="submit" value="${captioned_button('✎', _('Edit'))}" title="${_('Edit comment %(cnum)s', cnum=cnum)}" />
       </div>
     </form>
     <form py:if="'cnum' in change and can_append" id="reply-to-comment-${cnum}"
           method="get" action="#comment">
       <div class="inlinebuttons">
         <input type="hidden" name="replyto" value="${cnum}"/>
-        <input type="submit" value="${_('Reply')}" title="${_('Reply to comment %(cnum)s', cnum=cnum)}"/>
+        <input type="submit" value="${captioned_button('↳', _('Reply'))}" title="${_('Reply to comment %(cnum)s', cnum=cnum)}" />
       </div>
     </form>
   </div>
   <ul py:if="change.fields" class="changes">
     <li py:for="field_name, field in sorted(change.fields.iteritems(), key=lambda item: item[1].label.lower())"
-        class="${'trac-conflict' if preview and field_name in conflicts else None}">
-      <strong>${field.label}</strong>
+        class="trac-field-${field_name}${' trac-conflict' if preview and field_name in conflicts else None}">
+      <strong class="trac-field-${field_name}">${field.label}</strong>
       <py:choose>
         <py:when test="field_name == 'attachment'"><i18n:msg params="name">
           <a href="${href.attachment('ticket', ticket.id, field.new)}"><em>${field.new
@@ -94,6 +94,12 @@ Arguments:
         <py:otherwise><i18n:msg params="value">
           <em>${field.old}</em> deleted
         </i18n:msg></py:otherwise>
+        <py:if test="preview and field.by == 'user'">
+          (<button py:with="old = ticket.get_default(field_name) if field.old is empty else field.old"
+                   type="submit" name="revert_$field_name" class="trac-revert"
+                   title="Revert this change">revert<div id="revert-$field_name">${
+            '0' if 'cc_update' in field else old}</div></button>)
+        </py:if>
       </py:choose>
     </li>
   </ul>

Modified: incubator/bloodhound/vendor/trac/current/trac/ticket/tests/functional.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/ticket/tests/functional.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/ticket/tests/functional.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/ticket/tests/functional.py Tue Oct 16 15:55:00 2012
@@ -1,16 +1,11 @@
 #!/usr/bin/python
+# -*- coding: utf-8 -*-
 import os
 import re
 
 from datetime import datetime, timedelta
 
-try:
-    import babel
-    locale_en = babel.Locale('en_US')
-except ImportError:
-    babel = None
-    locale_en = None
-
+from trac.test import locale_en
 from trac.tests.functional import *
 from trac.util.datefmt import utc, localtz, format_date, format_datetime
 
@@ -200,6 +195,7 @@ class TestTicketQueryLinks(FunctionalTwi
         tc.formvalue('query', '0_summary', 'TestTicketQueryLinks')
         tc.submit('update')
         query_url = b.get_url()
+        tc.find(r'\(%d matches\)' % count)
         for i in range(count):
             tc.find('TestTicketQueryLinks%s' % i)
 
@@ -1576,7 +1572,8 @@ class RegressionTestTicket8247(Functiona
         tc.formvalue('milestone_table', 'sel', name)
         tc.submit('remove')
         tc.go(ticket_url)
-        tc.find('<strong>Milestone</strong>[ \n\t]*<em>%s</em> deleted' % name)
+        tc.find('<strong class="trac-field-milestone">Milestone</strong>'
+                '[ \n\t]*<em>%s</em> deleted' % name)
         tc.find('Changed <a.* ago</a> by admin')
         tc.notfind('anonymous')
 
@@ -1607,7 +1604,7 @@ class RegressionTestTicket9084(Functiona
         ticketid = self._tester.create_ticket()
         self._tester.add_comment(ticketid)
         self._tester.go_to_ticket(ticketid)
-        tc.submit('Reply', formname='reply-to-comment-1')
+        tc.submit('2', formname='reply-to-comment-1') # '1' hidden, '2' submit
         tc.formvalue('propertyform', 'comment', random_sentence(3))
         tc.submit('Submit changes')
         tc.notfind('AssertionError')

Modified: incubator/bloodhound/vendor/trac/current/trac/ticket/tests/model.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/ticket/tests/model.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/ticket/tests/model.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/ticket/tests/model.py Tue Oct 16 15:55:00 2012
@@ -154,6 +154,22 @@ class TicketTestCase(unittest.TestCase):
         for change in ticket.get_changelog():
             self.assertEqual(None, change[1])
 
+    def test_comment_with_whitespace_only_is_not_saved(self):
+        ticket = Ticket(self.env)
+        ticket.insert()
+
+        ticket.save_changes(comment='\n \n ')
+        self.assertEqual(0, len(ticket.get_changelog()))
+
+    def test_prop_whitespace_change_is_not_saved(self):
+        ticket = Ticket(self.env)
+        ticket.populate({'summary': 'ticket summary'})
+        ticket.insert()
+
+        ticket['summary'] = ' ticket summary '
+        ticket.save_changes()
+        self.assertEqual(0, len(ticket.get_changelog()))
+
     def test_ticket_default_values(self):
         """
         Verify that a ticket uses default values specified in the configuration

Modified: incubator/bloodhound/vendor/trac/current/trac/ticket/tests/query.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/ticket/tests/query.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/ticket/tests/query.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/ticket/tests/query.py Tue Oct 16 15:55:00 2012
@@ -1,15 +1,10 @@
-from trac.test import Mock, EnvironmentStub, MockPerm
+from trac.test import Mock, EnvironmentStub, MockPerm, locale_en
 from trac.ticket.query import Query, QueryModule, TicketQueryMacro
 from trac.util.datefmt import utc
 from trac.web.chrome import web_context
 from trac.web.href import Href
 from trac.wiki.formatter import LinkFormatter
 
-try:
-    from babel import Locale
-except ImportError:
-    Locale = None
-
 import unittest
 import difflib
 
@@ -37,9 +32,8 @@ class QueryTestCase(unittest.TestCase):
 
     def setUp(self):
         self.env = EnvironmentStub(default_data=True)
-        locale = Locale.parse('en_US') if Locale else None
         self.req = Mock(href=self.env.href, authname='anonymous', tz=utc,
-                        locale=locale, lc_time=locale)
+                        locale=locale_en, lc_time=locale_en)
         
     def tearDown(self):
         self.env.reset_db()

Modified: incubator/bloodhound/vendor/trac/current/trac/ticket/tests/report.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/ticket/tests/report.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/ticket/tests/report.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/ticket/tests/report.py Tue Oct 16 15:55:00 2012
@@ -1,9 +1,12 @@
 # -*- coding: utf-8 -*-
 
+import doctest
+
 from trac.db.mysql_backend import MySQLConnection
 from trac.ticket.report import ReportModule
 from trac.test import EnvironmentStub, Mock
 from trac.web.api import Request, RequestDone
+import trac
 
 import unittest
 from StringIO import StringIO
@@ -98,7 +101,10 @@ class ReportTestCase(unittest.TestCase):
 
 
 def suite():
-    return unittest.makeSuite(ReportTestCase, 'test')
+    suite = unittest.TestSuite()
+    suite.addTest(doctest.DocTestSuite(trac.ticket.report))
+    suite.addTest(unittest.makeSuite(ReportTestCase, 'test'))
+    return suite
 
 if __name__ == '__main__':
-    unittest.main()
+    unittest.main(defaultTest='suite')

Modified: incubator/bloodhound/vendor/trac/current/trac/ticket/tests/wikisyntax.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/ticket/tests/wikisyntax.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/ticket/tests/wikisyntax.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/ticket/tests/wikisyntax.py Tue Oct 16 15:55:00 2012
@@ -32,8 +32,8 @@ ticket:12-14,33
 ticket:12,33?order=created
 ------------------------------
 <p>
-<a href="/query?id=12-14%2C33" title="Tickets 12-14,33">ticket:12-14,33</a>
-<a href="/query?id=12%2C33&amp;order=created" title="Tickets 12,33">ticket:12,33?order=created</a>
+<a href="/query?id=12-14%2C33" title="Tickets 12-14, 33">ticket:12-14,33</a>
+<a href="/query?id=12%2C33&amp;order=created" title="Tickets 12, 33">ticket:12,33?order=created</a>
 </p>
 ------------------------------
 ============================== ticket link shorthand form
@@ -50,8 +50,8 @@ ticket:12,33?order=created
 #1,3,5,7
 ------------------------------
 <p>
-<a href="/query?id=1-5%2C42" title="Tickets 1-5,42">#1-5,42</a>
-<a href="/query?id=1%2C3%2C5%2C7" title="Tickets 1,3,5,7">#1,3,5,7</a>
+<a href="/query?id=1-5%2C42" title="Tickets 1-5, 42">#1-5,42</a>
+<a href="/query?id=1%2C3%2C5%2C7" title="Tickets 1, 3, 5, 7">#1,3,5,7</a>
 </p>
 ------------------------------
 ============================== ticket link shorthand form with long ranges (#10111 regression)
@@ -91,6 +91,21 @@ trac:#2041
 <a class="ext-link" href="http://trac.edgewall.org/intertrac/%232041" title="#2041 in Trac's Trac"><span class="icon"></span>trac:#2041</a>
 </p>
 ------------------------------
+============================== ticket syntax with unicode digits
+#⁴²
+#1-⁵,42
+#1,³,5,7
+#T²⁰⁴¹
+#trac²⁰⁴¹
+------------------------------
+<p>
+#⁴²
+<a class="new ticket" href="/ticket/1" title="This is the summary (new)">#1</a>-⁵,42
+<a class="new ticket" href="/ticket/1" title="This is the summary (new)">#1</a>,³,5,7
+#T²⁰⁴¹
+#trac²⁰⁴¹
+</p>
+------------------------------
 """ # " 
 
 def ticket_setup(tc):
@@ -146,6 +161,17 @@ trac:report:1
 <a class="ext-link" href="http://trac.edgewall.org/intertrac/report%3A1" title="report:1 in Trac's Trac"><span class="icon"></span>{trac 1}</a>
 </p>
 ------------------------------
+============================== report syntax with unicode digits
+{⁴²} !{⁴²}
+{T⁴²}
+{trac⁴²}
+------------------------------
+<p>
+{⁴²} !{⁴²}
+{T⁴²}
+{trac⁴²}
+</p>
+------------------------------
 """ # '
 
 def report_setup(tc):

Modified: incubator/bloodhound/vendor/trac/current/trac/ticket/web_ui.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/ticket/web_ui.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/ticket/web_ui.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/ticket/web_ui.py Tue Oct 16 15:55:00 2012
@@ -29,27 +29,34 @@ from trac.attachment import AttachmentMo
 from trac.config import BoolOption, Option, IntOption
 from trac.core import *
 from trac.mimeview.api import Mimeview, IContentConverter
-from trac.resource import Resource, ResourceNotFound, get_resource_url, \
-                         render_resource_link, get_resource_shortname
+from trac.resource import (
+    Resource, ResourceNotFound, get_resource_url, render_resource_link,
+    get_resource_shortname
+)
 from trac.search import ISearchSource, search_to_sql, shorten_result
 from trac.ticket.api import TicketSystem, ITicketManipulator
 from trac.ticket.model import Milestone, Ticket, group_milestones
 from trac.ticket.notification import TicketNotifyEmail
 from trac.timeline.api import ITimelineEventProvider
 from trac.util import as_bool, as_int, get_reporter_id
-from trac.util.datefmt import format_datetime, from_utimestamp, \
-                              to_utimestamp, utc
-from trac.util.text import exception_to_unicode, obfuscate_email_address, \
-                           shorten_line, to_unicode
+from trac.util.datefmt import (
+    format_datetime, from_utimestamp, to_utimestamp, utc
+)
+from trac.util.text import (
+    exception_to_unicode, empty, obfuscate_email_address, shorten_line,
+    to_unicode
+)
 from trac.util.presentation import separated
 from trac.util.translation import _, tag_, tagn_, N_, gettext, ngettext
 from trac.versioncontrol.diff import get_diff_options, diff_blocks
-from trac.web import arg_list_to_args, parse_arg_list, IRequestHandler, \
-                     RequestDone
-from trac.web.chrome import (Chrome, INavigationContributor, ITemplateProvider,
-                             add_ctxtnav, add_link, add_notice, add_script,
-                             add_script_data, add_stylesheet, add_warning,
-                             auth_link, prevnext_nav, web_context)
+from trac.web import (
+    IRequestHandler, RequestDone, arg_list_to_args, parse_arg_list
+)
+from trac.web.chrome import (
+    Chrome, INavigationContributor, ITemplateProvider,
+    add_ctxtnav, add_link, add_notice, add_script, add_script_data,
+    add_stylesheet, add_warning, auth_link, prevnext_nav, web_context
+)
 from trac.wiki.formatter import format_to, format_to_html, format_to_oneliner
 
 
@@ -106,7 +113,7 @@ class TicketModule(Component):
         """Delegate access to ticket default Options which were move to
         TicketSystem.
 
-        .. todo:: remove in 0.13
+        .. todo:: remove in 1.0
         """
         if name.startswith('default_'):
             if name not in self._warn_for_default_attr:
@@ -240,10 +247,10 @@ class TicketModule(Component):
         ts_start = to_utimestamp(start)
         ts_stop = to_utimestamp(stop)
 
-        status_map = {'new': ('newticket', N_("created")),
-                      'reopened': ('reopenedticket', N_("reopened")),
-                      'closed': ('closedticket', N_("closed")),
-                      'edit': ('editedticket', N_("updated"))}
+        status_map = {'new': ('newticket', 'created'),
+                      'reopened': ('reopenedticket', 'reopened'),
+                      'closed': ('closedticket', 'closed'),
+                      'edit': ('editedticket', 'updated')}
 
         ticket_realm = Resource('ticket')
 
@@ -381,9 +388,15 @@ class TicketModule(Component):
         elif field == 'title':
             title = TicketSystem(self.env).format_summary(summary, status,
                                                           resolution, type)
-            return tag_("Ticket %(ticketref)s (%(summary)s) %(verb)s",
+            message = {
+                'created': N_("Ticket %(ticketref)s (%(summary)s) created"),
+                'reopened': N_("Ticket %(ticketref)s (%(summary)s) reopened"),
+                'closed': N_("Ticket %(ticketref)s (%(summary)s) closed"),
+                'updated': N_("Ticket %(ticketref)s (%(summary)s) updated"),
+            }[verb]
+            return tag_(message,
                         ticketref=tag.em('#', ticket.id, title=title),
-                        summary=shorten_line(summary), verb=gettext(verb))
+                        summary=shorten_line(summary))
         elif field == 'description':
             descr = message = ''
             if status == 'new':
@@ -405,9 +418,9 @@ class TicketModule(Component):
                 description, comment, cid = event[3]
         tickets = sorted(tickets)
         if field == 'url':
-            return context.href.query(id=','.join([str(t) for t in tickets]))
+            return context.href.query(id=','.join(str(t) for t in tickets))
         elif field == 'title':
-            ticketids = ','.join([str(t) for t in tickets])
+            ticketids = u',\u200b'.join(str(t) for t in tickets)
             title = _("Tickets %(ticketids)s", ticketids=ticketids)
             return tag_("Tickets %(ticketlist)s batch updated",
                         ticketlist=tag.em('#', ticketids, title=title))
@@ -469,11 +482,6 @@ class TicketModule(Component):
 
         fields = self._prepare_fields(req, ticket)
 
-        # setup default values for the new ticket
-        
-        for field in fields:
-            ticket.values.setdefault(field['name'], field.get('value'))
-
         # position 'owner' immediately before 'cc',
         # if not already positioned after (?)
 
@@ -490,6 +498,8 @@ class TicketModule(Component):
                 del ticket.fields[curr_idx]
 
         data['fields'] = fields
+        data['fields_map'] = dict((field['name'], i)
+                                  for i, field in enumerate(fields))
 
         if req.get_header('X-Requested-With') == 'XMLHttpRequest':
             data['preview_mode'] = True
@@ -544,7 +554,7 @@ class TicketModule(Component):
                          'reassign_owner': req.authname,
                          'resolve_resolution': None,
                          'start_time': ticket['changetime']})
-        elif req.method == 'POST': # 'Preview' or 'Submit'
+        elif req.method == 'POST':
             if 'cancel_comment' in req.args:
                 req.redirect(req.href.ticket(ticket.id))
             elif 'edit_comment' in req.args:
@@ -598,7 +608,7 @@ class TicketModule(Component):
             # validates and there were no problems with the workflow side of
             # things.
             valid = self._validate_ticket(req, ticket, not valid) and valid
-            if 'preview' not in req.args:
+            if 'submit' in req.args:
                 if valid:
                     # redirected if successful
                     self._do_save(req, ticket, action)
@@ -709,13 +719,16 @@ class TicketModule(Component):
         return {'comments_order': req.session.get('ticket_comments_order',
                                                   'oldest'),
                 'comments_only': req.session.get('ticket_comments_only',
-                                                 False)}
+                                                 'false')}
         
     def _prepare_data(self, req, ticket, absurls=False):
         return {'ticket': ticket, 'to_utimestamp': to_utimestamp,
-                'context': web_context(req, ticket.resource,
-                                                absurls=absurls),
-                'preserve_newlines': self.must_preserve_newlines}
+                'context': web_context(req, ticket.resource, absurls=absurls),
+                'preserve_newlines': self.must_preserve_newlines,
+                'emtpy': empty}
+
+    def _cc_list(self, cc):
+        return Chrome(self.env).cc_list(cc)
 
     def _toggle_cc(self, req, cc):
         """Return an (action, recipient) tuple corresponding to a change
@@ -735,7 +748,7 @@ class TicketModule(Component):
                 entries.append(email)
         add = []
         remove = []
-        cc_list = Chrome(self.env).cc_list(cc)
+        cc_list = self._cc_list(cc)
         for entry in entries:
             if entry in cc_list:
                 remove.append(entry)
@@ -750,8 +763,15 @@ class TicketModule(Component):
         
     def _populate(self, req, ticket, plain_fields=False):
         if not plain_fields:
-            fields = dict([(k[6:], v) for k, v in req.args.iteritems()
-                           if k.startswith('field_')])
+            fields = dict((k[6:], v) for k, v in req.args.iteritems()
+                          if k.startswith('field_')
+                             and not 'revert_' + k[6:] in req.args)
+            # Handle revert of checkboxes (in particular, revert to 1)
+            for k in list(fields):
+                if k.startswith('checkbox_'):
+                    k = k[9:]
+                    if 'revert_' + k in req.args:
+                        fields[k] = ticket[k]
         else:
             fields = req.args.copy()
         # Prevent direct changes to protected fields (status and resolution are
@@ -761,7 +781,7 @@ class TicketModule(Component):
             fields.pop('checkbox_' + each, None)    # See Ticket.populate()
         ticket.populate(fields)
         # special case for updating the Cc: field
-        if 'cc_update' in req.args:
+        if 'cc_update' in req.args and 'revert_cc' not in req.args:
             cc_action, cc_entry, cc_list = self._toggle_cc(req, ticket['cc'])
             if cc_action == 'remove':
                 cc_list.remove(cc_entry)
@@ -1381,10 +1401,11 @@ class TicketModule(Component):
 
     def _query_link(self, req, name, value, text=None):
         """Return a link to /query with the appropriate name and value"""
-        default_query = self.ticketlink_query.startswith('?') and \
-                        self.ticketlink_query[1:] or self.ticketlink_query
+        default_query = self.ticketlink_query.lstrip('?')
         args = arg_list_to_args(parse_arg_list(default_query))
         args[name] = value
+        if name == 'resolution':
+            args['status'] = 'closed'
         return tag.a(text or value, href=req.href.query(args))
 
     def _query_link_words(self, context, name, value):
@@ -1410,7 +1431,7 @@ class TicketModule(Component):
                     items.append(rendered)
         return tag(items)
 
-    def _prepare_fields(self, req, ticket):
+    def _prepare_fields(self, req, ticket, field_changes=None):
         context = web_context(req, ticket.resource)
         fields = []
         owner_field = None
@@ -1453,18 +1474,33 @@ class TicketModule(Component):
                 field['rendered'] = self._query_link_words(context, name,
                                                            ticket[name])
             elif name == 'cc':
+                cc_changed = field_changes is not None and 'cc' in field_changes
                 field['rendered'] = self._query_link_words(context, name,
                                                            ticket[name])
                 if ticket.exists and \
                         'TICKET_EDIT_CC' not in req.perm(ticket.resource):
                     cc = ticket._old.get('cc', ticket['cc'])
                     cc_action, cc_entry, cc_list = self._toggle_cc(req, cc)
+                    cc_update = 'cc_update' in req.args \
+                                and 'revert_cc' not in req.args
                     field['edit_label'] = {
                             'add': _("Add to Cc"),
                             'remove': _("Remove from Cc"),
                             '': _("Add/Remove from Cc")}[cc_action]
                     field['cc_entry'] = cc_entry or _("<Author field>")
-                    field['cc_update'] = 'cc_update' in req.args or None
+                    field['cc_update'] = cc_update or None
+                    if cc_changed:
+                        field_changes['cc']['cc_update'] = cc_update
+                if cc_changed:
+                    # normalize the new CC: list; also remove the
+                    # change altogether if there's no real change
+                    old_cc_list = self._cc_list(field_changes['cc']['old'])
+                    new_cc_list = self._cc_list(field_changes['cc']['new']
+                                                .replace(' ', ','))
+                    if new_cc_list == old_cc_list:
+                        del field_changes['cc']
+                    else:
+                        field_changes['cc']['new'] = ','.join(new_cc_list)
 
             # per type settings
             if type_ in ('radio', 'select'):
@@ -1524,7 +1560,8 @@ class TicketModule(Component):
 
         # -- Ticket fields
 
-        fields = self._prepare_fields(req, ticket)
+        fields = self._prepare_fields(req, ticket, field_changes)
+        fields_map = dict((field['name'], i) for i, field in enumerate(fields))
 
         # -- Ticket Change History
 
@@ -1582,6 +1619,13 @@ class TicketModule(Component):
         # -- Workflow support
         
         selected_action = req.args.get('action')
+
+        # retrieve close time from changes
+        closetime = None
+        for c in changes:
+            s = c['fields'].get('status')
+            if s:
+                closetime = c['date'] if s['new'] == 'closed' else None
         
         # action_controls is an ordered list of "renders" tuples, where
         # renders is a list of (action_key, label, widgets, hints) representing
@@ -1631,13 +1675,14 @@ class TicketModule(Component):
         for user in 'reporter', 'owner':
             if chrome.format_author(req, ticket[user]) == ticket[user]:
                 data['%s_link' % user] = self._query_link(req, user,
-                                                            ticket[user])
+                                                          ticket[user])
         data.update({
             'context': context, 'conflicts': conflicts,
-            'fields': fields, 'changes': changes, 'replies': replies,
+            'fields': fields, 'fields_map': fields_map,
+            'changes': changes, 'replies': replies,
             'attachments': AttachmentModule(self.env).attachment_data(context),
             'action_controls': action_controls, 'action': selected_action,
-            'change_preview': change_preview,
+            'change_preview': change_preview, 'closetime': closetime,
         })
 
     def rendered_changelog_entries(self, req, ticket, when=None):
@@ -1692,8 +1737,7 @@ class TicketModule(Component):
         render_elt = lambda x: x
         sep = ', '
         if field == 'cc':
-            chrome = Chrome(self.env)
-            old_list, new_list = chrome.cc_list(old), chrome.cc_list(new)
+            old_list, new_list = self._cc_list(old), self._cc_list(new)
             if not (Chrome(self.env).show_email_addresses or 
                     'EMAIL_VIEW' in req.perm(resource_new or ticket.resource)):
                 render_elt = obfuscate_email_address
@@ -1729,8 +1773,8 @@ class TicketModule(Component):
         """Iterate on changelog entries, consolidating related changes
         in a `dict` object.
 
-        :since 0.13: the `db` parameter is no longer needed and will be removed
-        in version 0.14
+        :since 1.0: the `db` parameter is no longer needed and will be removed
+        in version 1.1.1
         """
         field_labels = TicketSystem(self.env).get_ticket_field_labels()
         changelog = ticket.get_changelog(when=when)

Modified: incubator/bloodhound/vendor/trac/current/trac/timeline/api.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/timeline/api.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/timeline/api.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/timeline/api.py Tue Oct 16 15:55:00 2012
@@ -3,7 +3,7 @@
 # Copyright (C) 2003-2009 Edgewall Software
 # Copyright (C) 2003-2005 Jonas Borgström <jonas@edgewall.com>
 # Copyright (C) 2004-2005 Christopher Lenz <cmlenz@gmx.de>
-# Copyright (C) 2005-2006 Christian Boos <cboos@neuf.fr>
+# Copyright (C) 2005-2006 Christian Boos <cboos@edgewall.org>
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which

Modified: incubator/bloodhound/vendor/trac/current/trac/timeline/templates/timeline.html
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/timeline/templates/timeline.html?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/timeline/templates/timeline.html (original)
+++ incubator/bloodhound/vendor/trac/current/trac/timeline/templates/timeline.html Tue Oct 16 15:55:00 2012
@@ -8,6 +8,11 @@
   <xi:include href="layout.html" />
   <head>
     <title>Timeline</title>
+    <script type="text/javascript">/*<![CDATA[*/
+      jQuery(document).ready(function($) {
+        $("#fromdate").datepicker();
+      });
+    /*]]>*/</script>
   </head>
 
   <body>
@@ -17,7 +22,7 @@
 
       <form id="prefs" method="get" action="">
        <div i18n:msg="">
-        <label>View changes from <input type="text" size="10" name="from" value="${format_date(fromdate)}" /></label> <br />
+        <label>View changes from <input type="text" id="fromdate" size="10" name="from" value="${format_date(fromdate)}" /></label> <br />
         and <label><input type="text" size="3" name="daysback" value="$daysback" /> days back</label><br />
         <label>done by <input type="text" size="16" name="authors" value="$authors" /></label>
        </div>

Modified: incubator/bloodhound/vendor/trac/current/trac/timeline/web_ui.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/timeline/web_ui.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/timeline/web_ui.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/timeline/web_ui.py Tue Oct 16 15:55:00 2012
@@ -3,7 +3,7 @@
 # Copyright (C) 2003-2009 Edgewall Software
 # Copyright (C) 2003-2005 Jonas Borgström <jonas@edgewall.com>
 # Copyright (C) 2004-2005 Christopher Lenz <cmlenz@gmx.de>
-# Copyright (C) 2005-2006 Christian Boos <cboos@neuf.fr>
+# Copyright (C) 2005-2006 Christian Boos <cboos@edgewall.org>
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -211,8 +211,9 @@ class TimelineModule(Component):
             data['context'] = rss_context
             return 'timeline.rss', data, 'application/rss+xml'
         else:
-            req.session['timeline.daysback'] = daysback
-            req.session['timeline.authors'] = authors
+            req.session.set('timeline.daysback', daysback,
+                            self.default_daysback)
+            req.session.set('timeline.authors', authors, '')
             # store lastvisit
             if events and not revisit:
                 lastviewed = to_utimestamp(events[0]['date'])
@@ -229,6 +230,7 @@ class TimelineModule(Component):
                                      format='rss')
         add_link(req, 'alternate', auth_link(req, rss_href), _('RSS Feed'),
                  'application/rss+xml', 'rss')
+        Chrome(self.env).add_jquery_ui(req)
 
         for filter_ in available_filters:
             data['filters'].append({'name': filter_[0], 'label': filter_[1],

Added: incubator/bloodhound/vendor/trac/current/trac/upgrades/db28.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/upgrades/db28.py?rev=1398858&view=auto
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/upgrades/db28.py (added)
+++ incubator/bloodhound/vendor/trac/current/trac/upgrades/db28.py Tue Oct 16 15:55:00 2012
@@ -0,0 +1,93 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2012 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.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/.
+
+import os.path
+
+from trac.attachment import Attachment
+from trac.util.text import exception_to_unicode, printerr, unicode_quote
+from trac.util.translation import _
+
+
+def do_upgrade(env, version, cursor):
+    """Move attachments from the `attachments` directory into `files`, hashing
+    the filenames in the process."""
+    path = env.path
+    old_dir = os.path.join(path, 'attachments')
+    if not os.path.exists(old_dir):
+        return
+    old_stat = os.stat(old_dir)
+    new_dir = os.path.join(path, 'files', 'attachments')
+    if not os.path.exists(new_dir):
+        os.makedirs(new_dir)
+
+    cursor.execute("""
+        SELECT type, id, filename FROM attachment ORDER BY type, id
+        """)
+    for row in cursor:
+        move_attachment_file(env, *row)
+
+    # Try to preserve permissions and ownerships of the attachments
+    # directory for $ENV/files
+    for dir, dirs, files in os.walk(os.path.join(path, 'files')):
+        try:
+            if hasattr(os, 'chmod'):
+                os.chmod(dir, old_stat.st_mode)
+            if hasattr(os, 'chflags') and hasattr(old_stat, 'st_flags'):
+                os.chflags(dir, old_stat.st_flags)
+            if hasattr(os, 'chown'):
+                os.chown(dir, old_stat.st_uid, old_stat.st_gid)
+        except OSError:
+            pass
+
+    # Remove empty directory hierarchy
+    try:
+        for dir, dirs, files in os.walk(old_dir, topdown=False):
+            os.rmdir(dir)
+    except OSError, e:
+        env.log.warning("Can't delete old attachments directory %s: %s",
+                         old_dir, exception_to_unicode(e))
+        # TRANSLATOR: Wrap message to 80 columns
+        printerr(_("""\
+The upgrade of attachments was successful, but the old attachments directory:
+
+  %(src_dir)s
+
+couldn't be removed, possibly due to the presence of files that weren't
+referenced in the database. The error was:
+
+  %(exception)s
+  
+This error can be ignored, but for keeping your environment clean you should
+backup any remaining files in that directory and remove it manually.
+""", src_dir=old_dir, exception=exception_to_unicode(e)))
+
+
+def move_attachment_file(env, parent_realm, parent_id, filename):
+    old_path = os.path.join(env.path, 'attachments', parent_realm,
+                            unicode_quote(parent_id))
+    if filename:
+        old_path = os.path.join(old_path, unicode_quote(filename))
+    old_path = os.path.normpath(old_path)
+    if os.path.isfile(old_path):
+        new_path = Attachment._get_path(env.path, parent_realm, parent_id,
+                                        filename)
+        try:
+            os.renames(old_path, new_path)
+        except OSError:
+            printerr(_("Unable to move attachment from:\n\n"
+                       "  %(old_path)s\n\nto:\n\n  %(new_path)s\n",
+                       old_path=old_path, new_path=new_path))
+            raise
+    else:
+        env.log.warning("Can't find file for 'attachment:%s:%s:%s', ignoring",
+                        filename, parent_realm, parent_id)

Propchange: incubator/bloodhound/vendor/trac/current/trac/upgrades/db28.py
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/bloodhound/vendor/trac/current/trac/upgrades/db29.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/upgrades/db29.py?rev=1398858&view=auto
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/upgrades/db29.py (added)
+++ incubator/bloodhound/vendor/trac/current/trac/upgrades/db29.py Tue Oct 16 15:55:00 2012
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2012 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.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/.
+
+import shutil
+
+from trac.util import create_unique_file
+from trac.util.text import exception_to_unicode
+
+
+_svn_components = [
+    'svn_fs.SubversionConnector',
+    'svn_prop.SubversionMergePropertyDiffRenderer',
+    'svn_prop.SubversionMergePropertyRenderer',
+    'svn_prop.SubversionPropertyRenderer',
+]
+_old_path = 'trac.versioncontrol.'
+_new_path = 'tracopt.versioncontrol.svn.'
+
+
+def do_upgrade(env, version, cursor):
+    """Automatically enable tracopt.versioncontrol.svn.* components,
+    unless they were explicitly disabled or the new svn components are
+    already enabled.
+    """
+    enable = [c for c in _svn_components
+              if env.is_component_enabled(_old_path + c) and
+              not env.is_component_enabled(_new_path + c)]
+    if not enable:
+        return
+    try:
+        backup, f = create_unique_file(env.config.filename
+                                       + '.tracopt-svn.bak')
+        f.close()
+        shutil.copyfile(env.config.filename, backup)
+        env.log.info("Saved backup of configuration file in %s", backup)
+    except IOError, e:
+        env.log.warn("Couldn't save backup of configuration file (%s)",
+                     exception_to_unicode(e))
+    for c in enable:
+        env.config.set('components', _new_path + c, 'enabled')
+    env.config.save()
+    env.log.info("Enabled components %r to cope with the move from %s to %s.",
+                 enable,
+                 _old_path.replace('.', '/'), _new_path.replace('.', '/'))

Propchange: incubator/bloodhound/vendor/trac/current/trac/upgrades/db29.py
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/bloodhound/vendor/trac/current/trac/util/__init__.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/util/__init__.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/util/__init__.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/util/__init__.py Tue Oct 16 15:55:00 2012
@@ -3,7 +3,7 @@
 # Copyright (C) 2003-2009 Edgewall Software
 # Copyright (C) 2003-2006 Jonas Borgström <jonas@edgewall.com>
 # Copyright (C) 2006 Matthew Good <trac@matt-good.net>
-# Copyright (C) 2005-2006 Christian Boos <cboos@neuf.fr>
+# Copyright (C) 2005-2006 Christian Boos <cboos@edgewall.org>
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -406,6 +406,7 @@ def fq_class_name(obj):
     m, n = c.__module__, c.__name__
     return n if m == '__builtin__' else '%s.%s' % (m, n)
 
+
 def arity(f):
     """Return the number of arguments expected by the given function, unbound
     or bound method.
@@ -524,7 +525,7 @@ def safe_repr(x):
     without risking to trigger an exception (e.g. from a buggy
     `x.__repr__`).
 
-    .. versionadded :: 0.13
+    .. versionadded :: 1.0
     """
     try:
         return to_unicode(repr(x))
@@ -546,6 +547,23 @@ def get_doc(obj):
     description = doc[1] if len(doc) > 1 else None
     return (summary, description)
 
+
+_dont_import = frozenset(['__file__', '__name__', '__package__'])
+
+def import_namespace(globals_dict, module_name):
+    """Import the namespace of a module into a globals dict.
+    
+    This function is used in stub modules to import all symbols defined in
+    another module into the global namespace of the stub, usually for
+    backward compatibility.
+    """
+    __import__(module_name)
+    module = sys.modules[module_name]
+    globals_dict.update(item for item in module.__dict__.iteritems()
+                        if item[0] not in _dont_import)
+    globals_dict.pop('import_namespace', None)
+
+
 # -- setuptools utils
 
 def get_module_path(module):
@@ -787,9 +805,16 @@ class Ranges(object):
     >>> str(Ranges("20-10", reorder=True))
     '10-20'
 
+    As rendered ranges are often using u',\u200b' (comma + Zero-width
+    space) to enable wrapping, we also support reading such ranges, as
+    they can be copy/pasted back.
+
+    >>> str(Ranges(u'1,\u200b3,\u200b5,\u200b6,\u200b7,\u200b9'))
+    '1,3,5-7,9'
+
     """
 
-    RE_STR = r"""\d+(?:[-:]\d+)?(?:,\d+(?:[-:]\d+)?)*"""
+    RE_STR = ur'[0-9]+(?:[-:][0-9]+)?(?:,\u200b?[0-9]+(?:[-:][0-9]+)?)*'
     
     def __init__(self, r=None, reorder=False):
         self.pairs = []
@@ -808,7 +833,7 @@ class Ranges(object):
             return
         p = self.pairs
         if isinstance(r, basestring):
-            r = r.split(',')
+            r = re.split(u',\u200b?', r)
         for x in r:
             try:
                 a, b = map(int, x.split('-', 1))
@@ -1059,3 +1084,4 @@ from trac.util.datefmt import pretty_tim
                               get_datetime_format_hint, http_date, \
                               parse_date
 
+__no_apidoc__ = 'compat presentation translation'

Modified: incubator/bloodhound/vendor/trac/current/trac/util/daemon.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/util/daemon.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/util/daemon.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/util/daemon.py Tue Oct 16 15:55:00 2012
@@ -22,7 +22,6 @@ import sys
 def daemonize(pidfile=None, progname=None, stdin='/dev/null',
               stdout='/dev/null', stderr='/dev/null', umask=022):
     """Fork a daemon process."""
-
     if pidfile:
         # Check whether the pid file already exists and refers to a still
         # process running
@@ -32,7 +31,8 @@ def daemonize(pidfile=None, progname=Non
                 try:
                     pid = int(fileobj.read())
                 except ValueError:
-                    sys.exit('Invalid PID in file %s' % pidfile)
+                    sys.exit('Invalid pid in file %s\nPlease remove it to '
+                             'proceed' % pidfile)
 
             try: # signal the process to see if it is still running
                 os.kill(pid, 0)
@@ -45,7 +45,7 @@ def daemonize(pidfile=None, progname=Non
 
         # The pid file must be writable
         try:
-            fileobj = open(pidfile, 'r+')
+            fileobj = open(pidfile, 'a+')
             fileobj.close()
         except IOError, e:
             from trac.util.text import exception_to_unicode

Modified: incubator/bloodhound/vendor/trac/current/trac/util/datefmt.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/util/datefmt.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/util/datefmt.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/util/datefmt.py Tue Oct 16 15:55:00 2012
@@ -3,7 +3,7 @@
 # Copyright (C) 2003-2009 Edgewall Software
 # Copyright (C) 2003-2006 Jonas Borgström <jonas@edgewall.com>
 # Copyright (C) 2006 Matthew Good <trac@matt-good.net>
-# Copyright (C) 2005-2006 Christian Boos <cboos@neuf.fr>
+# Copyright (C) 2005-2006 Christian Boos <cboos@edgewall.org>
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -26,12 +26,16 @@ from locale import getlocale, getpreferr
 
 try:
     import babel
-    from babel.dates import format_datetime as babel_format_datetime, \
-                            format_date as babel_format_date, \
-                            format_time as babel_format_time, \
-                            get_datetime_format, get_date_format, \
-                            get_time_format, get_month_names, \
-                            get_period_names, get_day_names
+    from babel import Locale
+    from babel.core import LOCALE_ALIASES
+    from babel.dates import (
+        format_datetime as babel_format_datetime, 
+        format_date as babel_format_date,
+        format_time as babel_format_time,
+        get_datetime_format, get_date_format,
+        get_time_format, get_month_names,
+        get_period_names, get_day_names
+    )
 except ImportError:
     babel = None
 
@@ -373,6 +377,17 @@ def get_timezone_list_jquery_ui(t=None):
             if zone == '+0000' else zone[:-2] + ':' + zone[-2:]
             for zone in sorted(zones, key=lambda tz: int(tz))]
 
+def get_first_week_day_jquery_ui(req):
+    """Get first week day for jQuery date picker"""
+    locale = req.lc_time
+    if locale == 'iso8601':
+        return 1 # Monday
+    if babel and locale:
+        if not locale.territory and locale.language in LOCALE_ALIASES:
+            locale = Locale.parse(LOCALE_ALIASES[locale.language])
+        return (locale.first_week_day + 1) % 7
+    return 0 # Sunday
+
 def is_24_hours(locale):
     """Returns `True` for 24 hour time formats."""
     if locale == 'iso8601':
@@ -396,7 +411,11 @@ def http_date(t=None):
 
 _ISO_8601_RE = re.compile(r'''
     (\d\d\d\d)(?:-?(\d\d)(?:-?(\d\d))?)?    # date
-    (?:T(\d\d)(?::?(\d\d)(?::?(\d\d))?)?)?  # time
+    (?:
+        [T ]
+        (\d\d)(?::?(\d\d)(?::?(\d\d)        # time
+        (?:[,.](\d{1,6}))?)?)?              # microseconds
+    )?
     (Z?(?:([-+])?(\d\d):?(\d\d)?)?)?$       # timezone
     ''', re.VERBOSE)
 
@@ -408,8 +427,9 @@ def _parse_date_iso8601(text, tzinfo):
             years = g[0]
             months = g[1] or '01'
             days = g[2] or '01'
-            hours, minutes, seconds = [x or '00' for x in g[3:6]]
-            z, tzsign, tzhours, tzminutes = g[6:10]
+            hours, minutes, seconds, useconds = [x or '00' for x in g[3:7]]
+            useconds = (useconds + '000000')[:6]
+            z, tzsign, tzhours, tzminutes = g[7:11]
             if z:
                 tz = timedelta(hours=int(tzhours or '0'),
                                minutes=int(tzminutes or '0')).seconds / 60
@@ -419,10 +439,9 @@ def _parse_date_iso8601(text, tzinfo):
                     tzinfo = FixedOffset(-tz if tzsign == '-' else tz,
                                          '%s%s:%s' %
                                          (tzsign, tzhours, tzminutes))
-            tm = time.strptime('%s ' * 6 % (years, months, days,
-                                            hours, minutes, seconds),
-                               '%Y %m %d %H %M %S ')
-            t = tzinfo.localize(datetime(*tm[0:6]))
+            tm = [int(x) for x in (years, months, days,
+                                   hours, minutes, seconds, useconds)]
+            t = tzinfo.localize(datetime(*tm))
             return tzinfo.normalize(t)
         except ValueError:
             pass

Modified: incubator/bloodhound/vendor/trac/current/trac/util/html.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/util/html.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/util/html.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/util/html.py Tue Oct 16 15:55:00 2012
@@ -71,47 +71,29 @@ class TracHTMLSanitizer(HTMLSanitizer):
         self.safe_css = frozenset(safe_css)
 
     # IE6 <http://heideri.ch/jso/#80>
-    _EXPRESSION_SEARCH = re.compile(u"""
-        [eE
-         \uFF25 # FULLWIDTH LATIN CAPITAL LETTER E
-         \uFF45 # FULLWIDTH LATIN SMALL LETTER E
-        ]
-        [xX
-         \uFF38 # FULLWIDTH LATIN CAPITAL LETTER X
-         \uFF58 # FULLWIDTH LATIN SMALL LETTER X
-        ]
-        [pP
-         \uFF30 # FULLWIDTH LATIN CAPITAL LETTER P
-         \uFF50 # FULLWIDTH LATIN SMALL LETTER P
-        ]
-        [rR
-         \u0280 # LATIN LETTER SMALL CAPITAL R
-         \uFF32 # FULLWIDTH LATIN CAPITAL LETTER R
-         \uFF52 # FULLWIDTH LATIN SMALL LETTER R
-        ]
-        [eE
-         \uFF25 # FULLWIDTH LATIN CAPITAL LETTER E
-         \uFF45 # FULLWIDTH LATIN SMALL LETTER E
-        ]
-        [sS
-         \uFF33 # FULLWIDTH LATIN CAPITAL LETTER S
-         \uFF53 # FULLWIDTH LATIN SMALL LETTER S
-        ]{2}
-        [iI
-         \u026A # LATIN LETTER SMALL CAPITAL I
-         \uFF29 # FULLWIDTH LATIN CAPITAL LETTER I
-         \uFF49 # FULLWIDTH LATIN SMALL LETTER I
-        ]
-        [oO
-         \uFF2F # FULLWIDTH LATIN CAPITAL LETTER O
-         \uFF4F # FULLWIDTH LATIN SMALL LETTER O
-        ]
-        [nN
-         \u0274 # LATIN LETTER SMALL CAPITAL N
-         \uFF2E # FULLWIDTH LATIN CAPITAL LETTER N
-         \uFF4E # FULLWIDTH LATIN SMALL LETTER N
-        ]
-        """, re.VERBOSE).search
+    _EXPRESSION_SEARCH = re.compile(
+        u'[eE\uFF25\uFF45]'         # FULLWIDTH LATIN CAPITAL LETTER E
+                                    # FULLWIDTH LATIN SMALL LETTER E
+        u'[xX\uFF38\uFF58]'         # FULLWIDTH LATIN CAPITAL LETTER X
+                                    # FULLWIDTH LATIN SMALL LETTER X
+        u'[pP\uFF30\uFF50]'         # FULLWIDTH LATIN CAPITAL LETTER P
+                                    # FULLWIDTH LATIN SMALL LETTER P
+        u'[rR\u0280\uFF32\uFF52]'   # LATIN LETTER SMALL CAPITAL R
+                                    # FULLWIDTH LATIN CAPITAL LETTER R
+                                    # FULLWIDTH LATIN SMALL LETTER R
+        u'[eE\uFF25\uFF45]'         # FULLWIDTH LATIN CAPITAL LETTER E
+                                    # FULLWIDTH LATIN SMALL LETTER E
+        u'[sS\uFF33\uFF53]{2}'      # FULLWIDTH LATIN CAPITAL LETTER S
+                                    # FULLWIDTH LATIN SMALL LETTER S
+        u'[iI\u026A\uFF29\uFF49]'   # LATIN LETTER SMALL CAPITAL I
+                                    # FULLWIDTH LATIN CAPITAL LETTER I
+                                    # FULLWIDTH LATIN SMALL LETTER I
+        u'[oO\uFF2F\uFF4F]'         # FULLWIDTH LATIN CAPITAL LETTER O
+                                    # FULLWIDTH LATIN SMALL LETTER O
+        u'[nN\u0274\uFF2E\uFF4E]'   # LATIN LETTER SMALL CAPITAL N
+                                    # FULLWIDTH LATIN CAPITAL LETTER N
+                                    # FULLWIDTH LATIN SMALL LETTER N
+    ).search
 
     # IE6 <http://openmya.hacker.jp/hasegawa/security/expression.txt>
     #     7) Particular bit of Unicode characters
@@ -184,7 +166,15 @@ class TracHTMLSanitizer(HTMLSanitizer):
         def _repl(match):
             t = match.group(1)
             if t:
-                return unichr(int(t, 16))
+                code = int(t, 16)
+                chr = unichr(code)
+                if code <= 0x1f:
+                    # replace space character because IE ignores control
+                    # characters
+                    chr = ' '
+                elif chr == '\\':
+                    chr = r'\\'
+                return chr
             t = match.group(2)
             if t == '\\':
                 return r'\\'
@@ -193,6 +183,14 @@ class TracHTMLSanitizer(HTMLSanitizer):
         return self._UNICODE_ESCAPE(_repl,
                                     self._NORMALIZE_NEWLINES('\n', text))
 
+    _CSS_COMMENTS = re.compile(r'/\*.*?\*/').sub
+
+    def _strip_css_comments(self, text):
+        """Replace comments with space character instead of superclass which
+        removes comments to avoid problems when nested comments.
+        """
+        return self._CSS_COMMENTS(' ', text)
+
 
 class Deuglifier(object):
     """Help base class used for cleaning up HTML riddled with ``<FONT

Modified: incubator/bloodhound/vendor/trac/current/trac/util/presentation.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/util/presentation.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/util/presentation.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/util/presentation.py Tue Oct 16 15:55:00 2012
@@ -19,9 +19,14 @@ tasks such as grouping or pagination.
 from math import ceil
 import re
 
-__all__ = ['classes', 'first_last', 'group', 'istext', 'prepared_paginate', 
-           'paginate', 'Paginator']
-
+__all__ = ['captioned_button', 'classes', 'first_last', 'group', 'istext',
+           'prepared_paginate', 'paginate', 'Paginator']
+__no_apidoc__ = 'prepared_paginate'
+
+def captioned_button(req, symbol, text):
+    """Return symbol and text or only symbol, according to user preferences."""
+    return symbol if req.session.get('ui.use_symbols') \
+        else u'%s %s' % (symbol, text)
 
 def classes(*args, **kwargs):
     """Helper function for dynamically assembling a list of CSS class names
@@ -190,6 +195,7 @@ def paginate(items, page=0, max_per_page
 
 
 class Paginator(object):
+    """Pagination controller"""
 
     def __init__(self, items, page=0, max_per_page=10, num_items=None):
         if not page:
@@ -255,11 +261,11 @@ class Paginator(object):
         from trac.util.translation import _
         start, stop = self.span
         total = self.num_items
-        if start+1 == stop:
+        if start + 1 == stop:
             return _("%(last)d of %(total)d", last=stop, total=total)
         else:
             return _("%(start)d - %(stop)d of %(total)d",
-                    start=self.span[0]+1, stop=self.span[1], total=total)
+                    start=self.span[0] + 1, stop=self.span[1], total=total)
 
 
 def separated(items, sep=','):
@@ -298,12 +304,12 @@ try:
         return _js_quote_re.sub(replace, text)
 
 except ImportError:
-    from trac.util.text import javascript_quote
+    from trac.util.text import to_js_string
     
     def to_json(value):
         """Encode `value` to JSON."""
         if isinstance(value, basestring):
-            return '"%s"' % javascript_quote(value)
+            return to_js_string(value)
         elif value is None:
             return 'null'
         elif value is False:

Modified: incubator/bloodhound/vendor/trac/current/trac/util/tests/datefmt.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/util/tests/datefmt.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/util/tests/datefmt.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/util/tests/datefmt.py Tue Oct 16 15:55:00 2012
@@ -53,15 +53,19 @@ else:
 
         def test_parse_date(self):
             tz = datefmt.get_timezone('Europe/Zurich')
-            t = datefmt.parse_date('2009-12-01T12:00:00', tz)
             t_utc = datetime.datetime(2009, 12, 1, 11, 0, 0, 0, datefmt.utc)
-            self.assertEqual(t_utc, t)
+            self.assertEqual(t_utc,
+                    datefmt.parse_date('2009-12-01T12:00:00', tz))
+            self.assertEqual(t_utc,
+                    datefmt.parse_date('2009-12-01 12:00:00', tz))
 
         def test_parse_date_dst(self):
             tz = datefmt.get_timezone('Europe/Zurich')
-            t = datefmt.parse_date('2009-08-01T12:00:00', tz)
             t_utc = datetime.datetime(2009, 8, 1, 10, 0, 0, 0, datefmt.utc)
-            self.assertEqual(t_utc, t)
+            self.assertEqual(t_utc,
+                    datefmt.parse_date('2009-08-01T12:00:00', tz))
+            self.assertEqual(t_utc,
+                    datefmt.parse_date('2009-08-01 12:00:00', tz))
 
         def test_parse_date_across_dst_boundary(self):
             tz = datefmt.get_timezone('Europe/Zurich')
@@ -88,6 +92,7 @@ else:
             expected = '2002-03-31 00:00:00 CET+0100'
             self.assertEqual(expected, date.strftime(format))
 
+
 class DateFormatTestCase(unittest.TestCase):
 
     def test_to_datetime(self):
@@ -219,6 +224,36 @@ class ISO8601TestCase(unittest.TestCase)
         self.assertEqual('2010-08-28T11:45:56+02:00',
                          datefmt.format_datetime(t, 'iso8601', tz, 'iso8601'))
 
+    def test_parse_date_offset(self):
+        t_utc = datetime.datetime(2009, 12, 1, 11, 0, 0, 0, datefmt.utc)
+        self.assertEqual(t_utc,
+                         datefmt.parse_date('2009-12-01T11:00:00Z'))
+        self.assertEqual(t_utc,
+                         datefmt.parse_date('2009-12-01T11:00:00+00:00'))
+        self.assertEqual(t_utc,
+                         datefmt.parse_date('2009-12-01T11:00:00-00:00'))
+        self.assertEqual(t_utc,
+                         datefmt.parse_date('2009-12-01T09:00:00-02:00'))
+        self.assertEqual(t_utc,
+                         datefmt.parse_date('2009-12-01T11:30:00+00:30'))
+
+    def test_parse_date_usec(self):
+        tz = datefmt.get_timezone('GMT +1:00')
+        t_utc = datetime.datetime(2009, 12, 1, 11, 0, 0, 98765, datefmt.utc)
+        self.assertEqual(t_utc,
+                         datefmt.parse_date('2009-12-01T12:00:00.098765', tz))
+        self.assertEqual(t_utc,
+                         datefmt.parse_date('2009-12-01T12:00:00,098765', tz))
+        self.assertEqual(datetime.datetime(2009, 12, 1, 11, 0, 0, 98700,
+                                           datefmt.utc),
+                         datefmt.parse_date('2009-12-01T12:00:00.0987', tz))
+        self.assertEqual(datetime.datetime(2009, 12, 1, 11, 0, 0, 90000,
+                                           datefmt.utc),
+                         datefmt.parse_date('2009-12-01T12:00:00.09', tz))
+        self.assertEqual(datetime.datetime(2009, 12, 1, 11, 0, 0, 0,
+                                           datefmt.utc),
+                         datefmt.parse_date('2009-12-01T12:00:00.0', tz))
+
     def test_with_babel_format(self):
         tz = datefmt.timezone('GMT +2:00')
         t = datetime.datetime(2010, 8, 28, 11, 45, 56, 123456, tz)

Modified: incubator/bloodhound/vendor/trac/current/trac/util/tests/html.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/util/tests/html.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/util/tests/html.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/util/tests/html.py Tue Oct 16 15:55:00 2012
@@ -17,6 +17,18 @@ class TracHTMLSanitizerTestCase(unittest
                     encoding='utf-8')
         self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
 
+    def test_expression_with_comments(self):
+        html = HTML(r'<div style="top:exp/**/ression(alert())">XSS</div>')
+        self.assertEqual('<div style="top:exp ression(alert())">XSS</div>',
+                         unicode(html | TracHTMLSanitizer()))
+        html = HTML(r'<div style="top:exp//**/**/ression(alert())">XSS</div>')
+        self.assertEqual(
+            '<div style="top:exp/ **/ression(alert())">XSS</div>',
+            unicode(html | TracHTMLSanitizer()))
+        html = HTML(r'<div style="top:ex/*p*/ression(alert())">XSS</div>')
+        self.assertEqual('<div style="top:ex ression(alert())">XSS</div>',
+                         unicode(html | TracHTMLSanitizer()))
+
     def test_url_with_javascript(self):
         html = HTML('<div style="background-image:url(javascript:alert())">'
                     'XSS</div>', encoding='utf-8')
@@ -31,6 +43,18 @@ class TracHTMLSanitizerTestCase(unittest
         html = HTML(r'<div style="top:exp\72 ess\000069 on(alert())">'
                     r'XSS</div>', encoding='utf-8')
         self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
+        # escaped backslash
+        html = HTML(r'<div style="top:exp\5c ression(alert())">XSS</div>')
+        self.assertEqual(r'<div style="top:exp\\ression(alert())">XSS</div>',
+                         unicode(html | TracHTMLSanitizer()))
+        html = HTML(r'<div style="top:exp\5c 72 ession(alert())">XSS</div>')
+        self.assertEqual(r'<div style="top:exp\\72 ession(alert())">XSS</div>',
+                         unicode(html | TracHTMLSanitizer()))
+        # escaped control characters
+        html = HTML(r'<div style="top:exp\000000res\1f sion(alert())">'
+                    r'XSS</div>')
+        self.assertEqual('<div style="top:exp res sion(alert())">XSS</div>',
+                         unicode(html | TracHTMLSanitizer()))
 
     def test_backslash_without_hex(self):
         html = HTML(r'<div style="top:e\xp\ression(alert())">XSS</div>',

Modified: incubator/bloodhound/vendor/trac/current/trac/util/tests/presentation.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/util/tests/presentation.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/util/tests/presentation.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/util/tests/presentation.py Tue Oct 16 15:55:00 2012
@@ -28,6 +28,8 @@ class ToJsonTestCase(unittest.TestCase):
         self.assertEqual('null', presentation.to_json(None))
         self.assertEqual('"String"', presentation.to_json('String'))
         self.assertEqual(r'"a \" quote"', presentation.to_json('a " quote'))
+        self.assertEqual('''"a ' single quote"''',
+                         presentation.to_json("a ' single quote"))
         self.assertEqual(r'"\u003cb\u003e\u0026\u003c/b\u003e"',
                          presentation.to_json('<b>&</b>'))
 
@@ -35,11 +37,11 @@ class ToJsonTestCase(unittest.TestCase):
         self.assertEqual('[1,2,[true,false]]',
                          presentation.to_json([1, 2, [True, False]]))
         self.assertEqual(r'{"one":1,"other":[null,0],'
-                         r'"three":[3,"\u0026\u003c\u003e"],'
+                         r'''"three":[3,"\u0026\u003c\u003e'"],'''
                          r'"two":2}',
                          presentation.to_json({"one": 1, "two": 2,
                                                "other": [None, 0],
-                                               "three": [3, "&<>"]}))
+                                               "three": [3, "&<>'"]}))
 
 
 def suite():



Mime
View raw message