/[thuban]/branches/WIP-pyshapelib-bramz/test/test_baserenderer.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/test/test_baserenderer.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2562 - (hide annotations)
Wed Feb 16 21:14:47 2005 UTC (20 years ago) by jonathan
Original Path: trunk/thuban/test/test_baserenderer.py
File MIME type: text/x-python
File size: 20230 byte(s)
Further wxPython 2.5 changes using patches from Daniel Calvelo Aros
so that that wxproj doesn't crash. Added GUI support for selecting
alpha channel (opacity can't be selected yet).

1 bh 1552 # Copyright (C) 2003 by Intevation GmbH
2     # Authors:
3     # Bernhard Herzog <[email protected]>
4     #
5     # This program is free software under the GPL (>=v2)
6     # Read the file COPYING coming with the software for details.
7    
8     """Test Thuban.Model.baserenderer"""
9    
10     __version__ = "$Revision$"
11     # $Source$
12     # $Id$
13    
14     import os
15     import binascii
16     import unittest
17    
18 bh 1585 from mockgeo import SimpleShapeStore
19 bh 1552 import support
20     support.initthuban()
21    
22     from Thuban.Model.color import Transparent, Color
23 bh 1557 from Thuban.Model.data import SHAPETYPE_ARC, SHAPETYPE_POLYGON, SHAPETYPE_POINT
24 bh 1552 from Thuban.Model.map import Map
25 bh 1928 from Thuban.Model.layer import BaseLayer, Layer, RasterLayer
26 bh 1552 from Thuban.Model.table import MemoryTable, \
27     FIELDTYPE_DOUBLE, FIELDTYPE_INT, FIELDTYPE_STRING
28 bh 1585 from Thuban.Model.classification import ClassGroupSingleton
29 bh 1555 import Thuban.Model.resource
30 bh 1552
31 bh 1585
32 bh 1928 from Thuban.UI.baserenderer import BaseRenderer, \
33     add_renderer_extension, init_renderer_extensions
34 bh 1552
35 jonathan 2562 from Thuban.version import versions
36 bh 1552
37     class MockDC:
38    
39     def __init__(self, size = None):
40     self.calls = []
41     self.size = size
42    
43     def GetSizeTuple(self):
44     return self.size
45    
46     def __getattr__(self, attr):
47     def method(*args):
48     self.calls.append((attr,) + args)
49     return method
50    
51     class P:
52    
53     """A simple point"""
54    
55     def __init__(self, x, y):
56     self.x = x
57     self.y = y
58    
59     def __eq__(self, other):
60     return self.x == other.x and self.y == other.y
61    
62     def __ne__(self, other):
63     return self.x != other.x and self.y != other.y
64    
65     def __repr__(self):
66     return "P(%r, %r)" % (self.x, self.y)
67    
68    
69     class SimpleRenderer(BaseRenderer):
70    
71     TRANSPARENT_PEN = ("pen", Transparent)
72     TRANSPARENT_BRUSH = ("brush", Transparent)
73    
74     def make_point(self, x, y):
75     return P(x, y)
76    
77     def tools_for_property(self, prop):
78     fill = prop.GetFill()
79     brush = ("brush", fill)
80    
81     stroke = prop.GetLineColor()
82     stroke_width = prop.GetLineWidth()
83     if stroke is Transparent:
84     pen = ("pen", Transparent)
85     else:
86     pen = ("pen", stroke, stroke_width)
87    
88     return pen, brush
89    
90     def label_font(self):
91     return "label font"
92    
93 jonathan 2551 def draw_raster_data(self, x, y, data, format='BMP'):
94 bh 1552 self.raster_data = data
95 bh 1928 self.raster_format = format
96 bh 1552
97 bh 1557
98 bh 1552 class MockProjection:
99    
100     """Objects that look like projections but simply apply non-uniform scalings
101     """
102    
103     def __init__(self, xscale, yscale):
104     self.xscale = float(xscale)
105     self.yscale = float(yscale)
106    
107     def Forward(self, x, y):
108     return (x * self.xscale, y * self.yscale)
109    
110     def Inverse(self, x, y):
111     return (x / self.xscale, y / self.yscale)
112    
113    
114     class TestBaseRenderer(unittest.TestCase):
115    
116     def setUp(self):
117     """Set self.to_destroy to an empty list
118    
119     Test should put all objects whose Destroy should be called atunittest.main
120     the end into this list so that they're destroyed in tearDown
121     """
122     self.to_destroy = []
123    
124     def tearDown(self):
125     for obj in self.to_destroy:
126     obj.Destroy()
127    
128     def test_arc_no_projection(self):
129     """Test BaseRenderer with arc layer and no projections"""
130     table = MemoryTable([("type", FIELDTYPE_STRING),
131     ("value", FIELDTYPE_DOUBLE),
132     ("code", FIELDTYPE_INT)],
133     [("UNKNOWN", 0.0, 0)])
134     shapes = [[[(0, 0), (10, 10)]]]
135     store = SimpleShapeStore(SHAPETYPE_ARC, shapes, table)
136    
137     map = Map("TestBaseRenderer")
138     self.to_destroy.append(map)
139     layer = Layer("arc layer", store)
140     map.AddLayer(layer)
141    
142     dc = MockDC()
143 bh 1867 renderer = SimpleRenderer(dc, map, 2, (10, 10))
144 bh 1552
145 bh 1867 renderer.render_map()
146 bh 1552
147     self.assertEquals(dc.calls,
148     [('BeginDrawing',),
149     ('SetBrush', ('brush', Transparent)),
150     ('SetPen', ('pen', Color(0, 0, 0), 1)),
151     ('DrawLines', [P(10, 10), P(30, -10)]),
152     ('SetFont', "label font"),
153     ('EndDrawing',)])
154    
155     def test_polygon_no_projection(self):
156     """Test BaseRenderer with polygon layer and no projections"""
157     table = MemoryTable([("type", FIELDTYPE_STRING),
158     ("value", FIELDTYPE_DOUBLE),
159     ("code", FIELDTYPE_INT)],
160     [("UNKNOWN", 0.0, 0)])
161     shapes = [[[(0, 0), (10, 10), (10, 0), (0, 0)]]]
162     store = SimpleShapeStore(SHAPETYPE_POLYGON, shapes, table)
163    
164     map = Map("TestBaseRenderer")
165     layer = Layer("polygon layer", store)
166     prop = layer.GetClassification().GetDefaultGroup().GetProperties()
167     prop.SetFill(Color(1, 1, 1))
168    
169     map.AddLayer(layer)
170     self.to_destroy.append(map)
171    
172     dc = MockDC()
173 bh 1867 renderer = SimpleRenderer(dc, map, 2, (10, 10))
174 bh 1552
175 bh 1867 renderer.render_map()
176 bh 1552
177     self.assertEquals(dc.calls,
178     [('BeginDrawing',),
179     ('SetBrush', ('brush', Color(1, 1, 1))),
180     ('SetPen', ('pen', Transparent)),
181     ('DrawPolygon', [P(10, 10), P(30, -10), P(30, 10),
182     P(10, 10)]),
183     ('SetBrush', ('brush', Transparent)),
184     ('SetPen', ('pen', Color(0, 0, 0), 1)),
185     ('DrawLines', [P(10, 10), P(30, -10), P(30, 10),
186     P(10, 10)]),
187     ('SetFont', "label font"),
188     ('EndDrawing',)])
189    
190     def test_complex_polygon(self):
191     """Test BaseRenderer with complex polygon and no projections"""
192     # A square inside a sqare. This has to be drawn with at least a
193     # draw polygon call and two draw lines calls.
194     shapes = [[[(0, 0), (0, 10), (10, 10), (10, 0), (0, 0)],
195     [(2, 2), (8, 2), (8, 8), (2, 8), (2, 2)]]]
196    
197     table = MemoryTable([("type", FIELDTYPE_STRING),
198     ("value", FIELDTYPE_DOUBLE),
199     ("code", FIELDTYPE_INT)],
200     [("UNKNOWN", 0.0, 0)])
201     store = SimpleShapeStore(SHAPETYPE_POLYGON, shapes, table)
202    
203     map = Map("TestBaseRenderer")
204     layer = Layer("polygon layer", store)
205     prop = layer.GetClassification().GetDefaultGroup().GetProperties()
206     prop.SetFill(Color(1, 1, 1))
207    
208     map.AddLayer(layer)
209     self.to_destroy.append(map)
210    
211     dc = MockDC()
212 bh 1867 renderer = SimpleRenderer(dc, map, 2, (10, 10))
213 bh 1552
214 bh 1867 renderer.render_map()
215 bh 1552
216     self.assertEquals(dc.calls,
217     [('BeginDrawing',),
218     ('SetBrush', ('brush', Color(1, 1, 1))),
219     ('SetPen', ('pen', Transparent)),
220     ('DrawPolygon',
221     [P(10, 10), P(10, -10), P(30, -10), P(30, 10),
222     P(10, 10),
223     P(14, 6), P(26, 6), P(26, -6), P(14, -6),
224     P(14, 6),
225     P(10, 10)]),
226     ('SetBrush', ('brush', Transparent)),
227     ('SetPen', ('pen', Color(0, 0, 0), 1)),
228     ('DrawLines', [P(10, 10), P(10, -10), P(30, -10),
229     P(30, 10), P(10, 10)]),
230     ('DrawLines', [P(14, 6), P(26, 6), P(26, -6),
231     P(14, -6), P(14, 6)]),
232     ('SetFont', "label font"),
233     ('EndDrawing',)])
234    
235     def test_point_no_projection(self):
236     """Test BaseRenderer with point layer and no projections"""
237     table = MemoryTable([("type", FIELDTYPE_STRING),
238     ("value", FIELDTYPE_DOUBLE),
239     ("code", FIELDTYPE_INT)],
240     [("UNKNOWN", 0.0, 0),
241     ("UNKNOWN", 0.0, 1)])
242     shapes = [[[(0, 0)]], [[(10, 10)]]]
243     store = SimpleShapeStore(SHAPETYPE_POINT, shapes, table)
244    
245     map = Map("TestBaseRenderer")
246     layer = Layer("point layer", store)
247     map.AddLayer(layer)
248     self.to_destroy.append(map)
249    
250     dc = MockDC()
251 bh 1867 renderer = SimpleRenderer(dc, map, 2, (10, 10))
252 bh 1552
253 bh 1867 renderer.render_map()
254 bh 1552
255     self.assertEquals(dc.calls,
256     [('BeginDrawing',),
257     ('SetBrush', ('brush', Transparent)),
258     ('SetPen', ('pen', Color(0, 0, 0), 1)),
259     ('DrawEllipse', 5, 5, 10, 10),
260     ('SetBrush', ('brush', Transparent)),
261     ('SetPen', ('pen', Color(0, 0, 0), 1)),
262     ('DrawEllipse', 25, -15, 10, 10),
263     ('SetFont', "label font"),
264     ('EndDrawing',)])
265    
266     def test_raster_no_projection(self):
267     """Test BaseRenderer with raster layer and no projections
268    
269     This test is very simple minded and perhaps can easily fail due
270     to round-off errors. It simply compares the complete BMP file
271     returned by gdalwarp.ProjectRasterFile to a BMP file data.
272     """
273 bh 1555 if not Thuban.Model.resource.has_gdal_support():
274     raise support.SkipTest("No gdal support")
275    
276 bh 1552 map = Map("TestBaseRenderer")
277    
278     layer = RasterLayer("raster layer",
279     os.path.join("..", "Data", "iceland",
280     "island.tif"))
281     map.AddLayer(layer)
282     self.to_destroy.append(map)
283    
284     dc = MockDC(size = (20, 20))
285 bh 1867 renderer = SimpleRenderer(dc, map, 34, (800, 2250))
286 bh 1552
287 bh 1867 renderer.render_map()
288 bh 1552
289     # The following commented out code block can be used to generate
290     # the base64 coded reference image data
291 jonathan 2562 #hexed = binascii.b2a_base64(renderer.raster_data[2][0])
292 bh 1552 #while hexed:
293 jonathan 2537 #print repr(hexed[:65])
294     #hexed = hexed[65:]
295 bh 1552
296 jonathan 2552 # The reference data as a base64 coded RAW image
297 bh 1552 raw_data = binascii.a2b_base64(
298 jonathan 2537 'UmbmUmbmUmbmUmbmUmbmAtYCJooCAtICAq4CJooCArICAuICArICAuYCAs4COn4CO'
299     'n4CAq4CAuICFpICUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmAuYCAqICAqoCAqoCFp'
300     'ICJooCIo4CCpoCQnoGOn4CDpYCOn4CUmbmUmbmNo6aEpYCLoYCAqICGpICFpICUmb'
301     'mAt4CUmbmNo6aAtICArYCAqoCKoYCMoICTnYKOn4CFpICUmbmUmbmUmbmUmbmAp4C'
302     'NoICArYCAr4CCpoCAqYCCpoCEpYCHo4CFpICHo4CGpICFpICKoYCTnYKMoICAp4CU'
303     'mbmUmbmUmbmUmbmUmbmUmbmAtYCAroCArYCCpoCAtYCAroCAtICAsYCUmbmAt4CAq'
304     'YCAroCMoICAs4CAs4CAtYCAt4CAqYCUmbmUmbmUmbmUmbmAtoCAtYCAq4CAtoCBp4'
305     'CAroCAqoCAq4CAr4CDpYCGpICAt4CAsICDpYCArICCpoCHo4CAs4CAuICUmbmUmbm'
306     'UmbmUmbmUmbmUmbmAuICAqICFpYCAq4CDpoCAqYCFpICAqYCUmbmNo6aAsYCCpoCD'
307     'pYCAqICAtoCUmbmAt4CAqoCCpoCAroCHo4CAsYCAq4CAsICAs4CAp4CUmbmAtYCAq'
308     'YCIooCHo4CAsICAr4CAqICEpYCAs4CAqICArICDpYCEpYCEpYCAr4CUmbmEpYCAs4'
309     'CAtICAs4CAqYCUmbmAtoCAp4CCpoCDpYCAq4CArICAqoCAqYCAqYCAtYCAtoCDpYC'
310     'At4CUmbmUmbmUmbmUmbmAt4CAsoCAsoCAp4CAp4CCpoCAsoCAt4CNo6aUmbmUmbmU'
311     'mbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmAt4CAtYCCpoCAqICAroCAr4CUmbmUm'
312     'bmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmb'
313     'mUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbm'
314     'UmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmU'
315     'mbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUm'
316     'bmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmb'
317     'mUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbm'
318     'UmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmU'
319     'mbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUm'
320     'bmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmb'
321     'mUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbm'
322     'UmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbm\n')
323 jonathan 2552
324 jonathan 2562 #print
325     #hexed = binascii.b2a_base64(renderer.raster_data[2][1])
326     #while hexed:
327     #print repr(hexed[:61])
328     #hexed = hexed[61:]
329    
330    
331     if versions['wxPython-tuple'] < (2,5,3):
332     raw_mask = binascii.a2b_base64(
333     'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
334     'AAAAAAAAAAAAAAAAAAA\n')
335     else:
336     raw_mask = binascii.a2b_base64(
337     '//8P//8P//8P//8P//8P//8P//8P//8P//8P//8P//8P//8P//8P//8P//8P/'
338     '/8P//8P//8P//8P//8P\n')
339    
340     self.assertEquals(renderer.raster_data,
341     (20,20,(raw_data, raw_mask, None)))
342    
343 jonathan 2537 self.assertEquals(renderer.raster_format, "RAW")
344 bh 1552
345     self.assertEquals(dc.calls,
346     [('BeginDrawing',),
347     ('SetFont', "label font"),
348     ('EndDrawing',)])
349    
350 jonathan 2562 if versions['wxPython-tuple'] >= (2,5,3):
351     layer.SetMaskType(layer.MASK_ALPHA)
352     renderer.render_map()
353    
354     #print
355     #hexed = binascii.b2a_base64(renderer.raster_data[2][2])
356     #while hexed:
357     #print repr(hexed[:61])
358     #hexed = hexed[61:]
359     raw_alpha = binascii.a2b_base64(
360     '/////////////////////////////////////////////////////////////'
361     '/////////////////////////////////////////////////////////////'
362     '/////////////////////////////////////////////////////////////'
363     '/////////////////////////////////////////////////////////////'
364     '/////////////////////////////////////////////////////////////'
365     '/////////////////////////////////////////////////////////////'
366     '/////////////////////////////////////////////////////////////'
367     '/////////////////////////////////////////////////////////////'
368     '/////////////////////////////////////////////w==\n')
369     self.assertEquals(renderer.raster_data,
370     (20,20,(raw_data, None, raw_alpha)))
371    
372    
373     layer.SetMaskType(layer.MASK_NONE)
374     renderer.render_map()
375     self.assertEquals(renderer.raster_data, (20,20,(raw_data, None, None)))
376    
377 bh 1552 def test_point_map_projection(self):
378     """Test BaseRenderer with point layer and map projection"""
379     table = MemoryTable([("type", FIELDTYPE_STRING),
380     ("value", FIELDTYPE_DOUBLE),
381     ("code", FIELDTYPE_INT)],
382     [("UNKNOWN", 0.0, 0)])
383     shapes = [[[(10, 10)]]]
384     store = SimpleShapeStore(SHAPETYPE_POINT, shapes, table)
385    
386     map = Map("TestBaseRenderer")
387     map.SetProjection(MockProjection(-3, 3))
388     layer = Layer("point layer", store)
389     map.AddLayer(layer)
390     self.to_destroy.append(map)
391    
392     dc = MockDC()
393 bh 1867 renderer = SimpleRenderer(dc, map, 2, (10, 10))
394 bh 1552
395 bh 1867 renderer.render_map()
396 bh 1552
397     self.assertEquals(dc.calls,
398     [('BeginDrawing',),
399     ('SetBrush', ('brush', Transparent)),
400     ('SetPen', ('pen', Color(0, 0, 0), 1)),
401     ('DrawEllipse', -55, -55, 10, 10),
402     ('SetFont', "label font"),
403     ('EndDrawing',)])
404    
405     def test_point_layer_projection(self):
406     """Test BaseRenderer with point layer and layer projection"""
407     table = MemoryTable([("type", FIELDTYPE_STRING),
408     ("value", FIELDTYPE_DOUBLE),
409     ("code", FIELDTYPE_INT)],
410     [("UNKNOWN", 0.0, 0)])
411     shapes = [[[(9, 9)]]]
412     store = SimpleShapeStore(SHAPETYPE_POINT, shapes, table)
413    
414     map = Map("TestBaseRenderer")
415     layer = Layer("point layer", store)
416     layer.SetProjection(MockProjection(3, -3))
417     map.AddLayer(layer)
418     self.to_destroy.append(map)
419    
420     dc = MockDC()
421 bh 1867 renderer = SimpleRenderer(dc, map, 2, (10, 10))
422 bh 1552
423 bh 1867 renderer.render_map()
424 bh 1552
425     self.assertEquals(dc.calls,
426     [('BeginDrawing',),
427     ('SetBrush', ('brush', Transparent)),
428     ('SetPen', ('pen', Color(0, 0, 0), 1)),
429     ('DrawEllipse', 11, 11, 10, 10),
430     ('SetFont', "label font"),
431     ('EndDrawing',)])
432    
433     def test_point_layer_and_map_projection(self):
434     """Test BaseRenderer with point layer and layer and map projection"""
435     table = MemoryTable([("type", FIELDTYPE_STRING),
436     ("value", FIELDTYPE_DOUBLE),
437     ("code", FIELDTYPE_INT)],
438     [("UNKNOWN", 0.0, 0)])
439     shapes = [[[(9, 9)]]]
440     store = SimpleShapeStore(SHAPETYPE_POINT, shapes, table)
441    
442     map = Map("TestBaseRenderer")
443     map.SetProjection(MockProjection(-3, 3))
444     layer = Layer("point layer", store)
445     layer.SetProjection(MockProjection(3, -3))
446     map.AddLayer(layer)
447     self.to_destroy.append(map)
448    
449     dc = MockDC()
450 bh 1867 renderer = SimpleRenderer(dc, map, 2, (10, 10))
451 bh 1552
452 bh 1867 renderer.render_map()
453 bh 1552
454     self.assertEquals(dc.calls,
455     [('BeginDrawing',),
456     ('SetBrush', ('brush', Transparent)),
457     ('SetPen', ('pen', Color(0, 0, 0), 1)),
458     ('DrawEllipse', -13, 23, 10, 10),
459     ('SetFont', "label font"),
460     ('EndDrawing',)])
461    
462    
463 bh 1591 def test_point_with_classification(self):
464     """Test BaseRenderer with point layer and classification"""
465     table = MemoryTable([("type", FIELDTYPE_STRING),
466     ("value", FIELDTYPE_DOUBLE),
467     ("code", FIELDTYPE_INT)],
468     [("UNKNOWN", 0.0, 0),
469     ("UNKNOWN", 0.0, 1)])
470     shapes = [[[(0, 0)]], [[(10, 10)]]]
471     store = SimpleShapeStore(SHAPETYPE_POINT, shapes, table)
472 bh 1552
473 bh 1591 map = Map("TestBaseRenderer")
474     layer = Layer("point layer", store)
475     group = ClassGroupSingleton(1)
476     group.GetProperties().SetFill(Color(0, 0, 1))
477     layer.GetClassification().AppendGroup(group)
478     layer.SetClassificationColumn("code")
479    
480     map.AddLayer(layer)
481     self.to_destroy.append(map)
482    
483     dc = MockDC()
484 bh 1867 renderer = SimpleRenderer(dc, map, 2, (10, 10))
485 bh 1591
486 bh 1867 renderer.render_map()
487 bh 1591
488     self.assertEquals(dc.calls,
489     [('BeginDrawing',),
490     ('SetBrush', ('brush', Transparent)),
491     ('SetPen', ('pen', Color(0, 0, 0), 1)),
492     ('DrawEllipse', 5, 5, 10, 10),
493     ('SetBrush', ('brush', Color(0, 0, 1))),
494     ('SetPen', ('pen', Color(0, 0, 0), 1)),
495     ('DrawEllipse', 25, -15, 10, 10),
496     ('SetFont', "label font"),
497     ('EndDrawing',)])
498    
499    
500 bh 1928 def test_renderer_extension(self):
501     """Test renderer with a renderer extension"""
502     class MyLayer(BaseLayer):
503     pass
504    
505     calls = []
506     def my_renderer(renderer, layer):
507     calls.append((renderer, layer))
508     return ()
509    
510     add_renderer_extension(MyLayer, my_renderer)
511    
512     try:
513     map = Map("test_renderer_extension")
514     layer = MyLayer("my layer")
515     map.AddLayer(layer)
516     self.to_destroy.append(map)
517    
518     dc = MockDC()
519     renderer = SimpleRenderer(dc, map, 2, (10, 10))
520     renderer.render_map()
521     finally:
522     init_renderer_extensions()
523    
524     self.assertEquals(calls, [(renderer, layer)])
525    
526    
527 bh 1552 if __name__ == "__main__":
528     support.run_tests()

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26