Browse Source

Fixed a Luminotes Desktop bug in which creating and then clicking on a new note link sometimes caused a red error message.

This was due to a floating point rounding error in Luminotes that occured when loading note revisions from a SQLite database.
Dan Helfman 9 years ago
parent
commit
a55934f948
4 changed files with 44 additions and 4 deletions
  1. 2
    0
      NEWS
  2. 7
    1
      controller/Database.py
  3. 35
    1
      controller/test/Test_database.py
  4. 0
    2
      model/Note.py

+ 2
- 0
NEWS View File

@@ -3,6 +3,8 @@
3 3
  * Decreased the default note text font size, so now you can see more of your
4 4
    note text at once.
5 5
  * Added more rounded corners to several display elements.
6
+ * Fixed a Luminotes Desktop bug in which creating and then clicking on a new
7
+   note link sometimes caused a red error message.
6 8
 
7 9
 1.5.10: December 4, 2008
8 10
  * Fixed a bug in which certain new installations of Luminotes Desktop

+ 7
- 1
controller/Database.py View File

@@ -69,11 +69,17 @@ class Database( object ):
69 69
       from pytz import utc
70 70
 
71 71
       TIMESTAMP_PATTERN = re.compile( "^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d).(\d+)(?:\+\d\d:\d\d$)?" )
72
+      MICROSECONDS_PER_SECOND = 1000000
72 73
 
73 74
       def convert_timestamp( value ):
74 75
         ( year, month, day, hours, minutes, seconds, fractional_seconds ) = \
75 76
           TIMESTAMP_PATTERN.search( value ).groups( 0 )
76
-        microseconds = int( float ( "0." + fractional_seconds ) * 1000000 )
77
+
78
+        # convert fractional seconds (with an arbitrary number of decimal places) to microseconds
79
+        microseconds = int( fractional_seconds )
80
+        while microseconds > MICROSECONDS_PER_SECOND:
81
+          fractional_seconds = fractional_seconds[ : -1 ]
82
+          microseconds = int( fractional_seconds or 0 )
77 83
 
78 84
         # ignore time zone in timestamp and assume UTC
79 85
         return datetime(

+ 35
- 1
controller/test/Test_database.py View File

@@ -66,6 +66,40 @@ class Test_database( object ):
66 66
     assert obj.revision.replace( tzinfo = utc ) == original_revision
67 67
     assert obj.value == basic_obj.value
68 68
 
69
+  def test_select_datetime( self ):
70
+    # this revision (with .504099) happens to test for a bug caused by floating point rounding errors
71
+    original_revision = "2008-01-01 01:00:42.504099+00:00"
72
+    basic_obj = Stub_object( object_id = "5", revision = original_revision, value = 1 )
73
+
74
+    self.database.save( basic_obj )
75
+    obj = self.database.select_one( Stub_object, Stub_object.sql_load( basic_obj.object_id ) )
76
+
77
+    assert obj.object_id == basic_obj.object_id
78
+    assert str( obj.revision.replace( tzinfo = utc ) ) == original_revision
79
+    assert obj.value == basic_obj.value
80
+
81
+  def test_select_datetime_with_many_fractional_digits( self ):
82
+    original_revision = "2008-01-01 01:00:42.5032429489284+00:00"
83
+    basic_obj = Stub_object( object_id = "5", revision = original_revision, value = 1 )
84
+
85
+    self.database.save( basic_obj )
86
+    obj = self.database.select_one( Stub_object, Stub_object.sql_load( basic_obj.object_id ) )
87
+
88
+    assert obj.object_id == basic_obj.object_id
89
+    assert str( obj.revision.replace( tzinfo = utc ) ) == "2008-01-01 01:00:42.503242+00:00"
90
+    assert obj.value == basic_obj.value
91
+
92
+  def test_select_datetime_with_zero_fractional_seconds( self ):
93
+    original_revision = "2008-01-01 01:00:42.0+00:00"
94
+    basic_obj = Stub_object( object_id = "5", revision = original_revision, value = 1 )
95
+
96
+    self.database.save( basic_obj )
97
+    obj = self.database.select_one( Stub_object, Stub_object.sql_load( basic_obj.object_id ) )
98
+
99
+    assert obj.object_id == basic_obj.object_id
100
+    assert str( obj.revision.replace( tzinfo = utc ) ) == "2008-01-01 01:00:42+00:00"
101
+    assert obj.value == basic_obj.value
102
+
69 103
   def test_select_one_tuple( self ):
70 104
     obj = self.database.select_one( tuple, Stub_object.sql_tuple() )
71 105
 
@@ -185,7 +219,7 @@ class Test_database( object ):
185 219
     self.connection.rollback()
186 220
     assert self.database.load( Stub_object, next_id ) == None
187 221
 
188
-  def test_next_id_with_explit_commit( self ):
222
+  def test_next_id_with_explicit_commit( self ):
189 223
     next_id = self.database.next_id( Stub_object, commit = False )
190 224
     self.database.commit()
191 225
     assert next_id

+ 0
- 2
model/Note.py View File

@@ -136,10 +136,8 @@ class Note( Persistent ):
136 136
   @staticmethod
137 137
   def sql_load( object_id, revision = None ):
138 138
     if revision:
139
-      print "select id, revision, title, contents, notebook_id, startup, deleted_from_id, rank, user_id from note where id = %s and revision = %s;" % ( quote( object_id ), quote( revision ) )
140 139
       return "select id, revision, title, contents, notebook_id, startup, deleted_from_id, rank, user_id from note where id = %s and revision = %s;" % ( quote( object_id ), quote( revision ) )
141 140
 
142
-    print "select id, revision, title, contents, notebook_id, startup, deleted_from_id, rank, user_id from note_current where id = %s;" % quote( object_id )
143 141
     return "select id, revision, title, contents, notebook_id, startup, deleted_from_id, rank, user_id from note_current where id = %s;" % quote( object_id )
144 142
 
145 143
   @staticmethod

Loading…
Cancel
Save