Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | # Functions used by widget tests. |
2 | ||
3 | import imp | |
4 | import os | |
5 | import re | |
6 | import string | |
7 | import sys | |
8 | import traceback | |
9 | import types | |
10 | import Tkinter | |
11 | import _tkinter | |
12 | ||
13 | if Tkinter.TkVersion >= 8.4: | |
14 | refcountafterdestroy = 7 | |
15 | else: | |
16 | refcountafterdestroy = 6 | |
17 | ||
18 | script_name = imp.find_module(__name__)[1] | |
19 | if not os.path.isabs(script_name): | |
20 | script_name = os.path.join(os.getcwd(), script_name) | |
21 | ||
22 | while 1: | |
23 | script_dir = os.path.dirname(script_name) | |
24 | if not os.path.islink(script_name): | |
25 | break | |
26 | script_name = os.path.join(script_dir, os.readlink(script_name)) | |
27 | script_dir = os.path.join(os.getcwd(), script_dir) | |
28 | script_dir = os.path.normpath(script_dir) | |
29 | ||
30 | # Add the '../../..' directory to the path. | |
31 | package_dir = os.path.dirname(script_dir) | |
32 | package_dir = os.path.dirname(package_dir) | |
33 | package_dir = os.path.dirname(package_dir) | |
34 | sys.path[:0] = [package_dir] | |
35 | ||
36 | import Pmw | |
37 | # Need to import TestVersion, rather than do its work here, since | |
38 | # __name__ will be known there. | |
39 | import TestVersion | |
40 | ||
41 | # Set this to 1 to generate tracebacks on exceptions, rather than | |
42 | # catching them and continuing with the tests. | |
43 | # This is useful for debugging the test scripts. | |
44 | dont_even_try = 0 | |
45 | ||
46 | _delay = 1 | |
47 | _verbose = 0 | |
48 | _printTraceback = 0 | |
49 | _initialised = 0 | |
50 | ||
51 | ############################################################################## | |
52 | # Public functions: | |
53 | ||
54 | rand = 12345 | |
55 | def random(): | |
56 | global rand | |
57 | rand = (rand * 125) % 2796203 | |
58 | return rand | |
59 | ||
60 | def initialise(): | |
61 | global _initialised, font, flagup, earthris, emptyimage, \ | |
62 | stringvar, floatvar, root, reliefs | |
63 | if not _initialised: | |
64 | root = Tkinter.Tk(className = 'PmwTest') | |
65 | root.withdraw() | |
66 | if os.name == 'nt': | |
67 | size = 16 | |
68 | else: | |
69 | size = 12 | |
70 | Pmw.initialise(root, size = size, fontScheme = 'pmw2') | |
71 | font = {} | |
72 | font['small'] = '6x13' | |
73 | font['large'] = '10x20' | |
74 | font['variable'] = '-Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-*' | |
75 | flagup = Tkinter.BitmapImage(file = 'flagup.bmp') | |
76 | earthris = Tkinter.PhotoImage(file = 'earthris.gif') | |
77 | emptyimage = Tkinter.PhotoImage() | |
78 | stringvar = Tkinter.StringVar() | |
79 | stringvar.set('this is some text') | |
80 | floatvar = Tkinter.DoubleVar() | |
81 | floatvar.set(50.0) | |
82 | if haveBlt(): | |
83 | global vectorSize, vector_x, vector_y | |
84 | vector_x = Pmw.Blt.Vector() | |
85 | vector_y = [] | |
86 | for y in range(3): | |
87 | vector_y.append(Pmw.Blt.Vector()) | |
88 | vectorSize = 50 | |
89 | for index in range(vectorSize): | |
90 | vector_x.append(index) | |
91 | vector_y[0].append(random() % 100) | |
92 | vector_y[1].append(random() % 200) | |
93 | vector_y[2].append(random() % 100 + 300) | |
94 | ||
95 | # "solid" relief type was added to 8.0 | |
96 | if Tkinter.TkVersion >= 8.0: | |
97 | reliefs = 'flat, groove, raised, ridge, solid, or sunken' | |
98 | else: | |
99 | reliefs = 'flat, groove, raised, ridge, or sunken' | |
100 | ||
101 | _initialised = 1 | |
102 | ||
103 | def haveBlt(): | |
104 | return Pmw.Blt.haveblt(root) | |
105 | ||
106 | def bell(): | |
107 | root.bell() | |
108 | ||
109 | def setdelay(newdelay): | |
110 | global _delay | |
111 | _delay = newdelay | |
112 | ||
113 | def setverbose(newverbose): | |
114 | global _verbose | |
115 | _verbose = newverbose | |
116 | ||
117 | def printtraceback(newprintTraceback = 1): | |
118 | global _printTraceback | |
119 | _printTraceback = newprintTraceback | |
120 | ||
121 | def num_options(widget): | |
122 | return len(widget.configure()) | |
123 | ||
124 | def callback(): | |
125 | return 1 | |
126 | ||
127 | def callback1(dummy): | |
128 | # Callback taking 1 argument | |
129 | return dummy | |
130 | ||
131 | def callback2(dummy1, dummy2): | |
132 | # Callback taking 2 arguments | |
133 | return (dummy1, dummy2) | |
134 | ||
135 | def callbackN(*args): | |
136 | # Callback taking zero or more arguments | |
137 | return args | |
138 | ||
139 | def actioncallback(): | |
140 | w = currentWidget() | |
141 | w.action('button press') | |
142 | ||
143 | def currentWidget(): | |
144 | return _currentWidget | |
145 | ||
146 | def delay(): | |
147 | return _delay | |
148 | ||
149 | def set_geom(width, height): | |
150 | _currentToplevel.geometry(str(width) + 'x' + str(height)) | |
151 | ||
152 | def runTests(allTestData): | |
153 | root.after(_delay, _runTest, None, None, allTestData, 0, -1, -1) | |
154 | root.mainloop() | |
155 | ||
156 | _pattern = None | |
157 | ||
158 | ############################################################################## | |
159 | # Private functions: | |
160 | ||
161 | def _print_results(result, expected, description): | |
162 | if type(expected) == types.ClassType: | |
163 | if hasattr(result, '__class__'): | |
164 | ok = (result.__class__ == expected) | |
165 | else: | |
166 | ok = 0 | |
167 | else: | |
168 | ok = (result == expected) | |
169 | ||
170 | # Megawidgets return a value of the correct type. Tk widgets | |
171 | # always return a string, so convert the string and check again. | |
172 | if not ok: | |
173 | if type(expected) == types.InstanceType: | |
174 | if result == str(expected) and ( | |
175 | expected is earthris or expected is stringvar or | |
176 | expected is floatvar or expected is flagup): | |
177 | ok = 1 | |
178 | elif hasattr(_tkinter, 'Tcl_Obj') and \ | |
179 | type(result) == _tkinter.Tcl_Obj: | |
180 | ok = (str(stringvar) == result.string) | |
181 | elif type(expected) == types.IntType: | |
182 | if type(result) is types.StringType: | |
183 | try: | |
184 | ok = (string.atoi(result) == expected) | |
185 | except ValueError: | |
186 | pass | |
187 | elif hasattr(_tkinter, 'Tcl_Obj') and \ | |
188 | type(result) == _tkinter.Tcl_Obj: | |
189 | ok = (string.atoi(str(result)) == expected) | |
190 | elif type(expected) == types.FloatType: | |
191 | if type(result) is types.StringType: | |
192 | try: | |
193 | ok = (string.atof(result) == expected) | |
194 | except ValueError: | |
195 | pass | |
196 | elif expected == callback: | |
197 | ok = re.search('^[0-9]*callback$', str(result)) is not None | |
198 | elif expected == callback1: | |
199 | ok = re.search('^[0-9]*callback1$', str(result)) is not None | |
200 | elif expected == callback2: | |
201 | ok = re.search('^[0-9]*callback2$', str(result)) is not None | |
202 | elif expected == actioncallback: | |
203 | ok = re.search('^[0-9]*actioncallback$',str(result)) is not None | |
204 | ||
205 | if not ok or _verbose > 0: | |
206 | print '====', description | |
207 | if not ok or _verbose > 1: | |
208 | print '==== result was:' | |
209 | print result, type(result) | |
210 | if ok: | |
211 | if _verbose > 1: | |
212 | print '++++ PASSED' | |
213 | else: | |
214 | print '---- result should have been:' | |
215 | print expected, type(expected) | |
216 | if _printTraceback: | |
217 | traceback.print_exc() | |
218 | print '---- FAILED' | |
219 | ||
220 | ||
221 | def _destroyToplevel(top, title): | |
222 | if _verbose > 0: | |
223 | print '==== destruction of Toplevel for', title | |
224 | top.destroy() | |
225 | ||
226 | def _Toplevel(title): | |
227 | if _verbose > 0: | |
228 | print '==== construction of Toplevel for', title | |
229 | top = Tkinter.Toplevel() | |
230 | top.geometry('+100+100') | |
231 | top.title(title) | |
232 | return top | |
233 | ||
234 | def _constructor(isWidget, top, classCmd, kw): | |
235 | if _verbose > 0: | |
236 | print '====', classCmd.__name__, 'construction' | |
237 | if isWidget: | |
238 | if dont_even_try: | |
239 | w = apply(classCmd, (top,), kw) | |
240 | else: | |
241 | try: | |
242 | w = apply(classCmd, (top,), kw) | |
243 | except: | |
244 | print 'Could not construct', classCmd.__name__ | |
245 | traceback.print_exc() | |
246 | print 'Can not continue' | |
247 | print 'Bye' | |
248 | return None | |
249 | ||
250 | isMegaWidget = hasattr(classCmd, 'defineoptions') | |
251 | # Check the option types: | |
252 | options = w.configure() | |
253 | option_list = options.keys() | |
254 | option_list.sort() | |
255 | for option in option_list: | |
256 | # Some of the options (like bd, bg and fg) have only two parts | |
257 | # and are just abbreviations. Only check 'real' options. | |
258 | if len(options[option]) == 5: | |
259 | initoption = isMegaWidget and w.isinitoption(option) | |
260 | if dont_even_try: | |
261 | value = w.cget(option) | |
262 | if option not in ('class', 'container') and not initoption: | |
263 | apply(w.configure, (), {option : value}) | |
264 | newvalue = w.cget(option) | |
265 | if newvalue != value: | |
266 | print '====', classCmd.__name__, 'widget', \ | |
267 | '\'' + option + '\'', 'option' | |
268 | print '---- setting option returns different value' | |
269 | print '==== new value was:' | |
270 | print newvalue, type(newvalue) | |
271 | print '---- set value was:' | |
272 | print value, type(value) | |
273 | print '---- FAILED' | |
274 | ||
275 | else: | |
276 | try: | |
277 | value = w.cget(option) | |
278 | if option not in ('class', 'container') and not initoption: | |
279 | try: | |
280 | apply(w.configure, (), {option : value}) | |
281 | newvalue = w.cget(option) | |
282 | if hasattr(_tkinter, 'Tcl_Obj') and \ | |
283 | ( | |
284 | (type(newvalue) == _tkinter.Tcl_Obj | |
285 | and str(newvalue) != str(value)) | |
286 | or | |
287 | (type(newvalue) != _tkinter.Tcl_Obj | |
288 | and newvalue != value) | |
289 | ) or \ | |
290 | ( | |
291 | not hasattr(_tkinter, 'Tcl_Obj') and | |
292 | newvalue != value | |
293 | ): | |
294 | print '====', classCmd.__name__, 'widget', \ | |
295 | '\'' + option + '\'', 'option' | |
296 | print '---- setting option returns different value' | |
297 | print '==== new value was:' | |
298 | print `newvalue`, type(newvalue) | |
299 | print '---- set value was:' | |
300 | print `value`, type(value) | |
301 | print '---- FAILED' | |
302 | ||
303 | except: | |
304 | print '====', classCmd.__name__, 'widget', \ | |
305 | '\'' + option + '\'', 'option' | |
306 | print '---- could not set option' | |
307 | print '---- FAILED' | |
308 | ||
309 | except KeyError: | |
310 | print '====', classCmd.__name__, 'widget', \ | |
311 | '\'' + option + '\'', 'option' | |
312 | print '---- unknown option' | |
313 | print '---- FAILED' | |
314 | ||
315 | ||
316 | if hasattr(classCmd, 'geometry'): | |
317 | w.geometry('+100+100') | |
318 | w.title(classCmd.__name__) | |
319 | else: | |
320 | w = apply(classCmd, (), kw) | |
321 | return w | |
322 | ||
323 | def _destructor(widget, isWidget): | |
324 | if _verbose > 0: | |
325 | print '====', widget.__class__.__name__, 'destruction' | |
326 | if isWidget: | |
327 | if dont_even_try: | |
328 | widget.destroy() | |
329 | else: | |
330 | try: | |
331 | widget.destroy() | |
332 | ref = sys.getrefcount(widget) | |
333 | if ref != refcountafterdestroy: | |
334 | print '====', widget.__class__.__name__, 'destructor' | |
335 | print '---- refcount', ref, 'not zero after destruction' | |
336 | print '---- FAILED' | |
337 | ||
338 | except: | |
339 | print 'Could not destroy', widget.__class__.__name__ | |
340 | traceback.print_exc() | |
341 | print 'Can not continue' | |
342 | print 'Bye' | |
343 | return None | |
344 | return 1 | |
345 | ||
346 | # Structure of allTestData: | |
347 | # ( | |
348 | # ( | |
349 | # 'ButtonBox', | |
350 | # ( | |
351 | # ( | |
352 | # Pmw.ButtonBox, | |
353 | # {}, | |
354 | # ( | |
355 | # (c.pack, ()), | |
356 | # (c.pack, ()), | |
357 | # (c.pack, ()), | |
358 | # ... | |
359 | # ) | |
360 | # ), | |
361 | # ( | |
362 | # Pmw.ButtonBox, | |
363 | # {}, | |
364 | # ( | |
365 | # (c.pack, ()), | |
366 | # (c.pack, ()), | |
367 | # (c.pack, ()), | |
368 | # ... | |
369 | # ) | |
370 | # ), | |
371 | # ... | |
372 | # ) | |
373 | # ), | |
374 | # ( | |
375 | # 'ButtonBox', | |
376 | # ( | |
377 | # ( | |
378 | # Pmw.ButtonBox, | |
379 | # {}, | |
380 | # ( | |
381 | # (c.pack, ()), | |
382 | # (c.pack, ()), | |
383 | # (c.pack, ()), | |
384 | # ... | |
385 | # ) | |
386 | # ), | |
387 | # ( | |
388 | # Pmw.ButtonBox, | |
389 | # {}, | |
390 | # ( | |
391 | # (c.pack, ()), | |
392 | # (c.pack, ()), | |
393 | # (c.pack, ()), | |
394 | # ... | |
395 | # ) | |
396 | # ), | |
397 | # ... | |
398 | # ) | |
399 | # ), | |
400 | # ... | |
401 | # ) | |
402 | ||
403 | def _runTest(top, w, allTestData, index0, index1, index2): | |
404 | if index0 >= len(allTestData): | |
405 | root.quit() | |
406 | return | |
407 | classCmd, fileTests = allTestData[index0] | |
408 | if classCmd == Tkinter.Menu: | |
409 | isToplevel = 1 | |
410 | else: | |
411 | isToplevel = hasattr(classCmd, 'userdeletefunc') | |
412 | isWidget = hasattr(classCmd, 'cget') | |
413 | title = classCmd.__name__ | |
414 | ||
415 | if index1 == -1: | |
416 | if isToplevel: | |
417 | top = None | |
418 | else: | |
419 | top = _Toplevel(title) | |
420 | global _currentToplevel | |
421 | _currentToplevel = top | |
422 | index1 = 0 | |
423 | elif index1 >= len(fileTests): | |
424 | if not isToplevel: | |
425 | _destroyToplevel(top, title) | |
426 | index1 = -1 | |
427 | index0 = index0 + 1 | |
428 | else: | |
429 | methodTests, kw = fileTests[index1] | |
430 | if index2 == -1: | |
431 | w = _constructor(isWidget, top, classCmd, kw) | |
432 | if w is None: | |
433 | root.quit() | |
434 | return | |
435 | global _currentWidget | |
436 | _currentWidget = w | |
437 | index2 = 0 | |
438 | elif index2 >= len(methodTests): | |
439 | if _destructor(w, isWidget) is None: | |
440 | root.quit() | |
441 | return | |
442 | index2 = -1 | |
443 | index1 = index1 + 1 | |
444 | else: | |
445 | methodTestData = methodTests[index2] | |
446 | if type(methodTestData[0]) == types.StringType: | |
447 | _configureTest(w, methodTestData) | |
448 | else: | |
449 | _methodTest(w, methodTestData) | |
450 | index2 = index2 + 1 | |
451 | root.update() | |
452 | root.after(_delay, _runTest, top, w, allTestData, index0, index1, index2) | |
453 | ||
454 | def _configureTest(w, testData): | |
455 | option = testData[0] | |
456 | value = testData[1] | |
457 | if dont_even_try: | |
458 | apply(w.configure, (), {option: value}) | |
459 | result = w.cget(option) | |
460 | else: | |
461 | try: | |
462 | apply(w.configure, (), {option: value}) | |
463 | result = w.cget(option) | |
464 | except: | |
465 | result = _getErrorValue() | |
466 | if len(testData) > 2: | |
467 | expected = testData[2] | |
468 | else: | |
469 | expected = value | |
470 | _print_results(result, expected, \ | |
471 | w.__class__.__name__ + ' option ' + str(testData)) | |
472 | ||
473 | def _getErrorValue(): | |
474 | exc_type, exc_value, exc_traceback = sys.exc_info() | |
475 | if type(exc_type) == types.ClassType: | |
476 | # Handle python 1.5 class exceptions. | |
477 | exc_type = exc_type.__name__ | |
478 | if type(exc_value) == types.StringType: | |
479 | return exc_type + ': ' + exc_value | |
480 | else: | |
481 | exc_value_str = str(exc_value) | |
482 | if exc_value_str[:1] == "'" and exc_value_str[-1:] == "'": | |
483 | exc_value_str = exc_value_str[1:-1] | |
484 | return exc_type + ': ' + exc_value_str | |
485 | ||
486 | def _methodTest(w, testData): | |
487 | func = testData[0] | |
488 | args = testData[1] | |
489 | kw = {} | |
490 | expected = None | |
491 | if len(testData) == 3: | |
492 | if type(testData[2]) == types.DictionaryType: | |
493 | kw = testData[2] | |
494 | else: | |
495 | expected = testData[2] | |
496 | elif len(testData) > 3: | |
497 | kw = testData[2] | |
498 | expected = testData[3] | |
499 | if type(args) != types.TupleType: | |
500 | args = (args,) | |
501 | if func is num_options: | |
502 | args = (w,) + args | |
503 | origArgs = args | |
504 | if type(func) == types.MethodType and func.im_self is None: | |
505 | args = (w,) + args | |
506 | if dont_even_try: | |
507 | result = apply(func, args, kw) | |
508 | else: | |
509 | try: | |
510 | result = apply(func, args, kw) | |
511 | except: | |
512 | result = _getErrorValue() | |
513 | if hasattr(func, 'im_func'): | |
514 | name = w.__class__.__name__ + ' method ' + \ | |
515 | func.im_func.func_code.co_name | |
516 | else: | |
517 | name = 'function ' + func.__name__ | |
518 | name = name + ' ' + str(origArgs) | |
519 | if kw: | |
520 | name = name + ' ' + str(kw) | |
521 | _print_results(result, expected, name) |