comparison rhodecode/lib/dbmigrate/migrate/versioning/schemadiff.py @ 1203:6832ef664673 beta

source code cleanup: remove trailing white space, normalize file endings
author Marcin Kuzminski <marcin@python-works.com>
date Sun, 03 Apr 2011 18:23:15 +0200
parents 08d2dcd71666
children 5b2cf21b1947
comparison
equal deleted inserted replaced
1202:eef9e273347a 1203:6832ef664673
37 class ColDiff(object): 37 class ColDiff(object):
38 """ 38 """
39 Container for differences in one :class:`~sqlalchemy.schema.Column` 39 Container for differences in one :class:`~sqlalchemy.schema.Column`
40 between two :class:`~sqlalchemy.schema.Table` instances, ``A`` 40 between two :class:`~sqlalchemy.schema.Table` instances, ``A``
41 and ``B``. 41 and ``B``.
42 42
43 .. attribute:: col_A 43 .. attribute:: col_A
44 44
45 The :class:`~sqlalchemy.schema.Column` object for A. 45 The :class:`~sqlalchemy.schema.Column` object for A.
46 46
47 .. attribute:: col_B 47 .. attribute:: col_B
48 48
49 The :class:`~sqlalchemy.schema.Column` object for B. 49 The :class:`~sqlalchemy.schema.Column` object for B.
50 50
51 .. attribute:: type_A 51 .. attribute:: type_A
52 52
53 The most generic type of the :class:`~sqlalchemy.schema.Column` 53 The most generic type of the :class:`~sqlalchemy.schema.Column`
54 object in A. 54 object in A.
55 55
56 .. attribute:: type_B 56 .. attribute:: type_B
57 57
58 The most generic type of the :class:`~sqlalchemy.schema.Column` 58 The most generic type of the :class:`~sqlalchemy.schema.Column`
59 object in A. 59 object in A.
60 60
61 """ 61 """
62 62
63 diff = False 63 diff = False
64 64
65 def __init__(self,col_A,col_B): 65 def __init__(self,col_A,col_B):
66 self.col_A = col_A 66 self.col_A = col_A
67 self.col_B = col_B 67 self.col_B = col_B
85 A = getattr(self.type_A,attr,None) 85 A = getattr(self.type_A,attr,None)
86 B = getattr(self.type_B,attr,None) 86 B = getattr(self.type_B,attr,None)
87 if not (A is None or B is None) and A!=B: 87 if not (A is None or B is None) and A!=B:
88 self.diff=True 88 self.diff=True
89 return 89 return
90 90
91 def __nonzero__(self): 91 def __nonzero__(self):
92 return self.diff 92 return self.diff
93 93
94 class TableDiff(object): 94 class TableDiff(object):
95 """ 95 """
96 Container for differences in one :class:`~sqlalchemy.schema.Table` 96 Container for differences in one :class:`~sqlalchemy.schema.Table`
97 between two :class:`~sqlalchemy.schema.MetaData` instances, ``A`` 97 between two :class:`~sqlalchemy.schema.MetaData` instances, ``A``
98 and ``B``. 98 and ``B``.
99 99
100 .. attribute:: columns_missing_from_A 100 .. attribute:: columns_missing_from_A
101 101
102 A sequence of column names that were found in B but weren't in 102 A sequence of column names that were found in B but weren't in
103 A. 103 A.
104 104
105 .. attribute:: columns_missing_from_B 105 .. attribute:: columns_missing_from_B
106 106
107 A sequence of column names that were found in A but weren't in 107 A sequence of column names that were found in A but weren't in
108 B. 108 B.
109 109
110 .. attribute:: columns_different 110 .. attribute:: columns_different
111 111
112 A dictionary containing information about columns that were 112 A dictionary containing information about columns that were
113 found to be different. 113 found to be different.
114 It maps column names to a :class:`ColDiff` objects describing the 114 It maps column names to a :class:`ColDiff` objects describing the
124 return bool( 124 return bool(
125 self.columns_missing_from_A or 125 self.columns_missing_from_A or
126 self.columns_missing_from_B or 126 self.columns_missing_from_B or
127 self.columns_different 127 self.columns_different
128 ) 128 )
129 129
130 class SchemaDiff(object): 130 class SchemaDiff(object):
131 """ 131 """
132 Compute the difference between two :class:`~sqlalchemy.schema.MetaData` 132 Compute the difference between two :class:`~sqlalchemy.schema.MetaData`
133 objects. 133 objects.
134 134
137 :class:`~sqlalchemy.schema.MetaData` objects. 137 :class:`~sqlalchemy.schema.MetaData` objects.
138 138
139 The length of a :class:`SchemaDiff` will give the number of 139 The length of a :class:`SchemaDiff` will give the number of
140 changes found, enabling it to be used much like a boolean in 140 changes found, enabling it to be used much like a boolean in
141 expressions. 141 expressions.
142 142
143 :param metadataA: 143 :param metadataA:
144 First :class:`~sqlalchemy.schema.MetaData` to compare. 144 First :class:`~sqlalchemy.schema.MetaData` to compare.
145 145
146 :param metadataB: 146 :param metadataB:
147 Second :class:`~sqlalchemy.schema.MetaData` to compare. 147 Second :class:`~sqlalchemy.schema.MetaData` to compare.
148 148
149 :param labelA: 149 :param labelA:
150 The label to use in messages about the first 150 The label to use in messages about the first
151 :class:`~sqlalchemy.schema.MetaData`. 151 :class:`~sqlalchemy.schema.MetaData`.
152 152
153 :param labelB: 153 :param labelB:
154 The label to use in messages about the second 154 The label to use in messages about the second
155 :class:`~sqlalchemy.schema.MetaData`. 155 :class:`~sqlalchemy.schema.MetaData`.
156 156
157 :param excludeTables: 157 :param excludeTables:
158 A sequence of table names to exclude. 158 A sequence of table names to exclude.
159 159
160 .. attribute:: tables_missing_from_A 160 .. attribute:: tables_missing_from_A
161 161
162 A sequence of table names that were found in B but weren't in 162 A sequence of table names that were found in B but weren't in
163 A. 163 A.
164 164
165 .. attribute:: tables_missing_from_B 165 .. attribute:: tables_missing_from_B
166 166
167 A sequence of table names that were found in A but weren't in 167 A sequence of table names that were found in A but weren't in
168 B. 168 B.
169 169
170 .. attribute:: tables_different 170 .. attribute:: tables_different
171 171
172 A dictionary containing information about tables that were found 172 A dictionary containing information about tables that were found
173 to be different. 173 to be different.
174 It maps table names to a :class:`TableDiff` objects describing the 174 It maps table names to a :class:`TableDiff` objects describing the
193 B_table_names - A_table_names - excludeTables 193 B_table_names - A_table_names - excludeTables
194 ) 194 )
195 self.tables_missing_from_B = sorted( 195 self.tables_missing_from_B = sorted(
196 A_table_names - B_table_names - excludeTables 196 A_table_names - B_table_names - excludeTables
197 ) 197 )
198 198
199 self.tables_different = {} 199 self.tables_different = {}
200 for table_name in A_table_names.intersection(B_table_names): 200 for table_name in A_table_names.intersection(B_table_names):
201 201
202 td = TableDiff() 202 td = TableDiff()
203 203
204 A_table = metadataA.tables[table_name] 204 A_table = metadataA.tables[table_name]
205 B_table = metadataB.tables[table_name] 205 B_table = metadataB.tables[table_name]
206 206
207 A_column_names = set(A_table.columns.keys()) 207 A_column_names = set(A_table.columns.keys())
208 B_column_names = set(B_table.columns.keys()) 208 B_column_names = set(B_table.columns.keys())
209 209
210 td.columns_missing_from_A = sorted( 210 td.columns_missing_from_A = sorted(
211 B_column_names - A_column_names 211 B_column_names - A_column_names
212 ) 212 )
213 213
214 td.columns_missing_from_B = sorted( 214 td.columns_missing_from_B = sorted(
215 A_column_names - B_column_names 215 A_column_names - B_column_names
216 ) 216 )
217 217
218 td.columns_different = {} 218 td.columns_different = {}
219 219
220 for col_name in A_column_names.intersection(B_column_names): 220 for col_name in A_column_names.intersection(B_column_names):
221 221
222 cd = ColDiff( 222 cd = ColDiff(
224 B_table.columns.get(col_name) 224 B_table.columns.get(col_name)
225 ) 225 )
226 226
227 if cd: 227 if cd:
228 td.columns_different[col_name]=cd 228 td.columns_different[col_name]=cd
229 229
230 # XXX - index and constraint differences should 230 # XXX - index and constraint differences should
231 # be checked for here 231 # be checked for here
232 232
233 if td: 233 if td:
234 self.tables_different[table_name]=td 234 self.tables_different[table_name]=td
235 235
236 def __str__(self): 236 def __str__(self):
237 ''' Summarize differences. ''' 237 ''' Summarize differences. '''
238 out = [] 238 out = []
239 column_template =' %%%is: %%r' % self.label_width 239 column_template =' %%%is: %%r' % self.label_width
240 240
241 for names,label in ( 241 for names,label in (
242 (self.tables_missing_from_A,self.labelA), 242 (self.tables_missing_from_A,self.labelA),
243 (self.tables_missing_from_B,self.labelB), 243 (self.tables_missing_from_B,self.labelB),
244 ): 244 ):
245 if names: 245 if names:
246 out.append( 246 out.append(
247 ' tables missing from %s: %s' % ( 247 ' tables missing from %s: %s' % (
248 label,', '.join(sorted(names)) 248 label,', '.join(sorted(names))
249 ) 249 )
250 ) 250 )
251 251
252 for name,td in sorted(self.tables_different.items()): 252 for name,td in sorted(self.tables_different.items()):
253 out.append( 253 out.append(
254 ' table with differences: %s' % name 254 ' table with differences: %s' % name
255 ) 255 )
256 for names,label in ( 256 for names,label in (
265 ) 265 )
266 for name,cd in td.columns_different.items(): 266 for name,cd in td.columns_different.items():
267 out.append(' column with differences: %s' % name) 267 out.append(' column with differences: %s' % name)
268 out.append(column_template % (self.labelA,cd.col_A)) 268 out.append(column_template % (self.labelA,cd.col_A))
269 out.append(column_template % (self.labelB,cd.col_B)) 269 out.append(column_template % (self.labelB,cd.col_B))
270 270
271 if out: 271 if out:
272 out.insert(0, 'Schema diffs:') 272 out.insert(0, 'Schema diffs:')
273 return '\n'.join(out) 273 return '\n'.join(out)
274 else: 274 else:
275 return 'No schema diffs' 275 return 'No schema diffs'