Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 132 lines (116 sloc) 4.673 kB
231dc0c @wuub add persistent history
authored
1 """
2 Conversion program to upgrade databases with float fields for
3 version 1.1
4
5 The implementation in versions <= 1.0 caused a DeprecationWarning
6 for Python version 2.5. The conversion function must be changed
7 and this makes databases built with old versions incompatible
8
9 Use this script to upgrade to the new version : select the directory
10 for the database in the window, this will upgrade all float fields
11
12 For safety reasons, a backup copy of old files for these fields is
13 saved in the directory with current datetime appended at the end of
14 file name. In case of any problem, remove new file for the field and
15 rename backup file by removing the datetime string
16 """
17 import os
18 import struct
19 import random
20 import math
21
22 class OldFloatFile:
23
24 block_len = 10
25 MIDSHORT = 3000 + 128*256
26 MAXSHORT = 256*256
27 X = MAXSHORT - MIDSHORT
28
29 def from_block(self,block):
30 if block[0]=='!':
31 return None
32 else:
33 s = block[1:]
34 if ord(s[0]) < 128:
35 # negative number
36 pack_exp = s[:2]
37 exp = 3000 - struct.unpack('>h',pack_exp)[0]
38 mant = struct.unpack('>d',chr(63)+s[2:])[0] - 1.1
39 else:
40 exp = self.X + struct.unpack('>h',s[:2])[0]
41 mant = struct.unpack('>d',chr(63)+s[2:])[0]
42 return math.ldexp(mant,exp)
43
44 class FloatFile:
45
46 block_len = 10
47 offsetneg = 16384
48 offsetpos = 16384*3
49
50 def to_block(self,value):
51 if value is None:
52 return '!'+chr(0)*9
53 elif not isinstance(value,float):
54 raise ValueError,'Bad type : expected float, got %s %s' \
55 %(value,value.__class__)
56 else:
57 # get mantissa and exponent
58 # f = mant*2**exp, 0.5 <= abs(mant) < 1
59 mant,exp = math.frexp(value)
60 if value>=0:
61 pack_exp = struct.pack('>H',exp+self.offsetpos)
62 return '-'+pack_exp+struct.pack('>d',mant)[1:]
63 else:
64 pack_exp = struct.pack('>H',self.offsetneg-exp)
65 return '-'+pack_exp+struct.pack('>d',1.1+mant)[1:]
66
67 def from_block(self,block):
68 if block[0]=='!':
69 return None
70 else:
71 s = block[1:]
72 if ord(s[0])<128:
73 # negative number
74 exp = self.offsetneg-struct.unpack('>H',s[:2])[0]
75 mant = struct.unpack('>d',chr(63)+s[2:])[0] - 1.1
76 else:
77 exp = struct.unpack('>H',s[:2])[0]-self.offsetpos
78 mant = struct.unpack('>d',chr(63)+s[2:])[0]
79 return math.ldexp(mant,exp)
80
81 def conv(old):
82 # update base to new version
83 of = OldFloatFile()
84 nf = FloatFile()
85 for (f,t) in old.fields.iteritems():
86 if t is float:
87 old_path = db._file[f].path
88 new_path = os.path.join(db._file[f].base,"new_"+db._file[f].name)
89 new_file = open(new_path,"wb")
90 for i,r in enumerate(db._file[f]):
91 v = of.from_block(r)
92 if v is None:
93 new_block = r
94 else:
95 new_block = nf.to_block(v)
96 if nf.from_block(new_block) != v:
97 raise ValueError,"conversion error : %s != %s" \
98 %(v,nf.from_block(new_block))
99 new_file.write(new_block)
100 print i,"lines"
101 new_file.close()
102
103 # double-check if values are the same between old and new file
104 db._file[f].open()
105 new_file = open(new_path,"rb")
106 bl = db._file[f].block_len
107 while True:
108 old = db._file[f].read(bl)
109 if not old:
110 break
111 new = new_file.read(bl)
112 if not of.from_block(old) == nf.from_block(new):
113 raise ValueError, "conversion error : %s != %s" \
114 %(of.from_block(old),nf.from_block(new))
115
116 new_file.close()
117 # replace old file
118 db.close()
119 # for safety, backup old file
120 import datetime
121 backup_name = db._file[f].name+datetime.datetime.now().strftime("%y%m%d%H%M%S")
122 os.rename(db._file[f].path,os.path.join(db._file[f].base,backup_name))
123 os.rename(new_path,old_path)
124
125 import buzhug
126 import tkFileDialog
127
128 path = tkFileDialog.askdirectory()
129 if path :
130 db = buzhug.Base(path).open()
131 conv(db)
Something went wrong with that request. Please try again.