From b6966d3db4b5928126c9df9d6188d2f72af27790 Mon Sep 17 00:00:00 2001 From: romavlasov Date: Mon, 10 Feb 2020 18:17:25 +0300 Subject: [PATCH 1/5] Add support of Maps Static API --- README.md | 2 + googlemaps/client.py | 12 ++- googlemaps/convert.py | 78 ++++++++++++++++ googlemaps/maps.py | 158 ++++++++++++++++++++++++++++++++ googlemaps/test/test_convert.py | 25 +++++ googlemaps/test/test_maps.py | 63 +++++++++++++ 6 files changed, 336 insertions(+), 2 deletions(-) create mode 100644 googlemaps/maps.py create mode 100644 googlemaps/test/test_maps.py diff --git a/README.md b/README.md index cb222b68..9f221f64 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ APIs: - Time Zone API - Roads API - Places API + - Maps Static API Keep in mind that the same [terms and conditions](https://developers.google.com/maps/terms) apply to usage of the APIs when they're accessed through this library. @@ -127,6 +128,7 @@ are returned from the API. - [Time Zone API](https://developers.google.com/maps/documentation/timezone/) - [Roads API](https://developers.google.com/maps/documentation/roads/) - [Places API](https://developers.google.com/places/) +- [Maps Static API](https://developers.google.com/maps/documentation/maps-static/) ### Support - [Report an issue](https://github.com/googlemaps/google-maps-services-python/issues) diff --git a/googlemaps/client.py b/googlemaps/client.py index d1136ce4..996f61cf 100644 --- a/googlemaps/client.py +++ b/googlemaps/client.py @@ -390,6 +390,7 @@ def _generate_auth_url(self, path, params, accepts_clientid): from googlemaps.places import places_photo from googlemaps.places import places_autocomplete from googlemaps.places import places_autocomplete_query +from googlemaps.maps import maps_download def make_api_method(func): @@ -433,6 +434,7 @@ def wrapper(*args, **kwargs): Client.places_photo = make_api_method(places_photo) Client.places_autocomplete = make_api_method(places_autocomplete) Client.places_autocomplete_query = make_api_method(places_autocomplete_query) +Client.maps_download = make_api_method(maps_download) def sign_hmac(secret, payload): @@ -463,11 +465,17 @@ def urlencode_params(params): """ # urlencode does not handle unicode strings in Python 2. # Firstly, normalize the values so they get encoded correctly. - params = [(key, normalize_for_urlencode(val)) for key, val in params] + extended = [] + for key, val in params: + if isinstance(val, list): + for v in val: + extended.append((key, normalize_for_urlencode(v))) + else: + extended.append((key, normalize_for_urlencode(val))) # Secondly, unquote unreserved chars which are incorrectly quoted # by urllib.urlencode, causing invalid auth signatures. See GH #72 # for more info. - return requests.utils.unquote_unreserved(urlencode(params)) + return requests.utils.unquote_unreserved(urlencode(extended)) try: diff --git a/googlemaps/convert.py b/googlemaps/convert.py index b5823f67..3411f3d8 100644 --- a/googlemaps/convert.py +++ b/googlemaps/convert.py @@ -280,6 +280,84 @@ def bounds(arg): "but got %s" % type(arg).__name__) +def markers(arg): + """Converts a dict of marker descriptors to the format expected by + the Google Maps server. + + For example: + p = { + "size": "small", + "color": "blue", + "label": "S", + "locations": [ + {"lat" : -33.867486, "lng" : 151.206990}, + "Sydney" + ] + } + convert.markers(p) + # 'size:small|color:blue|label:S|-33.867486,151.20699|Sydney' + + :param arg: The marker descriptors. + :type arg: dict + + :rtype: string + """ + if isinstance(arg, dict): + params = [] + + for descriptor in ['size', 'color', 'label']: + if descriptor in arg: + params.append("%s:%s" % (descriptor, arg[descriptor])) + + if 'locations' in arg: + params.append(location_list(arg['locations'])) + + return join_list('|', params) + + raise TypeError( + "Expected a markers dict, " + "but got %s" % type(arg).__name__) + + +def paths(arg): + """Converts a dict of path parameters to the format expected by + the Google Maps server. + + For example: + p = { + "weight": 5, + "color": "red", + "points": [ + {"lat" : 40.737102, "lng" : -73.990318}, + {"lat" : 40.755823, "lng" : -73.986397}, + ] + } + convert.paths(p) + # 'weight:5|color:red|40.737102,-73.990318|40.755823,-73.986397' + + :param arg: The path parameters. + :type arg: dict + + :rtype: string + """ + + if isinstance(arg, dict): + params = [] + + for parameter in ['weight', 'color', 'fillcolor', 'geodesic']: + if parameter in arg: + params.append("%s:%s" % (parameter, arg[parameter])) + + if 'points' in arg: + params.append(location_list(arg['points'])) + + return join_list('|', params) + + raise TypeError( + "Expected a path dict, " + "but got %s" % type(arg).__name__) + + def decode_polyline(polyline): """Decodes a Polyline string into a list of lat/lng dicts. diff --git a/googlemaps/maps.py b/googlemaps/maps.py new file mode 100644 index 00000000..0afbd8da --- /dev/null +++ b/googlemaps/maps.py @@ -0,0 +1,158 @@ +# +# Copyright 2020 Google Inc. All rights reserved. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# + +"""Performs requests to the Google Maps Static API.""" + +from googlemaps import convert + + +MAPS_IMAGE_FORMATS = set( + ['png8', 'png', 'png32', 'gif', 'jpg', 'jpg-baseline'] +) + +MAPS_MAP_TYPES = set( + ['roadmap', 'satellite', 'terrain', 'hybrid'] +) + +def maps_download(client, size, + center=None, zoom=None, scale=None, + format=None, maptype=None, language=None, region=None, + markers=None, path=None, visible=None, style=None): + """ + Downloads a map image from the Maps Static API. + + See https://developers.google.com/maps/documentation/maps-static/intro + for more info, including more detail for each parameter below. + + :param size: Defines the rectangular dimensions of the map image. + :type param: list + + :param center: Defines the center of the map, equidistant from all edges + of the map. + :type center: dict or list or string + + :param zoom: Defines the zoom level of the map, which determines the + magnification level of the map. + :type zoom: int + + :param scale: Affects the number of pixels that are returned. + :type scale: int + + :param format: Defines the format of the resulting image. + :type format: string + + :param maptype: defines the type of map to construct. There are several + possible maptype values, including roadmap, satellite, hybrid, + and terrain. + :type maptype: string + + :param language: defines the language to use for display of labels on + map tiles. + :type language: string + + :param region: defines the appropriate borders to display, based on + geo-political sensitivities. + :type region: string + + :param markers: define one or more markers to attach to the image at + specified locations. + :type markers: list of dict + + :param path: defines a single path of two or more connected points to + overlay on the image at specified locations. + :type path: dict + + :param visible: specifies one or more locations that should remain visible + on the map, though no markers or other indicators will be displayed. + :type visible: list of dict + + :param style: defines a custom style to alter the presentation of + a specific feature (roads, parks, and other features) of the map. + :type style: list of dict + + :rtype: iterator containing the raw image data, which typically can be + used to save an image file locally. For example: + + ``` + f = open(local_filename, 'wb') + for chunk in client.maps_download(size=(400, 400), + center=(52.520103, 13.404871), + zoom=15): + if chunk: + f.write(chunk) + f.close() + ``` + """ + + params = {} + + if len(size) != 2: + raise ValueError("Invalid size") + + params["size"] = convert.join_list("x", map(str, size)) + + if not markers: + if not (center or zoom is not None): + raise ValueError( + "both center and zoom are requered" + "when markers is not specifed" + ) + + if center: + params["center"] = convert.latlng(center) + + if zoom is not None: + params["zoom"] = zoom + + if scale is not None: + params["scale"] = scale + + if format: + if format not in MAPS_IMAGE_FORMATS: + raise ValueError("Invalid image format") + params['format'] = format + + if maptype: + if maptype not in MAPS_MAP_TYPES: + raise ValueError("Invalid maptype") + params["maptype"] = maptype + + if language: + params["language"] = language + + if region: + params["region"] = region + + if markers: + params["markers"] = [convert.markers(m) for m in markers] + + if path: + params["path"] = convert.paths(path) + + if visible: + params["visible"] = convert.location_list(visible) + + if style: + params["style"] = convert.components(style) + + response = client._request( + "/maps/api/staticmap", + params, + extract_body=lambda response: response, + requests_kwargs={"stream": True}, + ) + return response.iter_content() diff --git a/googlemaps/test/test_convert.py b/googlemaps/test/test_convert.py index 9cbde9ea..118d2606 100644 --- a/googlemaps/test/test_convert.py +++ b/googlemaps/test/test_convert.py @@ -113,6 +113,31 @@ def test_bounds(self): with self.assertRaises(TypeError): convert.bounds("test") + def test_markers(self): + c = {"size": "small", "color": "blue", "label": "S", + "locations": [ + {"lat" : -33.867486, "lng" : 151.206990}, "Sydney" + ]} + self.assertEqual( + "size:small|color:blue|label:S|-33.867486,151.20699|Sydney", + convert.markers(c)) + + with self.assertRaises(TypeError): + convert.bounds("test") + + def test_paths(self): + c = {"weight": 5, "color": "red", + "points": [ + {"lat" : 40.737102, "lng" : -73.990318}, + {"lat" : 40.755823, "lng" : -73.986397} + ]} + self.assertEqual( + "weight:5|color:red|40.737102,-73.990318|40.755823,-73.986397", + convert.paths(c)) + + with self.assertRaises(TypeError): + convert.bounds("test") + def test_polyline_decode(self): syd_mel_route = ("rvumEis{y[`NsfA~tAbF`bEj^h{@{KlfA~eA~`AbmEghAt~D|e@j" "lRpO~yH_\\v}LjbBh~FdvCxu@`nCplDbcBf_B|wBhIfhCnqEb~D~" diff --git a/googlemaps/test/test_maps.py b/googlemaps/test/test_maps.py new file mode 100644 index 00000000..8526ff4c --- /dev/null +++ b/googlemaps/test/test_maps.py @@ -0,0 +1,63 @@ +# +# Copyright 2020 Google Inc. All rights reserved. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# + +"""Tests for the maps module.""" + +from types import GeneratorType + +import responses + +import googlemaps +import googlemaps.test as _test + + +class MapsTest(_test.TestCase): + + def setUp(self): + self.key = "AIzaasdf" + self.client = googlemaps.Client(self.key) + + @responses.activate + def test_download(self): + url = 'https://maps.googleapis.com/maps/api/staticmap' + responses.add(responses.GET, url, status=200) + + response = self.client.maps_download( + size=(400, 400), zoom=6, center=(63.259591,-144.667969), + maptype="hybrid", format="png", scale=2, visible=["Tok,AK"], + path={ + "weight": 5, "color": "red", + "points": [(62.107733,-145.541936), + 'Delta+Junction,AK'] + }, + markers=[ + {"color": "blue", "label": "S", "locations": [(62.107733,-145.541936)]}, + {"size": "tiny", "color": "green", "locations": ['Delta+Junction,AK']}, + {"size": "mid", "color": "0xFFFF00", "label": "C", "locations": ["Tok,AK"]} + ] + ) + + self.assertTrue(isinstance(response, GeneratorType)) + self.assertEqual(1, len(responses.calls)) + self.assertURLEqual( + '%s?center=63.259591%%2C-144.667969&format=png&maptype=hybrid&' + 'markers=color%%3Ablue%%7Clabel%%3AS%%7C62.107733%%2C-145.541936&' + 'markers=size%%3Atiny%%7Ccolor%%3Agreen%%7CDelta%%2BJunction%%2CAK&' + 'markers=size%%3Amid%%7Ccolor%%3A0xFFFF00%%7Clabel%%3AC%%7CTok%%2CAK&' + 'path=weight%%3A5%%7Ccolor%%3Ared%%7C62.107733%%2C-145.541936%%7CDelta%%2BJunction%%2CAK&' + 'scale=2&size=400x400&visible=Tok%%2CAK&zoom=6&key=%s' + % (url, self.key), responses.calls[0].request.url) From a9749f23661254655009c357b6da432e804373d6 Mon Sep 17 00:00:00 2001 From: romavlasov Date: Mon, 10 Feb 2020 18:54:14 +0300 Subject: [PATCH 2/5] fix test --- googlemaps/test/test_convert.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/googlemaps/test/test_convert.py b/googlemaps/test/test_convert.py index 118d2606..9708b629 100644 --- a/googlemaps/test/test_convert.py +++ b/googlemaps/test/test_convert.py @@ -123,7 +123,7 @@ def test_markers(self): convert.markers(c)) with self.assertRaises(TypeError): - convert.bounds("test") + convert.markers("test") def test_paths(self): c = {"weight": 5, "color": "red", @@ -136,7 +136,7 @@ def test_paths(self): convert.paths(c)) with self.assertRaises(TypeError): - convert.bounds("test") + convert.paths("test") def test_polyline_decode(self): syd_mel_route = ("rvumEis{y[`NsfA~tAbF`bEj^h{@{KlfA~eA~`AbmEghAt~D|e@j" From d26518f97553be46cec463f2fdc62683b49cab0a Mon Sep 17 00:00:00 2001 From: romavlasov Date: Mon, 10 Feb 2020 19:44:42 +0300 Subject: [PATCH 3/5] increase codecov --- googlemaps/convert.py | 12 ++++++++++++ googlemaps/maps.py | 9 ++------- googlemaps/test/test_convert.py | 8 ++++++++ googlemaps/test/test_maps.py | 12 ++++++++++++ 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/googlemaps/convert.py b/googlemaps/convert.py index 3411f3d8..56f2dc3b 100644 --- a/googlemaps/convert.py +++ b/googlemaps/convert.py @@ -280,6 +280,18 @@ def bounds(arg): "but got %s" % type(arg).__name__) +def size(arg): + if isinstance(arg, int): + return "%sx%s" % (arg, arg) + elif _is_list(arg): + return "%sx%s" % (arg[0], arg[1]) + + raise TypeError( + "Expected a size int or list, " + "but got %s" % type(arg).__name__) + + + def markers(arg): """Converts a dict of marker descriptors to the format expected by the Google Maps server. diff --git a/googlemaps/maps.py b/googlemaps/maps.py index 0afbd8da..badbea65 100644 --- a/googlemaps/maps.py +++ b/googlemaps/maps.py @@ -39,7 +39,7 @@ def maps_download(client, size, for more info, including more detail for each parameter below. :param size: Defines the rectangular dimensions of the map image. - :type param: list + :type param: int or list :param center: Defines the center of the map, equidistant from all edges of the map. @@ -98,12 +98,7 @@ def maps_download(client, size, ``` """ - params = {} - - if len(size) != 2: - raise ValueError("Invalid size") - - params["size"] = convert.join_list("x", map(str, size)) + params = {"size": convert.size(size)} if not markers: if not (center or zoom is not None): diff --git a/googlemaps/test/test_convert.py b/googlemaps/test/test_convert.py index 9708b629..76fec3da 100644 --- a/googlemaps/test/test_convert.py +++ b/googlemaps/test/test_convert.py @@ -113,6 +113,14 @@ def test_bounds(self): with self.assertRaises(TypeError): convert.bounds("test") + def test_size(self): + self.assertEqual("1x1", convert.size(1)) + + self.assertEqual("2x3", convert.size((2, 3))) + + with self.assertRaises(TypeError): + convert.size("test") + def test_markers(self): c = {"size": "small", "color": "blue", "label": "S", "locations": [ diff --git a/googlemaps/test/test_maps.py b/googlemaps/test/test_maps.py index 8526ff4c..ba8a525a 100644 --- a/googlemaps/test/test_maps.py +++ b/googlemaps/test/test_maps.py @@ -39,6 +39,7 @@ def test_download(self): response = self.client.maps_download( size=(400, 400), zoom=6, center=(63.259591,-144.667969), maptype="hybrid", format="png", scale=2, visible=["Tok,AK"], + path={ "weight": 5, "color": "red", "points": [(62.107733,-145.541936), @@ -61,3 +62,14 @@ def test_download(self): 'path=weight%%3A5%%7Ccolor%%3Ared%%7C62.107733%%2C-145.541936%%7CDelta%%2BJunction%%2CAK&' 'scale=2&size=400x400&visible=Tok%%2CAK&zoom=6&key=%s' % (url, self.key), responses.calls[0].request.url) + + with self.assertRaises(ValueError): + self.client.maps_download(size=(400, 400)) + + with self.assertRaises(ValueError): + self.client.maps_download(size=(400, 400), center=(63.259591,-144.667969), + zoom=6, format='test') + + with self.assertRaises(ValueError): + self.client.maps_download(size=(400, 400), center=(63.259591,-144.667969), + zoom=6, maptype='test') From 2ac8ffc53b63f8a86526671ac015a3f5fd1c6b0d Mon Sep 17 00:00:00 2001 From: romavlasov Date: Tue, 11 Feb 2020 15:36:11 +0300 Subject: [PATCH 4/5] Make marker and path args more defined --- googlemaps/client.py | 7 ++- googlemaps/convert.py | 79 ----------------------- googlemaps/maps.py | 107 ++++++++++++++++++++++++++++++-- googlemaps/test/test_convert.py | 25 -------- googlemaps/test/test_maps.py | 64 +++++++++++++++---- 5 files changed, 161 insertions(+), 121 deletions(-) diff --git a/googlemaps/client.py b/googlemaps/client.py index 996f61cf..38458936 100644 --- a/googlemaps/client.py +++ b/googlemaps/client.py @@ -467,7 +467,7 @@ def urlencode_params(params): # Firstly, normalize the values so they get encoded correctly. extended = [] for key, val in params: - if isinstance(val, list): + if isinstance(val, (list, tuple)): for v in val: extended.append((key, normalize_for_urlencode(v))) else: @@ -497,4 +497,7 @@ def normalize_for_urlencode(value): def normalize_for_urlencode(value): """(Python 3) No-op.""" # urlencode in Python 3 handles all the types we are passing it. - return value + if isinstance(value, str): + return value + + return normalize_for_urlencode(str(value)) diff --git a/googlemaps/convert.py b/googlemaps/convert.py index 56f2dc3b..602cf4d0 100644 --- a/googlemaps/convert.py +++ b/googlemaps/convert.py @@ -289,85 +289,6 @@ def size(arg): raise TypeError( "Expected a size int or list, " "but got %s" % type(arg).__name__) - - - -def markers(arg): - """Converts a dict of marker descriptors to the format expected by - the Google Maps server. - - For example: - p = { - "size": "small", - "color": "blue", - "label": "S", - "locations": [ - {"lat" : -33.867486, "lng" : 151.206990}, - "Sydney" - ] - } - convert.markers(p) - # 'size:small|color:blue|label:S|-33.867486,151.20699|Sydney' - - :param arg: The marker descriptors. - :type arg: dict - - :rtype: string - """ - if isinstance(arg, dict): - params = [] - - for descriptor in ['size', 'color', 'label']: - if descriptor in arg: - params.append("%s:%s" % (descriptor, arg[descriptor])) - - if 'locations' in arg: - params.append(location_list(arg['locations'])) - - return join_list('|', params) - - raise TypeError( - "Expected a markers dict, " - "but got %s" % type(arg).__name__) - - -def paths(arg): - """Converts a dict of path parameters to the format expected by - the Google Maps server. - - For example: - p = { - "weight": 5, - "color": "red", - "points": [ - {"lat" : 40.737102, "lng" : -73.990318}, - {"lat" : 40.755823, "lng" : -73.986397}, - ] - } - convert.paths(p) - # 'weight:5|color:red|40.737102,-73.990318|40.755823,-73.986397' - - :param arg: The path parameters. - :type arg: dict - - :rtype: string - """ - - if isinstance(arg, dict): - params = [] - - for parameter in ['weight', 'color', 'fillcolor', 'geodesic']: - if parameter in arg: - params.append("%s:%s" % (parameter, arg[parameter])) - - if 'points' in arg: - params.append(location_list(arg['points'])) - - return join_list('|', params) - - raise TypeError( - "Expected a path dict, " - "but got %s" % type(arg).__name__) def decode_polyline(polyline): diff --git a/googlemaps/maps.py b/googlemaps/maps.py index badbea65..23b66c06 100644 --- a/googlemaps/maps.py +++ b/googlemaps/maps.py @@ -28,6 +28,105 @@ ['roadmap', 'satellite', 'terrain', 'hybrid'] ) + +class StaticMapParam(object): + """Base class to handle parameters for Maps Static API.""" + + def __init__(self): + self.params = [] + + def __str__(self): + """Converts a list of parameters to the format expected by + the Google Maps server. + + :rtype: str + + """ + return convert.join_list('|', self.params) + + +class StaticMapMarker(StaticMapParam): + """Handles marker parameters for Maps Static API.""" + + def __init__(self, locations, + size=None, color=None, label=None): + """ + :param locations: Specifies the locations of the markers on + the map. + :type locations: list + + :param size: Specifies the size of the marker. + :type size: str + + :param color: Specifies a color of the marker. + :type color: str + + :param label: Specifies a single uppercase alphanumeric + character to be displaied on marker. + :type label: str + """ + + super(StaticMapMarker, self).__init__() + + if size: + self.params.append("size:%s" % size) + + if color: + self.params.append("color:%s" % color) + + if label: + if len(label) != 1 or not label.isupper() or not label.isalnum(): + raise ValueError("Invalid label") + self.params.append("label:%s" % label) + + self.params.append(convert.location_list(locations)) + + +class StaticMapPath(StaticMapParam): + """Handles path parameters for Maps Static API.""" + + def __init__(self, points, + weight=None, color=None, + fillcolor=None, geodesic=None): + """ + :param points: Specifies the point through which the path + will be built. + :type points: list + + :param weight: Specifies the thickness of the path in pixels. + :type weight: int + + :param color: Specifies a color of the path. + :type color: str + + :param fillcolor: Indicates both that the path marks off a + polygonal area and specifies the fill color to use as an + overlay within that area. + :type fillcolor: str + + :param geodesic: Indicates that the requested path should be + interpreted as a geodesic line that follows the curvature + of the earth. + :type geodesic: bool + """ + + super(StaticMapPath, self).__init__() + + if weight: + self.params.append("weight:%s" % weight) + + if color: + self.params.append("color:%s" % color) + + if fillcolor: + self.params.append("fillcolor:%s" % fillcolor) + + if geodesic: + self.params.append("geodesic:%s" % geodesic) + + self.params.append(convert.location_list(points)) + + def maps_download(client, size, center=None, zoom=None, scale=None, format=None, maptype=None, language=None, region=None, @@ -70,11 +169,11 @@ def maps_download(client, size, :param markers: define one or more markers to attach to the image at specified locations. - :type markers: list of dict + :type markers: StaticMapMarker :param path: defines a single path of two or more connected points to overlay on the image at specified locations. - :type path: dict + :type path: StaticMapPath :param visible: specifies one or more locations that should remain visible on the map, though no markers or other indicators will be displayed. @@ -133,10 +232,10 @@ def maps_download(client, size, params["region"] = region if markers: - params["markers"] = [convert.markers(m) for m in markers] + params["markers"] = markers if path: - params["path"] = convert.paths(path) + params["path"] = path if visible: params["visible"] = convert.location_list(visible) diff --git a/googlemaps/test/test_convert.py b/googlemaps/test/test_convert.py index 76fec3da..dc0fe2b1 100644 --- a/googlemaps/test/test_convert.py +++ b/googlemaps/test/test_convert.py @@ -121,31 +121,6 @@ def test_size(self): with self.assertRaises(TypeError): convert.size("test") - def test_markers(self): - c = {"size": "small", "color": "blue", "label": "S", - "locations": [ - {"lat" : -33.867486, "lng" : 151.206990}, "Sydney" - ]} - self.assertEqual( - "size:small|color:blue|label:S|-33.867486,151.20699|Sydney", - convert.markers(c)) - - with self.assertRaises(TypeError): - convert.markers("test") - - def test_paths(self): - c = {"weight": 5, "color": "red", - "points": [ - {"lat" : 40.737102, "lng" : -73.990318}, - {"lat" : 40.755823, "lng" : -73.986397} - ]} - self.assertEqual( - "weight:5|color:red|40.737102,-73.990318|40.755823,-73.986397", - convert.paths(c)) - - with self.assertRaises(TypeError): - convert.paths("test") - def test_polyline_decode(self): syd_mel_route = ("rvumEis{y[`NsfA~tAbF`bEj^h{@{KlfA~eA~`AbmEghAt~D|e@j" "lRpO~yH_\\v}LjbBh~FdvCxu@`nCplDbcBf_B|wBhIfhCnqEb~D~" diff --git a/googlemaps/test/test_maps.py b/googlemaps/test/test_maps.py index ba8a525a..cad50ab4 100644 --- a/googlemaps/test/test_maps.py +++ b/googlemaps/test/test_maps.py @@ -24,6 +24,9 @@ import googlemaps import googlemaps.test as _test +from googlemaps.maps import StaticMapMarker +from googlemaps.maps import StaticMapPath + class MapsTest(_test.TestCase): @@ -31,25 +34,64 @@ def setUp(self): self.key = "AIzaasdf" self.client = googlemaps.Client(self.key) + @responses.activate + def test_static_map_marker(self): + marker = StaticMapMarker( + locations=[{"lat": -33.867486, "lng": 151.206990}, "Sydney"], + size='small', color='blue', label="S" + ) + + self.assertEqual( + "size:small|color:blue|label:S|" + "-33.867486,151.20699|Sydney", + str(marker) + ) + + with self.assertRaises(ValueError): + StaticMapMarker(locations=["Sydney"], label="XS") + + @responses.activate + def test_static_map_path(self): + path = StaticMapPath( + points=[{"lat": -33.867486, "lng": 151.206990}, "Sydney"], + weight=5, color="red", geodesic=True, fillcolor="Red" + ) + + self.assertEqual( + "weight:5|color:red|fillcolor:Red|""geodesic:True|" + "-33.867486,151.20699|Sydney", + str(path) + ) + @responses.activate def test_download(self): url = 'https://maps.googleapis.com/maps/api/staticmap' responses.add(responses.GET, url, status=200) + path = StaticMapPath( + points=[(62.107733,-145.541936), 'Delta+Junction,AK'], + weight=5, color="red" + ) + + m1 = StaticMapMarker( + locations=[(62.107733,-145.541936)], + color="blue", label="S" + ) + + m2 = StaticMapMarker( + locations=['Delta+Junction,AK'], + size="tiny", color="green" + ) + + m3 = StaticMapMarker( + locations=["Tok,AK"], + size="mid", color="0xFFFF00", label="C" + ) + response = self.client.maps_download( size=(400, 400), zoom=6, center=(63.259591,-144.667969), maptype="hybrid", format="png", scale=2, visible=["Tok,AK"], - - path={ - "weight": 5, "color": "red", - "points": [(62.107733,-145.541936), - 'Delta+Junction,AK'] - }, - markers=[ - {"color": "blue", "label": "S", "locations": [(62.107733,-145.541936)]}, - {"size": "tiny", "color": "green", "locations": ['Delta+Junction,AK']}, - {"size": "mid", "color": "0xFFFF00", "label": "C", "locations": ["Tok,AK"]} - ] + path=path, markers=[m1, m2, m3] ) self.assertTrue(isinstance(response, GeneratorType)) From 171848e79e7bd2d989f87f13bfa8c2af479b7c9b Mon Sep 17 00:00:00 2001 From: romavlasov Date: Tue, 11 Feb 2020 20:17:01 +0300 Subject: [PATCH 5/5] rename maps_download -> static_map --- googlemaps/client.py | 4 ++-- googlemaps/maps.py | 16 ++++++++-------- googlemaps/test/test_maps.py | 12 ++++++------ 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/googlemaps/client.py b/googlemaps/client.py index 38458936..ae2b4891 100644 --- a/googlemaps/client.py +++ b/googlemaps/client.py @@ -390,7 +390,7 @@ def _generate_auth_url(self, path, params, accepts_clientid): from googlemaps.places import places_photo from googlemaps.places import places_autocomplete from googlemaps.places import places_autocomplete_query -from googlemaps.maps import maps_download +from googlemaps.maps import static_map def make_api_method(func): @@ -434,7 +434,7 @@ def wrapper(*args, **kwargs): Client.places_photo = make_api_method(places_photo) Client.places_autocomplete = make_api_method(places_autocomplete) Client.places_autocomplete_query = make_api_method(places_autocomplete_query) -Client.maps_download = make_api_method(maps_download) +Client.static_map = make_api_method(static_map) def sign_hmac(secret, payload): diff --git a/googlemaps/maps.py b/googlemaps/maps.py index 23b66c06..eedcc422 100644 --- a/googlemaps/maps.py +++ b/googlemaps/maps.py @@ -127,10 +127,10 @@ def __init__(self, points, self.params.append(convert.location_list(points)) -def maps_download(client, size, - center=None, zoom=None, scale=None, - format=None, maptype=None, language=None, region=None, - markers=None, path=None, visible=None, style=None): +def static_map(client, size, + center=None, zoom=None, scale=None, + format=None, maptype=None, language=None, region=None, + markers=None, path=None, visible=None, style=None): """ Downloads a map image from the Maps Static API. @@ -188,9 +188,9 @@ def maps_download(client, size, ``` f = open(local_filename, 'wb') - for chunk in client.maps_download(size=(400, 400), - center=(52.520103, 13.404871), - zoom=15): + for chunk in client.static_map(size=(400, 400), + center=(52.520103, 13.404871), + zoom=15): if chunk: f.write(chunk) f.close() @@ -202,7 +202,7 @@ def maps_download(client, size, if not markers: if not (center or zoom is not None): raise ValueError( - "both center and zoom are requered" + "both center and zoom are required" "when markers is not specifed" ) diff --git a/googlemaps/test/test_maps.py b/googlemaps/test/test_maps.py index cad50ab4..a20b84fe 100644 --- a/googlemaps/test/test_maps.py +++ b/googlemaps/test/test_maps.py @@ -88,7 +88,7 @@ def test_download(self): size="mid", color="0xFFFF00", label="C" ) - response = self.client.maps_download( + response = self.client.static_map( size=(400, 400), zoom=6, center=(63.259591,-144.667969), maptype="hybrid", format="png", scale=2, visible=["Tok,AK"], path=path, markers=[m1, m2, m3] @@ -106,12 +106,12 @@ def test_download(self): % (url, self.key), responses.calls[0].request.url) with self.assertRaises(ValueError): - self.client.maps_download(size=(400, 400)) + self.client.static_map(size=(400, 400)) with self.assertRaises(ValueError): - self.client.maps_download(size=(400, 400), center=(63.259591,-144.667969), - zoom=6, format='test') + self.client.static_map(size=(400, 400), center=(63.259591,-144.667969), + zoom=6, format='test') with self.assertRaises(ValueError): - self.client.maps_download(size=(400, 400), center=(63.259591,-144.667969), - zoom=6, maptype='test') + self.client.static_map(size=(400, 400), center=(63.259591,-144.667969), + zoom=6, maptype='test')