1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
"""
Encoding/decoding custom objects with __geo_interface__
"""
import unittest
import geojson
from geojson.mapping import to_mapping
class EncodingDecodingTest(unittest.TestCase):
def setUp(self):
class Restaurant:
"""
Basic Restaurant class
"""
def __init__(self, name, latlng):
super().__init__()
self.name = name
self.latlng = latlng
class Restaurant1(Restaurant):
"""
Extends Restaurant with __geo_interface__ returning dict
"""
@property
def __geo_interface__(self):
return {'type': "Point", 'coordinates': self.latlng}
class Restaurant2(Restaurant):
"""
Extends Restaurant with __geo_interface__ returning another
__geo_interface__ object
"""
@property
def __geo_interface__(self):
return geojson.Point(self.latlng)
class RestaurantFeature1(Restaurant):
"""
Extends Restaurant with __geo_interface__ returning dict
"""
@property
def __geo_interface__(self):
return {
'geometry': {
'type': "Point",
'coordinates': self.latlng,
},
'type': "Feature",
'properties': {
'name': self.name,
},
}
class RestaurantFeature2(Restaurant):
"""
Extends Restaurant with __geo_interface__ returning another
__geo_interface__ object
"""
@property
def __geo_interface__(self):
return geojson.Feature(
geometry=geojson.Point(self.latlng),
properties={'name': self.name})
self.name = "In N Out Burger"
self.latlng = [-54.0, 4.0]
self.restaurant_nogeo = Restaurant(self.name, self.latlng)
self.restaurant1 = Restaurant1(self.name, self.latlng)
self.restaurant2 = Restaurant2(self.name, self.latlng)
self.restaurant_str = ('{"coordinates": [-54.0, 4.0],'
' "type": "Point"}')
self.restaurant_feature1 = RestaurantFeature1(self.name, self.latlng)
self.restaurant_feature2 = RestaurantFeature2(self.name, self.latlng)
self.restaurant_feature_str = ('{"geometry":'
' {"coordinates": [-54.0, 4.0],'
' "type": "Point"},'
' "properties":'
' {"name": "In N Out Burger"},'
' "type": "Feature"}')
def test_encode(self):
"""
Ensure objects that implement __geo_interface__ can be encoded into
GeoJSON strings
"""
actual = geojson.dumps(self.restaurant1, sort_keys=True)
self.assertEqual(actual, self.restaurant_str)
actual = geojson.dumps(self.restaurant2, sort_keys=True)
self.assertEqual(actual, self.restaurant_str)
# Classes that don't implement geo interface should raise TypeError
with self.assertRaises(TypeError):
geojson.dumps(self.restaurant_nogeo)
def test_encode_nested(self):
"""
Ensure nested objects that implement __geo_interface__ can be encoded
into GeoJSON strings
"""
actual = geojson.dumps(self.restaurant_feature1, sort_keys=True)
self.assertEqual(actual, self.restaurant_feature_str)
actual = geojson.dumps(self.restaurant_feature2, sort_keys=True)
self.assertEqual(actual, self.restaurant_feature_str)
def test_decode(self):
"""
Ensure a GeoJSON string can be decoded into GeoJSON objects
"""
actual = geojson.loads(self.restaurant_str)
expected = self.restaurant1.__geo_interface__
self.assertEqual(expected, actual)
def test_decode_nested(self):
"""
Ensure a GeoJSON string can be decoded into nested GeoJSON objects
"""
actual = geojson.loads(self.restaurant_feature_str)
expected = self.restaurant_feature1.__geo_interface__
self.assertEqual(expected, actual)
nested = expected['geometry']
expected = self.restaurant1.__geo_interface__
self.assertEqual(nested, expected)
def test_invalid(self):
with self.assertRaises(ValueError) as cm:
geojson.loads('{"type":"Point", "coordinates":[[-Infinity, 4.0]]}')
self.assertIn('is not JSON compliant', str(cm.exception))
def test_mapping(self):
self.assertEqual(to_mapping(geojson.Point([1.0, 2.0])),
{"coordinates": [1.0, 2.0], "type": "Point"})
def test_GeoJSON(self):
self.assertEqual(None, geojson.GeoJSON().__geo_interface__)
self.assertEqual({"type": "GeoJSON"}, to_mapping(geojson.GeoJSON()))
|