Source code for bingmaps.urls.elevations_build_urls

from marshmallow import fields, Schema, post_dump, validate


[docs]class ElevationsUrl(object): """This class helps in building a url for elevations API service. :ivar data: Data required for building up the URL :ivar protocol: http protocol for the url :ivar schema: Elevations schema to which the data will be dumped All the URL values are retrieved from the schema. Example: :: >>> data = {'method': 'Polyline', ... 'points': [35.89431, ... -110.72522, ... 35.89393, ... -110.72578], ... 'samples': 10, ... 'key': 'abs'} >>> url = ElevationsUrl(data, 'http', Polyline()) >>> url.main_url 'dev.virtualearth.net' >>> url.protocol 'http:/' >>> url.resourcePath >>> url.restApi 'Elevation' >>> url.rest 'REST' >>> url.version 'v1' >>> url.query 'Polyline?points=35.89431,-110.72522,35.89393,-110.72578&h\ eights=sealevel&samples=10&key=abs' """ def __init__(self, data, protocol, schema): self.data = data self.http_protocol = protocol self.schema_dict = self.schema_values(schema) def schema_values(self, schema): is_valid_schema = schema.validate(self.data) if bool(is_valid_schema): raise KeyError(is_valid_schema) else: return schema.dump(self.data).data @property def protocol(self): """This property helps in returning the http protocol to be used as part of the URL. :ivar http_protocol: The http protocol passed in (http/https) :getter: Returns a string relevant to the http protocol - http: ``http:/`` - https: ``https:/`` :type: string """ if self.http_protocol == 'http': return 'http:/' else: return 'https:/' @property def main_url(self): """This property helps in returning the main URL used in bingmaps rest services :getter: Returns a URL - ``dev.virtualearth.net`` :type: string """ return 'dev.virtualearth.net' @property def rest(self): """This property make the URL accessible for REST services. :getter: Returns a string saying that the URL is a REST service URL - ``REST`` :type: string """ return 'REST' @property def version(self): """This property gives the version of the Bing Maps REST services :getter: Returns a string of Bing Maps REST services version - ``v1`` for Elevations services :type: string """ if 'version' in self.schema_dict: return self.schema_dict['version'] else: return None @property def restApi(self): """This property gives a part of the URL that identifies the REST API :getter: Returns a part of the URL that identifies the REST API - ``Elevations`` for Elevations services :type: string """ if 'restApi' in self.schema_dict: return self.schema_dict['restApi'] else: return None @property def resourcePath(self): """This property gives a part of the URL that specifies a resource such as an address or landmark. :getter: Returns a string that identifies the resource path such as address or landmark - ``None`` for Elevations services :type: string """ if 'resourcePath' in self.schema_dict: return self.schema_dict['resourcePath'] else: return None @property def query(self): """This property helps in retrieving the query part of the URL :getter: Returns a part of the URL which consist of all the query parameters. :type: string """ return self.schema_dict['query']
[docs]class Elevations(Schema): """Main class for Elevations API schema Data Fields: :ivar version: A string containing v and an integer that specifies the version of the Bing Maps REST Services. - default: v1 :ivar restApi: A part of the URL path that identifies the REST API. - default: 'Elevation' (for Elevations API services) :ivar resourcePath: A part of the URL path that specifies a resource, such as an address or landmark. This schema helps in creating the main parameters of all types of elevations API based services (List, Polyline, SeaLevel, Bounds). The above mentioned data fields make up the main parameters of the url. Example: The below example can show you a typical example for how the main URL parameters can be passed in as a dictionary :: >>> data = {'version': 'v1', ... 'restApi': 'Elevation', ... 'resourcePath': ''} When you dump an empty dictionary, the class helps you in filling the dictionary with default values. You can see the same behaviour in the below example: :: >>> data = {} >>> schema = Elevations() >>> schema.dump(data).data OrderedDict([('version', 'v1'), ('restApi', 'Elevation')]) .. note:: Elevations class is common for all the elevations based services with the same default data. """ version = fields.Constant( 'v1' ) restApi = fields.Constant( 'Elevation' ) resourcePath = fields.Str() class Meta: """Meta class helps in ordering all the fields in the specified order """ fields = ('version', 'restApi', 'resourcePath') ordered = True
[docs]class Coordinates(Elevations, Schema): """Inherited from :class:`Elevations` Schema for query parameters in which all the fields will be in a ordered way. All the fields will be dumped in the same order as mentioned in the schema. Data Fields for the schema (taken from https://msdn.microsoft.com/en-us/library/jj158961.aspx): :ivar method[Required]: A method for calculating elevations (ex. List/Polyline/SeaLevel/Bounds) - REQUIRED field - 'List' [default]: Use this for returning elevations for a given pair of coordinates. :ivar points[Required]: A set of coordinates on the Earth to use in elevation calculations. The exact use of these points depends on the type of elevation request. A set of latitude and longitude values in WGS84 decimal degrees. If you are requesting elevations or elevation offsets for a set of points, the maximum number of points is 1024. Points should be given as ``lat1,long1,lat2,long2,latn,longn`` - REQUIRED field :ivar heights[Optional]: A string that specifies which sea level model to use to calculate elevation. One of the following values: - sealevel [default]: Use the geoid Earth model (EGM2008 2.5’). - ellipsoid: Use the ellipsoid Earth model (WGS84). :ivar o[Optional]: A string specifying the output as JSON or xml. :ivar key[Required]: Bing maps key - REQUIRED field This schema helps in serializing the data. Post-Dump: After dumping the data, build_query_string builds up the queryParameters string. The final value after dumping the data would be a string. Example: :: >>> data = {'method': 'List', ... 'points': [15.5467, 34.5676], ... 'key': 'abs'} >>> schema = Coordinates() >>> schema.dump(data).data OrderedDict([('version', 'v1'), ('restApi', 'Elevation'), ('query\ ', 'List?points=15.5467,34.5676&heights=sealevel&key=abs')]) """ method = fields.Str( required=True, validate=validate.Equal( 'List', error='The method should be List' ), error_messages={'required': 'method for calculating elevations should' 'be specified'} ) points = fields.List( fields.Float, validate=validate.Length( min=2, error='Both latitude and longitude should be entered' ), required=True, error_messages={'required': 'Latitudes, Longitudes not specified'} ) heights = fields.Str( default='sealevel' ) o = fields.Str() key = fields.Str( required=True, error_messages={'required': 'Need Bing maps key'} ) class Meta: fields = ('version', 'restApi', 'resourcePath', 'method', 'points', 'heights', 'o', 'key') ordered = True @post_dump
[docs] def build_query_string(self, data): """This method occurs after dumping the data into the class. Args: data (dict): dictionary of all the query values Returns: data (dict): ordered dict of all the values """ query = [] keys_to_be_removed = [] for key, value in data.items(): if key not in ['version', 'restApi', 'resourcePath']: if not key == 'method': if key == 'points': value = ','.join(str(val) for val in value) keys_to_be_removed.append(key) query.append('{0}={1}'.format(key, value)) keys_to_be_removed.append(key) keys_to_be_removed.append(key) querystring = '&'.join(query) data['query'] = '{0}?{1}'.format(data['method'], querystring) for k in list(set(keys_to_be_removed)): del data[k] return data
[docs]class Polyline(Elevations, Schema): """Inherited from :class:`Elevations` Schema for query parameters in which all the fields will be in a ordered way. All the fields will be dumped in the same order as mentioned in the schema. Data Fields for the schema (taken from https://msdn.microsoft.com/en-us/library/jj158961.aspx): :ivar method[Required]: A method for calculating elevations (ex. List/Polyline/SeaLevel/Bounds) - REQUIRED field - 'Polyline' [default]: Use this for returning elevations for a given pair of coordinates. :ivar points[Required]: A set of coordinates on the Earth to use in elevation calculations. The exact use of these points depends on the type of elevation request. A set of latitude and longitude values in WGS84 decimal degrees. If you are requesting elevations or elevation offsets for a set of points, the maximum number of points is 1024. Points should be at least 2 pairs of latitudes and longitudes for Polyline method - It should be a minimum total of 4 points for Polyline method. Points should be given as ``lat1,long1,lat2,long2,latn,longn`` :ivar heights[Optional]: A string that specifies which sea level model to use to calculate elevation. One of the following values: - sealevel [default]: Use the geoid Earth model (EGM2008 2.5’). - ellipsoid: Use the ellipsoid Earth model (WGS84). :ivar samples[Required]: Specifies the number of equally-spaced elevation values to provide along a polyline path. A positive integer. The maximum number of samples is 1024. :ivar o[Optional]: A string specifying the output as JSON or xml. :ivar key[Required]: Bing maps key - REQUIRED field This schema helps in serializing the data. Post-Dump: After dumping the data, build_query_string builds up the queryParameters string. The final value after dumping the data would be a string. Example: :: >>> data = {'method': 'Polyline', ... 'points': [35.89431, -110.72522, 35.89393, -110.72578], ... 'samples': 10, ... 'key': 'abs'} >>> schema = Polyline() >>> schema.dump(data).data OrderedDict([('version', 'v1'), ('restApi', 'Elevation'), ('query\ ', 'Polyline?points=35.89431,-110.72522,35.89393,-110.72578&heights=sealevel&\ samples=10&key=abs')]) """ method = fields.Str( required=True, validate=validate.Equal( 'Polyline', error='The method should be Polyline' ), error_messages={'required': 'method for calculating elevations should' 'be specified'} ) points = fields.List( fields.Float, validate=validate.Length( min=4, error='At least 2 locations should be provided' ), required=True, error_messages={'required': 'Latitudes, Longitudes not specified'} ) heights = fields.Str( default='sealevel' ) samples = fields.Int( required=True, error_messages={'required': 'need a samples value'} ) o = fields.Str() key = fields.Str( required=True, error_messages={'required': 'Need Bing maps key'} ) class Meta: fields = ('version', 'restApi', 'resourcePath', 'method', 'points', 'heights', 'samples', 'o', 'key') ordered = True @post_dump
[docs] def build_query_string(self, data): """This method occurs after dumping the data into the class. Args: data (dict): dictionary of all the query values Returns: data (dict): ordered dict of all the values """ query = [] keys_to_be_removed = [] for key, value in data.items(): if key not in ['version', 'restApi', 'resourcePath']: if not key == 'method': if key == 'points': value = ','.join(str(val) for val in value) keys_to_be_removed.append(key) query.append('{0}={1}'.format(key, value)) keys_to_be_removed.append(key) keys_to_be_removed.append(key) querystring = '&'.join(query) data['query'] = '{0}?{1}'.format(data['method'], querystring) for k in list(set(keys_to_be_removed)): del data[k] return data
[docs]class Offset(Elevations, Schema): """Inherited from :class:`Elevations` Schema for query parameters in which all the fields will be in a ordered way. All the fields will be dumped in the same order as mentioned in the schema. Data Fields for the schema (taken from https://msdn.microsoft.com/en-us/library/jj158961.aspx: :ivar method[Required]: A method for calculating elevations (ex. List/Polyline/SeaLevel/Bounds) - REQUIRED field - 'SeaLevel' [default]: Use this for returning elevations for a given pair of coordinates. :ivar points[Required]: A set of coordinates on the Earth to use in elevation calculations. The exact use of these points depends on the type of elevation request. A set of latitude and longitude values in WGS84 decimal degrees. If you are requesting elevations or elevation offsets for a set of points, the maximum number of points is 1024. Points should be given as ``lat1,long1,lat2,long2,latn,longn`` - REQUIRED field :ivar o[Optional]: A string specifying the output as JSON or xml. :ivar key[Required: Bing maps key - REQUIRED field This schema helps in serializing the data. Post-Dump: After dumping the data, build_query_string builds up the queryParameters string. The final value after dumping the data would be a string. Example: :: >>> data = {'method': 'SeaLevel', ... 'points': [15.5467, 34.5676], ... 'key': 'abs'} >>> schema = Offset() >>> schema.dump(data).data OrderedDict([('version', 'v1'), ('restApi', 'Elevation'), ('query\ ', 'SeaLevel?points=15.5467,34.5676&key=abs')]) """ method = fields.Str( required=True, validate=validate.Equal( 'SeaLevel', error='The method should be SeaLevel' ), error_messages={'required': 'method for calculating elevations should' 'be specified'} ) points = fields.List( fields.Float, validate=validate.Length( min=2, error='Both latitude and longitude should be entered' ), required=True, error_messages={'required': 'Latitudes, Longitudes not specified'} ) o = fields.Str() key = fields.Str( required=True, error_messages={'required': 'Need Bing maps key'} ) class Meta: fields = ('version', 'restApi', 'resourcePath', 'method', 'points', 'o', 'key') ordered = True @post_dump
[docs] def build_query_string(self, data): """This method occurs after dumping the data into the class. Args: data (dict): dictionary of all the query values Returns: data (dict): ordered dict of all the values """ query = [] keys_to_be_removed = [] for key, value in data.items(): if key not in ['version', 'restApi', 'resourcePath']: if not key == 'method': if key == 'points': value = ','.join(str(val) for val in value) keys_to_be_removed.append(key) query.append('{0}={1}'.format(key, value)) keys_to_be_removed.append(key) keys_to_be_removed.append(key) querystring = '&'.join(query) data['query'] = '{0}?{1}'.format(data['method'], querystring) for k in list(set(keys_to_be_removed)): del data[k] return data
[docs]class BoundingBox(Elevations, Schema): """Inherited from :class:`Elevations` Schema for query parameters in which all the fields will be in a ordered way. All the fields will be dumped in the same order as mentioned in the schema. Data Fields for the schema (taken from https://msdn.microsoft.com/en-us/library/jj158961.aspx: :ivar method[Required]: A method for calculating elevations (ex. List/Polyline/SeaLevel/Bounds) - REQUIRED field - 'Bounds' [default]: Use this for returning elevations for a given pair of coordinates. :ivar bounds[Required]: Specifies the rectangular area over which to provide elevation values. A bounding box defined as a set of WGS84 latitudes and longitudes in the following order: - south latitude, west longitude, north latitude, east longitude - REQUIRED field :ivar rows,cols[Required]: Specifies the number of rows and columns to use to divide the bounding box area into a grid. The rows and columns that define the bounding box each count as two (2) of the rows and columns. Elevation values are returned for all vertices of the grid. Integers with a value of two (2) or greater. The number of rows and columns can define a maximum of 1024 locations (rows * cols <= 1024). :ivar heights[Optional]: A string that specifies which sea level model to use to calculate elevation. One of the following values: - sealevel [default]: Use the geoid Earth model (EGM2008 2.5’). - ellipsoid: Use the ellipsoid Earth model (WGS84). :ivar o[Optional]: A string specifying the output as JSON or xml. :ivar key[Required]: Bing maps key This schema helps in serializing the data. Post-Dump: After dumping the data, build_query_string builds up the queryParameters string. The final value after dumping the data would be a string. Example: :: >>> data = {'method': 'Bounds', ... 'bounds': [15.5463, 34.6577, 16.4365, 35.3245], ... 'rows': 4, ... 'cols': 5, ... 'key': 'abs'} >>> schema = BoundingBox() >>> schema.dump(data).data OrderedDict([('version', 'v1'), ('restApi', 'Elevation'), ('query\ ', 'Bounds?bounds=15.5463,34.6577,16.4365,35.3245&rows=4&cols=5&heights=\ sealevel&key=abs')]) """ method = fields.Str( required=True, validate=validate.Equal( 'Bounds', error='The method should be Bounds' ), error_messages={'required': 'method for calculating elevations should' 'be specified'} ) bounds = fields.List( fields.Float, validate=validate.Length( min=4, max=4, error='All four should be entered: south latitude, west longitude,' 'north latitude and east longitude' ), required=True, error_messages={'required': 'Bounds not specified'} ) rows = fields.Int( required=True, error_messages={'required': 'Number of rows should be specified'} ) cols = fields.Int( required=True, error_messages={'required': 'Number of columns should be specified'} ) heights = fields.Str( default='sealevel' ) o = fields.Str() key = fields.Str( required=True, error_messages={'required': 'Need bing maps key'} ) class Meta: fields = ('version', 'restApi', 'resourcePath', 'method', 'bounds', 'rows', 'cols', 'heights', 'o', 'key') ordered = True @post_dump
[docs] def build_query_string(self, data): """This method occurs after dumping the data into the class. Args: data (dict): dictionary of all the query values Returns: data (dict): ordered dict of all the values """ query = [] keys_to_be_removed = [] for key, value in data.items(): if key not in ['version', 'restApi', 'resourcePath']: if not key == 'method': if key == 'bounds': value = ','.join(str(val) for val in value) keys_to_be_removed.append(key) query.append('{0}={1}'.format(key, value)) keys_to_be_removed.append(key) keys_to_be_removed.append(key) querystring = '&'.join(query) data['query'] = '{0}?{1}'.format(data['method'], querystring) for k in list(set(keys_to_be_removed)): del data[k] return data