Skip to content

Commit 5688558

Browse files
committed
change geojson module from classes to functions
1 parent ad7c194 commit 5688558

File tree

7 files changed

+144
-173
lines changed

7 files changed

+144
-173
lines changed

planet/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
GoogleEarthEngineDelivery, Tool, ClipTool)
2121
from .api.__version__ import __version__ # NOQA
2222
from .auth import Auth
23-
from .geojson import Geometry
2423

2524

2625
__all__ = [
@@ -38,5 +37,4 @@
3837
ClipTool,
3938
Tool,
4039
Auth,
41-
Geometry
4240
]

planet/api/order_details.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,5 +730,5 @@ def __init__(
730730
Parameters:
731731
aoi: clip GeoJSON.
732732
"""
733-
parameters = {'aoi': geojson.Polygon(aoi)}
733+
parameters = {'aoi': geojson.as_polygon(aoi)}
734734
super().__init__('clip', parameters)

planet/geojson.py

Lines changed: 88 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# License for the specific language governing permissions and limitations under
1313
# the License.
1414
"""Functionality for interacting with GeoJSON."""
15-
import json
1615
import logging
1716

1817
import shapely.geometry as sgeom
@@ -31,114 +30,94 @@ class WrongTypeException(GeoJSONException):
3130
pass
3231

3332

34-
class Geometry(dict):
35-
'''Manage and validate GeoJSON geometry description.'''
36-
def __init__(
37-
self,
38-
data: dict
39-
):
40-
"""
41-
Initialize GeoJSON.
42-
43-
If data represents a GeoJSON FeatureClass, the geometry of the first
44-
Feature is used.
45-
46-
Parameters:
47-
data: GeoJSON geometry, Feature, or FeatureClass.
48-
"""
49-
geom = self._geom_from_dict(data)
50-
super().__init__(geom)
51-
self._validate()
52-
53-
@classmethod
54-
def _geom_from_dict(
55-
cls,
56-
data: dict
57-
):
58-
'''Extract the geometry description from GeoJSON.
59-
60-
If data represents a FeatureClass, the geometry from the first feature
61-
is used.
62-
63-
Parameters:
64-
data: GeoJSON geometry, Feature, or FeatureClass.
65-
66-
Raises:
67-
GeoJSONException: If data is not valid GeoJSON geometry, Feature,
33+
class DataLossWarning(UserWarning):
34+
"""Warn that data will be lost."""
35+
36+
37+
def as_geom(data: dict) -> dict:
38+
"""Extract the geometry from GeoJSON and validate.
39+
40+
Parameters:
41+
data: GeoJSON geometry, Feature, or FeatureClass.
42+
43+
Returns:
44+
GeoJSON geometry.
45+
46+
Raises:
47+
GeoJSONException: If data is not valid GeoJSON geometry, Feature,
6848
or FeatureClass.
69-
'''
70-
if set(('coordinates', 'type')).issubset(set(data.keys())):
71-
# already a geom
72-
ret = data
73-
else:
49+
DataLossWarning: If more than one Feature is in a FeatureClass.
50+
"""
51+
geom = geom_from_geojson(data)
52+
validate_geom(geom)
53+
return geom
54+
55+
56+
def as_polygon(data: dict) -> dict:
57+
geom = as_geom(data)
58+
geom_type = geom['type']
59+
if geom_type.lower() != 'polygon':
60+
raise WrongTypeException(
61+
f'Invalid geometry type: {geom_type} is not Polygon.')
62+
return geom
63+
64+
65+
def geom_from_geojson(data: dict) -> dict:
66+
"""Get GeoJSON geometry from GeoJSON.
67+
68+
Parameters:
69+
data: GeoJSON geometry, Feature, or FeatureClass.
70+
71+
Returns:
72+
GeoJSON geometry.
73+
74+
Raises:
75+
GeoJSONException: If data is not valid GeoJSON geometry
76+
"""
77+
if set(('coordinates', 'type')).issubset(set(data.keys())):
78+
# already a geom
79+
ret = data
80+
else:
81+
try:
82+
# feature
83+
ret = as_geom(data["geometry"])
84+
except KeyError:
7485
try:
75-
# feature
76-
ret = cls._geom_from_dict(data["geometry"])
86+
# featureclass
87+
features = data['features']
7788
except KeyError:
78-
try:
79-
# featureclass
80-
features = data['features']
81-
except KeyError:
82-
raise GeoJSONException('Invalid GeoJSON')
83-
84-
ret = cls._geom_from_dict(features[0])
85-
return ret
86-
87-
def __eq__(self, other):
88-
def _tuple_to_list(obj):
89-
return json.loads(
90-
json.dumps(obj).replace(")", "]").replace("(", "["))
91-
92-
return _tuple_to_list(self) == _tuple_to_list(other)
93-
94-
def _validate(self):
95-
'''
96-
Raises:
97-
GeoJSONException: If data is not valid GeoJSON geometry, Feature,
98-
or FeatureClass.
99-
WrongTypeException: If geometry coordinates do not fit type.
100-
'''
101-
data = self
102-
if 'type' not in data:
103-
raise GeoJSONException(
104-
'Missing \'type\' key.')
105-
elif 'coordinates' not in data:
106-
raise GeoJSONException(
107-
'Missing \'coordinates\' key.')
108-
109-
try:
110-
sgeom.shape(data)
111-
except ValueError as e:
112-
# invalid type or coordinates
113-
raise GeoJSONException(e)
114-
except TypeError:
115-
# wrong type
116-
raise WrongTypeException('Geometry coordinates do not fit type')
117-
118-
@property
119-
def type(self):
120-
return self['type']
121-
122-
123-
class Polygon(Geometry):
124-
def __init__(
125-
self,
126-
data: dict
127-
):
128-
"""
129-
Initialize GeoJSON.
130-
131-
If data represents a GeoJSON FeatureClass, the geometry of the first
132-
Feature is used.
133-
134-
Parameters:
135-
data: Feature, FeatureClass, or geometry GeoJSON description.
136-
137-
138-
Raises:
139-
WrongTypeException: If data geometry type is not Polygon.
140-
"""
141-
super().__init__(data)
142-
if self.type.lower() != 'polygon':
143-
raise WrongTypeException(
144-
f'Invalid geometry type: {self.type} is not Polygon.')
89+
raise GeoJSONException('Invalid GeoJSON: {data}')
90+
91+
if len(features) > 1:
92+
raise DataLossWarning(
93+
'FeatureClass has more than one Feature, using only first'
94+
' feature.')
95+
96+
ret = as_geom(features[0])
97+
return ret
98+
99+
100+
def validate_geom(data: dict):
101+
"""Validate GeoJSON geometry.
102+
103+
Parameters:
104+
data: GeoJSON geometry.
105+
106+
Raises:
107+
GeoJSONException: If data is not a valid GeoJSON geometry.
108+
"""
109+
if 'type' not in data:
110+
raise GeoJSONException(
111+
'Missing \'type\' key.')
112+
elif 'coordinates' not in data:
113+
raise GeoJSONException(
114+
'Missing \'coordinates\' key.')
115+
116+
try:
117+
sgeom.shape(data)
118+
except ValueError as e:
119+
# invalid type or coordinates
120+
raise GeoJSONException(e)
121+
except TypeError:
122+
# wrong type
123+
raise GeoJSONException('Geometry coordinates do not fit type')

planet/scripts/cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ def read_file_geojson(ctx, param, value):
236236
return value
237237

238238
json_value = read_file_json(ctx, param, value)
239-
geo = planet.Geometry(json_value)
239+
geo = planet.geojson.as_geom(json_value)
240240
return geo
241241

242242

@@ -299,7 +299,7 @@ async def create(ctx, name, ids, bundle, item_type, email, cloudconfig, clip,
299299
raise click.BadParameter("Specify only one of '--clip' or '--tools'")
300300
elif clip:
301301
try:
302-
clip = planet.geojson.Polygon(clip)
302+
clip = planet.geojson.as_polygon(clip)
303303
except planet.geojson.GeoJSONException as e:
304304
raise click.BadParameter(e)
305305

tests/unit/test_cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,10 @@ def test_id(order_details):
183183
return order_details['products'][0]['item_ids'][0]
184184

185185

186-
def test_cli_read_file_geojson(clipaoi):
186+
def test_cli_read_file_geojson(clipaoi, geom_geojson):
187187
with open(clipaoi, 'r') as cfile:
188188
res = planet.scripts.cli.read_file_geojson({}, 'clip', cfile)
189-
assert type(res) == planet.Geometry
189+
assert res == geom_geojson
190190

191191

192192
@pytest.fixture

0 commit comments

Comments
 (0)