Skip to content

Commit f94fbe0

Browse files
authored
Merge pull request sharedstreets#24 from remix/krithin/timeout-upstream-tile-requests
Add a timeout for upstream tile requests.
2 parents 8969761 + 701b90e commit f94fbe0

2 files changed

Lines changed: 30 additions & 27 deletions

File tree

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
setup(
1515
name = 'sharedstreets',
16-
version = '0.5.0',
16+
version = '0.6.0',
1717
author = 'Kevin Webb, Denis Carriere, Danny Whalen, Michal Migurski',
1818
description = 'Python implementation of SharedStreets Reference System',
1919
license = 'MIT',

sharedstreets/tile.py

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
# Used for Mercator projection and tile space
1818
OSM = ModestMaps.OpenStreetMap.Provider()
1919

20+
UPSTREAM_SHST_REQUEST_TIMEOUT_S = 20
21+
2022
class Tile:
2123
''' Container for dicts of SharedStreets geometries, intersections, references, and metadata.
2224
'''
@@ -39,7 +41,8 @@ def round_coord(float):
3941
def iter_objects(url, DataClass):
4042
''' Generate a stream of objects from the protobuf URL.
4143
'''
42-
response, position = requests.get(url), 0
44+
response = requests.get(url, timeout=UPSTREAM_SHST_REQUEST_TIMEOUT_S)
45+
position = 0
4346
logger.debug('Got {} bytes: {}'.format(len(response.content), repr(response.content[:32])))
4447

4548
if response.status_code not in range(200, 299):
@@ -66,70 +69,70 @@ def is_inside(southwest, northeast, geometry):
6669
'''
6770
lons = [geometry.lonlats[i] for i in range(0, len(geometry.lonlats), 2)]
6871
lats = [geometry.lonlats[i] for i in range(1, len(geometry.lonlats), 2)]
69-
72+
7073
if max(lons) < southwest.lon or northeast.lon < min(lons):
7174
return False
72-
75+
7376
elif max(lats) < southwest.lat or northeast.lat < min(lats):
7477
return False
75-
78+
7679
return True
7780

7881
def get_tile(zoom, x, y, data_url_template=None):
7982
''' Get a single Tile instance.
80-
83+
8184
zoom, x, y: Web mercator tile coordinates using OpenStreetMap convention.
82-
85+
8386
https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Zoom_levels
84-
87+
8588
data_url_template: RFC 6570 URI template for upstream protobuf tiles
8689
with z, x, y, and layer expressions. Default to DATA_URL_TEMPLATE.
87-
90+
8891
https://tools.ietf.org/html/rfc6570#section-2.2)
8992
'''
9093
if data_url_template is None:
9194
data_url_template = DATA_URL_TEMPLATE
92-
95+
9396
# Define lat/lon for filtered area
9497
tile_coord = ModestMaps.Core.Coordinate(y, x, zoom)
9598
data_coord = tile_coord.zoomTo(DATA_ZOOM).container()
9699
tile_sw = OSM.coordinateLocation(tile_coord.down())
97100
tile_ne = OSM.coordinateLocation(tile_coord.right())
98101
data_zxy = dict(z=int(data_coord.zoom), x=int(data_coord.column), y=int(data_coord.row))
99-
102+
100103
logger.debug((tile_coord, data_coord, tile_sw, tile_ne))
101-
104+
102105
# Filter geometries within the selected tile
103106
geom_data_url = uritemplate.expand(data_url_template, layer='geometry', **data_zxy)
104107
geometries = {geom.id: geom for geom in iter_objects(geom_data_url,
105108
data_classes['geometry']) if is_inside(tile_sw, tile_ne, geom)}
106-
109+
107110
logger.debug('{} geometries'.format(len(geometries)))
108-
111+
109112
# Get intersections attached to one of the filtered geometries
110113
inter_data_url = uritemplate.expand(data_url_template, layer='intersection', **data_zxy)
111114

112115
intersection_ids = {id for id in itertools.chain(*[(geom.fromIntersectionId,
113116
geom.toIntersectionId) for geom in geometries.values()])}
114117
intersections = {inter.id: inter for inter in iter_objects(inter_data_url,
115118
data_classes['intersection']) if inter.id in intersection_ids}
116-
119+
117120
logger.debug('{} intersections'.format(len(intersections)))
118-
121+
119122
# Get references attached to one of the filtered geometries
120123
ref_data_url = uritemplate.expand(data_url_template, layer='reference', **data_zxy)
121124
references = {ref.id: ref for ref in iter_objects(ref_data_url,
122125
data_classes['reference']) if ref.geometryId in geometries}
123-
126+
124127
logger.debug('{} references'.format(len(references)))
125-
128+
126129
# Get metadata attached to one of the filtered geometries
127130
md_data_url = uritemplate.expand(data_url_template, layer='metadata', **data_zxy)
128131
metadata = {md.geometryId: md for md in iter_objects(md_data_url,
129132
data_classes['metadata']) if md.geometryId in geometries}
130-
133+
131134
logger.debug('{} metadata'.format(len(metadata)))
132-
135+
133136
return Tile(geometries, intersections, references, metadata)
134137

135138
def geometry_feature(geometry, metadata, id_length):
@@ -181,7 +184,7 @@ def reference_feature(reference, id_length):
181184
'''
182185
'''
183186
LR0, LR1 = reference.locationReferences
184-
187+
185188
return {
186189
'role': 'SharedStreets:Reference',
187190
'id': reference.id[:id_length],
@@ -211,26 +214,26 @@ def reference_feature(reference, id_length):
211214

212215
def make_geojson(tile, id_length=32):
213216
''' Get a GeoJSON dictionary for a geographic tile.
214-
217+
215218
tile: Tile instance with lists of SharedStreets entities.
216-
219+
217220
id_length: Desired length of SharedStreets ID strings. Normally 32-char
218221
MD5 hashes, these can be truncated to conserve storage. Default 12.
219222
'''
220223
geojson = dict(type='FeatureCollection', features=[], references=[])
221-
224+
222225
for geometry in tile.geometries.values():
223226
geojson['features'].append(geometry_feature(geometry, tile.metadata[geometry.id], id_length))
224227
#break
225-
228+
226229
for intersection in tile.intersections.values():
227230
geojson['features'].append(intersection_feature(intersection, id_length))
228231
#break
229-
232+
230233
for reference in tile.references.values():
231234
geojson['references'].append(reference_feature(reference, id_length))
232235
#break
233-
236+
234237
return geojson
235238

236239
parser = argparse.ArgumentParser(description='Download a tile of SharedStreets data')

0 commit comments

Comments
 (0)