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

Contents of /branches/WIP-pyshapelib-bramz/test/test_proj.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2698 - (show annotations)
Mon Sep 18 00:56:26 2006 UTC (18 years, 5 months ago) by bernhard
Original Path: trunk/thuban/test/test_proj.py
File MIME type: text/x-python
File size: 18871 byte(s)
Fixed behaviour with the proj bug and python >=2.4 
when decimal_point != '.'. So de_DE locales will work fine again.

1 # Copyright (c) 2002, 2003, 2006 by Intevation GmbH
2 # Authors:
3 # Bernhard Herzog <[email protected]>
4 # Bernhard Reiter <[email protected]>
5 #
6 # This program is free software under the GPL (>=v2)
7 # Read the file COPYING coming with Thuban for details.
8
9 """
10 Test the Thuban-specific Projection class
11 """
12
13 __version__ = "$Revision$"
14 # $Source$
15 # $Id$
16
17 import unittest
18 import locale
19 import os
20
21 import localessupport
22 import xmlsupport
23 import support
24 support.initthuban()
25
26 from Thuban import _
27 from Thuban.Model.proj import Projection, ProjFile, \
28 PROJ_UNITS_METERS, PROJ_UNITS_DEGREES
29 from Thuban.Model.messages import PROJECTION_ADDED, PROJECTION_REMOVED, \
30 PROJECTION_REPLACED
31 import Thuban.Model.resource as resource
32
33 from xmlsupport import sax_eventlist
34
35 from xml.sax import SAXParseException
36
37
38 class TestProjection(unittest.TestCase, support.FloatComparisonMixin):
39
40 """Test cases for the Thuban-specific Projection class
41 """
42
43 def test(self):
44 """Test Projection"""
45 params = ["zone=26", "proj=utm", "ellps=clrk66"]
46 proj = Projection(params)
47 self.assertEquals(proj.params, params)
48
49 # It's not clear whether this value is really the correct one
50 # but a test failure here probably still means a bug somewhere
51 self.assertFloatSeqEqual(proj.Forward(0, 0),
52 [3623101.8103431347, 0.0],
53 epsilon = 1e-5)
54 self.assertFloatSeqEqual(proj.Inverse(3623101.8103431347, 0.0),
55 [-0.00065775699878736467, 0])
56
57 self.assertFloatSeqEqual(proj.ForwardBBox((0, 0, 2, 2)),
58 (3620891.3077618643, 0.0,
59 3875381.8535437919, 252962.10480170773),
60 epsilon = 1e-5)
61 self.assertFloatSeqEqual(proj.InverseBBox((3620891.3077618643, 0.0,
62 3875381.8535437919,
63 252962.10480170773)),
64 (-0.018341599754143501, 0.0,
65 2.017992992681688, 2.0377390677846736),
66 epsilon = 1e-5)
67
68 # GetName()
69 self.assertEquals(proj.GetName(), _("Unknown"))
70
71 # GetParameter()
72 self.assertEquals(proj.GetParameter("zone"), "26")
73 self.assertEquals(proj.GetParameter("proj"), "utm")
74 self.assertEquals(proj.GetParameter("ellps"), "clrk66")
75 self.assertEquals(proj.GetParameter("hallo"), "")
76
77 # GetAllParameters()
78 self.assertEquals(proj.GetAllParameters(), params)
79
80 # GetName()
81 proj = Projection(params, "MyName")
82 self.assertEquals(proj.GetName(), "MyName")
83
84 def test_get_parameter_without_equals_sign(self):
85 """Test Projection.GetParameter() for a parameter without '=' sign"""
86 proj = Projection(["proj=utm", "zone=34", "south", "ellps=clrk66"])
87 # The Projection class pretends that for parameters specified
88 # without a value the value is the same as the parameter name.
89 self.assertEquals(proj.GetParameter("south"), "south")
90
91 def test_get_projection_units_geo(self):
92 """Test Projection.GetProjectedUnits() for geographic projection.
93 Test for the alias 'longlat' as well.
94 """
95 proj = Projection(["proj=latlong", "to_meter=0.017453292519943295",
96 "ellps=clrk66"])
97 self.assertEquals(proj.GetProjectedUnits(), PROJ_UNITS_DEGREES)
98 proj = Projection(["proj=longlat", "to_meter=0.017453292519943295",
99 "ellps=clrk66"])
100 self.assertEquals(proj.GetProjectedUnits(), PROJ_UNITS_DEGREES)
101
102 def test_lc_numeric_robustness(self):
103 """Test if an LC_NUMERIC local with comma as decimal_point will work.
104
105 Some versions of proj are not robust against this.
106 Starting with Python 2.4 there is a different behaviour when
107 calling C extensions and now they will see changes locales settings
108 which might tickle the bug in proj.
109 """
110 params = ["proj=latlong", "to_meter=0.01745", "ellps=clrk66"]
111
112 oldlocale = localessupport.setdecimalcommalocale()
113 if oldlocale == None:
114 raise support.SkipTest(
115 "No locale with comma as decimal_point found.")
116
117 proj = Projection(params)
118 #print proj.work_around_broken_proj
119 result1 = proj.Forward(1.2,3.2)
120
121 locale.setlocale(locale.LC_NUMERIC, "C")
122 proj = Projection(params)
123 result2= proj.Forward(1.2,3.2)
124
125 locale.setlocale(locale.LC_NUMERIC, oldlocale)
126 self.assertFloatSeqEqual(result1, result2, epsilon = 1e-5 )
127
128 def test_get_projection_units_normal(self):
129 """Test Projection.GetProjectedUnits() for normal projection"""
130 proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
131 self.assertEquals(proj.GetProjectedUnits(), PROJ_UNITS_METERS)
132
133 def test_label(self):
134 """Test Projection.Label() without epsg"""
135 proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"],
136 name = "My Projection")
137 self.assertEquals(proj.Label(), "My Projection")
138
139 def test_label_epsg(self):
140 """Test Projection.Label() with epsg"""
141 proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"],
142 name = "My Projection", epsg="42")
143 self.assertEquals(proj.Label(), "EPSG 42 My Projection")
144
145 def test_epsgcode_for_non_epsg_projection(self):
146 """Test Projection.EPSGCode() without epsg"""
147 proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"],
148 name = "My Projection")
149 self.assertEquals(proj.EPSGCode(), None)
150
151 def test_epsgcode_for_real_epsg_projection(self):
152 """Test Projection.EPSGCode() with epsg"""
153 proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"],
154 name = "My Projection", epsg="42")
155 self.assertEquals(proj.EPSGCode(), "42")
156
157
158
159 class TestProjFileSimple:
160
161 def test_init(self):
162 """Test ProjFile coinstructor"""
163 proj_file = ProjFile("some_filename")
164 self.assertEquals(proj_file.GetFilename(), "some_filename")
165 self.assertEquals(len(proj_file.GetProjections()), 0)
166
167 def test_set_filename(self):
168 """Test ProjFile.SetFilename()"""
169 proj_file = ProjFile("some_filename")
170 proj.SetFilename("other_name")
171 self.assertEquals(proj_file.GetFilename(), "other_name")
172
173
174 class TestProjFile(unittest.TestCase, support.SubscriberMixin):
175
176 """Test cases for ProjFile objects"""
177
178 def setUp(self):
179 self.clear_messages()
180 self.proj0 = Projection(["proj=tmerc", "ellps=clrk66"])
181 self.proj1 = Projection(["proj=utm", "ellps=clrk66"])
182 self.proj2 = Projection(["proj=lcc", "ellps=clrk66",
183 "lat_1=0", "lat_2=20"])
184 self.proj_file = ProjFile("some_filename")
185 for msg in [PROJECTION_ADDED, PROJECTION_REMOVED, PROJECTION_REPLACED]:
186 self.proj_file.Subscribe(msg, self.subscribe_with_params, msg)
187
188 def tearDown(self):
189 self.clear_messages()
190 self.proj_file.Destroy()
191
192 def test_add_remove(self):
193 """Test ProjFile.Add() and ProjFile.Remove()"""
194 self.proj_file.Add(self.proj0)
195 self.proj_file.Add(self.proj1)
196 self.assertEquals(self.proj_file.GetProjections(),
197 [self.proj0, self.proj1])
198 self.check_messages([(self.proj0, PROJECTION_ADDED),
199 (self.proj1, PROJECTION_ADDED)])
200 self.clear_messages()
201
202 self.proj_file.Remove(self.proj0)
203 self.assertEquals(self.proj_file.GetProjections(), [self.proj1])
204 self.check_messages([(self.proj0, PROJECTION_REMOVED)])
205
206 def test_remove_non_existing(self):
207 """Test ProjFile.Remove(<proj not in projfile>)"""
208 self.assertRaises(ValueError, self.proj_file.Remove, self.proj0)
209 # Nothing happened, so no messages should have been sent
210 self.check_messages([])
211
212 def test_replace(self):
213 """Test ProjFile.Replace()"""
214 self.proj_file.Add(self.proj0)
215 self.proj_file.Add(self.proj1)
216 self.clear_messages()
217
218 # Replace()
219 self.proj_file.Replace(self.proj0, self.proj2)
220 self.assertEquals(self.proj_file.GetProjections(),
221 [self.proj2, self.proj1])
222 self.check_messages([(self.proj0, self.proj2, PROJECTION_REPLACED)])
223
224 def test_replace_non_existing(self):
225 """Test ProjFile.Replace(<proj not in projfile>, <some proj>)"""
226 self.proj_file.Add(self.proj0)
227 self.proj_file.Add(self.proj1)
228 self.clear_messages()
229 self.assertRaises(ValueError,
230 self.proj_file.Replace, self.proj2, self.proj0)
231 # All projections should still be there
232 self.assertEquals(self.proj_file.GetProjections(),
233 [self.proj0, self.proj1])
234 # Nothing happened, so no messages should have been sent
235 self.check_messages([])
236
237
238 class ProjFileTest(unittest.TestCase, support.FileTestMixin,
239 xmlsupport.ValidationTest):
240
241 """Base class for the proj file tests that read or write files"""
242
243 def filename(self):
244 """Return the filename for the test"""
245 return self.temp_file_name(self.id() + ".proj")
246
247
248 class ProjFileReadTests(ProjFileTest):
249
250 """Test read ProjFile objects from files
251
252 The files only cover error handling and the system projection file.
253 """
254
255 def test_read_non_existing_file(self):
256 """Test read_proj_file with non-existing file"""
257 self.assertRaises(IOError,
258 resource.read_proj_file,
259 self.temp_file_name("nonexistent.proj"))
260
261 def test_read_unreadable_file(self):
262 """Test read_proj_file with unreadable file
263
264 As currently written this only works on unix-like systems and
265 not e.g. on MS Windows.
266 """
267 if os.name != "posix":
268 raise support.SkipTest("Test only works on posix systems")
269 filename = self.filename()
270 file = open(filename, "w")
271 file.close()
272 os.chmod(filename, 0200) # write-only
273 self.assertRaises(IOError, resource.read_proj_file, filename)
274
275 def test_read_empty_file(self):
276 """Test read_proj_file with empty file"""
277 filename = self.filename()
278 file = open(filename, "w")
279 file.close()
280
281 self.assertRaises(SAXParseException, resource.read_proj_file, filename)
282
283 def test_get_system_proj_file(self):
284 """Test resource.get_system_proj_file(DEFAULT_PROJ_FILE)
285
286 This is primarily to test whether the system proj file contains
287 invalid projection paramers and whether the proj file is not
288 empty
289 """
290 projfile, warnings\
291 = resource.get_system_proj_file(resource.DEFAULT_PROJ_FILE)
292 self.assertEquals(warnings, [])
293 self.assert_(len(projfile.GetProjections()) > 0)
294
295 # see whether it got cached and we get the same projfile object
296 # when we read the file again
297 projfile2, warnings \
298 = resource.get_system_proj_file(resource.DEFAULT_PROJ_FILE)
299 self.assert_(projfile is projfile2)
300
301
302 class WriteProjFileTests(ProjFileTest):
303
304 """Test cases for writing proj files"""
305
306 def compare_xml(self, xml1, xml2):
307 self.assertEquals(sax_eventlist(xml1), sax_eventlist(xml2))
308
309 def doTestWrite(self, projfile, expected):
310 filename = self.filename()
311
312 resource.write_proj_file(projfile)
313
314 file = open(filename)
315 written_contents = file.read()
316 file.close()
317 self.compare_xml(written_contents, expected)
318 self.validate_data(written_contents)
319 self.validate_data(expected)
320
321 def test_write(self):
322 """Test write_proj_file"""
323 pf = ProjFile(self.filename())
324 pf.Add(Projection(['proj=tmerc', 'ellps=clrk66',
325 'lat_0=90w', 'lon_0=90w', 'k=1'],
326 "Transverse Mercator",))
327 pf.Add(Projection(["proj=tmerc",
328 "lat_0=0.000000000", "lon_0=-62.000000000",
329 "k=0.999500", "x_0=400000.000", "y_0=0.000",
330 "ellps=clrk80", "units=m"],
331 "Anguilla 1957 / British West Indies Grid",
332 epsg="200"))
333 file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
334 <!DOCTYPE projectionlist SYSTEM "projfile.dtd">
335 <projectionlist>
336 <projection name="Transverse Mercator">
337 <parameter value="proj=tmerc"/>
338 <parameter value="ellps=clrk66"/>
339 <parameter value="lat_0=90w"/>
340 <parameter value="lon_0=90w"/>
341 <parameter value="k=1"/>
342 </projection>
343 <projection epsg="200"
344 name="Anguilla 1957 / British West Indies Grid">
345 <parameter value="proj=tmerc"/>
346 <parameter value="lat_0=0.000000000"/>
347 <parameter value="lon_0=-62.000000000"/>
348 <parameter value="k=0.999500"/>
349 <parameter value="x_0=400000.000"/>
350 <parameter value="y_0=0.000"/>
351 <parameter value="ellps=clrk80"/>
352 <parameter value="units=m"/>
353 </projection>
354 </projectionlist>
355 '''
356 self.doTestWrite(pf, file_contents)
357
358 def test_write_empty_file(self):
359 """Test write empty ProjFile"""
360 pf = ProjFile(self.filename())
361 file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
362 <!DOCTYPE projectionlist SYSTEM "projfile.dtd">
363 <projectionlist>
364 </projectionlist>
365 '''
366 self.doTestWrite(pf, file_contents)
367
368
369 class ProjFileLoadTestCase(support.FileLoadTestCase):
370
371 """Base class for the test cases that read specific test files"""
372
373 file_extension = ".proj"
374
375 def tearDown(self):
376 """Clear the cache explicitly"""
377 resource.clear_proj_file_cache()
378
379
380 class TestLoadingProjFile(ProjFileLoadTestCase):
381
382 file_contents = '''\
383 <?xml version="1.0" encoding="UTF-8"?>
384 <!DOCTYPE projectionlist SYSTEM "projfile.dtd">
385 <projectionlist>
386 <projection name="Transverse Mercator">
387 <parameter value="proj=tmerc"/>
388 <parameter value="ellps=clrk66"/>
389 <parameter value="lat_0=90w"/>
390 <parameter value="lon_0=90w"/>
391 <parameter value="k=1"/>
392 </projection>
393 <projection epsg="200" name="Anguilla 1957 / British West Indies Grid">
394 <parameter value="proj=tmerc"/>
395 <parameter value="lat_0=0.000000000"/>
396 <parameter value="lon_0=-62.000000000"/>
397 <parameter value="k=0.999500"/>
398 <parameter value="x_0=400000.000"/>
399 <parameter value="y_0=0.000"/>
400 <parameter value="ellps=clrk80"/>
401 <parameter value="units=m"/>
402 </projection>
403 </projectionlist>
404 '''
405
406 def check_projection(self, proj, label, parameters):
407 """Check the values of the proj's label and parameters"""
408 self.assertEquals(proj.Label(), label)
409 params = proj.GetAllParameters()[:]
410 params.sort()
411 self.assertEquals(params, parameters)
412
413 def test(self):
414 projfile, warnings = resource.read_proj_file(self.filename())
415 # no warnings
416 self.assertEquals(warnings, [])
417
418 # There are two projections
419 projs = projfile.GetProjections()
420 self.assertEquals(len(projs), 2)
421
422 self.check_projection(projs[0],
423 "Transverse Mercator",
424 ['ellps=clrk66', 'k=1', 'lat_0=90w', 'lon_0=90w',
425 'proj=tmerc'])
426 self.check_projection(projs[1],
427 "EPSG 200 Anguilla 1957 / British West Indies Grid",
428 ["ellps=clrk80", "k=0.999500",
429 "lat_0=0.000000000", "lon_0=-62.000000000",
430 "proj=tmerc", "units=m",
431 "x_0=400000.000", "y_0=0.000"])
432
433 def test_caching(self):
434 # test whether the projfile cache works
435 projfile, warnings = resource.read_proj_file(self.filename())
436 projfile2, warnings = resource.read_proj_file(self.filename())
437
438 # Both projfiles should be the same object
439 self.assert_(projfile2 is projfile)
440
441 # If we clear the cache we should get a new one.
442 resource.clear_proj_file_cache()
443 projfile3, warnings = resource.read_proj_file(self.filename())
444 self.assert_(projfile3 is not projfile)
445
446
447 class TestLoadingProjFileWithEmptyProjectionlist(ProjFileLoadTestCase):
448
449 file_contents = '''\
450 <?xml version="1.0" encoding="UTF-8"?>
451 <!DOCTYPE projectionlist SYSTEM "projfile.dtd">
452 <projectionlist>
453 </projectionlist>
454 '''
455
456 def test(self):
457 projfile, warnings = resource.read_proj_file(self.filename())
458 # no warnings
459 self.assertEquals(warnings, [])
460
461 # There are no projections
462 self.assertEquals(len(projfile.GetProjections()), 0)
463
464
465 class TestProjFileWithInvalidParameters(ProjFileLoadTestCase):
466
467 file_contents = '''\
468 <?xml version="1.0" encoding="UTF-8"?>
469 <!DOCTYPE projectionlist SYSTEM "projfile.dtd">
470 <projectionlist>
471 <projection name="Universal Transverse Mercator">
472 <parameter value="proj=utm"/>
473 <parameter value="ellps=clrk66"/>
474 <!-- an invalid zone number to trigger the parameter checking
475 in the proj library -->
476 <parameter value="zone=1000"/>
477 </projection>
478 <projection name="Transverse Mercator">
479 <parameter value="proj=tmerc"/>
480 <parameter value="ellps=clrk66"/>
481 <parameter value="lat_0=90w"/>
482 <parameter value="lon_0=90w"/>
483 <parameter value="k=1"/>
484 </projection>
485 </projectionlist>
486 '''
487
488 def setUp(self):
489 support.FileLoadTestCase.setUp(self)
490
491 def test(self):
492 """Test reading a proj file with invalid parameters"""
493 projfile, warnings = resource.read_proj_file(self.filename())
494 projs = projfile.GetProjections()
495 self.assertEquals(len(projs), 1)
496 params = projs[0].GetAllParameters()[:]
497 params.sort()
498 self.assertEquals(params, ['ellps=clrk66', 'k=1', 'lat_0=90w',
499 'lon_0=90w', 'proj=tmerc'])
500 self.assertEquals(warnings,
501 ['Error in projection "Universal Transverse Mercator":'
502 ' invalid UTM zone number'])
503
504
505 if __name__ == "__main__":
506 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