Edgewall Software

Ticket #6466: 6466-float-timestamps-2-r8770.patch

File 6466-float-timestamps-2-r8770.patch, 34.0 KB (added by rblank, 3 years ago)

Improved patch, SQLite and PostgreSQL work.

  • contrib/sourceforge2trac.py

    diff --git a/contrib/sourceforge2trac.py b/contrib/sourceforge2trac.py
    a b  
    1919    def __init__(self, e): 
    2020        for field in e: 
    2121            if field.get('name').endswith('date'): 
    22                 setattr(self, field.get('name'), datetime.fromtimestamp(int(field.text))) 
     22                setattr(self, field.get('name'), datetime.fromtimestamp(float(field.text))) 
    2323            else: 
    2424                setattr(self, field.get('name'), field.text)         
    2525 
  • trac/attachment.py

    diff --git a/trac/attachment.py b/trac/attachment.py
    a b  
    150150        self.filename = row[0] 
    151151        self.description = row[1] 
    152152        self.size = row[2] and int(row[2]) or 0 
    153         time = row[3] and int(row[3]) or 0 
     153        time = row[3] or 0.0 
    154154        self.date = datetime.fromtimestamp(time, utc) 
    155155        self.author = row[4] 
    156156        self.ipnr = row[5] 
     
    207207            handle_ta = False 
    208208 
    209209        self.size = size and int(size) or 0 
    210         timestamp = int(t or time.time()) 
     210        timestamp = float(t or time.time()) 
    211211        self.date = datetime.fromtimestamp(timestamp, utc) 
    212212 
    213213        # Make sure the path to the attachment is inside the environment 
     
    265265            attachment.filename = filename 
    266266            attachment.description = description 
    267267            attachment.size = size and int(size) or 0 
    268             time = time and int(time) or 0 
     268            time = time or 0.0 
    269269            attachment.date = datetime.fromtimestamp(time, utc) 
    270270            attachment.author = author 
    271271            attachment.ipnr = ipnr 
  • trac/db/mysql_backend.py

    diff --git a/trac/db/mysql_backend.py b/trac/db/mysql_backend.py
    a b  
    133133        coldefs = [] 
    134134        for column in table.columns: 
    135135            ctype = column.type 
     136            if ctype == 'real': 
     137                ctype = 'double precision' 
    136138            if column.auto_increment: 
    137139                ctype = 'INT UNSIGNED NOT NULL AUTO_INCREMENT' 
    138140                # Override the column type, as a text field cannot 
  • trac/db/postgres_backend.py

    diff --git a/trac/db/postgres_backend.py b/trac/db/postgres_backend.py
    a b  
    3838    register_type(UNICODE) 
    3939    register_adapter(Markup, lambda markup: QuotedString(unicode(markup))) 
    4040    register_adapter(Empty, lambda empty: AsIs("''")) 
     41    # Work around a loss of precision for float values in psycopg 
     42    # See http://trac.edgewall.org/ticket/6466#comment:17 
     43    register_adapter(float, lambda value: AsIs(repr(value))) 
    4144 
    4245    has_psycopg = True 
    4346except ImportError: 
     
    9295        coldefs = [] 
    9396        for column in table.columns: 
    9497            ctype = column.type 
     98            if ctype == 'real': 
     99                ctype = 'double precision' 
    95100            if column.auto_increment: 
    96101                ctype = 'SERIAL' 
    97102            if len(table.key) == 1 and column.name in table.key: 
     
    173178            dsn.append('port=' + str(port)) 
    174179        cnx = psycopg.connect(' '.join(dsn)) 
    175180        cnx.set_client_encoding('UNICODE') 
     181        cursor = cnx.cursor() 
     182        cursor.execute("SET extra_float_digits TO 2") 
     183        cnx.commit() 
    176184        try: 
    177185            self.schema = None 
    178186            if 'schema' in params: 
    179187                self.schema = params['schema'] 
    180                 cnx.cursor().execute('SET search_path TO %s', (self.schema,)) 
     188                cursor.execute('SET search_path TO %s', (self.schema,)) 
    181189                cnx.commit() 
    182190        except PGSchemaError: 
    183191            cnx.rollback() 
  • trac/db/tests/api.py

    diff --git a/trac/db/tests/api.py b/trac/db/tests/api.py
    a b  
    11# -*- coding: utf-8 -*- 
    22 
     3from datetime import datetime, timedelta 
    34import os 
    45import unittest 
    56 
    67from trac.db.api import _parse_db_str 
     8from trac.util.datefmt import to_timestamp, utc 
    79from trac.test import EnvironmentStub 
    810 
    911 
     
    108110        self.assertEqual([(u'<em>märkup</em>',)], cursor.fetchall()) 
    109111 
    110112 
     113class RealsTestCase(unittest.TestCase): 
     114     
     115    def setUp(self): 
     116        self.env = EnvironmentStub() 
     117        self.id = 0 
     118     
     119    def assertRoundTrips(self, db, when): 
     120        """Check that a time stored as a timestamp makes a perfect round-trip 
     121        through the database.""" 
     122        cursor = db.cursor() 
     123        self.id += 1 
     124        when_ts = to_timestamp(when) 
     125        cursor.execute("INSERT INTO ticket_change (ticket,time,field) " 
     126                       "VALUES (%s,%s,'field')", (self.id, when_ts)) 
     127        db.commit() 
     128        cursor.execute("SELECT time FROM ticket_change " 
     129                       "WHERE ticket=%s AND field='field'", (self.id,)) 
     130        rows = cursor.fetchall() 
     131        self.assertEqual([(when_ts,)], rows) 
     132        self.assertEqual(when, datetime.fromtimestamp(rows[0][0], utc)) 
     133        cursor.execute("SELECT ticket FROM ticket_change " 
     134                       "WHERE time=%s AND field='field'", (when_ts,)) 
     135        self.assertEqual([(self.id,)], cursor.fetchall()) 
     136         
     137    def test_time_round_trip(self): 
     138        """Vary each digit in the microseconds field of a time and check a 
     139        round-trip through the database.""" 
     140        db = self.env.get_db_cnx() 
     141        base = datetime(2037, 2, 3, 4, 5, 6, 123456, utc) 
     142        self.assertRoundTrips(db, base) 
     143        for digit in range(7): 
     144            for i in range(1, 10): 
     145                when = base + timedelta(0, 0, i * 10 ** digit) 
     146                self.assertRoundTrips(db, when) 
     147 
     148 
    111149def suite(): 
    112150    suite = unittest.TestSuite() 
    113151    suite.addTest(unittest.makeSuite(ParseConnectionStringTestCase, 'test')) 
    114152    suite.addTest(unittest.makeSuite(StringsTestCase, 'test')) 
     153    suite.addTest(unittest.makeSuite(RealsTestCase, 'test')) 
    115154    return suite 
    116155 
    117156if __name__ == '__main__': 
  • trac/db_default.py

    diff --git a/trac/db_default.py b/trac/db_default.py
    a b  
    1717from trac.db import Table, Column, Index 
    1818 
    1919# Database version identifier. Used for automatic upgrades. 
    20 db_version = 22 
     20db_version = 23 
    2121 
    2222def __mkreports(reports): 
    2323    """Utility function used to create report data in same syntax as the 
     
    4545        Column('cookie'), 
    4646        Column('name'), 
    4747        Column('ipnr'), 
    48         Column('time', type='int')], 
     48        Column('time', type='real')], 
    4949    Table('session', key=('sid', 'authenticated'))[ 
    5050        Column('sid'), 
    5151        Column('authenticated', type='int'), 
    52         Column('last_visit', type='int'), 
     52        Column('last_visit', type='real'), 
    5353        Index(['last_visit']), 
    5454        Index(['authenticated'])], 
    5555    Table('session_attribute', key=('sid', 'authenticated', 'name'))[ 
     
    6767        Column('id'), 
    6868        Column('filename'), 
    6969        Column('size', type='int'), 
    70         Column('time', type='int'), 
     70        Column('time', type='real'), 
    7171        Column('description'), 
    7272        Column('author'), 
    7373        Column('ipnr')], 
     
    7676    Table('wiki', key=('name', 'version'))[ 
    7777        Column('name'), 
    7878        Column('version', type='int'), 
    79         Column('time', type='int'), 
     79        Column('time', type='real'), 
    8080        Column('author'), 
    8181        Column('ipnr'), 
    8282        Column('text'), 
     
    8787    # Version control cache 
    8888    Table('revision', key='rev')[ 
    8989        Column('rev'), 
    90         Column('time', type='int'), 
     90        Column('time', type='real'), 
    9191        Column('author'), 
    9292        Column('message'), 
    9393        Index(['time'])], 
     
    104104    Table('ticket', key='id')[ 
    105105        Column('id', auto_increment=True), 
    106106        Column('type'), 
    107         Column('time', type='int'), 
    108         Column('changetime', type='int'), 
     107        Column('time', type='real'), 
     108        Column('changetime', type='real'), 
    109109        Column('component'), 
    110110        Column('severity'), 
    111111        Column('priority'), 
     
    123123        Index(['status'])],     
    124124    Table('ticket_change', key=('ticket', 'time', 'field'))[ 
    125125        Column('ticket', type='int'), 
    126         Column('time', type='int'), 
     126        Column('time', type='real'), 
    127127        Column('author'), 
    128128        Column('field'), 
    129129        Column('oldvalue'), 
     
    144144        Column('description')], 
    145145    Table('milestone', key='name')[ 
    146146        Column('name'), 
    147         Column('due', type='int'), 
    148         Column('completed', type='int'), 
     147        Column('due', type='real'), 
     148        Column('completed', type='real'), 
    149149        Column('description')], 
    150150    Table('version', key='name')[ 
    151151        Column('name'), 
    152         Column('time', type='int'), 
     152        Column('time', type='real'), 
    153153        Column('description')], 
    154154 
    155155    # Report system 
  • trac/ticket/model.py

    diff --git a/trac/ticket/model.py b/trac/ticket/model.py
    a b  
    328328        db = self._get_db(db) 
    329329        cursor = db.cursor() 
    330330        sid = str(self.id) 
    331         when_ts = when and to_timestamp(when) or 0 
     331        when_ts = to_timestamp(when) 
    332332        if when_ts: 
    333333            cursor.execute("SELECT time,author,field,oldvalue,newvalue," 
    334334                           "1 AS permanent FROM ticket_change " 
     
    356356                           (self.id, sid, sid)) 
    357357        log = [] 
    358358        for t, author, field, oldvalue, newvalue, permanent in cursor: 
    359             log.append((datetime.fromtimestamp(int(t), utc), author, field, 
     359            log.append((datetime.fromtimestamp(t, utc), author, field, 
    360360                       oldvalue or '', newvalue or '', permanent)) 
    361361        return log 
    362362 
     
    389389                           "WHERE ticket=%s AND time=%s", 
    390390                           (self.id, ts)) 
    391391            fields = {} 
    392             change = {'date': datetime.fromtimestamp(int(ts), utc), 
     392            change = {'date': datetime.fromtimestamp(ts, utc), 
    393393                      'author': author, 'fields': fields} 
    394394            for field, author, old, new in cursor: 
    395395                fields[field] = {'author': author, 'old': old, 'new': new} 
     
    445445                           (self.id, ts0, db.like_escape('_comment') + '%')) 
    446446            for field, author, comment, ts in cursor: 
    447447                rev = int(field[8:]) 
    448                 history.append((rev, datetime.fromtimestamp(int(ts0), utc), 
     448                history.append((rev, datetime.fromtimestamp(ts0, utc), 
    449449                                author0, comment)) 
    450450                ts0, author0 = ts, author 
    451451            history.sort() 
    452452            rev = history and (history[-1][0] + 1) or 0 
    453             history.append((rev, datetime.fromtimestamp(int(ts), utc), 
     453            history.append((rev, datetime.fromtimestamp(ts, utc), 
    454454                            author, last_comment)) 
    455455        return history 
    456456 
     
    758758    def _from_database(self, row): 
    759759        name, due, completed, description = row 
    760760        self.name = self._old_name = name 
    761         self.due = due and datetime.fromtimestamp(int(due), utc) or None 
     761        self.due = due and datetime.fromtimestamp(due, utc) or None 
    762762        self.completed = completed and \ 
    763                          datetime.fromtimestamp(int(completed), utc) or None 
     763                         datetime.fromtimestamp(completed, utc) or None 
    764764        self.description = description or '' 
    765765 
    766766    def delete(self, retarget_to=None, author=None, db=None): 
     
    890890                raise ResourceNotFound(_('Version %(name)s does not exist.', 
    891891                                         name=name)) 
    892892            self.name = self._old_name = name 
    893             self.time = row[0] and datetime.fromtimestamp(int(row[0]), utc) or None 
     893            self.time = row[0] and datetime.fromtimestamp(row[0], utc) or None 
    894894            self.description = row[1] or '' 
    895895        else: 
    896896            self.name = self._old_name = None 
     
    975975        for name, time, description in cursor: 
    976976            version = cls(env) 
    977977            version.name = version._old_name = name 
    978             version.time = time and datetime.fromtimestamp(int(time), utc) or None 
     978            version.time = time and datetime.fromtimestamp(time, utc) or None 
    979979            version.description = description or '' 
    980980            versions.append(version) 
    981981        def version_order(v): 
  • trac/ticket/query.py

    diff --git a/trac/ticket/query.py b/trac/ticket/query.py
    a b  
    331331                elif val is None: 
    332332                    val = '--' 
    333333                elif name in self.time_fields: 
    334                     val = datetime.fromtimestamp(int(val or 0), utc) 
     334                    val = datetime.fromtimestamp(float(val or 0), utc) 
    335335                elif field and field['type'] == 'checkbox': 
    336336                    try: 
    337337                        val = bool(int(val)) 
     
    10201020        # The most recent query is stored in the user session; 
    10211021        orig_list = None 
    10221022        orig_time = datetime.now(utc) 
    1023         query_time = int(req.session.get('query_time', 0)) 
     1023        query_time = float(req.session.get('query_time', 0)) 
    10241024        query_time = datetime.fromtimestamp(query_time, utc) 
    10251025        query_constraints = unicode(query.constraints) 
    10261026        try: 
  • trac/ticket/templates/report.rss

    diff --git a/trac/ticket/templates/report.rss b/trac/ticket/templates/report.rss
    a b  
    2626                </py:when> 
    2727                <py:when test="col in ('time', 'changetime', 'created', 'modified')"> 
    2828                  <!-- FIXME: we end up with multiple pubDate --> 
    29                   <pubDate py:if="cell.value != 'None'">${http_date(fromtimestamp(int(cell.value)))}</pubDate> 
     29                  <pubDate py:if="cell.value != 'None'">${http_date(fromtimestamp(float(cell.value)))}</pubDate> 
    3030                </py:when> 
    3131                <py:when test="col == 'summary'"> 
    3232                  <title>#$row.id: $cell.value</title> 
  • trac/ticket/templates/report_view.html

    diff --git a/trac/ticket/templates/report_view.html b/trac/ticket/templates/report_view.html
    a b  
    144144 
    145145                        <!--! generic fields --> 
    146146                        <py:when test="col == 'time'"> 
    147                           <td class="date" py:attrs="td_attrs">${cell.value != '' and format_time(int(cell.value)) or '--'} 
     147                          <td class="date" py:attrs="td_attrs">${cell.value != '' and format_time(float(cell.value)) or '--'} 
    148148                            <hr py:if="fullrow"/> 
    149149                          </td> 
    150150                        </py:when> 
    151151 
    152152                        <py:when test="col in ('date', 'created', 'modified')"> 
    153                           <td class="date" py:attrs="td_attrs">${cell.value != '' and format_date(int(cell.value)) or '--'} 
     153                          <td class="date" py:attrs="td_attrs">${cell.value != '' and format_date(float(cell.value)) or '--'} 
    154154                            <hr py:if="fullrow"/> 
    155155                          </td> 
    156156                        </py:when> 
    157157 
    158158                        <py:when test="col == 'datetime'"> 
    159                           <td class="date" py:attrs="td_attrs">${cell.value != '' and format_datetime(int(cell.value)) or '--'} 
     159                          <td class="date" py:attrs="td_attrs">${cell.value != '' and format_datetime(float(cell.value)) or '--'} 
    160160                            <hr py:if="fullrow"/> 
    161161                          </td> 
    162162                        </py:when> 
  • trac/ticket/tests/model.py

    diff --git a/trac/ticket/tests/model.py b/trac/ticket/tests/model.py
    a b  
    312312                          sorted(log[1:3])) 
    313313        self.assertEqual((t3, 'jim', 'comment', '', 'Other', True), log[3]) 
    314314 
     315    def test_subsecond_change(self): 
     316        """Perform two ticket changes within a second.""" 
     317        tkt_id = self._insert_ticket('Test', reporter='joe', component='foo') 
     318        ticket = Ticket(self.env, tkt_id) 
     319        t1 = datetime(2001, 1, 1, 1, 1, 1, 123456, utc) 
     320        ticket.save_changes('jane', 'Testing', t1) 
     321        t2 = datetime(2001, 1, 1, 1, 1, 1, 789012, utc) 
     322        ticket.save_changes('jim', 'Other', t2) 
     323        log = ticket.get_changelog() 
     324        self.assertEqual(2, len(log)) 
     325        self.assertEqual((t1, 'jane', 'comment', '', 'Testing', True), log[0]) 
     326        self.assertEqual((t2, 'jim', 'comment', '', 'Other', True), log[1]) 
     327 
    315328    def test_changelog_with_reverted_change(self): 
    316329        tkt_id = self._insert_ticket('Test', reporter='joe', component='foo') 
    317330        ticket = Ticket(self.env, tkt_id) 
  • trac/ticket/web_ui.py

    diff --git a/trac/ticket/web_ui.py b/trac/ticket/web_ui.py
    a b  
    16491649                comment_history.setdefault(rev, {}).update({'comment': old}) 
    16501650                comment_history.setdefault(rev + 1, {}).update( 
    16511651                        {'author': author, 
    1652                          'date': datetime.fromtimestamp(int(new), utc)}) 
     1652                         'date': datetime.fromtimestamp(float(new), utc)}) 
    16531653            elif old or new: 
    16541654                current['fields'][field] = {'old': old, 'new': new} 
    16551655        if current: 
  • new file trac/upgrades/db23.py

    diff --git a/trac/upgrades/db23.py b/trac/upgrades/db23.py
    new file mode 100644
    - +  
     1from trac.db import Table, Column, Index, DatabaseManager 
     2 
     3def do_upgrade(env, ver, cursor): 
     4    # Convert time values from int to real 
     5    tables = [ 
     6        Table('auth_cookie', key=('cookie', 'ipnr', 'name'))[ 
     7            Column('cookie'), 
     8            Column('name'), 
     9            Column('ipnr'), 
     10            Column('time', type='real')], 
     11        Table('session', key=('sid', 'authenticated'))[ 
     12            Column('sid'), 
     13            Column('authenticated', type='int'), 
     14            Column('last_visit', type='real'), 
     15            Index(['last_visit']), 
     16            Index(['authenticated'])], 
     17        Table('attachment', key=('type', 'id', 'filename'))[ 
     18            Column('type'), 
     19            Column('id'), 
     20            Column('filename'), 
     21            Column('size', type='int'), 
     22            Column('time', type='real'), 
     23            Column('description'), 
     24            Column('author'), 
     25            Column('ipnr')], 
     26        Table('wiki', key=('name', 'version'))[ 
     27            Column('name'), 
     28            Column('version', type='int'), 
     29            Column('time', type='real'), 
     30            Column('author'), 
     31            Column('ipnr'), 
     32            Column('text'), 
     33            Column('comment'), 
     34            Column('readonly', type='int'), 
     35            Index(['time'])], 
     36        Table('revision', key='rev')[ 
     37            Column('rev'), 
     38            Column('time', type='real'), 
     39            Column('author'), 
     40            Column('message'), 
     41            Index(['time'])], 
     42        Table('ticket', key='id')[ 
     43            Column('id', auto_increment=True), 
     44            Column('type'), 
     45            Column('time', type='real'), 
     46            Column('changetime', type='real'), 
     47            Column('component'), 
     48            Column('severity'), 
     49            Column('priority'), 
     50            Column('owner'), 
     51            Column('reporter'), 
     52            Column('cc'), 
     53            Column('version'), 
     54            Column('milestone'), 
     55            Column('status'), 
     56            Column('resolution'), 
     57            Column('summary'), 
     58            Column('description'), 
     59            Column('keywords'), 
     60            Index(['time']), 
     61            Index(['status'])],     
     62        Table('ticket_change', key=('ticket', 'time', 'field'))[ 
     63            Column('ticket', type='int'), 
     64            Column('time', type='real'), 
     65            Column('author'), 
     66            Column('field'), 
     67            Column('oldvalue'), 
     68            Column('newvalue'), 
     69            Index(['ticket']), 
     70            Index(['time'])], 
     71        Table('milestone', key='name')[ 
     72            Column('name'), 
     73            Column('due', type='real'), 
     74            Column('completed', type='real'), 
     75            Column('description')], 
     76        Table('version', key='name')[ 
     77            Column('name'), 
     78            Column('time', type='real'), 
     79            Column('description')], 
     80    ] 
     81     
     82    for table in tables: 
     83        cursor.execute("CREATE TEMPORARY TABLE %s_old " 
     84                       "AS SELECT * FROM %s" % (table.name, table.name)) 
     85        cursor.execute("DROP TABLE %s" % table.name) 
     86     
     87    db_connector, _ = DatabaseManager(env)._get_connector() 
     88    for table in tables: 
     89        for stmt in db_connector.to_sql(table): 
     90            cursor.execute(stmt) 
     91     
     92    for table in tables: 
     93        cursor.execute("INSERT INTO %s SELECT * FROM %s_old" 
     94                       % (table.name, table.name)) 
     95        cursor.execute("DROP TABLE %s_old" % table.name) 
  • trac/util/datefmt.py

    diff --git a/trac/util/datefmt.py b/trac/util/datefmt.py
    a b  
    5757    """Return the corresponding POSIX timestamp""" 
    5858    if dt: 
    5959        diff = dt - _epoc 
    60         return diff.days * 86400 + diff.seconds 
     60        return diff.days * 86400 + diff.seconds + diff.microseconds * 1e-6 
    6161    else: 
    62         return 0 
     62        return 0.0 
    6363 
    6464 
    6565# -- formatting 
  • trac/util/tests/datefmt.py

    diff --git a/trac/util/tests/datefmt.py b/trac/util/tests/datefmt.py
    a b  
    4242                             tz.utcoffset(None)) 
    4343            self.assertEqual('GMT +4:00', tz.zone) 
    4444 
     45 
    4546class DateFormatTestCase(unittest.TestCase): 
    4647 
    4748    def test_to_datetime(self): 
     
    9495        self.assertEqual('2009-08-20',  
    9596                         datefmt.format_date(a_date, format='%Y-%m-%d')) 
    9697 
     98 
     99class ToTimestampTestCase(unittest.TestCase): 
     100     
     101    def test_sub_second(self): 
     102        t = datetime.datetime(2001, 2, 3, 4, 5, 6, 123456, datefmt.utc) 
     103        ts = datefmt.to_timestamp(t) 
     104        self.assertNotEqual(ts, int(ts)) 
     105        self.assertEqual(t, datetime.datetime.fromtimestamp(ts, datefmt.utc)) 
     106 
     107 
    97108def suite(): 
    98109    suite = unittest.TestSuite() 
    99110    if PytzTestCase: 
     
    101112    else: 
    102113        print "SKIP: utils/tests/datefmt.py (no pytz installed)" 
    103114    suite.addTest(unittest.makeSuite(DateFormatTestCase)) 
     115    suite.addTest(unittest.makeSuite(ToTimestampTestCase)) 
    104116    return suite 
    105117 
    106118if __name__ == '__main__': 
  • trac/versioncontrol/svn_fs.py

    diff --git a/trac/versioncontrol/svn_fs.py b/trac/versioncontrol/svn_fs.py
    a b  
    781781                                 core.SVN_PROP_REVISION_DATE, self.pool()) 
    782782        if not _date: 
    783783            return None 
    784         ts = core.svn_time_from_cstring(_date, self.pool()) / 1000000 
     784        ts = core.svn_time_from_cstring(_date, self.pool()) / 1000000.0 
    785785        return datetime.fromtimestamp(ts, utc) 
    786786 
    787787    def _get_prop(self, name): 
     
    847847        author = author and to_unicode(author, 'utf-8') 
    848848        _date = self._get_prop(core.SVN_PROP_REVISION_DATE) 
    849849        if _date: 
    850             ts = core.svn_time_from_cstring(_date, self.pool()) / 1000000 
     850            ts = core.svn_time_from_cstring(_date, self.pool()) / 1000000.0 
    851851            date = datetime.fromtimestamp(ts, utc) 
    852852        else: 
    853853            date = None 
  • trac/versioncontrol/tests/svn_fs.py

    diff --git a/trac/versioncontrol/tests/svn_fs.py b/trac/versioncontrol/tests/svn_fs.py
    a b  
    145145        self.assertEqual(u'/tête', node.path) 
    146146        self.assertEqual(Node.DIRECTORY, node.kind) 
    147147        self.assertEqual(HEAD, node.rev) 
    148         self.assertEqual(datetime(2007, 4, 30, 17, 45, 26, 0, utc), 
     148        self.assertEqual(datetime(2007, 4, 30, 17, 45, 26, 234375, utc), 
    149149                         node.last_modified) 
    150150        node = self.repos.get_node(u'/tête/README.txt') 
    151151        self.assertEqual('README.txt', node.name) 
    152152        self.assertEqual(u'/tête/README.txt', node.path) 
    153153        self.assertEqual(Node.FILE, node.kind) 
    154154        self.assertEqual(3, node.rev) 
    155         self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 0, utc), node.last_modified) 
     155        self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 234643, utc), node.last_modified) 
    156156 
    157157    def test_get_node_specific_rev(self): 
    158158        node = self.repos.get_node(u'/tête', 1) 
     
    160160        self.assertEqual(u'/tête', node.path) 
    161161        self.assertEqual(Node.DIRECTORY, node.kind) 
    162162        self.assertEqual(1, node.rev) 
    163         self.assertEqual(datetime(2005, 4, 1, 10, 0, 52, 0, utc), node.last_modified) 
     163        self.assertEqual(datetime(2005, 4, 1, 10, 0, 52, 353248, utc), node.last_modified) 
    164164        node = self.repos.get_node(u'/tête/README.txt', 2) 
    165165        self.assertEqual('README.txt', node.name) 
    166166        self.assertEqual(u'/tête/README.txt', node.path) 
    167167        self.assertEqual(Node.FILE, node.kind) 
    168168        self.assertEqual(2, node.rev) 
    169         self.assertEqual(datetime(2005, 4, 1, 13, 12, 18, 0, utc), node.last_modified) 
     169        self.assertEqual(datetime(2005, 4, 1, 13, 12, 18, 216267, utc), node.last_modified) 
    170170 
    171171    def test_get_dir_entries(self): 
    172172        node = self.repos.get_node(u'/tête') 
     
    383383        self.assertEqual(0, chgset.rev) 
    384384        self.assertEqual('', chgset.message) 
    385385        self.assertEqual('', chgset.author) 
    386         self.assertEqual(datetime(2005, 4, 1, 9, 57, 41, 0, utc), chgset.date) 
     386        self.assertEqual(datetime(2005, 4, 1, 9, 57, 41, 312767, utc), chgset.date) 
    387387        self.assertRaises(StopIteration, chgset.get_changes().next) 
    388388 
    389389    def test_changeset_added_dirs(self): 
     
    391391        self.assertEqual(1, chgset.rev) 
    392392        self.assertEqual('Initial directory layout.', chgset.message) 
    393393        self.assertEqual('john', chgset.author) 
    394         self.assertEqual(datetime(2005, 4, 1, 10, 0, 52, 0, utc), chgset.date) 
     394        self.assertEqual(datetime(2005, 4, 1, 10, 0, 52, 353248, utc), chgset.date) 
    395395 
    396396        changes = chgset.get_changes() 
    397397        self.assertEqual(('branches', Node.DIRECTORY, Changeset.ADD, None, -1), 
     
    407407        self.assertEqual(3, chgset.rev) 
    408408        self.assertEqual('Fixed README.\n', chgset.message) 
    409409        self.assertEqual('kate', chgset.author) 
    410         self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 0, utc), chgset.date) 
     410        self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 234643, utc), chgset.date) 
    411411 
    412412        changes = chgset.get_changes() 
    413413        self.assertEqual((u'tête/README.txt', Node.FILE, Changeset.EDIT, 
     
    419419        self.assertEqual(5, chgset.rev) 
    420420        self.assertEqual('Moved directories.', chgset.message) 
    421421        self.assertEqual('kate', chgset.author) 
    422         self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 0, utc), chgset.date) 
     422        self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 658099, utc), chgset.date) 
    423423 
    424424        changes = chgset.get_changes() 
    425425        self.assertEqual((u'tête/dir1/dir2', Node.DIRECTORY, Changeset.MOVE, 
     
    433433        self.assertEqual(6, chgset.rev) 
    434434        self.assertEqual('More things to read', chgset.message) 
    435435        self.assertEqual('john', chgset.author) 
    436         self.assertEqual(datetime(2005, 4, 1, 18, 56, 46, 0, utc), chgset.date) 
     436        self.assertEqual(datetime(2005, 4, 1, 18, 56, 46, 985846, utc), chgset.date) 
    437437 
    438438        changes = chgset.get_changes() 
    439439        self.assertEqual((u'tête/README2.txt', Node.FILE, Changeset.COPY, 
     
    550550        self.assertEqual('/dir1', node.path) 
    551551        self.assertEqual(Node.DIRECTORY, node.kind) 
    552552        self.assertEqual(5, node.rev) 
    553         self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 0, utc), node.last_modified) 
     553        self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 658099, utc), node.last_modified) 
    554554        node = self.repos.get_node('/README.txt') 
    555555        self.assertEqual('README.txt', node.name) 
    556556        self.assertEqual('/README.txt', node.path) 
    557557        self.assertEqual(Node.FILE, node.kind) 
    558558        self.assertEqual(3, node.rev) 
    559         self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 0, utc), node.last_modified) 
     559        self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 234643, utc), node.last_modified) 
    560560 
    561561    def test_get_node_specific_rev(self): 
    562562        node = self.repos.get_node('/dir1', 4) 
     
    564564        self.assertEqual('/dir1', node.path) 
    565565        self.assertEqual(Node.DIRECTORY, node.kind) 
    566566        self.assertEqual(4, node.rev) 
    567         self.assertEqual(datetime(2005, 4, 1, 15, 42, 35, 0, utc), node.last_modified) 
     567        self.assertEqual(datetime(2005, 4, 1, 15, 42, 35, 450595, utc), node.last_modified) 
    568568        node = self.repos.get_node('/README.txt', 2) 
    569569        self.assertEqual('README.txt', node.name) 
    570570        self.assertEqual('/README.txt', node.path) 
    571571        self.assertEqual(Node.FILE, node.kind) 
    572572        self.assertEqual(2, node.rev) 
    573         self.assertEqual(datetime(2005, 4, 1, 13, 12, 18, 0, utc), node.last_modified) 
     573        self.assertEqual(datetime(2005, 4, 1, 13, 12, 18, 216267, utc), node.last_modified) 
    574574 
    575575    def test_get_dir_entries(self): 
    576576        node = self.repos.get_node('/') 
     
    675675        self.assertEqual(0, chgset.rev) 
    676676        self.assertEqual('', chgset.message) 
    677677        self.assertEqual('', chgset.author) 
    678         self.assertEqual(datetime(2005, 4, 1, 9, 57, 41, 0, utc), chgset.date) 
     678        self.assertEqual(datetime(2005, 4, 1, 9, 57, 41, 312767, utc), chgset.date) 
    679679        self.assertRaises(StopIteration, chgset.get_changes().next) 
    680680 
    681681    def test_changeset_added_dirs(self): 
     
    683683        self.assertEqual(4, chgset.rev) 
    684684        self.assertEqual('More directories.', chgset.message) 
    685685        self.assertEqual('john', chgset.author) 
    686         self.assertEqual(datetime(2005, 4, 1, 15, 42, 35, 0, utc), chgset.date) 
     686        self.assertEqual(datetime(2005, 4, 1, 15, 42, 35, 450595, utc), chgset.date) 
    687687 
    688688        changes = chgset.get_changes() 
    689689        self.assertEqual(('dir1', Node.DIRECTORY, 'add', None, -1), 
     
    699699        self.assertEqual(3, chgset.rev) 
    700700        self.assertEqual('Fixed README.\n', chgset.message) 
    701701        self.assertEqual('kate', chgset.author) 
    702         self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 0, utc), chgset.date) 
     702        self.assertEqual(datetime(2005, 4, 1, 13, 24, 58, 234643, utc), chgset.date) 
    703703 
    704704        changes = chgset.get_changes() 
    705705        self.assertEqual(('README.txt', Node.FILE, Changeset.EDIT, 
     
    711711        self.assertEqual(5, chgset.rev) 
    712712        self.assertEqual('Moved directories.', chgset.message) 
    713713        self.assertEqual('kate', chgset.author) 
    714         self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 0, utc), chgset.date) 
     714        self.assertEqual(datetime(2005, 4, 1, 16, 25, 39, 658099, utc), chgset.date) 
    715715 
    716716        changes = chgset.get_changes() 
    717717        self.assertEqual(('dir1/dir2', Node.DIRECTORY, Changeset.MOVE, 
     
    725725        self.assertEqual(6, chgset.rev) 
    726726        self.assertEqual('More things to read', chgset.message) 
    727727        self.assertEqual('john', chgset.author) 
    728         self.assertEqual(datetime(2005, 4, 1, 18, 56, 46, 0, utc), chgset.date) 
     728        self.assertEqual(datetime(2005, 4, 1, 18, 56, 46, 985846, utc), chgset.date) 
    729729 
    730730        changes = chgset.get_changes() 
    731731        self.assertEqual(('README2.txt', Node.FILE, Changeset.COPY, 
  • trac/web/auth.py

    diff --git a/trac/web/auth.py b/trac/web/auth.py
    a b  
    148148        cursor = db.cursor() 
    149149        cursor.execute("INSERT INTO auth_cookie (cookie,name,ipnr,time) " 
    150150                       "VALUES (%s, %s, %s, %s)", (cookie, remote_user, 
    151                        req.remote_addr, int(time.time()))) 
     151                       req.remote_addr, time.time())) 
    152152        db.commit() 
    153153 
    154154        req.authname = remote_user 
     
    173173        db = self.env.get_db_cnx() 
    174174        cursor = db.cursor() 
    175175        cursor.execute("DELETE FROM auth_cookie WHERE name=%s OR time < %s", 
    176                        (req.authname, int(time.time()) - 86400 * 10)) 
     176                       (req.authname, time.time() - 86400 * 10)) 
    177177        db.commit() 
    178178        self._expire_cookie(req) 
    179179        custom_redirect = self.config['metanav'].get('logout.redirect') 
  • trac/web/session.py

    diff --git a/trac/web/session.py b/trac/web/session.py
    a b  
    6161        if not row: 
    6262            return 
    6363        self._new = False 
    64         self.last_visit = int(row[0] or 0) 
     64        self.last_visit = float(row[0] or 0) 
    6565 
    6666        cursor.execute("SELECT name,value FROM session_attribute " 
    6767                       "WHERE sid=%s and authenticated=%s", 
     
    7777            return 
    7878 
    7979        authenticated = int(self.authenticated) 
    80         now = int(time.time()) 
     80        now = time.time() 
    8181        db = self.env.get_db_cnx() 
    8282        cursor = db.cursor() 
    8383 
     
    241241            # we didn't have an anonymous session for this sid 
    242242            cursor.execute("INSERT INTO session (sid,last_visit,authenticated)" 
    243243                           " VALUES(%s,%s,1)", 
    244                            (self.req.authname, int(time.time()))) 
     244                           (self.req.authname, time.time())) 
    245245        self._new = False 
    246246        db.commit() 
    247247 
  • trac/web/tests/session.py

    diff --git a/trac/web/tests/session.py b/trac/web/tests/session.py
    a b  
    194194        cursor = self.db.cursor() 
    195195        cursor.execute("INSERT INTO session " 
    196196                       "VALUES ('123456', 0, %s)", 
    197                        (int(now - UPDATE_INTERVAL - 3600),)) 
     197                       (now - UPDATE_INTERVAL - 3600,)) 
    198198        cursor.execute("INSERT INTO session_attribute VALUES " 
    199199                       "('123456', 0, 'foo', 'bar')") 
    200200 
     
    287287 
    288288        cursor.execute("SELECT last_visit FROM session WHERE sid='123456' AND " 
    289289                       "authenticated=0") 
    290         self.assertAlmostEqual(now, int(cursor.fetchone()[0]), -1) 
     290        self.assertAlmostEqual(now, float(cursor.fetchone()[0]), -6) 
    291291 
    292292    def test_modify_detached_session(self): 
    293293        """ 
  • trac/wiki/admin.py

    diff --git a/trac/wiki/admin.py b/trac/wiki/admin.py
    a b  
    116116                       " SELECT 1+COALESCE(max(version),0),%s,%s," 
    117117                       " 'trac','127.0.0.1',%s FROM wiki " 
    118118                       " WHERE name=%s", 
    119                        (title, int(time.time()), data, title)) 
     119                       (title, time.time(), data, title)) 
    120120        if not old: 
    121121            WikiSystem(self.env).pages.invalidate(db) 
    122122        if handle_ta: