Software Freedom Law Center

Changeset 57

Show
Ignore:
Timestamp:
03/19/08 18:00:19 (6 months ago)
Author:
bkuhn
Message:

r60@hughes: bkuhn | 2008-03-19 17:59:34 -0400

  • Brought in sync with r6719 of Trac upstream, which was accomplished via:

svk smerge /loblaw/local/branches/trac.upstream-r6719 .

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/trac/cgi-bin/trac.cgi

    • Property svn:executable set to *
  • trunk/trac/cgi-bin/trac.fcgi

    • Property svn:executable set to *
  • trunk/trac/ChangeLog

    r46 r57  
    1 Trac 0.11b1 'Genshi' (December 18, 2007
    2 http://svn.edgewall.org/repos/trac/tags/trac-0.11b1 
    3  
    4  Trac 0.11b1 contains a great number of new features, improvements and 
     1Trac 0.11b2 'Genshi' (March 12, 2008
     2http://svn.edgewall.org/repos/trac/tags/trac-0.11b2 
     3 
     4 Trac 0.11b2 contains a great number of new features, improvements and 
    55 bug fixes. The following list contains only a few highlights: 
    66 
     
    1717 A more complete list of new features can be found in the RELEASE file. 
    1818 The complete list of closed tickets can be found here: 
    19    http://trac.edgewall.org/query?status=closed&milestone=0.10 
     19   http://trac.edgewall.org/query?status=closed&milestone=0.11 
     20 
     21Trac 0.11b1 'Genshi' (December 18, 2007) 
     22http://svn.edgewall.org/repos/trac/tags/trac-0.11b1 
     23 
     24 See 0.11b2. 
    2025 
    2126Trac 0.10.4 (April 20, 2007) 
  • trunk/trac/contrib/checkwiki.py

    • Property svn:executable set to *
  • trunk/trac/contrib/htdigest.py

    • Property svn:executable set to *
  • trunk/trac/contrib/rpm/makerpm

    • Property svn:executable set to *
  • trunk/trac/contrib/trac-post-commit-hook

    • Property svn:executable set to *
  • trunk/trac/contrib/workflow/migrate_original_to_basic.py

    • Property svn:executable set to *
  • trunk/trac/contrib/workflow/showworkflow

    • Property svn:executable set to *
  • trunk/trac/contrib/workflow/workflow_parser.py

    • Property svn:executable set to *
  • trunk/trac/RELEASE

    r46 r57  
    1 Release Notes for Trac 0.11 beta1 Genshi Release 
     1Release Notes for Trac 0.11 beta2 Genshi Release 
    22================================================ 
    3 December 18, 2007 
     3March 12, 2008 
    44 
    55Highlights 
  • trunk/trac/sample-plugins/permissions/vulnerability_tickets.py

    r46 r57  
    22from trac.perm import IPermissionPolicy, IPermissionRequestor 
    33 
    4 revision = "$Rev: 2 $" 
     4revision = "$Rev: 41 $" 
    55url = "$URL: /mirror/sample-plugins/permissions/vulnerability_tickets.py $" 
    66 
     
    4141            db = self.env.get_db_cnx() 
    4242            cursor = db.cursor() 
    43             for keywords, summary in cursor.execute("SELECT keywords, summary " 
    44                                                     " FROM ticket WHERE id=%s", 
    45                                                     (resource.id,))
     43            cursor.execute("SELECT keywords, summary FROM ticket WHERE id=%s", 
     44                           (resource.id,)) 
     45            for keywords, summary in cursor
    4646                fields = ''.join([f for f in (keywords, summary) if f]).lower() 
    4747                if 'security' in fields or 'vulnerability' in fields: 
  • trunk/trac/setup.py

    • Property svn:executable set to *
    r46 r57  
    3030    url = 'http://trac.edgewall.org/', 
    3131    download_url = 'http://trac.edgewall.org/wiki/TracDownload', 
     32    classifiers = [ 
     33        'Environment :: Web Environment', 
     34        'Framework :: Trac', 
     35        'Intended Audience :: Developers', 
     36        'License :: OSI Approved :: BSD License', 
     37        'Operating System :: OS Independent', 
     38        'Programming Language :: Python', 
     39        'Topic :: Software Development :: Bug Tracking', 
     40        'Topic :: Software Development :: Version Control', 
     41    ], 
    3242 
    3343    packages = find_packages(exclude=['*.tests']), 
  • trunk/trac/THANKS

    r46 r57  
    99 * Toni Brkic                     toni.brkic@switchcore.com 
    1010 * Eli Carter                     eli.carter@commprove.com 
     11 * Michele Cella 
    1112 * Felix Colins                   felix@keyghost.com 
    1213 * Wesley Crucius                 wcrucius@sandc.com 
     
    1617 * Markus Fuchs                    
    1718 * Eric Gillespie                 epg@netbsd.org 
     19 * Daniel Kahn Gillmor 
    1820 * Matthew Good                   trac@matt-good.net 
    1921 * Shun-ichi Goto                 gotoh@taiyo.co.jp 
  • trunk/trac/trac/admin/console.py

    • Property svn:executable set to *
  • trunk/trac/trac/admin/web_ui.py

    r46 r57  
    3131from trac.util import get_pkginfo, get_module_path 
    3232from trac.util.compat import partial 
     33from trac.util.text import to_unicode 
    3334from trac.util.translation import _ 
    3435from trac.web import HTTPNotFound, IRequestHandler 
     
    396397            raise TracError(_('No file uploaded')) 
    397398        upload = req.args['plugin_file'] 
    398         if not upload.filename: 
     399        if isinstance(upload, unicode) or not upload.filename: 
    399400            raise TracError(_('No file uploaded')) 
    400401        plugin_filename = upload.filename.replace('\\', '/').replace(':', '/') 
     
    481482                plugin_filename = os.path.basename(dist.location) 
    482483 
    483             description = inspect.getdoc(component
     484            description = to_unicode(inspect.getdoc(component)
    484485            if description: 
    485486                description = description.split('.', 1)[0] + '.' 
  • trunk/trac/trac/attachment.py

    r46 r57  
    372372            parent_id = '/'.join(segments[:-1]) 
    373373            filename = len(segments) > 1 and segments[-1] 
    374             if not filename: # if there's a trailing '/', show the list 
    375                 return self._render_list(req, parent_realm(id=parent_id)) 
    376374 
    377375        parent = parent_realm(id=parent_id) 
     376         
     377        # Link the attachment page to parent resource 
     378        parent_name = get_resource_name(self.env, parent) 
     379        parent_url = get_resource_url(self.env, parent, req.href) 
     380        add_link(req, 'up', parent_url, parent_name) 
     381        add_ctxtnav(req, _('Back to %(parent)s', parent=parent_name),  
     382                    parent_url) 
     383         
     384        if action != 'new' and not filename:  
     385            # there's a trailing '/', show the list 
     386            return self._render_list(req, parent) 
     387 
    378388        attachment = Attachment(self.env, parent.child('attachment', filename)) 
    379          
    380         add_link(req, 'up', get_resource_url(self.env, parent, req.href), 
    381                  get_resource_name(self.env, parent)) 
    382389         
    383390        if req.method == 'POST': 
     
    394401 
    395402        add_stylesheet(req, 'common/css/code.css') 
    396         add_ctxtnav(req, _('Back to %(parent)s',  
    397                            parent=get_resource_name(self.env, parent)),  
    398                     req.chrome['links']['up'][0]['href']) 
    399403        return 'attachment.html', data, None 
    400404 
     
    613617        } 
    614618 
    615         add_link(req, 'up', get_resource_url(self.env, parent, req.href), 
    616                  get_resource_name(self.env, parent)) 
    617  
    618619        return 'attachment.html', data, None 
    619620 
    620621    def _render_view(self, req, attachment): 
    621622        req.perm(attachment.resource).require('ATTACHMENT_VIEW') 
    622         req.check_modified(attachment.date) 
     623        can_delete = 'ATTACHMENT_DELETE' in req.perm(attachment.resource) 
     624        req.check_modified(attachment.date, str(can_delete)) 
    623625 
    624626        data = {'mode': 'view', 
  • trunk/trac/trac/db/mysql_backend.py

    r46 r57  
    1 # -*- coding: iso8859-1 -*- 
     1# -*- coding: utf-8 -*- 
    22# 
    33# Copyright (C) 2005-2006 Edgewall Software 
     
    177177        if type == 'int': 
    178178            type = 'signed' 
     179        elif type == 'text': 
     180            type = 'char' 
    179181        return 'CAST(%s AS %s)' % (column, type) 
    180182 
  • trunk/trac/trac/db_default.py

    r46 r57  
    281281  LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' 
    282282  ORDER BY (milestone IS NULL), milestone DESC, (status = 'closed'),  
    283         (CASE status WHEN 'closed' THEN modified ELSE (-1)*p.value END) DESC 
    284 """), 
     283        (CASE status WHEN 'closed' THEN changetime ELSE (-1) * %s END) DESC 
     284""" % db.cast('p.value', 'int')), 
    285285#---------------------------------------------------------------------------- 
    286286('My Tickets', 
  • trunk/trac/trac/htdocs/css/about.css

    r46 r57  
    1414  padding: 3px; 
    1515} 
    16 #content.about #config td.value { font-family: monospace; } 
    17 #content.about #config tr.modified { background: #fee; } 
    18 #content.about #config tr.modified td.value { font-weight: bold; } 
     16#content.about #config tr.modified { background: #ffd; } 
     17#content.about #config tr.modified td.value { font-style: italic; } 
    1918#content.about #config td.doc { padding: 3px 1em; } 
  • trunk/trac/trac/htdocs/css/report.css

    r46 r57  
    2121#query fieldset, #query fieldset input, #query fieldset select { font-size: 11px } 
    2222#query fieldset { margin-top: 1em } 
    23 #query fieldset.collapsed { border-width: 0 } 
     23#query fieldset.collapsed {  
     24 border-width: 0; 
     25 margin-bottom: 0pt; 
     26 padding: 0pt .5em; 
     27
    2428#query .option, #query .option input, #query .option select { font-size: 11px } 
    2529#query .option { float: left; line-height: 2em; margin: .9em 2.5em 0 .5em; padding: 0 0 .1em } 
  • trunk/trac/trac/htdocs/css/trac.css

    r46 r57  
    438438table.listing tbody tr.odd { background-color: #f7f7f7 } 
    439439table.listing tbody tr:hover { background: #eed !important } 
     440table.listing tbody tr.focus { background: #ddf !important } 
    440441 
    441442/* Styles for the page history table 
  • trunk/trac/trac/htdocs/js/blame.js

    r46 r57  
    7979 
    8080            // workaround non-clickable "Close" issue in Firefox 
    81             if ($.browser == 'mozilla'
     81            if ($.browser.mozilla
    8282              message.find("div.inlinebuttons").next().css("clear", "right"); 
    8383   
  • trunk/trac/trac/htdocs/js/expand_dir.js

    r46 r57  
    11// Enable expanding/folding folders in TracBrowser 
    22 
    3 var FOLDERID_COUNTER = 0; 
    4 var SUBFOLDER_INDENT = 20; 
    5  
    63(function($){ 
     4  var FOLDERID_COUNTER = 0; 
     5  var SUBFOLDER_INDENT = 20; 
    76   
    87  // enableExpandDir adds the capability to folder rows to be expanded and folded 
  • trunk/trac/trac/htdocs/js/query.js

    r46 r57  
    134134      // Convenience function for creating an <input type="radio"> 
    135135      function createRadio(name, value, id) { 
    136         var input = document.createElement("input"); 
    137         input.type = "radio"; 
    138         if (name) input.name = name; 
    139         if (value) input.value = value; 
    140         if (id) input.id = id; 
    141         return input; 
     136        var str = '<input type="radio"'; 
     137        if (name) str += ' name="' + name + '"'; 
     138        if (value) str += ' value="' + value + '"'; 
     139        if (id) str += ' id="' + id + '"';  
     140        str += '/>'; 
     141        var span = document.createElement('span'); 
     142        // create radio button with innerHTML to avoid IE mangling it. 
     143        span.innerHTML = str;  
     144        return span; 
    142145      } 
    143146   
  • trunk/trac/trac/htdocs/js/trac.js

    r46 r57  
    1 jQuery.noConflict(); // jQuery is now removed from the $ namespace 
    2                      // to use the $ shorthand, use (function($){ ... })(jQuery); 
    3                      // and for the onload handler: jQuery(function($){ ... }); 
    4  
    51(function($){ 
    62   
  • trunk/trac/trac/mimeview/api.py

    r46 r57  
    585585        if not content: 
    586586            return '' 
     587        if not isinstance(context, Context): 
     588            # backwards compatibility: the first argument used to be the 
     589            # request prior to 0.11 
     590            context = Context.from_request(context) 
    587591 
    588592        # Ensure we have a MIME type for this content 
  • trunk/trac/trac/mimeview/rst.py

    r46 r57  
    2727from distutils.version import StrictVersion 
    2828import re 
     29try: 
     30    from docutils import nodes 
     31    from docutils.core import publish_parts 
     32    from docutils.parsers import rst 
     33    from docutils import __version__ 
     34    has_docutils = True 
     35except ImportError: 
     36    has_docutils = False 
    2937 
    3038from trac.core import * 
     
    4856 
    4957    def render(self, context, mimetype, content, filename=None, rev=None): 
    50         try: 
    51             from docutils import nodes 
    52             from docutils.core import publish_parts 
    53             from docutils.parsers import rst 
    54             from docutils import __version__ 
    55         except ImportError: 
     58        global has_docutils 
     59        if not has_docutils: 
    5660            raise TracError(_('Docutils not found')) 
    5761        if StrictVersion(__version__) < StrictVersion('0.3.9'): 
  • trunk/trac/trac/notification.py

    r46 r57  
    2525from trac.util.text import CRLF 
    2626from trac.util.translation import _ 
    27 from trac.web.chrome import Chrome 
    2827 
    2928MAXHEADERLEN = 76 
    30  
     29EMAIL_LOOKALIKE_PATTERN = (r"[a-zA-Z0-9.'=+_-]+" '@' 
     30                            '(?:[a-zA-Z0-9_-]+\.)+[a-zA-Z]{2,4}') 
    3131 
    3232class NotificationSystem(Component): 
     
    118118        self.db = env.get_db_cnx() 
    119119 
     120        from trac.web.chrome import Chrome 
    120121        self.template = Chrome(self.env).load_template(self.template_name, 
    121122                                                       method='text') 
     
    167168 
    168169    def __init__(self, env): 
     170        global EMAIL_LOOKALIKE_PATTERN 
    169171        Notify.__init__(self, env) 
    170172 
    171         addrfmt = r'[\w\d_\.\-\+=]+\@(?:(?:[\w\d\-])+\.)+(?:[\w\d]{2,4})' 
     173        addrfmt = EMAIL_LOOKALIKE_PATTERN 
    172174        admit_domains = self.env.config.get('notification', 'admit_domains') 
    173175        if admit_domains: 
  • trunk/trac/trac/prefs/templates/prefs_datetime.html

    r46 r57  
    1212 
    1313    <div class="field" py:with="session_tzname = settings.session.get('tz'); 
    14                                 default_tzname = timezones[len(timezones)/2]; 
    15                                 selected_tz = timezone(session_tzname or default_tzname) or timezone(default_tzname) or utc; 
    16                                 selected_tzname = '%s' % selected_tz"> 
     14                                selected_tz = timezone(session_tzname) or utc"> 
    1715      <label>Time zone: 
    1816      <select name="tz"> 
    1917        <option>Default time zone</option> 
    2018        <option py:for="tzname in timezones" 
    21                 selected="${selected_tzname.startswith('Etc/') and 
     19                selected="${session_tzname != None and 
     20                            session_tzname.startswith('Etc/') and 
    2221                            selected_tz == timezone(tzname) or 
    23                             selected_tzname == tzname or None}">$tzname</option> 
     22                            session_tzname == tzname or None}">$tzname</option> 
    2423      </select></label> 
    2524      <p class="hint">Configuring your time zone will result in all 
     
    3029        Example: The current time is <strong>${format_time(now, 'iso8601', tzinfo=utc)}</strong> (UTC). 
    3130        <br /> 
    32         In ${session_tzname and 'your' or ''} time zone ${selected_tz.tzname(None)}, this would be displayed as 
    33         <strong>${format_time(now, 'iso8601', tzinfo=selected_tz)}</strong>. 
     31        In ${session_tzname and 'your' or 'the Default'} time zone ${session_tzname and ' ' + selected_tz.tzname(None) or ''}, this would be displayed as 
     32        <strong>${format_time(now, 'iso8601', tzinfo=(session_tzname and selected_tz or localtz))}</strong>. 
    3433      </p> 
    3534 
  • trunk/trac/trac/prefs/web_ui.py

    r46 r57  
    2323from trac.core import * 
    2424from trac.prefs.api import IPreferencePanelProvider 
    25 from trac.util.datefmt import all_timezones, get_timezone 
     25from trac.util.datefmt import all_timezones, get_timezone, localtz 
    2626from trac.util.translation import _ 
    2727from trac.web import HTTPNotFound, IRequestHandler 
     
    9696        return 'prefs_%s.html' % (panel or 'general'), { 
    9797            'settings': {'session': req.session, 'session_id': req.session.sid}, 
    98             'timezones': all_timezones, 'timezone': get_timezone 
     98            'timezones': all_timezones, 'timezone': get_timezone, 
     99            'localtz': localtz 
    99100        } 
    100101 
  • trunk/trac/trac/resource.py

    r46 r57  
    105105            if r.id: 
    106106                name += ':' + unicode(r.id) # id can be numerical 
    107             if r.version
     107            if r.version is not None
    108108                name += '@' + unicode(r.version) 
    109109            path.append(name) 
     
    149149        "<Resource u'wiki:WikiStart@3'>" 
    150150 
     151        >>> main0 = main3(version=0) 
     152        >>> repr(main0) 
     153        "<Resource u'wiki:WikiStart@0'>" 
     154 
    151155        In a copy, if `id` is overriden, then the original `version` value 
    152156        will not be reused. 
     
    160164        realm = resource_or_realm 
    161165        if isinstance(resource_or_realm, Resource): 
    162             if (id, version, parent) == (False, False, False)
     166            if id is False and version is False and parent is False
    163167                return resource_or_realm 
    164168            else: # copy and override 
  • trunk/trac/trac/templates/error.html

    r46 r57  
    3232       $("#traceback pre").hide(); 
    3333       $("#tbtoggle").parent().show(); 
    34  
     34        
     35       $("#systeminfo").append("<tr><th>jQuery:</th><td>"+$().jquery+"</td></tr>"); 
     36       $("#systeminfo").before("<p>User Agent: <tt>"+navigator.userAgent+"</tt></p>"); 
     37      }); 
     38    /*]]>*/</script> 
     39    <script type="text/javascript">/*<![CDATA[*/ 
     40      jQuery(document).ready(function($) { 
    3541       var descr = $("#description").text(); 
    3642       descr = descr.replace(/==== System Information ====\s+/m, 
     
    4147       ); 
    4248       $("#description").text(descr); 
    43  
    44        $("#systeminfo").append("<tr><th>jQuery:</th><td>"+$().jquery+"</td></tr>"); 
    45        $("#systeminfo").before("<p>User Agent: <tt>"+navigator.userAgent+"</tt></p>"); 
    4649      }); 
    4750    /*]]>*/</script> 
     
    5457           value="${'dev' in trac.version and 'devel' or trac.version}" /> 
    5558    <input type="hidden" name="summary" value="$message" /> 
    56     <textarea name="description" rows="3" cols="10"> 
     59    <textarea id="description" name="description" rows="3" cols="10"> 
     60 
    5761==== How to Reproduce ==== 
    5862 
  • trunk/trac/trac/templates/layout.html

    r46 r57  
    3535    </ul> 
    3636  </div> 
    37  
     37   
    3838  <py:match path="body" once="true"><body> 
    39     <div id="banner"> 
    40       <div id="header" py:choose=""> 
    41         <a py:when="chrome.logo.src" id="logo" href="${chrome.logo.link}"><img 
    42           src="${chrome.logo.src}" alt="${chrome.logo.alt}" 
    43           height="${chrome.logo.height or None}" width="${chrome.logo.width or None}" /></a> 
    44         <h1 py:otherwise=""><a href="${chrome.logo.link}">${project.name}</a></h1> 
    45       </div> 
    46       <form id="search" action="${href.search()}" method="get"> 
    47         <div py:if="'SEARCH_VIEW' in perm"> 
    48           <label for="proj-search">Search:</label> 
    49           <input type="text" id="proj-search" name="q" size="18" accesskey="f" value="" /> 
    50           <input type="submit" value="Search" /> 
    51         </div> 
    52       </form> 
    53       ${navigation('metanav')} 
    54     </div> 
    55     ${navigation('mainnav')} 
    56  
    57     <div id="main"> 
    58       <div id="ctxtnav" class="nav"> 
    59         <h2>Context Navigation</h2> 
    60           <ul> 
    61             <li py:for="i, elm in enumerate(chrome.ctxtnav)" class="${i == 0 and 'first ' or None}${i+1 == len(chrome.ctxtnav) and 'last' or None}">$elm</li> 
    62           </ul> 
    63         <hr /> 
    64       </div> 
    65       <div id="warning" py:if="chrome.warnings" class="system-message"> 
    66         <py:choose test="len(chrome.warnings)"> 
    67           <py:when test="1"> 
    68             <strong>Warning:</strong> ${chrome.warnings[0]} 
    69           </py:when> 
    70           <py:otherwise> 
    71             <strong>Warnings:</strong> 
    72             <ul><li py:for="w in chrome.warnings">$w</li></ul> 
    73           </py:otherwise> 
    74         </py:choose> 
    75       </div> 
    76       <div id="notice" py:if="chrome.notices" class="system-message"> 
    77         <py:choose test="len(chrome.notices)"> 
    78           <py:when test="1"> 
    79             <strong>Notice:</strong> ${chrome.notices[0]} 
    80           </py:when> 
    81           <py:otherwise> 
    82             <strong>Notices:</strong> 
    83             <ul><li py:for="w in chrome.notices">$w</li></ul> 
    84           </py:otherwise> 
    85         </py:choose> 
    86       </div> 
    87  
    88       ${select('*|text()')} 
    89  
     39    ${select('*|text()')} 
     40     
    9041      <script type="text/javascript" py:if="chrome.late_links"> 
    9142        <py:for each="link in chrome.late_links.get('stylesheet')"> 
    92           $.loadStyleSheet("${link.href}", "${link.title}"); 
     43          jQuery.loadStyleSheet("${link.href}", "${link.title}"); 
    9344        </py:for> 
    9445      </script> 
     
    10657        </ul> 
    10758      </div> 
    108     </div> 
    109  
    110     <div id="footer" xml:lang="en"><hr/> 
    111       <a id="tracpowered" href="http://trac.edgewall.org/"><img 
    112         src="${chrome.htdocs_location}trac_logo_mini.png" height="30" 
    113         width="107" alt="Trac Powered"/></a> 
    114       <p class="left"> 
    115         Powered by <a href="${href.about()}"><strong>Trac ${trac.version}</strong></a><br /> 
    116         By <a href="http://www.edgewall.org/">Edgewall Software</a>. 
    117       </p> 
    118       <p class="right">${chrome.footer}</p> 
    119     </div> 
    120   </body></py:match> 
    121  
     59    </body></py:match> 
     60     
     61  <xi:include href="$chrome.theme"><xi:fallback /></xi:include> 
    12262  <xi:include href="site.html"><xi:fallback /></xi:include> 
    12363 
  • trunk/trac/trac/test.py

    • Property svn:executable set to *
  • trunk/trac/trac/tests/config.py

    r46 r57  
    212212        config = self._read() 
    213213        self.assertEquals('x', config.get('a', 'option')) 
    214         time.sleep(1) # needed because of low mtime granularity 
     214        time.sleep(2) # needed because of low mtime granularity, 
     215                      # especially on fat filesystems 
    215216 
    216217        self._write(['[a]', 'option = y']) 
  • trunk/trac/trac/ticket/admin.py

    r46 r57  
    114114                              in self.env.get_known_users() 
    115115                              if valid_owner(username)] 
     116            data['owners'].insert(0, '') 
     117            data['owners'].sort() 
    116118        else: 
    117119            data['owners'] = None 
  • trunk/trac/trac/ticket/default_workflow.py

    r46 r57  
    216216        hints = [] 
    217217        if 'reset_workflow' in operations: 
    218             control.append(tag("from invalid state")) 
     218            control.append(tag("from invalid state ")) 
    219219            hints.append(_("Current state no longer exists")) 
    220220        if 'del_owner' in operations: 
     
    240240                hints.append(_("The owner will change")) 
    241241            elif len(owners) == 1: 
    242                 control.append(tag('to %s' % owners[0])) 
     242                control.append(tag('to %s ' % owners[0])) 
    243243                hints.append(_("The owner will change to %s") % owners[0]) 
    244244            else: 
     
    272272                hints.append(_("The resolution will be set")) 
    273273        if 'leave_status' in operations: 
    274             control.append('as ' + ticket['status']) 
     274            control.append('as %s ' % ticket['status']) 
    275275        else: 
    276276            if status != '*': 
  • trunk/trac/trac/ticket/model.py

    r46 r57  
    613613            raise ResourceNotFound('Milestone %s does not exist.' % name, 
    614614                                   'Invalid Milestone Name') 
     615        self._from_database(row) 
     616 
     617    exists = property(fget=lambda self: self._old_name is not None) 
     618    is_completed = property(fget=lambda self: self.completed is not None) 
     619    is_late = property(fget=lambda self: self.due and \ 
     620                                         self.due.date() < date.today()) 
     621 
     622    def _from_database(self, row): 
    615623        name, due, completed, description = row 
    616         self.name = name 
     624        self.name = self._old_name = name 
    617625        self.due = due and datetime.fromtimestamp(int(due), utc) or None 
    618626        self.completed = completed and \ 
    619627                         datetime.fromtimestamp(int(completed), utc) or None 
    620628        self.description = description or '' 
    621  
    622     exists = property(fget=lambda self: self._old_name is not None) 
    623     is_completed = property(fget=lambda self: self.completed is not None) 
    624     is_late = property(fget=lambda self: self.due and \ 
    625                                          self.due.date() < date.today()) 
    626629 
    627630    def delete(self, retarget_to=None, author=None, db=None): 
     
    702705        cursor.execute(sql) 
    703706        milestones = [] 
    704         for name,due,completed,description in cursor: 
     707        for row in cursor: 
    705708            milestone = Milestone(env) 
    706             milestone.name = milestone._old_name = name 
    707             milestone.due = due and datetime.fromtimestamp(int(due), utc) or None 
    708             if completed: 
    709                 milestone.completed = datetime.fromtimestamp(int(completed), utc) 
    710             else: 
    711                 milestone.completed = None 
    712             milestone.description = description or '' 
     709            milestone._from_database(row) 
    713710            milestones.append(milestone) 
    714711        def milestone_order(m): 
  • trunk/trac/trac/ticket/templates/ticket_notify_email.txt

    r46 r57  
    2929--  
    3030Ticket URL: <$ticket.link> 
    31 $project.name <${abs_href()}> 
     31$project.name <${project.url or abs_href()}> 
    3232$project.descr 
  • trunk/trac/trac/ticket/web_ui.py

    r46 r57  
    1717import csv 
    1818from datetime import datetime 
     19from itertools import chain 
    1920import os 
    2021import pkg_resources 
     
    179180        sql, args = search_to_sql(db, ['b.newvalue'], terms) 
    180181        sql2, args2 = search_to_sql(db, ['summary', 'keywords', 'description', 
    181                                          'reporter', 'cc', 'id'], terms) 
     182                                         'reporter', 'cc',  
     183                                         db.cast('id', 'text')], terms) 
    182184        cursor = db.cursor() 
    183185        cursor.execute("SELECT DISTINCT a.summary,a.description,a.reporter, " 
     
    413415                                         'view')) 
    414416 
    415         data = {'ticket': ticket, 'comment': None} 
    416417        data = self._prepare_data(req, ticket) 
    417418        data['comment'] = None 
     
    10581059                    value