Compare commits
141 Commits
python-0.1
...
0.24.0-cli
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2687f0c73a | ||
|
|
6b117e26b1 | ||
|
|
9c428dbf31 | ||
|
|
20a610d1d8 | ||
|
|
4b599ecf78 | ||
|
|
3a240bf6ad | ||
|
|
7577936c33 | ||
|
|
193513bfea | ||
|
|
c3c28dfd5e | ||
|
|
e5d2182da3 | ||
|
|
33f23e0902 | ||
|
|
94aeceb894 | ||
|
|
e21d3e2e70 | ||
|
|
adde2d3a46 | ||
|
|
6143c04c82 | ||
|
|
3b121c8793 | ||
|
|
e70aefba1d | ||
|
|
423fe42007 | ||
|
|
5e141e3a10 | ||
|
|
50aa537a7a | ||
|
|
e25e2c26a0 | ||
|
|
8025f657b8 | ||
|
|
2a47000f32 | ||
|
|
53e9ad4d2e | ||
|
|
ea5818f08f | ||
|
|
2f8edbe5ce | ||
|
|
552a7d4886 | ||
|
|
a34da0adb5 | ||
|
|
ab5ef64e83 | ||
|
|
f0cef02dfc | ||
|
|
e78063ae75 | ||
|
|
d66804b93d | ||
|
|
6572891036 | ||
|
|
59940ea994 | ||
|
|
b9da6c9ec5 | ||
|
|
ace7683ffe | ||
|
|
6017b53ea0 | ||
|
|
e15c6127d3 | ||
|
|
4bd8726720 | ||
|
|
5d20d0bdf5 | ||
|
|
db5ead6f98 | ||
|
|
44fae489a3 | ||
|
|
71c93fe13a | ||
|
|
d9c569881a | ||
|
|
244d579f6f | ||
|
|
c90859e58b | ||
|
|
12eecc271d | ||
|
|
f216b6d922 | ||
|
|
573a304bd2 | ||
|
|
f5cbc195cc | ||
|
|
e324afd77f | ||
|
|
0196292093 | ||
|
|
f652a52a8d | ||
|
|
1c38b33501 | ||
|
|
59751d7c9c | ||
|
|
ffa1080277 | ||
|
|
b279fafbc5 | ||
|
|
07ed2a4112 | ||
|
|
da7d43cc08 | ||
|
|
39800122b2 | ||
|
|
12ac2c269d | ||
|
|
74c0bb6f26 | ||
|
|
c9d0f0447f | ||
|
|
596189185f | ||
|
|
35f743164e | ||
|
|
4308b5f351 | ||
|
|
9fb04fdc24 | ||
|
|
a2fd0bf142 | ||
|
|
6534b12606 | ||
|
|
8d9c3a4bf7 | ||
|
|
ad46de1156 | ||
|
|
97f1611d62 | ||
|
|
bc4c9fea33 | ||
|
|
177c19f935 | ||
|
|
e110ab4cc3 | ||
|
|
e646000f24 | ||
|
|
05e2cc981e | ||
|
|
cbc19b869c | ||
|
|
199788748b | ||
|
|
e3f23adfdd | ||
|
|
39dabffb85 | ||
|
|
03e1d1ca61 | ||
|
|
90d8d207eb | ||
|
|
c14fb057d3 | ||
|
|
9e247685b8 | ||
|
|
1fdb4d3b3a | ||
|
|
029541f298 | ||
|
|
45d9edbba6 | ||
|
|
39c54f3e0c | ||
|
|
54e40645fa | ||
|
|
a86b8e86f9 | ||
|
|
8674dabeb2 | ||
|
|
080a386b8f | ||
|
|
972aba6cfb | ||
|
|
9b43e8a92e | ||
|
|
4e311aef47 | ||
|
|
b65d003742 | ||
|
|
b171951bc7 | ||
|
|
462773a138 | ||
|
|
fad2f25183 | ||
|
|
2f54ef7e4e | ||
|
|
ab4d77edf2 | ||
|
|
0b12f26f47 | ||
|
|
a116aba660 | ||
|
|
29d5a332b6 | ||
|
|
b2825f46a4 | ||
|
|
a791d02dcc | ||
|
|
e2612645c3 | ||
|
|
c5fed2cc80 | ||
|
|
a1f339376e | ||
|
|
019df2b4e0 | ||
|
|
9e67beab3d | ||
|
|
5c7d1e9ac1 | ||
|
|
6e54507b5a | ||
|
|
14925ea448 | ||
|
|
26e0a5e00f | ||
|
|
a99e0cb513 | ||
|
|
1e4fef5868 | ||
|
|
3973483af2 | ||
|
|
88edad9414 | ||
|
|
88ad551e4a | ||
|
|
94eaf84f91 | ||
|
|
0df0b0d49c | ||
|
|
b260c29b8c | ||
|
|
da8aa5a8c0 | ||
|
|
423534068a | ||
|
|
6f508b550d | ||
|
|
1462f87d97 | ||
|
|
6ae8aa45fd | ||
|
|
02cb4862f9 | ||
|
|
07f00cc0ae | ||
|
|
544e0fa763 | ||
|
|
2bbd6bac91 | ||
|
|
2f8dbbb5dc | ||
|
|
3484cce88b | ||
|
|
56c90cc541 | ||
|
|
3583cc6f47 | ||
|
|
850dc09a4f | ||
|
|
876bae6b56 | ||
|
|
8f30359cc7 | ||
|
|
7775d2373d |
79
NEWS.md
79
NEWS.md
@@ -1,3 +1,82 @@
|
||||
May 7th, 2018
|
||||
=============
|
||||
* Version `0.24.0` of the client, `0.31.0` of the server, and `0.18.0` of the python library.
|
||||
* Support for TomTom routing, geocoding and isolines.
|
||||
|
||||
March 28th, 2018
|
||||
================
|
||||
* Version `0.30.5` of server side and `0.17.6` of the python library
|
||||
* All the returned polygons are now always MULTIPOLYGON #488
|
||||
|
||||
March 27th, 2018
|
||||
================
|
||||
* Version `0.17.5` of python library
|
||||
* Avoid reaching provider for empty geocodings (but still incrementing empty service use) #476
|
||||
|
||||
March 16th, 2018
|
||||
================
|
||||
* Version `0.30.3` of server side
|
||||
* Fix problem with invalid Mapbox isolines #483
|
||||
* Version `0.30.4` of server side
|
||||
* Added ST_CollectionExtract to ST_MakeValid for Mapbox isolines to avoid non-polygonal geometries #486
|
||||
|
||||
March 14th, 2018
|
||||
================
|
||||
* Version `0.17.4` of the python library
|
||||
* Fix bug with previous version when checking quotas #480
|
||||
* Version `0.17.3` of the python library
|
||||
* Fix bug with Mapbox routing not using the proper quota value #477
|
||||
|
||||
February 22th, 2018
|
||||
==================
|
||||
* Version `0.17.2` of the python library
|
||||
* Fix bug with Mapbox isolines not stopping at the seacoast #471
|
||||
|
||||
February 27th, 2018
|
||||
==================
|
||||
* Version `0.17.1` of the python library
|
||||
* Fix bug when the mapzen credentials are not in the db config and we keep getting them
|
||||
|
||||
February 22th, 2018
|
||||
==================
|
||||
* Version `0.17.0` of the python library
|
||||
* Change default provider to Mapbox
|
||||
* Remove the obligatory nature of the Mapzen configuration due to its deprecation as provider
|
||||
|
||||
February 13th, 2018
|
||||
==================
|
||||
* Version `0.16.7` of the python library
|
||||
* Pick the first result when Mapbox geocoder returns multiple results #462
|
||||
* Normalize input for Mapbox geocoder #462
|
||||
|
||||
February 12th, 2018
|
||||
==================
|
||||
* Version `0.16.6` of the python library
|
||||
* Using Mapbox permanent geocoder #455
|
||||
|
||||
February 5th, 2018
|
||||
==================
|
||||
* Version `0.16.5` of the python library
|
||||
* Fix displaced routing shape #443
|
||||
* Check for empty coordinates object before converting it to polygon
|
||||
* 422 errors that come from Mapbox now returns an empty result because is a bad input from the user data
|
||||
|
||||
February 2th, 2018
|
||||
==================
|
||||
* Version `0.16.4` of the python library
|
||||
* Create a QuotaExceededException instead of using a generic one
|
||||
* Version `0.30.2` of server side
|
||||
* Return empty value when the quota is exceeded and don't send the exception to external loggers
|
||||
to avoid noise
|
||||
|
||||
January 31th, 2018
|
||||
==================
|
||||
* Version `0.16.3` of the python library
|
||||
* Fix for Mapbox geocoder to handle empty requests and empty responses
|
||||
* Remove raising an exception when non parameters are passed to the HERE geocoder
|
||||
* Fix for HERE geocoder with non empty requests
|
||||
* Added more coverage to the google geocoder credentials parse logic
|
||||
|
||||
January 29th, 2018
|
||||
==================
|
||||
* Version `0.30.1` of server side
|
||||
|
||||
28
README.md
28
README.md
@@ -45,7 +45,7 @@ Steps to deploy a new Data Services API version :
|
||||
|
||||
```sql
|
||||
CREATE DATABASE dataservices_db ENCODING = 'UTF8' LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8';
|
||||
CREATE USER dataservices_user;
|
||||
CREATE USER geocoder_api;
|
||||
```
|
||||
|
||||
- Install needed extensions in `dataservices_db` database
|
||||
@@ -90,19 +90,23 @@ Steps to deploy a new Data Services API version :
|
||||
```
|
||||
psql -U postgres -d dataservices_db -f src/pg/test/fixtures/load_fixtures.sql
|
||||
```
|
||||
- Give permission to execute and select to the `dataservices_user` user:
|
||||
- Give permission to execute and select to the `geocoder_api` user:
|
||||
```
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;CREATE EXTENSION IF NOT EXISTS observatory VERSION 'dev'; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT SELECT ON ALL TABLES IN SCHEMA cdb_observatory TO dataservices_user; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA cdb_observatory TO dataservices_user; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT SELECT ON ALL TABLES IN SCHEMA observatory TO dataservices_user; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA observatory TO dataservices_user; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT SELECT ON ALL TABLES IN SCHEMA cdb_observatory TO geocoder_api; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA cdb_observatory TO geocoder_api; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT USAGE ON SCHEMA cdb_observatory TO geocoder_api; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT SELECT ON ALL TABLES IN SCHEMA observatory TO geocoder_api; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA observatory TO geocoder_api; COMMIT" -e
|
||||
psql -U postgres -d dataservices_db -c "BEGIN;GRANT USAGE ON SCHEMA observatory TO geocoder_api; COMMIT" -e
|
||||
```
|
||||
|
||||
### Server configuration
|
||||
|
||||
Configuration for the different services must be stored in the server database using `CDB_Conf_SetConf()`.
|
||||
|
||||
**All the configuration inside brackets [] is optional**
|
||||
|
||||
#### Redis configuration
|
||||
|
||||
If sentinel is used:
|
||||
@@ -167,6 +171,15 @@ SELECT CDB_Conf_SetConf(
|
||||
);
|
||||
```
|
||||
|
||||
#### TomTom configuration
|
||||
|
||||
```sql
|
||||
SELECT CDB_Conf_SetConf(
|
||||
'tomtom_conf',
|
||||
'{"routing": {"api_keys": ["your_api_key"], "monthly_quota": 999999}, "geocoder": {"api_keys": ["your_api_key"], "monthly_quota": 999999}, "isolines": {"api_keys": ["your_api_key"], "monthly_quota": 1500000}}'
|
||||
);
|
||||
```
|
||||
|
||||
#### Data Observatory
|
||||
|
||||
```sql
|
||||
@@ -296,3 +309,6 @@ ALTER ROLE "<USER_ROLE>" SET search_path="$user", public, cartodb, cdb_dataservi
|
||||
#### Option 2 (from builder)
|
||||
|
||||
See [the **Configuring Dataservices** documentation](http://cartodb.readthedocs.io/en/latest/operations/configure_data_services.html)
|
||||
|
||||
### Rate limits
|
||||
See [docs](https://github.com/CartoDB/dataservices-api/blob/master/doc/rate_limits.md)
|
||||
|
||||
202
client/cdb_dataservices_client--0.23.0--0.24.0.sql
Normal file
202
client/cdb_dataservices_client--0.23.0--0.24.0.sql
Normal file
@@ -0,0 +1,202 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.24.0'" to load this file. \quit
|
||||
|
||||
-- Make sure we have a sane search path to create/update the extension
|
||||
SET search_path = "$user",cartodb,public,cdb_dataservices_client;
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_tomtom_geocode_street_point (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
DECLARE
|
||||
ret Geometry;
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
SELECT cdb_dataservices_client._cdb_tomtom_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_tomtom_isochrone (source geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline AS $$
|
||||
DECLARE
|
||||
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_tomtom_isochrone(username, orgname, source, mode, range, options);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client.cdb_tomtom_isodistance (source geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline AS $$
|
||||
DECLARE
|
||||
|
||||
username text;
|
||||
orgname text;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_tomtom_isodistance(username, orgname, source, mode, range, options);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_geocode_street_point_exception_safe (searchtext text ,city text DEFAULT NULL ,state_province text DEFAULT NULL ,country text DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
DECLARE
|
||||
ret Geometry;
|
||||
username text;
|
||||
orgname text;
|
||||
_returned_sqlstate TEXT;
|
||||
_message_text TEXT;
|
||||
_pg_exception_context TEXT;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
|
||||
BEGIN
|
||||
SELECT cdb_dataservices_client._cdb_tomtom_geocode_street_point(username, orgname, searchtext, city, state_province, country) INTO ret; RETURN ret;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE,
|
||||
_message_text = MESSAGE_TEXT,
|
||||
_pg_exception_context = PG_EXCEPTION_CONTEXT;
|
||||
RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context;
|
||||
RETURN ret;
|
||||
END;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_isochrone_exception_safe (source geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline AS $$
|
||||
DECLARE
|
||||
|
||||
username text;
|
||||
orgname text;
|
||||
_returned_sqlstate TEXT;
|
||||
_message_text TEXT;
|
||||
_pg_exception_context TEXT;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
|
||||
BEGIN
|
||||
RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_tomtom_isochrone(username, orgname, source, mode, range, options);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE,
|
||||
_message_text = MESSAGE_TEXT,
|
||||
_pg_exception_context = PG_EXCEPTION_CONTEXT;
|
||||
RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context;
|
||||
|
||||
END;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_isodistance_exception_safe (source geometry(Geometry, 4326) ,mode text ,range integer[] ,options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline AS $$
|
||||
DECLARE
|
||||
|
||||
username text;
|
||||
orgname text;
|
||||
_returned_sqlstate TEXT;
|
||||
_message_text TEXT;
|
||||
_pg_exception_context TEXT;
|
||||
BEGIN
|
||||
IF session_user = 'publicuser' OR session_user ~ 'cartodb_publicuser_*' THEN
|
||||
RAISE EXCEPTION 'The api_key must be provided';
|
||||
END IF;
|
||||
SELECT u, o INTO username, orgname FROM cdb_dataservices_client._cdb_entity_config() AS (u text, o text);
|
||||
-- JSON value stored "" is taken as literal
|
||||
IF username IS NULL OR username = '' OR username = '""' THEN
|
||||
RAISE EXCEPTION 'Username is a mandatory argument, check it out';
|
||||
END IF;
|
||||
|
||||
|
||||
BEGIN
|
||||
RETURN QUERY SELECT * FROM cdb_dataservices_client._cdb_tomtom_isodistance(username, orgname, source, mode, range, options);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
GET STACKED DIAGNOSTICS _returned_sqlstate = RETURNED_SQLSTATE,
|
||||
_message_text = MESSAGE_TEXT,
|
||||
_pg_exception_context = PG_EXCEPTION_CONTEXT;
|
||||
RAISE WARNING USING ERRCODE = _returned_sqlstate, MESSAGE = _message_text, DETAIL = _pg_exception_context;
|
||||
|
||||
END;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql' SECURITY DEFINER STABLE PARALLEL UNSAFE;
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text);
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_geocode_street_point (username text, orgname text, searchtext text, city text DEFAULT NULL, state_province text DEFAULT NULL, country text DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT cdb_dataservices_server.cdb_tomtom_geocode_street_point (username, orgname, searchtext, city, state_province, country);
|
||||
|
||||
$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_isochrone (username text, orgname text, source geometry(Geometry, 4326), mode text, range integer[], options text[]);
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_isochrone (username text, orgname text, source geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone (username, orgname, source, mode, range, options);
|
||||
|
||||
$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_isodistance (username text, orgname text, source geometry(Geometry, 4326), mode text, range integer[], options text[]);
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_client._cdb_tomtom_isodistance (username text, orgname text, source geometry(Geometry, 4326), mode text, range integer[], options text[] DEFAULT ARRAY[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_client.isoline AS $$
|
||||
CONNECT cdb_dataservices_client._server_conn_str();
|
||||
|
||||
SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance (username, orgname, source, mode, range, options);
|
||||
|
||||
$$ LANGUAGE plproxy VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_tomtom_geocode_street_point(searchtext text, city text, state_province text, country text) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_tomtom_geocode_street_point_exception_safe(searchtext text, city text, state_province text, country text ) TO publicuser;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_tomtom_isochrone(source geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_tomtom_isochrone_exception_safe(source geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client.cdb_tomtom_isodistance(source geometry(Geometry, 4326), mode text, range integer[], options text[]) TO publicuser;
|
||||
GRANT EXECUTE ON FUNCTION cdb_dataservices_client._cdb_tomtom_isodistance_exception_safe(source geometry(Geometry, 4326), mode text, range integer[], options text[] ) TO publicuser;
|
||||
25
client/cdb_dataservices_client--0.24.0--0.23.0.sql
Normal file
25
client/cdb_dataservices_client--0.24.0--0.23.0.sql
Normal file
@@ -0,0 +1,25 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_client UPDATE TO '0.23.0'" to load this file. \quit
|
||||
|
||||
-- Make sure we have a sane search path to create/update the extension
|
||||
SET search_path = "$user",cartodb,public,cdb_dataservices_client;
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_tomtom_geocode_street_point (text, text, text, text);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_tomtom_isochrone (geometry(Geometry, 4326), text, integer[], text[]);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client.cdb_tomtom_isodistance (geometry(Geometry, 4326), text, integer[], text[]);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_geocode_street_point_exception_safe (text, text, text, text);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_isochrone_exception_safe (geometry(Geometry, 4326), text, integer[], text[]);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_isodistance_exception_safe (geometry(Geometry, 4326), text, integer[], text[]);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_geocode_street_point (username text, orgname text, searchtext text, city text, state_province text, country text);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_isochrone (username text, orgname text, source geometry(Geometry, 4326), mode text, range integer[], options text[]);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_client._cdb_tomtom_isodistance (username text, orgname text, source geometry(Geometry, 4326), mode text, range integer[], options text[]);
|
||||
4960
client/cdb_dataservices_client--0.24.0.sql
Normal file
4960
client/cdb_dataservices_client--0.24.0.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
comment = 'CartoDB dataservices client API extension'
|
||||
default_version = '0.23.0'
|
||||
default_version = '0.24.0'
|
||||
requires = 'plproxy, cartodb'
|
||||
superuser = true
|
||||
schema = cdb_dataservices_client
|
||||
|
||||
@@ -94,6 +94,14 @@
|
||||
- { name: state_province, type: text, default: 'NULL'}
|
||||
- { name: country, type: text, default: 'NULL'}
|
||||
|
||||
- name: cdb_tomtom_geocode_street_point
|
||||
return_type: Geometry
|
||||
params:
|
||||
- { name: searchtext, type: text}
|
||||
- { name: city, type: text, default: 'NULL'}
|
||||
- { name: state_province, type: text, default: 'NULL'}
|
||||
- { name: country, type: text, default: 'NULL'}
|
||||
|
||||
- name: cdb_mapzen_geocode_street_point
|
||||
return_type: Geometry
|
||||
params:
|
||||
@@ -132,6 +140,16 @@
|
||||
- { name: range, type: "integer[]" }
|
||||
- { name: options, type: "text[]", default: 'ARRAY[]::text[]' }
|
||||
|
||||
- name: cdb_tomtom_isochrone
|
||||
return_type: SETOF cdb_dataservices_client.isoline
|
||||
multi_row: true
|
||||
multi_field: true
|
||||
params:
|
||||
- { name: source, type: "geometry(Geometry, 4326)" }
|
||||
- { name: mode, type: text }
|
||||
- { name: range, type: "integer[]" }
|
||||
- { name: options, type: "text[]", default: 'ARRAY[]::text[]' }
|
||||
|
||||
- name: cdb_mapzen_isochrone
|
||||
return_type: SETOF cdb_dataservices_client.isoline
|
||||
multi_row: true
|
||||
@@ -152,6 +170,16 @@
|
||||
- { name: range, type: "integer[]" }
|
||||
- { name: options, type: "text[]", default: 'ARRAY[]::text[]' }
|
||||
|
||||
- name: cdb_tomtom_isodistance
|
||||
return_type: SETOF cdb_dataservices_client.isoline
|
||||
multi_row: true
|
||||
multi_field: true
|
||||
params:
|
||||
- { name: source, type: "geometry(Geometry, 4326)" }
|
||||
- { name: mode, type: text }
|
||||
- { name: range, type: "integer[]" }
|
||||
- { name: options, type: "text[]", default: 'ARRAY[]::text[]' }
|
||||
|
||||
- name: cdb_mapzen_isodistance
|
||||
return_type: SETOF cdb_dataservices_client.isoline
|
||||
multi_row: true
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
-- Only show warning or error messages in the tests output
|
||||
SET client_min_messages TO WARNING;
|
||||
-- Install dependencies
|
||||
CREATE EXTENSION postgis;
|
||||
CREATE EXTENSION plpythonu;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
-- Only show warning or error messages in the tests output
|
||||
SET client_min_messages TO WARNING;
|
||||
-- Install dependencies
|
||||
CREATE EXTENSION postgis;
|
||||
CREATE EXTENSION plpythonu;
|
||||
|
||||
@@ -4,7 +4,7 @@ The [geocoder](https://carto.com/data/geocoder-api/) functions allow you to matc
|
||||
|
||||
_**This service is subject to quota limitations and extra fees may apply**. View the [Quota Information](https://carto.com/docs/carto-engine/dataservices-api/quota-information/) section for details and recommendations about to quota consumption._
|
||||
|
||||
Here is an example of how to geocode a single country:
|
||||
The following example displays how to geocode a single country:
|
||||
|
||||
```bash
|
||||
https://{username}.carto.com/api/v2/sql?q=SELECT cdb_geocode_admin0_polygon('USA')&api_key={api_key}
|
||||
@@ -312,7 +312,7 @@ INSERT INTO {tablename} (the_geom) SELECT cdb_geocode_ipaddress_point('102.23.34
|
||||
|
||||
## Street-Level Geocoder
|
||||
|
||||
This function geocodes your data into a point geometry for a street address. CARTO uses several different service providers for street-level geocoding, depending on your platform. If you access CARTO on a Google Cloud Platform, [Google Maps geocoding](https://developers.google.com/maps/documentation/geocoding/intro) is applied. All other platform users are provided with [HERE geocoding services](https://developer.here.com/rest-apis/documentation/geocoder/topics/quick-start.html). Additional service providers will be implemented in the future.
|
||||
This function geocodes your data into a point geometry for a street address. CARTO uses several different service providers for street-level geocoding, depending on your platform. If you access CARTO on a Google Cloud Platform, [Google Maps geocoding](https://developers.google.com/maps/documentation/geocoding/intro) is applied. All other platform users are provided with [Mapbox geocoding services](https://www.mapbox.com/). [Contact us](mailto:sales@carto.com) if you have any specific questions or requirements about the location data service provider being used with your account._.
|
||||
|
||||
**This service is subject to quota limitations, and extra fees may apply**. View the [Quota information](https://carto.com/docs/carto-engine/dataservices-api/quota-information/) for details and recommendations about quota consumption.
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ You can use the isoline functions to retrieve, for example, isochrone lines from
|
||||
https://{username}.carto.com/api/v2/sql?q=INSERT INTO {table} (the_geom) SELECT the_geom FROM cdb_isodistance('POINT(-3.70568 40.42028)'::geometry, 'car', ARRAY[300, 600, 900]::integer[])&api_key={api_key}
|
||||
```
|
||||
|
||||
The following functions provide an isoline generator service, based on time or distance. This service uses the isolines service defined for your account. The default service limits the usage of displayed polygons represented on top of [HERE](https://developer.here.com/coverage-info) maps.
|
||||
The following functions provide an isoline generator service, based on time or distance. This service uses the isolines service defined for your account. The default service limits the usage of displayed polygons represented on top of [Mapbox](https://www.mapbox.com/) maps.
|
||||
|
||||
## cdb_isodistance(_source geometry, mode text, range integer[], [options text[]]_)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ By using CARTO libraries and the SQL API, you can apply location data services t
|
||||
|
||||
**Note:** Based on your account plan, some of these data services are subject to different [quota limitations](https://carto.com/docs/carto-engine/dataservices-api/quota-information/#quota-information).
|
||||
|
||||
_The Data Services API is collaborating with [Mapzen](https://mapzen.com/), and several other geospatial service providers, in order to supply the best location data services from within our CARTO Engine._
|
||||
_In order to supply the best location data services from within our CARTO Engine, the Data Services API collaborates with [Mapbox](https://www.mapbox.com/) and several other geospatial service providers. [Contact us](mailto:sales@carto.com) if you have any specific questions or requirements about the location data service provider being used with your account._
|
||||
|
||||
## Data Services Integration
|
||||
|
||||
|
||||
@@ -59,9 +59,9 @@ Result:
|
||||
```sql
|
||||
service | monthly_quota | used_quota | soft_limit | provider
|
||||
----------------+---------------+------------+------------+------------------
|
||||
isolines | 100 | 0 | f | mapzen
|
||||
hires_geocoder | 100 | 0 | f | mapzen
|
||||
routing | 50 | 0 | f | mapzen
|
||||
isolines | 100 | 0 | f | mapbox
|
||||
hires_geocoder | 100 | 0 | f | mapbox
|
||||
routing | 50 | 0 | f | mapbox
|
||||
observatory | 0 | 0 | f | data observatory
|
||||
(4 rows)
|
||||
|
||||
@@ -100,7 +100,7 @@ Suppose you want to geocode a whole table. In order to check that you have enoug
|
||||
SELECT COUNT(*) FROM {tablename} WHERE {street_name_column} IS NOT NULL;
|
||||
```
|
||||
|
||||
Result: here's a sample result of 10000 records:
|
||||
Result: A sample result of 10000 records:
|
||||
|
||||
```sql
|
||||
count
|
||||
|
||||
@@ -14,7 +14,7 @@ Name | Type | Description | Accepted values
|
||||
`destination` | `geometry(Point)` | Destination point, in 4326 projection, which defines the end location. |
|
||||
`mode` | `text` | Type of transport used to calculate the routes. | `car`, `walk`, `bicycle` or `public_transport`
|
||||
`options` | `text[]` | (Optional) Multiple options to add more capabilities to the analysis. See [Optional routing parameters](#optional-routing-parameters) for details.
|
||||
`units` | `text` | Unit used to represent the length of the route. | `kilometers`, `miles`. By default is `kilometers`
|
||||
`units` | `text` | (Optional) Unit used to represent the length of the route. | `kilometers`, `miles`. By default is `kilometers`. This option is not supported by Mapbox provider
|
||||
|
||||
|
||||
#### Returns
|
||||
@@ -22,7 +22,7 @@ Name | Type | Description | Accepted values
|
||||
Name | Type | Description
|
||||
--- | --- | ---
|
||||
`duration` | `integer` | Duration in seconds of the calculated route.
|
||||
`length` | `real` | Length in the defined unit in the `units` field. `kilometers` by default .
|
||||
`length` | `real` | Length in the defined unit in the `units` field. `meters` by default .
|
||||
`the_geom` | `geometry(LineString)` | LineString geometry of the calculated route in the 4326 projection.
|
||||
|
||||
#### Examples
|
||||
@@ -49,7 +49,7 @@ Name | Type | Description | Accepted values
|
||||
`waypoints` | `geometry(Point)[]` | Array of ordered points, in 4326 projection, which defines the origin point, one or more locations for the route path to travel through, and the destination. The first element of the array defines the origin and the last element the destination of the route. |
|
||||
`mode` | `text` | Type of transport used to calculate the routes. | `car`, `walk`, `bicycle` or `public_transport`
|
||||
`options` | `text[]` | (Optional) Multiple options to add more capabilities to the analysis. See [Optional routing parameters](#optional-routing-parameters) for details.
|
||||
`units` | `text` | Unit used to represent the length of the route. | `kilometers`, `miles`. By default is `kilometers`
|
||||
`units` | `text` | (Optional) Unit used to represent the length of the route. | `kilometers`, `miles`. By default is `kilometers`. This option is not supported by Mapbox provider
|
||||
|
||||
|
||||
#### Returns
|
||||
@@ -57,7 +57,7 @@ Name | Type | Description | Accepted values
|
||||
Name | Type | Description
|
||||
--- | --- | ---
|
||||
`duration` | `integer` | Duration in seconds of the calculated route.
|
||||
`length` | `real` | Length in the defined unit in the `units` field. `kilometers` by default .
|
||||
`length` | `real` | Length in the defined unit in the `units` field. `meters` by default .
|
||||
`the_geom` | `geometry(LineString)` | LineString geometry of the calculated route in the 4326 projection.
|
||||
|
||||
*Note*: A request to the function _cdb\_route\_with\_waypoints(waypoints geometry(Point)[], mode text, [options text[], units text])_ with only two points in the geometry array are automatically defined as origin and destination. It is equivalent to performing the following request with these two locations as parameters: _cdb\_route\_point\_to\_point(origin geometry(Point), destination geometry(Point), mode text, [options text[], units text])_.
|
||||
@@ -75,10 +75,9 @@ INSERT INTO <TABLE> (duration, length, the_geom) SELECT duration, length, shape
|
||||
UPDATE <TABLE> SET the_geom = (SELECT shape FROM cdb_route_with_waypoints(Array['POINT(-3.7109 40.4234)'::GEOMETRY, 'POINT(-3.7059 40.4203)'::geometry, 'POINT(-3.7046 40.4180)'::geometry]::geometry[], 'car', ARRAY['mode_type=shortest']::text[]))
|
||||
```
|
||||
|
||||
|
||||
### Optional routing parameters
|
||||
|
||||
The optional value parameters must be passed using the format: `option=value`.
|
||||
The optional value parameters must be passed using the format: `option=value`. Not all are available for all the routing providers
|
||||
|
||||
Name | Type | Description | Accepted values
|
||||
--- | --- | --- | ---
|
||||
|
||||
470
server/extension/cdb_dataservices_server--0.30.5--0.31.0.sql
Normal file
470
server/extension/cdb_dataservices_server--0.30.5--0.31.0.sql
Normal file
@@ -0,0 +1,470 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.31.0'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT)
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tomtom import TomTomRouting
|
||||
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.polyline import polyline_to_linestring
|
||||
from cartodb_services.refactor.service.tomtom_routing_config import TomTomRoutingConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('routing', TomTomRoutingConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = TomTomRouting(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
if not waypoints or len(waypoints) < 2:
|
||||
service_manager.logger.info("Empty origin or destination")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
if len(waypoints) > 25:
|
||||
service_manager.logger.info("Too many waypoints (max 25)")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
waypoint_coords = []
|
||||
for waypoint in waypoints:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon']
|
||||
waypoint_coords.append(Coordinate(lon,lat))
|
||||
|
||||
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
|
||||
|
||||
resp = client.directions(waypoint_coords, profile)
|
||||
if resp and resp.shape:
|
||||
shape_linestring = polyline_to_linestring(resp.shape)
|
||||
if shape_linestring:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
return [shape_linestring, resp.length, int(round(resp.duration))]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to calculate TomTom routing', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to calculate TomTom routing')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_point_to_point(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
origin geometry(Point, 4326),
|
||||
destination geometry(Point, 4326),
|
||||
mode TEXT,
|
||||
options text[] DEFAULT ARRAY[]::text[],
|
||||
units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.tools import Logger
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_routing_config = GD["user_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
params = {'origin': origin, 'destination': destination, 'mode': mode, 'options': options, 'units': units}
|
||||
|
||||
with metrics('cdb_route_with_point', user_routing_config, logger, params):
|
||||
waypoints = [origin, destination]
|
||||
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT,
|
||||
options text[] DEFAULT ARRAY[]::text[],
|
||||
units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.tools import Logger
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_routing_config = GD["user_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
params = {'waypoints': waypoints, 'mode': mode, 'options': options, 'units': units}
|
||||
|
||||
with metrics('cdb_route_with_waypoints', user_routing_config, logger, params):
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_geocoder_config = GD["user_geocoder_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
params = {'searchtext': searchtext, 'city': city, 'state_province': state_province, 'country': country}
|
||||
|
||||
with metrics('cdb_geocode_street_point', user_geocoder_config, logger, params):
|
||||
if user_geocoder_config.heremaps_geocoder:
|
||||
here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(here_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
elif user_geocoder_config.google_geocoder:
|
||||
google_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_google_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(google_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
elif user_geocoder_config.mapzen_geocoder:
|
||||
mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapzen_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(mapzen_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
elif user_geocoder_config.mapbox_geocoder:
|
||||
mapbox_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
elif user_geocoder_config.tomtom_geocoder:
|
||||
tomtom_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_tomtom_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(tomtom_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
else:
|
||||
raise Exception('Requested geocoder is not available')
|
||||
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
# The configuration is retrieved but no checks are performed on it
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_geocoder_config = GD["user_geocoder_config_{0}".format(username)]
|
||||
|
||||
tomtom_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_tomtom_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(tomtom_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
from iso3166 import countries
|
||||
from cartodb_services.tools import ServiceManager, QuotaExceededException
|
||||
from cartodb_services.tomtom import TomTomGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.tomtom_geocoder_config import TomTomGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', TomTomGeocoderConfigBuilder, username, orgname, GD)
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits()
|
||||
geocoder = TomTomGeocoder(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
country_iso3166 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
if country_iso3:
|
||||
country_iso3166 = countries.get(country_iso3).alpha2.lower()
|
||||
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3166)
|
||||
if coordinates:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"])
|
||||
point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0]
|
||||
return point['st_setsrid']
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using TomTom', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using TomTom')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tomtom import TomTomIsolines
|
||||
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.tomtom_isolines_config import TomTomIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', TomTomIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
tomtom_isolines = TomTomIsolines(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
|
||||
origin = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = tomtom_isolines.calculate_isodistance(origin, r, profile)
|
||||
isolines[r] = isoline
|
||||
|
||||
result = []
|
||||
for r in data_range:
|
||||
|
||||
if len(isolines[r]) >= 3:
|
||||
# -- TODO encapsulate this block into a func/method
|
||||
locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point
|
||||
wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
|
||||
result.append([source, r, multipolygon])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get TomTom isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get TomTom isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isochrones(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tomtom import TomTomIsolines
|
||||
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.coordinates import coordinates_to_polygon
|
||||
from cartodb_services.refactor.service.tomtom_isolines_config import TomTomIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', TomTomIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
tomtom_isolines = TomTomIsolines(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
|
||||
origin = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
|
||||
|
||||
resp = tomtom_isolines.calculate_isochrone(origin, data_range, profile)
|
||||
|
||||
if resp:
|
||||
result = []
|
||||
for isochrone in resp:
|
||||
result_polygon = coordinates_to_polygon(isochrone.coordinates)
|
||||
if result_polygon:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
result.append([source, isochrone.duration, result_polygon])
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
result.append([source, isochrone.duration, None])
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(result))
|
||||
return result
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return []
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get TomTom isochrones', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get TomTom isochrones')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.tools import Logger
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
if user_isolines_config.google_services_user:
|
||||
raise Exception('This service is not available for google service users.')
|
||||
|
||||
params = {'source': source, 'mode': mode, 'range': range, 'options': options}
|
||||
|
||||
with metrics('cdb_isodistance', user_isolines_config, logger, params):
|
||||
if user_isolines_config.heremaps_provider:
|
||||
here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(here_plan, [username, orgname, source, mode, range, options])
|
||||
elif user_isolines_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options])
|
||||
elif user_isolines_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
elif user_isolines_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options])
|
||||
else:
|
||||
raise Exception('Requested isolines provider is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
-- tomtom isodistance
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options])
|
||||
|
||||
return result
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.tools import Logger
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
if user_isolines_config.google_services_user:
|
||||
raise Exception('This service is not available for google service users.')
|
||||
|
||||
params = {'source': source, 'mode': mode, 'range': range, 'options': options}
|
||||
|
||||
with metrics('cdb_isochrone', user_isolines_config, logger, params):
|
||||
if user_isolines_config.heremaps_provider:
|
||||
here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(here_plan, [username, orgname, source, mode, range, options])
|
||||
elif user_isolines_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options])
|
||||
elif user_isolines_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
elif user_isolines_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options])
|
||||
else:
|
||||
raise Exception('Requested isolines provider is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
-- tomtom isochrone
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options])
|
||||
return result
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
182
server/extension/cdb_dataservices_server--0.31.0--0.30.5.sql
Normal file
182
server/extension/cdb_dataservices_server--0.31.0--0.30.5.sql
Normal file
@@ -0,0 +1,182 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.30.5'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_tomtom_route_with_waypoints(TEXT, TEXT, geometry(Point, 4326)[], TEXT);
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_point_to_point(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
origin geometry(Point, 4326),
|
||||
destination geometry(Point, 4326),
|
||||
mode TEXT,
|
||||
options text[] DEFAULT ARRAY[]::text[],
|
||||
units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.tools import Logger
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_routing_config = GD["user_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
with metrics('cdb_route_with_point', user_routing_config, logger):
|
||||
waypoints = [origin, destination]
|
||||
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE ;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT,
|
||||
options text[] DEFAULT ARRAY[]::text[],
|
||||
units text DEFAULT 'kilometers')
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.tools import Logger
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_routing_config = GD["user_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
with metrics('cdb_route_with_waypoints', user_routing_config, logger):
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE ;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.tools import Logger,LoggerConfig
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_geocoder_config = GD["user_geocoder_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
with metrics('cdb_geocode_street_point', user_geocoder_config, logger):
|
||||
if user_geocoder_config.heremaps_geocoder:
|
||||
here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(here_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
elif user_geocoder_config.google_geocoder:
|
||||
google_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_google_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(google_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
elif user_geocoder_config.mapzen_geocoder:
|
||||
mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapzen_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(mapzen_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
elif user_geocoder_config.mapbox_geocoder:
|
||||
mapbox_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
else:
|
||||
raise Exception('Requested geocoder is not available')
|
||||
|
||||
$$ LANGUAGE plpythonu STABLE ;
|
||||
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_tomtom_geocode_street_point(TEXT, TEXT, TEXT, TEXT, TEXT, TEXT);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_tomtom_geocode_street_point(TEXT, TEXT, TEXT, TEXT, TEXT, TEXT);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_tomtom_isodistance(TEXT, TEXT, geometry(Geometry, 4326), TEXT, integer[], text[]);
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_tomtom_isochrones(TEXT, TEXT, geometry(Geometry, 4326), TEXT, integer[], text[]);
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.tools import Logger
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
if user_isolines_config.google_services_user:
|
||||
raise Exception('This service is not available for google service users.')
|
||||
|
||||
with metrics('cb_isodistance', user_isolines_config, logger):
|
||||
if user_isolines_config.heremaps_provider:
|
||||
here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(here_plan, [username, orgname, source, mode, range, options])
|
||||
elif user_isolines_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options])
|
||||
elif user_isolines_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
else:
|
||||
raise Exception('Requested isolines provider is not available')
|
||||
$$ LANGUAGE plpythonu STABLE ;
|
||||
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_tomtom_isodistance(TEXT, TEXT, geometry(Geometry, 4326), TEXT, integer[], text[]);
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.metrics import metrics
|
||||
from cartodb_services.tools import Logger
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
if user_isolines_config.google_services_user:
|
||||
raise Exception('This service is not available for google service users.')
|
||||
|
||||
with metrics('cb_isochrone', user_isolines_config, logger):
|
||||
if user_isolines_config.heremaps_provider:
|
||||
here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(here_plan, [username, orgname, source, mode, range, options])
|
||||
elif user_isolines_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapzen_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapzen_plan, [username, orgname, source, mode, range, options])
|
||||
elif user_isolines_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
else:
|
||||
raise Exception('Requested isolines provider is not available')
|
||||
$$ LANGUAGE plpythonu STABLE ;
|
||||
|
||||
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_tomtom_isochrone(TEXT, TEXT, geometry(Geometry, 4326), TEXT, integer[], text[]);
|
||||
3658
server/extension/cdb_dataservices_server--0.31.0.sql
Normal file
3658
server/extension/cdb_dataservices_server--0.31.0.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
comment = 'CartoDB dataservices server extension'
|
||||
default_version = '0.30.1'
|
||||
default_version = '0.31.0'
|
||||
requires = 'plpythonu, plproxy, postgis, cdb_geocoder'
|
||||
superuser = true
|
||||
schema = cdb_dataservices_server
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.30.2'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_here_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
from cartodb_services.tools import LegacyServiceManager
|
||||
from cartodb_services.tools import QuotaExceededException
|
||||
from cartodb_services.here import HereMapsGeocoder
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
service_manager = LegacyServiceManager('geocoder', username, orgname, GD)
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits()
|
||||
geocoder = HereMapsGeocoder(service_manager.config.heremaps_app_id, service_manager.config.heremaps_app_code, service_manager.logger, service_manager.config.heremaps_service_params)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country)
|
||||
if coordinates:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"])
|
||||
point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0]
|
||||
return point['st_setsrid']
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using here maps', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using here maps')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_google_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
from cartodb_services.tools import LegacyServiceManager, QuotaExceededException
|
||||
from cartodb_services.google import GoogleMapsGeocoder
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
service_manager = LegacyServiceManager('geocoder', username, orgname, GD)
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits(quota=False)
|
||||
geocoder = GoogleMapsGeocoder(service_manager.config.google_client_id, service_manager.config.google_api_key, service_manager.logger)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country)
|
||||
if coordinates:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"])
|
||||
point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0]
|
||||
return point['st_setsrid']
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using google maps', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using google maps')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
from cartodb_services.tools import ServiceManager, QuotaExceededException
|
||||
from cartodb_services.mapzen import MapzenGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.mapzen_geocoder_config import MapzenGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapzenGeocoderConfigBuilder, username, orgname)
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits()
|
||||
geocoder = MapzenGeocoder(service_manager.config.mapzen_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
country_iso3 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3, search_type='address')
|
||||
if coordinates:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"])
|
||||
point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0]
|
||||
return point['st_setsrid']
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using mapzen', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using mapzen')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
from iso3166 import countries
|
||||
from cartodb_services.tools import ServiceManager, QuotaExceededException
|
||||
from cartodb_services.mapbox import MapboxGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD)
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits()
|
||||
geocoder = MapboxGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
country_iso3166 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
if country_iso3:
|
||||
country_iso3166 = countries.get(country_iso3).alpha2.lower()
|
||||
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3166)
|
||||
if coordinates:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"])
|
||||
point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0]
|
||||
return point['st_setsrid']
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using mapbox', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using mapbox')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
@@ -0,0 +1,114 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.30.1'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_here_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
from cartodb_services.tools import LegacyServiceManager
|
||||
from cartodb_services.here import HereMapsGeocoder
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
service_manager = LegacyServiceManager('geocoder', username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
geocoder = HereMapsGeocoder(service_manager.config.heremaps_app_id, service_manager.config.heremaps_app_code, service_manager.logger, service_manager.config.heremaps_service_params)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country)
|
||||
if coordinates:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"])
|
||||
point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0]
|
||||
return point['st_setsrid']
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using here maps', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using here maps')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapzen import MapzenGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.mapzen_geocoder_config import MapzenGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapzenGeocoderConfigBuilder, username, orgname)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
geocoder = MapzenGeocoder(service_manager.config.mapzen_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
country_iso3 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3, search_type='address')
|
||||
if coordinates:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"])
|
||||
point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0]
|
||||
return point['st_setsrid']
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using mapzen', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using mapzen')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
from iso3166 import countries
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
geocoder = MapboxGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
country_iso3166 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
if country_iso3:
|
||||
country_iso3166 = countries.get(country_iso3).alpha2.lower()
|
||||
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3166)
|
||||
if coordinates:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"])
|
||||
point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0]
|
||||
return point['st_setsrid']
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using mapbox', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using mapbox')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
@@ -0,0 +1,70 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.30.3'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
mapbox_isolines = MapboxIsolines(client, service_manager.logger)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
|
||||
origin = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = mapbox_isolines.calculate_isodistance(origin, r, profile)
|
||||
isolines[r] = isoline
|
||||
|
||||
result = []
|
||||
for r in data_range:
|
||||
|
||||
if len(isolines[r]) >= 3:
|
||||
# -- TODO encapsulate this block into a func/method
|
||||
locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point
|
||||
wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
|
||||
result.append([source, r, multipolygon])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get Mapbox isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
3357
server/extension/old_versions/cdb_dataservices_server--0.30.2.sql
Normal file
3357
server/extension/old_versions/cdb_dataservices_server--0.30.2.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,70 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.30.2'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
mapbox_isolines = MapboxIsolines(client, service_manager.logger)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
|
||||
origin = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = mapbox_isolines.calculate_isodistance(origin, r, profile)
|
||||
isolines[r] = isoline
|
||||
|
||||
result = []
|
||||
for r in data_range:
|
||||
|
||||
if len(isolines[r]) >= 3:
|
||||
# -- TODO encapsulate this block into a func/method
|
||||
locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point
|
||||
wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
|
||||
result.append([source, r, multipolygon])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get Mapbox isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
@@ -0,0 +1,69 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.30.4'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
mapbox_isolines = MapboxIsolines(client, service_manager.logger)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
|
||||
origin = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = mapbox_isolines.calculate_isodistance(origin, r, profile)
|
||||
isolines[r] = isoline
|
||||
|
||||
result = []
|
||||
for r in data_range:
|
||||
|
||||
if len(isolines[r]) >= 3:
|
||||
# -- TODO encapsulate this block into a func/method
|
||||
locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point
|
||||
wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
|
||||
result.append([source, r, multipolygon])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get Mapbox isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
3360
server/extension/old_versions/cdb_dataservices_server--0.30.3.sql
Normal file
3360
server/extension/old_versions/cdb_dataservices_server--0.30.3.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,69 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.30.3'" to load this file. \quit
|
||||
|
||||
-- HERE goes your code to upgrade/downgrade
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
mapbox_isolines = MapboxIsolines(client, service_manager.logger)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
|
||||
origin = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = mapbox_isolines.calculate_isodistance(origin, r, profile)
|
||||
isolines[r] = isoline
|
||||
|
||||
result = []
|
||||
for r in data_range:
|
||||
|
||||
if len(isolines[r]) >= 3:
|
||||
# -- TODO encapsulate this block into a func/method
|
||||
locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point
|
||||
wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
|
||||
result.append([source, r, multipolygon])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get Mapbox isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
@@ -0,0 +1,68 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.30.5'" to load this file. \quit
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
mapbox_isolines = MapboxIsolines(client, service_manager.logger)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
|
||||
origin = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = mapbox_isolines.calculate_isodistance(origin, r, profile)
|
||||
isolines[r] = isoline
|
||||
|
||||
result = []
|
||||
for r in data_range:
|
||||
|
||||
if len(isolines[r]) >= 3:
|
||||
# -- TODO encapsulate this block into a func/method
|
||||
locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point
|
||||
wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT st_multi(ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3)) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
|
||||
result.append([source, r, multipolygon])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get Mapbox isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
3360
server/extension/old_versions/cdb_dataservices_server--0.30.4.sql
Normal file
3360
server/extension/old_versions/cdb_dataservices_server--0.30.4.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,68 @@
|
||||
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
|
||||
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.30.4'" to load this file. \quit
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
|
||||
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
mapbox_isolines = MapboxIsolines(client, service_manager.logger)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
|
||||
origin = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = mapbox_isolines.calculate_isodistance(origin, r, profile)
|
||||
isolines[r] = isoline
|
||||
|
||||
result = []
|
||||
for r in data_range:
|
||||
|
||||
if len(isolines[r]) >= 3:
|
||||
# -- TODO encapsulate this block into a func/method
|
||||
locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point
|
||||
wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
|
||||
result.append([source, r, multipolygon])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get Mapbox isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get Mapbox isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
3360
server/extension/old_versions/cdb_dataservices_server--0.30.5.sql
Normal file
3360
server/extension/old_versions/cdb_dataservices_server--0.30.5.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -65,6 +65,67 @@ RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
waypoints geometry(Point, 4326)[],
|
||||
mode TEXT)
|
||||
RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tomtom import TomTomRouting
|
||||
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.polyline import polyline_to_linestring
|
||||
from cartodb_services.refactor.service.tomtom_routing_config import TomTomRoutingConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('routing', TomTomRoutingConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
client = TomTomRouting(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
if not waypoints or len(waypoints) < 2:
|
||||
service_manager.logger.info("Empty origin or destination")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
if len(waypoints) > 25:
|
||||
service_manager.logger.info("Too many waypoints (max 25)")
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
|
||||
waypoint_coords = []
|
||||
for waypoint in waypoints:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % waypoint)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % waypoint)[0]['lon']
|
||||
waypoint_coords.append(Coordinate(lon,lat))
|
||||
|
||||
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
|
||||
|
||||
resp = client.directions(waypoint_coords, profile)
|
||||
if resp and resp.shape:
|
||||
shape_linestring = polyline_to_linestring(resp.shape)
|
||||
if shape_linestring:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
return [shape_linestring, resp.length, int(round(resp.duration))]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return [None, None, None]
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to calculate TomTom routing', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to calculate TomTom routing')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_route_with_waypoints(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
|
||||
@@ -18,7 +18,9 @@ RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
with metrics('cdb_route_with_point', user_routing_config, logger):
|
||||
params = {'origin': origin, 'destination': destination, 'mode': mode, 'options': options, 'units': units}
|
||||
|
||||
with metrics('cdb_route_with_point', user_routing_config, logger, params):
|
||||
waypoints = [origin, destination]
|
||||
|
||||
if user_routing_config.mapzen_provider:
|
||||
@@ -29,6 +31,10 @@ RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
@@ -53,7 +59,9 @@ RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
with metrics('cdb_route_with_waypoints', user_routing_config, logger):
|
||||
params = {'waypoints': waypoints, 'mode': mode, 'options': options, 'units': units}
|
||||
|
||||
with metrics('cdb_route_with_waypoints', user_routing_config, logger, params):
|
||||
if user_routing_config.mapzen_provider:
|
||||
mapzen_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapzen_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapzen_plan, [username, orgname, waypoints, mode])
|
||||
@@ -62,6 +70,10 @@ RETURNS cdb_dataservices_server.simple_route AS $$
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_mapbox_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
elif user_routing_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_route_with_waypoints($1, $2, $3, $4) as route;", ["text", "text", "geometry(Point, 4326)[]", "text"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, waypoints, mode])
|
||||
return [result[0]['shape'],result[0]['length'], result[0]['duration']]
|
||||
else:
|
||||
raise Exception('Requested routing method is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
@@ -12,7 +12,9 @@ RETURNS Geometry AS $$
|
||||
logger_config = GD["logger_config"]
|
||||
logger = Logger(logger_config)
|
||||
|
||||
with metrics('cdb_geocode_street_point', user_geocoder_config, logger):
|
||||
params = {'searchtext': searchtext, 'city': city, 'state_province': state_province, 'country': country}
|
||||
|
||||
with metrics('cdb_geocode_street_point', user_geocoder_config, logger, params):
|
||||
if user_geocoder_config.heremaps_geocoder:
|
||||
here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(here_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
@@ -25,6 +27,9 @@ RETURNS Geometry AS $$
|
||||
elif user_geocoder_config.mapbox_geocoder:
|
||||
mapbox_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
elif user_geocoder_config.tomtom_geocoder:
|
||||
tomtom_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_tomtom_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(tomtom_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
else:
|
||||
raise Exception('Requested geocoder is not available')
|
||||
|
||||
@@ -82,21 +87,35 @@ RETURNS Geometry AS $$
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_geocoder_config = GD["user_geocoder_config_{0}".format(username)]
|
||||
|
||||
mapzen_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(mapzen_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
mapbox_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_mapbox_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
# The configuration is retrieved but no checks are performed on it
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_geocoder_config = GD["user_geocoder_config_{0}".format(username)]
|
||||
|
||||
tomtom_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_tomtom_geocode_street_point($1, $2, $3, $4, $5, $6) as point; ", ["text", "text", "text", "text", "text", "text"])
|
||||
return plpy.execute(tomtom_plan, [username, orgname, searchtext, city, state_province, country], 1)[0]['point']
|
||||
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_here_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
from cartodb_services.tools import LegacyServiceManager
|
||||
from cartodb_services.tools import QuotaExceededException
|
||||
from cartodb_services.here import HereMapsGeocoder
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
service_manager = LegacyServiceManager('geocoder', username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits()
|
||||
geocoder = HereMapsGeocoder(service_manager.config.heremaps_app_id, service_manager.config.heremaps_app_code, service_manager.logger, service_manager.config.heremaps_service_params)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country)
|
||||
if coordinates:
|
||||
@@ -107,6 +126,9 @@ RETURNS Geometry AS $$
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
@@ -118,14 +140,14 @@ $$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_google_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
from cartodb_services.tools import LegacyServiceManager
|
||||
from cartodb_services.tools import LegacyServiceManager, QuotaExceededException
|
||||
from cartodb_services.google import GoogleMapsGeocoder
|
||||
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
|
||||
service_manager = LegacyServiceManager('geocoder', username, orgname, GD)
|
||||
service_manager.assert_within_limits(quota=False)
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits(quota=False)
|
||||
geocoder = GoogleMapsGeocoder(service_manager.config.google_client_id, service_manager.config.google_api_key, service_manager.logger)
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city, state=state_province, country=country)
|
||||
if coordinates:
|
||||
@@ -136,6 +158,9 @@ RETURNS Geometry AS $$
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
@@ -147,7 +172,7 @@ $$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tools import ServiceManager, QuotaExceededException
|
||||
from cartodb_services.mapzen import MapzenGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.mapzen_geocoder_config import MapzenGeocoderConfigBuilder
|
||||
@@ -156,9 +181,9 @@ RETURNS Geometry AS $$
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapzenGeocoderConfigBuilder, username, orgname)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits()
|
||||
geocoder = MapzenGeocoder(service_manager.config.mapzen_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
country_iso3 = None
|
||||
if country:
|
||||
@@ -174,6 +199,9 @@ RETURNS Geometry AS $$
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
@@ -186,7 +214,7 @@ $$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
from iso3166 import countries
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tools import ServiceManager, QuotaExceededException
|
||||
from cartodb_services.mapbox import MapboxGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.mapbox_geocoder_config import MapboxGeocoderConfigBuilder
|
||||
@@ -195,9 +223,9 @@ RETURNS Geometry AS $$
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', MapboxGeocoderConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits()
|
||||
geocoder = MapboxGeocoder(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
country_iso3166 = None
|
||||
@@ -217,11 +245,60 @@ RETURNS Geometry AS $$
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using mapbox', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using mapbox')
|
||||
service_manager.logger.error('Error trying to geocode street point using Mapbox', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using Mapbox')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_geocode_street_point(username TEXT, orgname TEXT, searchtext TEXT, city TEXT DEFAULT NULL, state_province TEXT DEFAULT NULL, country TEXT DEFAULT NULL)
|
||||
RETURNS Geometry AS $$
|
||||
from iso3166 import countries
|
||||
from cartodb_services.tools import ServiceManager, QuotaExceededException
|
||||
from cartodb_services.tomtom import TomTomGeocoder
|
||||
from cartodb_services.tools.country import country_to_iso3
|
||||
from cartodb_services.refactor.service.tomtom_geocoder_config import TomTomGeocoderConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('geocoder', TomTomGeocoderConfigBuilder, username, orgname, GD)
|
||||
|
||||
try:
|
||||
service_manager.assert_within_limits()
|
||||
geocoder = TomTomGeocoder(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
country_iso3166 = None
|
||||
if country:
|
||||
country_iso3 = country_to_iso3(country)
|
||||
if country_iso3:
|
||||
country_iso3166 = countries.get(country_iso3).alpha2.lower()
|
||||
|
||||
coordinates = geocoder.geocode(searchtext=searchtext, city=city,
|
||||
state_province=state_province,
|
||||
country=country_iso3166)
|
||||
if coordinates:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
plan = plpy.prepare("SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326); ", ["double precision", "double precision"])
|
||||
point = plpy.execute(plan, [coordinates[0], coordinates[1]], 1)[0]
|
||||
return point['st_setsrid']
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return None
|
||||
except QuotaExceededException as qe:
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
return None
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to geocode street point using TomTom', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to geocode street point using TomTom')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
@@ -169,7 +169,7 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
# -- TODO encapsulate this block into a func/method
|
||||
locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point
|
||||
wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326) as geom".format(wkt_coordinates)
|
||||
sql = "SELECT st_multi(ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3)) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
@@ -188,6 +188,70 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isodistance(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tomtom import TomTomIsolines
|
||||
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.refactor.service.tomtom_isolines_config import TomTomIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', TomTomIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
tomtom_isolines = TomTomIsolines(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
|
||||
origin = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
|
||||
|
||||
# -- TODO Support options properly
|
||||
isolines = {}
|
||||
for r in data_range:
|
||||
isoline = tomtom_isolines.calculate_isodistance(origin, r, profile)
|
||||
isolines[r] = isoline
|
||||
|
||||
result = []
|
||||
for r in data_range:
|
||||
|
||||
if len(isolines[r]) >= 3:
|
||||
# -- TODO encapsulate this block into a func/method
|
||||
locations = isolines[r] + [ isolines[r][0] ] # close the polygon repeating the first point
|
||||
wkt_coordinates = ','.join(["%f %f" % (l.longitude, l.latitude) for l in locations])
|
||||
sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MPolyFromText('MULTIPOLYGON((({0})))', 4326)),3) as geom".format(wkt_coordinates)
|
||||
multipolygon = plpy.execute(sql, 1)[0]['geom']
|
||||
else:
|
||||
multipolygon = None
|
||||
|
||||
result.append([source, r, multipolygon])
|
||||
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(isolines))
|
||||
return result
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get TomTom isolines', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get TomTom isolines')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isochrones(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
@@ -311,3 +375,63 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isochrones(
|
||||
username TEXT,
|
||||
orgname TEXT,
|
||||
source geometry(Geometry, 4326),
|
||||
mode TEXT,
|
||||
data_range integer[],
|
||||
options text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.tools import ServiceManager
|
||||
from cartodb_services.tomtom import TomTomIsolines
|
||||
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.coordinates import coordinates_to_polygon
|
||||
from cartodb_services.refactor.service.tomtom_isolines_config import TomTomIsolinesConfigBuilder
|
||||
|
||||
import cartodb_services
|
||||
cartodb_services.init(plpy, GD)
|
||||
|
||||
service_manager = ServiceManager('isolines', TomTomIsolinesConfigBuilder, username, orgname, GD)
|
||||
service_manager.assert_within_limits()
|
||||
|
||||
try:
|
||||
tomtom_isolines = TomTomIsolines(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
|
||||
origin = Coordinate(lon,lat)
|
||||
else:
|
||||
raise Exception('source is NULL')
|
||||
|
||||
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
|
||||
|
||||
resp = tomtom_isolines.calculate_isochrone(origin, data_range, profile)
|
||||
|
||||
if resp:
|
||||
result = []
|
||||
for isochrone in resp:
|
||||
result_polygon = coordinates_to_polygon(isochrone.coordinates)
|
||||
if result_polygon:
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
result.append([source, isochrone.duration, result_polygon])
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
result.append([source, isochrone.duration, None])
|
||||
service_manager.quota_service.increment_success_service_use()
|
||||
service_manager.quota_service.increment_isolines_service_use(len(result))
|
||||
return result
|
||||
else:
|
||||
service_manager.quota_service.increment_empty_service_use()
|
||||
return []
|
||||
except BaseException as e:
|
||||
import sys
|
||||
service_manager.quota_service.increment_failed_service_use()
|
||||
service_manager.logger.error('Error trying to get TomTom isochrones', sys.exc_info(), data={"username": username, "orgname": orgname})
|
||||
raise Exception('Error trying to get TomTom isochrones')
|
||||
finally:
|
||||
service_manager.quota_service.increment_total_service_use()
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
|
||||
|
||||
@@ -14,7 +14,9 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
if user_isolines_config.google_services_user:
|
||||
raise Exception('This service is not available for google service users.')
|
||||
|
||||
with metrics('cb_isodistance', user_isolines_config, logger):
|
||||
params = {'source': source, 'mode': mode, 'range': range, 'options': options}
|
||||
|
||||
with metrics('cdb_isodistance', user_isolines_config, logger, params):
|
||||
if user_isolines_config.heremaps_provider:
|
||||
here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(here_plan, [username, orgname, source, mode, range, options])
|
||||
@@ -24,6 +26,9 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
elif user_isolines_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
elif user_isolines_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options])
|
||||
else:
|
||||
raise Exception('Requested isolines provider is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
@@ -70,3 +75,17 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
|
||||
return result
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
-- tomtom isodistance
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_isodistance(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_isodistance($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options])
|
||||
|
||||
return result
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
@@ -14,7 +14,9 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
if user_isolines_config.google_services_user:
|
||||
raise Exception('This service is not available for google service users.')
|
||||
|
||||
with metrics('cb_isochrone', user_isolines_config, logger):
|
||||
params = {'source': source, 'mode': mode, 'range': range, 'options': options}
|
||||
|
||||
with metrics('cdb_isochrone', user_isolines_config, logger, params):
|
||||
if user_isolines_config.heremaps_provider:
|
||||
here_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_here_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(here_plan, [username, orgname, source, mode, range, options])
|
||||
@@ -24,6 +26,9 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
elif user_isolines_config.mapbox_provider:
|
||||
mapbox_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_mapbox_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
elif user_isolines_config.tomtom_provider:
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.cdb_tomtom_isochrone($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
return plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options])
|
||||
else:
|
||||
raise Exception('Requested isolines provider is not available')
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
@@ -68,3 +73,16 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
result = plpy.execute(mapbox_plan, [username, orgname, source, mode, range, options])
|
||||
return result
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
-- tomtom isochrone
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_tomtom_isochrone(username TEXT, orgname TEXT, source geometry(Geometry, 4326), mode TEXT, range integer[], options text[] DEFAULT array[]::text[])
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
|
||||
tomtom_plan = plpy.prepare("SELECT * FROM cdb_dataservices_server._cdb_tomtom_isochrones($1, $2, $3, $4, $5, $6) as isoline; ", ["text", "text", "geometry(geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
result = plpy.execute(tomtom_plan, [username, orgname, source, mode, range, options])
|
||||
return result
|
||||
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
-- Only show warning or error messages in the tests output
|
||||
SET client_min_messages TO WARNING;
|
||||
-- Install dependencies
|
||||
CREATE EXTENSION postgis;
|
||||
CREATE EXTENSION plpythonu;
|
||||
@@ -37,6 +39,12 @@ SELECT cartodb.cdb_conf_setconf('mapbox_conf', '{"routing": {"api_keys": ["routi
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cartodb.cdb_conf_setconf('tomtom_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}');
|
||||
cdb_conf_setconf
|
||||
------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT cartodb.cdb_conf_setconf('logger_conf', '{"geocoder_log_path": "/dev/null"}');
|
||||
cdb_conf_setconf
|
||||
------------------
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
-- Only show warning or error messages in the tests output
|
||||
SET client_min_messages TO WARNING;
|
||||
-- Install dependencies
|
||||
CREATE EXTENSION postgis;
|
||||
CREATE EXTENSION plpythonu;
|
||||
@@ -14,6 +16,7 @@ SELECT cartodb.cdb_conf_setconf('redis_metadata_config', '{"redis_host": "localh
|
||||
SELECT cartodb.cdb_conf_setconf('heremaps_conf', '{"geocoder": {"app_id": "dummy_id", "app_code": "dummy_code", "geocoder_cost_per_hit": 1}, "isolines": {"app_id": "dummy_id", "app_code": "dummy_code"}}');
|
||||
SELECT cartodb.cdb_conf_setconf('mapzen_conf', '{"routing": {"api_key": "routing_dummy_api_key", "monthly_quota": 1500000}, "geocoder": {"api_key": "geocoder_dummy_api_key", "monthly_quota": 1500000}, "matrix": {"api_key": "matrix_dummy_api_key", "monthly_quota": 1500000}}');
|
||||
SELECT cartodb.cdb_conf_setconf('mapbox_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "matrix": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}');
|
||||
SELECT cartodb.cdb_conf_setconf('tomtom_conf', '{"routing": {"api_keys": ["routing_dummy_api_key"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["geocoder_dummy_api_key"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["matrix_dummy_api_key"], "monthly_quota": 1500000}}');
|
||||
SELECT cartodb.cdb_conf_setconf('logger_conf', '{"geocoder_log_path": "/dev/null"}');
|
||||
SELECT cartodb.cdb_conf_setconf('data_observatory_conf', '{"connection": {"whitelist": ["ethervoid"], "production": "host=localhost port=5432 dbname=contrib_regression user=geocoder_api", "staging": "host=localhost port=5432 dbname=dataservices_db user=geocoder_api"}, "monthly_quota": 100000}');
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ NOTE: a system installation is required at present because the library is meant
|
||||
|
||||
|
||||
## Running the unit tests
|
||||
Just run `nosetests test/`
|
||||
Just run `MAPBOX_API_KEY=xxx nosetests test/`
|
||||
```shell
|
||||
$ nosetests test/
|
||||
......................................................................................................
|
||||
|
||||
@@ -67,10 +67,10 @@ class HereMapsGeocoder(Traceable):
|
||||
def geocode(self, **kwargs):
|
||||
params = {}
|
||||
for key, value in kwargs.iteritems():
|
||||
if value:
|
||||
if value and value.strip():
|
||||
params[key] = value
|
||||
if not params:
|
||||
raise NoGeocodingParams()
|
||||
return []
|
||||
return self._execute_geocode(params)
|
||||
|
||||
def _execute_geocode(self, params):
|
||||
|
||||
@@ -8,11 +8,12 @@ from mapbox import Geocoder
|
||||
from cartodb_services.metrics import Traceable
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
from cartodb_services.tools.qps import qps_retry
|
||||
from cartodb_services.tools.normalize import normalize
|
||||
|
||||
GEOCODER_NAME = 'geocoder_name'
|
||||
EPHEMERAL_GEOCODER = 'mapbox.places'
|
||||
PERMANENT_GEOCODER = 'mapbox.places-permanent'
|
||||
DEFAULT_GEOCODER = EPHEMERAL_GEOCODER
|
||||
DEFAULT_GEOCODER = PERMANENT_GEOCODER
|
||||
|
||||
ENTRY_FEATURES = 'features'
|
||||
ENTRY_CENTER = 'center'
|
||||
@@ -32,17 +33,23 @@ class MapboxGeocoder(Traceable):
|
||||
self._token = token
|
||||
self._logger = logger
|
||||
self._geocoder_name = service_params.get(GEOCODER_NAME,
|
||||
EPHEMERAL_GEOCODER)
|
||||
DEFAULT_GEOCODER)
|
||||
self._geocoder = Geocoder(access_token=self._token,
|
||||
name=self._geocoder_name)
|
||||
|
||||
def _parse_geocoder_response(self, response):
|
||||
json_response = json.loads(response)
|
||||
|
||||
# If Mapbox returns more that one result, take the first one
|
||||
if json_response:
|
||||
feature = json_response[ENTRY_FEATURES][0]
|
||||
if type(json_response) == list:
|
||||
json_response = json_response[0]
|
||||
|
||||
return self._extract_lng_lat_from_feature(feature)
|
||||
if json_response[ENTRY_FEATURES]:
|
||||
feature = json_response[ENTRY_FEATURES][0]
|
||||
return self._extract_lng_lat_from_feature(feature)
|
||||
else:
|
||||
return []
|
||||
else:
|
||||
return []
|
||||
|
||||
@@ -57,14 +64,30 @@ class MapboxGeocoder(Traceable):
|
||||
latitude = location[1]
|
||||
return [longitude, latitude]
|
||||
|
||||
def _validate_input(self, searchtext, city=None, state_province=None,
|
||||
country=None):
|
||||
if searchtext and searchtext.strip():
|
||||
return True
|
||||
elif city:
|
||||
return True
|
||||
elif state_province:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@qps_retry(qps=10)
|
||||
def geocode(self, searchtext, city=None, state_province=None,
|
||||
country=None):
|
||||
address = [searchtext]
|
||||
if not self._validate_input(searchtext, city, state_province, country):
|
||||
return []
|
||||
|
||||
address = []
|
||||
if searchtext and searchtext.strip():
|
||||
address.append(normalize(searchtext))
|
||||
if city:
|
||||
address.append(city)
|
||||
address.append(normalize(city))
|
||||
if state_province:
|
||||
address.append(state_province)
|
||||
address.append(normalize(state_province))
|
||||
|
||||
country = [country] if country else None
|
||||
|
||||
@@ -77,6 +100,8 @@ class MapboxGeocoder(Traceable):
|
||||
return self._parse_geocoder_response(response.text)
|
||||
elif response.status_code == requests.codes.bad_request:
|
||||
return []
|
||||
elif response.status_code == requests.codes.unprocessable_entity:
|
||||
return []
|
||||
else:
|
||||
raise ServiceException(response.status_code, response)
|
||||
except requests.Timeout as te:
|
||||
|
||||
@@ -4,6 +4,7 @@ Uses the Mapbox Time Matrix service.
|
||||
'''
|
||||
|
||||
import json
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.spherical import (get_angles,
|
||||
calculate_dest_location)
|
||||
from cartodb_services.mapbox.matrix_client import (validate_profile,
|
||||
@@ -11,7 +12,9 @@ from cartodb_services.mapbox.matrix_client import (validate_profile,
|
||||
PROFILE_WALKING,
|
||||
PROFILE_DRIVING,
|
||||
PROFILE_CYCLING,
|
||||
ENTRY_DURATIONS)
|
||||
ENTRY_DURATIONS,
|
||||
ENTRY_DESTINATIONS,
|
||||
ENTRY_LOCATION)
|
||||
|
||||
MAX_SPEEDS = {
|
||||
PROFILE_WALKING: 3.3333333, # In m/s, assuming 12km/h walking speed
|
||||
@@ -49,8 +52,11 @@ class MapboxIsolines():
|
||||
response = self._matrix_client.matrix([origin] + targets,
|
||||
profile)
|
||||
json_response = json.loads(response)
|
||||
if not json_response:
|
||||
return []
|
||||
|
||||
costs = [None] * number_of_angles
|
||||
destinations = [None] * number_of_angles
|
||||
|
||||
for idx, cost in enumerate(json_response[ENTRY_DURATIONS][0][1:]):
|
||||
if cost:
|
||||
@@ -58,7 +64,11 @@ class MapboxIsolines():
|
||||
else:
|
||||
costs[idx] = isorange
|
||||
|
||||
return costs
|
||||
for idx, destination in enumerate(json_response[ENTRY_DESTINATIONS][1:]):
|
||||
destinations[idx] = Coordinate(destination[ENTRY_LOCATION][0],
|
||||
destination[ENTRY_LOCATION][1])
|
||||
|
||||
return costs, destinations
|
||||
|
||||
def calculate_isochrone(self, origin, time_ranges,
|
||||
profile=DEFAULT_PROFILE):
|
||||
@@ -120,10 +130,15 @@ class MapboxIsolines():
|
||||
# NOTE: sometimes it cannot calculate the cost and returns None.
|
||||
# Just assume isorange and stop the calculations there
|
||||
|
||||
costs = cost_method(origin=origin, targets=location_estimates,
|
||||
isorange=isorange, profile=profile,
|
||||
unit_factor=unit_factor,
|
||||
number_of_angles=number_of_angles)
|
||||
costs, destinations = cost_method(origin=origin,
|
||||
targets=location_estimates,
|
||||
isorange=isorange,
|
||||
profile=profile,
|
||||
unit_factor=unit_factor,
|
||||
number_of_angles=number_of_angles)
|
||||
|
||||
if not costs:
|
||||
continue
|
||||
|
||||
errors = [(cost - isorange) / float(isorange) for cost in costs]
|
||||
max_abs_error = max([abs(e) for e in errors])
|
||||
@@ -147,8 +162,8 @@ class MapboxIsolines():
|
||||
# delete points that got None
|
||||
location_estimates_filtered = []
|
||||
for i, c in enumerate(costs):
|
||||
if c != isorange:
|
||||
location_estimates_filtered.append(location_estimates[i])
|
||||
if c != isorange and c < isorange * (1 + tolerance):
|
||||
location_estimates_filtered.append(destinations[i])
|
||||
|
||||
return location_estimates_filtered
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@ VALID_PROFILES = [PROFILE_DRIVING_TRAFFIC,
|
||||
PROFILE_WALKING]
|
||||
|
||||
ENTRY_DURATIONS = 'durations'
|
||||
ENTRY_DESTINATIONS = 'destinations'
|
||||
ENTRY_LOCATION = 'location'
|
||||
|
||||
|
||||
def validate_profile(profile):
|
||||
@@ -72,6 +74,8 @@ class MapboxMatrixClient(Traceable):
|
||||
return response.text
|
||||
elif response.status_code == requests.codes.bad_request:
|
||||
return '{}'
|
||||
elif response.status_code == requests.codes.unprocessable_entity:
|
||||
return '{}'
|
||||
else:
|
||||
raise ServiceException(response.status_code, response)
|
||||
except requests.Timeout as te:
|
||||
|
||||
@@ -91,6 +91,8 @@ class MapboxRouting(Traceable):
|
||||
return self._parse_routing_response(response.text)
|
||||
elif response.status_code == requests.codes.bad_request:
|
||||
return MapboxRoutingResponse(None, None, None)
|
||||
elif response.status_code == requests.codes.unprocessable_entity:
|
||||
return MapboxRoutingResponse(None, None, None)
|
||||
else:
|
||||
raise ServiceException(response.status_code, response)
|
||||
except requests.Timeout as te:
|
||||
|
||||
@@ -28,7 +28,7 @@ def coordinates_to_polygon(coordinates):
|
||||
wkt_coordinates = ','.join(result_coordinates)
|
||||
|
||||
try:
|
||||
sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MakePolygon(ST_GeomFromText('LINESTRING({0})', 4326))),3) as geom".format(wkt_coordinates)
|
||||
sql = "SELECT st_multi(ST_CollectionExtract(ST_MakeValid(ST_MakePolygon(ST_GeomFromText('LINESTRING({0})', 4326))),3)) as geom".format(wkt_coordinates)
|
||||
geometry = plpy.execute(sql, 1)[0]['geom']
|
||||
except BaseException as e:
|
||||
plpy.warning("Can't generate POLYGON from coordinates: {0}".format(e))
|
||||
|
||||
@@ -136,7 +136,8 @@ class RoutingConfig(ServiceConfig):
|
||||
ROUTING_PROVIDER_KEY = 'routing_provider'
|
||||
MAPZEN_PROVIDER = 'mapzen'
|
||||
MAPBOX_PROVIDER = 'mapbox'
|
||||
DEFAULT_PROVIDER = MAPZEN_PROVIDER
|
||||
TOMTOM_PROVIDER = 'tomtom'
|
||||
DEFAULT_PROVIDER = MAPBOX_PROVIDER
|
||||
QUOTA_KEY = 'mapzen_routing_quota'
|
||||
SOFT_LIMIT_KEY = 'soft_mapzen_routing_limit'
|
||||
METRICS_LOG_KEY = 'routing_log_path'
|
||||
@@ -147,11 +148,16 @@ class RoutingConfig(ServiceConfig):
|
||||
self._routing_provider = self._redis_config[self.ROUTING_PROVIDER_KEY]
|
||||
if not self._routing_provider:
|
||||
self._routing_provider = self.DEFAULT_PROVIDER
|
||||
self._mapzen_api_key = self._db_config.mapzen_routing_api_key
|
||||
self._mapzen_service_params = self._db_config.mapzen_routing_service_params
|
||||
self._mapbox_api_keys = self._db_config.mapbox_routing_api_keys
|
||||
self._mapbox_service_params = self._db_config.mapbox_routing_service_params
|
||||
self._set_monthly_quota()
|
||||
if self._routing_provider == self.MAPZEN_PROVIDER:
|
||||
self._mapzen_api_key = self._db_config.mapzen_routing_api_key
|
||||
self._mapzen_service_params = self._db_config.mapzen_routing_service_params
|
||||
elif self._routing_provider == self.MAPBOX_PROVIDER:
|
||||
self._mapbox_api_keys = self._db_config.mapbox_routing_api_keys
|
||||
self._mapbox_service_params = self._db_config.mapbox_routing_service_params
|
||||
elif self._routing_provider == self.TOMTOM_PROVIDER:
|
||||
self._tomtom_api_keys = self._db_config.tomtom_routing_api_keys
|
||||
self._tomtom_service_params = self._db_config.tomtom_routing_service_params
|
||||
self._routing_quota = self._get_effective_monthly_quota(self.QUOTA_KEY)
|
||||
self._set_soft_limit()
|
||||
self._period_end_date = date_parse(self._redis_config[self.PERIOD_END_DATE])
|
||||
|
||||
@@ -161,6 +167,8 @@ class RoutingConfig(ServiceConfig):
|
||||
return 'routing_mapzen'
|
||||
elif self._routing_provider == self.MAPBOX_PROVIDER:
|
||||
return 'routing_mapbox'
|
||||
elif self._routing_provider == self.TOMTOM_PROVIDER:
|
||||
return 'routing_tomtom'
|
||||
|
||||
@property
|
||||
def provider(self):
|
||||
@@ -190,9 +198,25 @@ class RoutingConfig(ServiceConfig):
|
||||
def mapbox_service_params(self):
|
||||
return self._mapbox_service_params
|
||||
|
||||
@property
|
||||
def tomtom_provider(self):
|
||||
return self._routing_provider == self.TOMTOM_PROVIDER
|
||||
|
||||
@property
|
||||
def tomtom_api_keys(self):
|
||||
return self._tomtom_api_keys
|
||||
|
||||
@property
|
||||
def tomtom_service_params(self):
|
||||
return self._tomtom_service_params
|
||||
|
||||
@property
|
||||
def routing_quota(self):
|
||||
return self._routing_quota
|
||||
|
||||
@property
|
||||
def monthly_quota(self):
|
||||
return self._monthly_quota
|
||||
return self._routing_quota
|
||||
|
||||
@property
|
||||
def period_end_date(self):
|
||||
@@ -202,9 +226,6 @@ class RoutingConfig(ServiceConfig):
|
||||
def soft_limit(self):
|
||||
return self._soft_limit
|
||||
|
||||
def _set_monthly_quota(self):
|
||||
self._monthly_quota = self._get_effective_monthly_quota(self.QUOTA_KEY)
|
||||
|
||||
def _set_soft_limit(self):
|
||||
if self.SOFT_LIMIT_KEY in self._redis_config and self._redis_config[self.SOFT_LIMIT_KEY].lower() == 'true':
|
||||
self._soft_limit = True
|
||||
@@ -225,8 +246,9 @@ class IsolinesRoutingConfig(ServiceConfig):
|
||||
GEOCODER_PROVIDER_KEY = 'geocoder_provider'
|
||||
MAPZEN_PROVIDER = 'mapzen'
|
||||
MAPBOX_PROVIDER = 'mapbox'
|
||||
TOMTOM_PROVIDER = 'tomtom'
|
||||
HEREMAPS_PROVIDER = 'heremaps'
|
||||
DEFAULT_PROVIDER = MAPZEN_PROVIDER
|
||||
DEFAULT_PROVIDER = MAPBOX_PROVIDER
|
||||
METRICS_LOG_KEY = 'isolines_log_path'
|
||||
|
||||
def __init__(self, redis_connection, db_conn, username, orgname=None):
|
||||
@@ -258,6 +280,9 @@ class IsolinesRoutingConfig(ServiceConfig):
|
||||
self._mapbox_matrix_api_keys = self._db_config.mapbox_matrix_api_keys
|
||||
self._mapbox_matrix_service_params = db_config.mapbox_matrix_service_params
|
||||
self._mapbox_isochrones_service_params = db_config.mapbox_isochrones_service_params
|
||||
elif self._isolines_provider == self.TOMTOM_PROVIDER:
|
||||
self._tomtom_isolinesx_api_keys = self._db_config.tomtom_isolines_api_keys
|
||||
self._tomtom_isolines_service_params = db_config.tomtom_isolines_service_params
|
||||
|
||||
@property
|
||||
def service_type(self):
|
||||
@@ -267,6 +292,8 @@ class IsolinesRoutingConfig(ServiceConfig):
|
||||
return 'mapzen_isolines'
|
||||
elif self._isolines_provider == self.MAPBOX_PROVIDER:
|
||||
return 'mapbox_isolines'
|
||||
elif self._isolines_provider == self.TOMTOM_PROVIDER:
|
||||
return 'tomtom_isolines'
|
||||
|
||||
@property
|
||||
def google_services_user(self):
|
||||
@@ -328,6 +355,18 @@ class IsolinesRoutingConfig(ServiceConfig):
|
||||
def mapbox_provider(self):
|
||||
return self._isolines_provider == self.MAPBOX_PROVIDER
|
||||
|
||||
@property
|
||||
def tomtom_isolines_api_keys(self):
|
||||
return self._tomtom_isolines_api_keys
|
||||
|
||||
@property
|
||||
def tomtom_isolines_service_params(self):
|
||||
return self._tomtom_isolines_service_params
|
||||
|
||||
@property
|
||||
def tomtom_provider(self):
|
||||
return self._isolines_provider == self.TOMTOM_PROVIDER
|
||||
|
||||
@property
|
||||
def heremaps_provider(self):
|
||||
return self._isolines_provider == self.HEREMAPS_PROVIDER
|
||||
@@ -386,12 +425,14 @@ class GeocoderConfig(ServiceConfig):
|
||||
GEOCODER_PROVIDER = 'geocoder_provider'
|
||||
MAPBOX_GEOCODER = 'mapbox'
|
||||
MAPBOX_GEOCODER_API_KEYS = 'mapbox_geocoder_api_keys'
|
||||
TOMTOM_GEOCODER = 'tomtom'
|
||||
TOMTOM_GEOCODER_API_KEYS = 'tomtom_geocoder_api_keys'
|
||||
QUOTA_KEY = 'geocoding_quota'
|
||||
SOFT_LIMIT_KEY = 'soft_geocoding_limit'
|
||||
USERNAME_KEY = 'username'
|
||||
ORGNAME_KEY = 'orgname'
|
||||
PERIOD_END_DATE = 'period_end_date'
|
||||
DEFAULT_PROVIDER = MAPZEN_GEOCODER
|
||||
DEFAULT_PROVIDER = MAPBOX_GEOCODER
|
||||
METRICS_LOG_KEY = 'geocoder_log_path'
|
||||
|
||||
def __init__(self, redis_connection, db_conn, username, orgname=None, forced_provider=None):
|
||||
@@ -415,6 +456,9 @@ class GeocoderConfig(ServiceConfig):
|
||||
elif self._geocoder_provider == self.MAPBOX_GEOCODER:
|
||||
if not self.mapbox_api_keys:
|
||||
raise ConfigException("""Mapbox config is not set up""")
|
||||
elif self._geocoder_provider == self.TOMTOM_GEOCODER:
|
||||
if not self.tomtom_api_keys:
|
||||
raise ConfigException("""TomTom config is not set up""")
|
||||
|
||||
return True
|
||||
|
||||
@@ -450,6 +494,10 @@ class GeocoderConfig(ServiceConfig):
|
||||
self._mapbox_api_keys = db_config.mapbox_geocoder_api_keys
|
||||
self._cost_per_hit = 0
|
||||
self._mapbox_service_params = db_config.mapbox_geocoder_service_params
|
||||
elif self._geocoder_provider == self.TOMTOM_GEOCODER:
|
||||
self._tomtom_api_keys = db_config.tomtom_geocoder_api_keys
|
||||
self._cost_per_hit = 0
|
||||
self._tomtom_service_params = db_config.tomtom_geocoder_service_params
|
||||
|
||||
@property
|
||||
def service_type(self):
|
||||
@@ -459,6 +507,8 @@ class GeocoderConfig(ServiceConfig):
|
||||
return 'geocoder_mapzen'
|
||||
elif self._geocoder_provider == self.MAPBOX_GEOCODER:
|
||||
return 'geocoder_mapbox'
|
||||
elif self._geocoder_provider == self.TOMTOM_GEOCODER:
|
||||
return 'geocoder_tomtom'
|
||||
elif self._geocoder_provider == self.NOKIA_GEOCODER:
|
||||
return 'geocoder_here'
|
||||
|
||||
@@ -478,6 +528,10 @@ class GeocoderConfig(ServiceConfig):
|
||||
def mapbox_geocoder(self):
|
||||
return self._geocoder_provider == self.MAPBOX_GEOCODER
|
||||
|
||||
@property
|
||||
def tomtom_geocoder(self):
|
||||
return self._geocoder_provider == self.TOMTOM_GEOCODER
|
||||
|
||||
@property
|
||||
def google_client_id(self):
|
||||
return self._google_maps_client_id
|
||||
@@ -529,6 +583,14 @@ class GeocoderConfig(ServiceConfig):
|
||||
def mapbox_service_params(self):
|
||||
return self._mapbox_service_params
|
||||
|
||||
@property
|
||||
def tomtom_api_keys(self):
|
||||
return self._tomtom_api_keys
|
||||
|
||||
@property
|
||||
def tomtom_service_params(self):
|
||||
return self._tomtom_service_params
|
||||
|
||||
@property
|
||||
def is_high_resolution(self):
|
||||
return True
|
||||
@@ -559,6 +621,7 @@ class ServicesDBConfig:
|
||||
self._get_here_config()
|
||||
self._get_mapzen_config()
|
||||
self._get_mapbox_config()
|
||||
self._get_tomtom_config()
|
||||
self._get_data_observatory_config()
|
||||
|
||||
def _get_server_config(self):
|
||||
@@ -576,50 +639,67 @@ class ServicesDBConfig:
|
||||
heremaps_conf_json = self._get_conf('heremaps_conf')
|
||||
if not heremaps_conf_json:
|
||||
raise ConfigException('Here maps configuration missing')
|
||||
else:
|
||||
heremaps_conf = json.loads(heremaps_conf_json)
|
||||
self._heremaps_geocoder_app_id = heremaps_conf['geocoder']['app_id']
|
||||
self._heremaps_geocoder_app_code = heremaps_conf['geocoder']['app_code']
|
||||
self._heremaps_geocoder_cost_per_hit = heremaps_conf['geocoder'][
|
||||
'geocoder_cost_per_hit']
|
||||
self._heremaps_geocoder_service_params = heremaps_conf['geocoder'].get('service', {})
|
||||
self._heremaps_isolines_app_id = heremaps_conf['isolines']['app_id']
|
||||
self._heremaps_isolines_app_code = heremaps_conf['isolines']['app_code']
|
||||
self._heremaps_isolines_service_params = heremaps_conf['isolines'].get('service', {})
|
||||
|
||||
heremaps_conf = json.loads(heremaps_conf_json)
|
||||
self._heremaps_geocoder_app_id = heremaps_conf['geocoder']['app_id']
|
||||
self._heremaps_geocoder_app_code = heremaps_conf['geocoder']['app_code']
|
||||
self._heremaps_geocoder_cost_per_hit = heremaps_conf['geocoder'][
|
||||
'geocoder_cost_per_hit']
|
||||
self._heremaps_geocoder_service_params = heremaps_conf['geocoder'].get('service', {})
|
||||
self._heremaps_isolines_app_id = heremaps_conf['isolines']['app_id']
|
||||
self._heremaps_isolines_app_code = heremaps_conf['isolines']['app_code']
|
||||
self._heremaps_isolines_service_params = heremaps_conf['isolines'].get('service', {})
|
||||
|
||||
def _get_mapzen_config(self):
|
||||
mapzen_conf_json = self._get_conf('mapzen_conf')
|
||||
# We dont use mapzen anymore so we don't need to check for its configuration
|
||||
if not mapzen_conf_json:
|
||||
raise ConfigException('Mapzen configuration missing')
|
||||
else:
|
||||
mapzen_conf = json.loads(mapzen_conf_json)
|
||||
self._mapzen_matrix_api_key = mapzen_conf['matrix']['api_key']
|
||||
self._mapzen_matrix_quota = mapzen_conf['matrix']['monthly_quota']
|
||||
self._mapzen_matrix_service_params = mapzen_conf['matrix'].get('service', {})
|
||||
self._mapzen_isochrones_service_params = mapzen_conf.get('isochrones', {}).get('service', {})
|
||||
self._mapzen_routing_api_key = mapzen_conf['routing']['api_key']
|
||||
self._mapzen_routing_quota = mapzen_conf['routing']['monthly_quota']
|
||||
self._mapzen_routing_service_params = mapzen_conf['routing'].get('service', {})
|
||||
self._mapzen_geocoder_api_key = mapzen_conf['geocoder']['api_key']
|
||||
self._mapzen_geocoder_quota = mapzen_conf['geocoder']['monthly_quota']
|
||||
self._mapzen_geocoder_service_params = mapzen_conf['geocoder'].get('service', {})
|
||||
return
|
||||
|
||||
mapzen_conf = json.loads(mapzen_conf_json)
|
||||
self._mapzen_matrix_api_key = mapzen_conf['matrix']['api_key']
|
||||
self._mapzen_matrix_quota = mapzen_conf['matrix']['monthly_quota']
|
||||
self._mapzen_matrix_service_params = mapzen_conf['matrix'].get('service', {})
|
||||
self._mapzen_isochrones_service_params = mapzen_conf.get('isochrones', {}).get('service', {})
|
||||
self._mapzen_routing_api_key = mapzen_conf['routing']['api_key']
|
||||
self._mapzen_routing_quota = mapzen_conf['routing']['monthly_quota']
|
||||
self._mapzen_routing_service_params = mapzen_conf['routing'].get('service', {})
|
||||
self._mapzen_geocoder_api_key = mapzen_conf['geocoder']['api_key']
|
||||
self._mapzen_geocoder_quota = mapzen_conf['geocoder']['monthly_quota']
|
||||
self._mapzen_geocoder_service_params = mapzen_conf['geocoder'].get('service', {})
|
||||
|
||||
def _get_mapbox_config(self):
|
||||
mapbox_conf_json = self._get_conf('mapbox_conf')
|
||||
if not mapbox_conf_json:
|
||||
raise ConfigException('Mapbox configuration missing')
|
||||
|
||||
mapbox_conf = json.loads(mapbox_conf_json)
|
||||
self._mapbox_matrix_api_keys = mapbox_conf['matrix']['api_keys']
|
||||
self._mapbox_matrix_quota = mapbox_conf['matrix']['monthly_quota']
|
||||
self._mapbox_matrix_service_params = mapbox_conf['matrix'].get('service', {})
|
||||
self._mapbox_isochrones_service_params = mapbox_conf.get('isochrones', {}).get('service', {})
|
||||
self._mapbox_routing_api_keys = mapbox_conf['routing']['api_keys']
|
||||
self._mapbox_routing_quota = mapbox_conf['routing']['monthly_quota']
|
||||
self._mapbox_routing_service_params = mapbox_conf['routing'].get('service', {})
|
||||
self._mapbox_geocoder_api_keys = mapbox_conf['geocoder']['api_keys']
|
||||
self._mapbox_geocoder_quota = mapbox_conf['geocoder']['monthly_quota']
|
||||
self._mapbox_geocoder_service_params = mapbox_conf['geocoder'].get('service', {})
|
||||
|
||||
def _get_tomtom_config(self):
|
||||
tomtom_conf_json = self._get_conf('tomtom_conf')
|
||||
if not tomtom_conf_json:
|
||||
raise ConfigException('TomTom configuration missing')
|
||||
else:
|
||||
mapbox_conf = json.loads(mapbox_conf_json)
|
||||
self._mapbox_matrix_api_keys = mapbox_conf['matrix']['api_keys']
|
||||
self._mapbox_matrix_quota = mapbox_conf['matrix']['monthly_quota']
|
||||
self._mapbox_matrix_service_params = mapbox_conf['matrix'].get('service', {})
|
||||
self._mapbox_isochrones_service_params = mapbox_conf.get('isochrones', {}).get('service', {})
|
||||
self._mapbox_routing_api_keys = mapbox_conf['routing']['api_keys']
|
||||
self._mapbox_routing_quota = mapbox_conf['routing']['monthly_quota']
|
||||
self._mapbox_routing_service_params = mapbox_conf['routing'].get('service', {})
|
||||
self._mapbox_geocoder_api_keys = mapbox_conf['geocoder']['api_keys']
|
||||
self._mapbox_geocoder_quota = mapbox_conf['geocoder']['monthly_quota']
|
||||
self._mapbox_geocoder_service_params = mapbox_conf['geocoder'].get('service', {})
|
||||
tomtom_conf = json.loads(tomtom_conf_json)
|
||||
self._tomtom_isolines_api_keys = tomtom_conf['isolines']['api_keys']
|
||||
self._tomtom_isolines_quota = tomtom_conf['isolines']['monthly_quota']
|
||||
self._tomtom_isolines_service_params = tomtom_conf.get('isolines', {}).get('service', {})
|
||||
self._tomtom_routing_api_keys = tomtom_conf['routing']['api_keys']
|
||||
self._tomtom_routing_quota = tomtom_conf['routing']['monthly_quota']
|
||||
self._tomtom_routing_service_params = tomtom_conf['routing'].get('service', {})
|
||||
self._tomtom_geocoder_api_keys = tomtom_conf['geocoder']['api_keys']
|
||||
self._tomtom_geocoder_quota = tomtom_conf['geocoder']['monthly_quota']
|
||||
self._tomtom_geocoder_service_params = tomtom_conf['geocoder'].get('service', {})
|
||||
|
||||
def _get_data_observatory_config(self):
|
||||
do_conf_json = self._get_conf('data_observatory_conf')
|
||||
@@ -754,6 +834,42 @@ class ServicesDBConfig:
|
||||
def mapbox_geocoder_service_params(self):
|
||||
return self._mapbox_geocoder_service_params
|
||||
|
||||
@property
|
||||
def tomtom_isolines_api_keys(self):
|
||||
return self._tomtom_isolines_api_keys
|
||||
|
||||
@property
|
||||
def tomtom_isolines_monthly_quota(self):
|
||||
return self._tomtom_isolines_quota
|
||||
|
||||
@property
|
||||
def tomtom_isolines_service_params(self):
|
||||
return self._tomtom_isolines_service_params
|
||||
|
||||
@property
|
||||
def tomtom_routing_api_keys(self):
|
||||
return self._tomtom_routing_api_keys
|
||||
|
||||
@property
|
||||
def tomtom_routing_monthly_quota(self):
|
||||
return self._tomtom_routing_quota
|
||||
|
||||
@property
|
||||
def tomtom_routing_service_params(self):
|
||||
return self._tomtom_routing_service_params
|
||||
|
||||
@property
|
||||
def tomtom_geocoder_api_keys(self):
|
||||
return self._tomtom_geocoder_api_keys
|
||||
|
||||
@property
|
||||
def tomtom_geocoder_monthly_quota(self):
|
||||
return self._tomtom_geocoder_quota
|
||||
|
||||
@property
|
||||
def tomtom_geocoder_service_params(self):
|
||||
return self._tomtom_geocoder_service_params
|
||||
|
||||
@property
|
||||
def data_observatory_connection_str(self):
|
||||
return self._data_observatory_connection_str
|
||||
|
||||
@@ -69,25 +69,16 @@ class QuotaChecker:
|
||||
|
||||
def check(self):
|
||||
""" Check if the current user quota surpasses the current quota """
|
||||
if re.match('geocoder_*',
|
||||
if re.match('^geocoder_',
|
||||
self._user_service_config.service_type) is not None:
|
||||
return self.__check_geocoder_quota()
|
||||
elif re.match('here_isolines',
|
||||
elif re.match('.*_isolines$',
|
||||
self._user_service_config.service_type) is not None:
|
||||
return self.__check_isolines_quota()
|
||||
elif re.match('mapzen_isolines',
|
||||
self._user_service_config.service_type) is not None:
|
||||
return self.__check_isolines_quota()
|
||||
elif re.match('mapbox_isolines',
|
||||
self._user_service_config.service_type) is not None:
|
||||
return self.__check_isolines_quota()
|
||||
elif re.match('routing_mapzen',
|
||||
elif re.match('^routing_',
|
||||
self._user_service_config.service_type) is not None:
|
||||
return self.__check_routing_quota()
|
||||
elif re.match('routing_mapbox',
|
||||
self._user_service_config.service_type) is not None:
|
||||
return self.__check_routing_quota()
|
||||
elif re.match('obs_*',
|
||||
elif re.match('^obs_',
|
||||
self._user_service_config.service_type) is not None:
|
||||
return self.__check_data_observatory_quota()
|
||||
else:
|
||||
@@ -122,7 +113,7 @@ class QuotaChecker:
|
||||
return False
|
||||
|
||||
def __check_routing_quota(self):
|
||||
user_quota = self._user_service_config.monthly_quota
|
||||
user_quota = self._user_service_config.routing_quota
|
||||
today = date.today()
|
||||
service_type = self._user_service_config.service_type
|
||||
current_used = self._user_service.used_quota(service_type, today)
|
||||
|
||||
@@ -22,8 +22,10 @@ class UserMetricsService:
|
||||
SERVICE_HERE_ISOLINES = 'here_isolines'
|
||||
SERVICE_MAPZEN_ISOLINES = 'mapzen_isolines'
|
||||
SERVICE_MAPBOX_ISOLINES = 'mapbox_isolines'
|
||||
SERVICE_TOMTOM_ISOLINES = 'tomtom_isolines'
|
||||
SERVICE_MAPZEN_ROUTING = 'routing_mapzen'
|
||||
SERVICE_MAPBOX_ROUTING = 'routing_mapbox'
|
||||
SERVICE_TOMTOM_ROUTING = 'routing_tomtom'
|
||||
SERVICE_OBSERVATORY = 'obs_general'
|
||||
DAY_OF_MONTH_ZERO_PADDED = '%d'
|
||||
|
||||
@@ -36,10 +38,12 @@ class UserMetricsService:
|
||||
def used_quota(self, service_type, date):
|
||||
if service_type in [self.SERVICE_HERE_ISOLINES,
|
||||
self.SERVICE_MAPZEN_ISOLINES,
|
||||
self.SERVICE_MAPBOX_ISOLINES]:
|
||||
self.SERVICE_MAPBOX_ISOLINES,
|
||||
self.SERVICE_TOMTOM_ISOLINES]:
|
||||
return self.__used_isolines_quota(service_type, date)
|
||||
elif service_type in [self.SERVICE_MAPZEN_ROUTING,
|
||||
self.SERVICE_MAPBOX_ROUTING]:
|
||||
self.SERVICE_MAPBOX_ROUTING,
|
||||
self.SERVICE_TOMTOM_ROUTING]:
|
||||
return self.__used_routing_quota(service_type, date)
|
||||
elif service_type == self.SERVICE_OBSERVATORY:
|
||||
return self.__used_observatory_quota(service_type, date)
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
from dateutil.parser import parse as date_parse
|
||||
from cartodb_services.refactor.service.utils import round_robin
|
||||
from cartodb_services.tomtom.types import TOMTOM_GEOCODER_APIKEY_ROUNDROBIN
|
||||
|
||||
|
||||
class TomTomGeocoderConfig(object):
|
||||
"""
|
||||
Configuration needed to operate the TomTom geocoder service.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
geocoding_quota,
|
||||
soft_geocoding_limit,
|
||||
period_end_date,
|
||||
cost_per_hit,
|
||||
log_path,
|
||||
tomtom_api_keys,
|
||||
username,
|
||||
organization,
|
||||
service_params,
|
||||
GD):
|
||||
self._geocoding_quota = geocoding_quota
|
||||
self._soft_geocoding_limit = soft_geocoding_limit
|
||||
self._period_end_date = period_end_date
|
||||
self._cost_per_hit = cost_per_hit
|
||||
self._log_path = log_path
|
||||
self._tomtom_api_keys = tomtom_api_keys
|
||||
self._username = username
|
||||
self._organization = organization
|
||||
self._service_params = service_params
|
||||
self._GD = GD
|
||||
|
||||
@property
|
||||
def service_type(self):
|
||||
return 'geocoder_tomtom'
|
||||
|
||||
@property
|
||||
def provider(self):
|
||||
return 'tomtom'
|
||||
|
||||
@property
|
||||
def is_high_resolution(self):
|
||||
return True
|
||||
|
||||
@property
|
||||
def geocoding_quota(self):
|
||||
return self._geocoding_quota
|
||||
|
||||
@property
|
||||
def soft_geocoding_limit(self):
|
||||
return self._soft_geocoding_limit
|
||||
|
||||
@property
|
||||
def period_end_date(self):
|
||||
return self._period_end_date
|
||||
|
||||
@property
|
||||
def cost_per_hit(self):
|
||||
return self._cost_per_hit
|
||||
|
||||
@property
|
||||
def log_path(self):
|
||||
return self._log_path
|
||||
|
||||
@property
|
||||
def tomtom_api_key(self):
|
||||
return round_robin(self._tomtom_api_keys, self._GD,
|
||||
TOMTOM_GEOCODER_APIKEY_ROUNDROBIN)
|
||||
|
||||
@property
|
||||
def username(self):
|
||||
return self._username
|
||||
|
||||
@property
|
||||
def organization(self):
|
||||
return self._organization
|
||||
|
||||
@property
|
||||
def service_params(self):
|
||||
return self._service_params
|
||||
|
||||
# TODO: for BW compat, remove
|
||||
@property
|
||||
def google_geocoder(self):
|
||||
return False
|
||||
|
||||
|
||||
class TomTomGeocoderConfigBuilder(object):
|
||||
|
||||
def __init__(self, server_conf, user_conf, org_conf, username, orgname, GD):
|
||||
self._server_conf = server_conf
|
||||
self._user_conf = user_conf
|
||||
self._org_conf = org_conf
|
||||
self._username = username
|
||||
self._orgname = orgname
|
||||
self._GD = GD
|
||||
|
||||
def get(self):
|
||||
tomtom_server_conf = self._server_conf.get('tomtom_conf')
|
||||
tomtom_api_keys = tomtom_server_conf['geocoder']['api_keys']
|
||||
tomtom_service_params = tomtom_server_conf['geocoder'].get('service', {})
|
||||
|
||||
geocoding_quota = self._get_quota()
|
||||
soft_geocoding_limit = self._user_conf.get('soft_geocoding_limit').lower() == 'true'
|
||||
cost_per_hit = 0
|
||||
period_end_date_str = self._org_conf.get('period_end_date') or self._user_conf.get('period_end_date')
|
||||
period_end_date = date_parse(period_end_date_str)
|
||||
|
||||
logger_conf = self._server_conf.get('logger_conf')
|
||||
log_path = logger_conf.get('geocoder_log_path', None)
|
||||
|
||||
return TomTomGeocoderConfig(geocoding_quota,
|
||||
soft_geocoding_limit,
|
||||
period_end_date,
|
||||
cost_per_hit,
|
||||
log_path,
|
||||
tomtom_api_keys,
|
||||
self._username,
|
||||
self._orgname,
|
||||
tomtom_service_params,
|
||||
self._GD)
|
||||
|
||||
def _get_quota(self):
|
||||
geocoding_quota = self._org_conf.get('geocoding_quota') or self._user_conf.get('geocoding_quota')
|
||||
if geocoding_quota is '':
|
||||
return 0
|
||||
|
||||
return int(geocoding_quota)
|
||||
@@ -0,0 +1,123 @@
|
||||
from dateutil.parser import parse as date_parse
|
||||
from cartodb_services.refactor.service.utils import round_robin
|
||||
from cartodb_services.tomtom.types import TOMTOM_ISOLINES_APIKEY_ROUNDROBIN
|
||||
|
||||
|
||||
class TomTomIsolinesConfig(object):
|
||||
"""
|
||||
Configuration needed to operate the TomTom directions service.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
isolines_quota,
|
||||
soft_isolines_limit,
|
||||
period_end_date,
|
||||
cost_per_hit,
|
||||
log_path,
|
||||
tomtom_api_keys,
|
||||
username,
|
||||
organization,
|
||||
service_params,
|
||||
GD):
|
||||
self._isolines_quota = isolines_quota
|
||||
self._soft_isolines_limit = soft_isolines_limit
|
||||
self._period_end_date = period_end_date
|
||||
self._cost_per_hit = cost_per_hit
|
||||
self._log_path = log_path
|
||||
self._tomtom_api_keys = tomtom_api_keys
|
||||
self._username = username
|
||||
self._organization = organization
|
||||
self._service_params = service_params
|
||||
self._GD = GD
|
||||
|
||||
@property
|
||||
def service_type(self):
|
||||
return 'tomtom_isolines'
|
||||
|
||||
@property
|
||||
def provider(self):
|
||||
return 'tomtom'
|
||||
|
||||
@property
|
||||
def is_high_resolution(self):
|
||||
return True
|
||||
|
||||
@property
|
||||
def isolines_quota(self):
|
||||
return self._isolines_quota
|
||||
|
||||
@property
|
||||
def soft_isolines_limit(self):
|
||||
return self._soft_isolines_limit
|
||||
|
||||
@property
|
||||
def period_end_date(self):
|
||||
return self._period_end_date
|
||||
|
||||
@property
|
||||
def cost_per_hit(self):
|
||||
return self._cost_per_hit
|
||||
|
||||
@property
|
||||
def log_path(self):
|
||||
return self._log_path
|
||||
|
||||
@property
|
||||
def tomtom_api_key(self):
|
||||
return round_robin(self._tomtom_api_keys, self._GD,
|
||||
TOMTOM_ISOLINES_APIKEY_ROUNDROBIN)
|
||||
|
||||
@property
|
||||
def username(self):
|
||||
return self._username
|
||||
|
||||
@property
|
||||
def organization(self):
|
||||
return self._organization
|
||||
|
||||
@property
|
||||
def service_params(self):
|
||||
return self._service_params
|
||||
|
||||
|
||||
class TomTomIsolinesConfigBuilder(object):
|
||||
|
||||
def __init__(self, server_conf, user_conf, org_conf, username, orgname, GD):
|
||||
self._server_conf = server_conf
|
||||
self._user_conf = user_conf
|
||||
self._org_conf = org_conf
|
||||
self._username = username
|
||||
self._orgname = orgname
|
||||
self._GD = GD
|
||||
|
||||
def get(self):
|
||||
tomtom_server_conf = self._server_conf.get('tomtom_conf')
|
||||
tomtom_api_keys = tomtom_server_conf['isolines']['api_keys']
|
||||
tomtom_service_params = tomtom_server_conf['isolines'].get('service', {})
|
||||
|
||||
isolines_quota = self._get_quota()
|
||||
soft_isolines_limit = self._user_conf.get('soft_here_isolines_limit').lower() == 'true'
|
||||
cost_per_hit = 0
|
||||
period_end_date_str = self._org_conf.get('period_end_date') or self._user_conf.get('period_end_date')
|
||||
period_end_date = date_parse(period_end_date_str)
|
||||
|
||||
logger_conf = self._server_conf.get('logger_conf')
|
||||
log_path = logger_conf.get('isolines_log_path', None)
|
||||
|
||||
return TomTomIsolinesConfig(isolines_quota,
|
||||
soft_isolines_limit,
|
||||
period_end_date,
|
||||
cost_per_hit,
|
||||
log_path,
|
||||
tomtom_api_keys,
|
||||
self._username,
|
||||
self._orgname,
|
||||
tomtom_service_params,
|
||||
self._GD)
|
||||
|
||||
def _get_quota(self):
|
||||
isolines_quota = self._org_conf.get('here_isolines_quota') or self._user_conf.get('here_isolines_quota')
|
||||
if isolines_quota is '':
|
||||
return 0
|
||||
|
||||
return int(isolines_quota)
|
||||
@@ -0,0 +1,131 @@
|
||||
from dateutil.parser import parse as date_parse
|
||||
from cartodb_services.refactor.service.utils import round_robin
|
||||
from cartodb_services.tomtom.types import TOMTOM_ROUTING_APIKEY_ROUNDROBIN
|
||||
|
||||
|
||||
class TomTomRoutingConfig(object):
|
||||
"""
|
||||
Configuration needed to operate the TomTom directions service.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
routing_quota,
|
||||
soft_routing_limit,
|
||||
monthly_quota,
|
||||
period_end_date,
|
||||
cost_per_hit,
|
||||
log_path,
|
||||
tomtom_api_keys,
|
||||
username,
|
||||
organization,
|
||||
service_params,
|
||||
GD):
|
||||
self._routing_quota = routing_quota
|
||||
self._soft_routing_limit = soft_routing_limit
|
||||
self._monthly_quota = monthly_quota
|
||||
self._period_end_date = period_end_date
|
||||
self._cost_per_hit = cost_per_hit
|
||||
self._log_path = log_path
|
||||
self._tomtom_api_keys = tomtom_api_keys
|
||||
self._username = username
|
||||
self._organization = organization
|
||||
self._service_params = service_params
|
||||
self._GD = GD
|
||||
|
||||
@property
|
||||
def service_type(self):
|
||||
return 'routing_tomtom'
|
||||
|
||||
@property
|
||||
def provider(self):
|
||||
return 'tomtom'
|
||||
|
||||
@property
|
||||
def is_high_resolution(self):
|
||||
return True
|
||||
|
||||
@property
|
||||
def routing_quota(self):
|
||||
return self._routing_quota
|
||||
|
||||
@property
|
||||
def soft_limit(self):
|
||||
return self._soft_routing_limit
|
||||
|
||||
@property
|
||||
def monthly_quota(self):
|
||||
return self._monthly_quota
|
||||
|
||||
@property
|
||||
def period_end_date(self):
|
||||
return self._period_end_date
|
||||
|
||||
@property
|
||||
def cost_per_hit(self):
|
||||
return self._cost_per_hit
|
||||
|
||||
@property
|
||||
def log_path(self):
|
||||
return self._log_path
|
||||
|
||||
@property
|
||||
def tomtom_api_key(self):
|
||||
return round_robin(self._tomtom_api_keys, self._GD,
|
||||
TOMTOM_ROUTING_APIKEY_ROUNDROBIN)
|
||||
|
||||
@property
|
||||
def username(self):
|
||||
return self._username
|
||||
|
||||
@property
|
||||
def organization(self):
|
||||
return self._organization
|
||||
|
||||
@property
|
||||
def service_params(self):
|
||||
return self._service_params
|
||||
|
||||
|
||||
class TomTomRoutingConfigBuilder(object):
|
||||
|
||||
def __init__(self, server_conf, user_conf, org_conf, username, orgname, GD):
|
||||
self._server_conf = server_conf
|
||||
self._user_conf = user_conf
|
||||
self._org_conf = org_conf
|
||||
self._username = username
|
||||
self._orgname = orgname
|
||||
self._GD = GD
|
||||
|
||||
def get(self):
|
||||
tomtom_server_conf = self._server_conf.get('tomtom_conf')
|
||||
tomtom_api_keys = tomtom_server_conf['routing']['api_keys']
|
||||
monthly_quota = tomtom_server_conf['routing']['monthly_quota']
|
||||
tomtom_service_params = tomtom_server_conf['routing'].get('service', {})
|
||||
|
||||
routing_quota = self._get_quota()
|
||||
soft_routing_limit = self._user_conf.get('soft_mapzen_routing_limit').lower() == 'true'
|
||||
cost_per_hit = 0
|
||||
period_end_date_str = self._org_conf.get('period_end_date') or self._user_conf.get('period_end_date')
|
||||
period_end_date = date_parse(period_end_date_str)
|
||||
|
||||
logger_conf = self._server_conf.get('logger_conf')
|
||||
log_path = logger_conf.get('routing_log_path', None)
|
||||
|
||||
return TomTomRoutingConfig(routing_quota,
|
||||
soft_routing_limit,
|
||||
monthly_quota,
|
||||
period_end_date,
|
||||
cost_per_hit,
|
||||
log_path,
|
||||
tomtom_api_keys,
|
||||
self._username,
|
||||
self._orgname,
|
||||
tomtom_service_params,
|
||||
self._GD)
|
||||
|
||||
def _get_quota(self):
|
||||
routing_quota = self._org_conf.get('mapzen_routing_quota') or self._user_conf.get('mapzen_routing_quota')
|
||||
if routing_quota is '':
|
||||
return 0
|
||||
|
||||
return int(routing_quota)
|
||||
@@ -0,0 +1,3 @@
|
||||
from geocoder import TomTomGeocoder
|
||||
from routing import TomTomRouting, TomTomRoutingResponse
|
||||
from isolines import TomTomIsolines, TomTomIsochronesResponse
|
||||
@@ -0,0 +1,112 @@
|
||||
#!/usr/local/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import json
|
||||
import requests
|
||||
from uritemplate import URITemplate
|
||||
from cartodb_services.metrics import Traceable
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
from cartodb_services.tools.qps import qps_retry
|
||||
from cartodb_services.tools.normalize import normalize
|
||||
|
||||
BASEURI = ('https://api.tomtom.com/search/2/geocode/'
|
||||
'{searchtext}.JSON'
|
||||
'?key={apiKey}'
|
||||
'&limit=1')
|
||||
ENTRY_RESULTS = 'results'
|
||||
ENTRY_POSITION = 'position'
|
||||
ENTRY_LON = 'lon'
|
||||
ENTRY_LAT = 'lat'
|
||||
|
||||
|
||||
class TomTomGeocoder(Traceable):
|
||||
'''
|
||||
Python wrapper for the TomTom Geocoder service.
|
||||
'''
|
||||
|
||||
def __init__(self, apikey, logger, service_params=None):
|
||||
service_params = service_params or {}
|
||||
self._apikey = apikey
|
||||
self._logger = logger
|
||||
|
||||
def _uri(self, searchtext, countries=None):
|
||||
baseuri = BASEURI + '&countrySet={}'.format(countries) \
|
||||
if countries else BASEURI
|
||||
uri = URITemplate(baseuri).expand(apiKey=self._apikey,
|
||||
searchtext=searchtext.encode('utf-8'))
|
||||
return uri
|
||||
|
||||
def _parse_geocoder_response(self, response):
|
||||
json_response = json.loads(response)
|
||||
|
||||
if json_response and json_response[ENTRY_RESULTS]:
|
||||
result = json_response[ENTRY_RESULTS][0]
|
||||
return self._extract_lng_lat_from_feature(result)
|
||||
else:
|
||||
return []
|
||||
|
||||
def _extract_lng_lat_from_feature(self, result):
|
||||
position = result[ENTRY_POSITION]
|
||||
longitude = position[ENTRY_LON]
|
||||
latitude = position[ENTRY_LAT]
|
||||
return [longitude, latitude]
|
||||
|
||||
def _validate_input(self, searchtext, city=None, state_province=None,
|
||||
country=None):
|
||||
if searchtext and searchtext.strip():
|
||||
return True
|
||||
elif city:
|
||||
return True
|
||||
elif state_province:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@qps_retry(qps=5)
|
||||
def geocode(self, searchtext, city=None, state_province=None,
|
||||
country=None):
|
||||
if searchtext:
|
||||
searchtext = searchtext.decode('utf-8')
|
||||
if city:
|
||||
city = city.decode('utf-8')
|
||||
if state_province:
|
||||
state_province = state_province.decode('utf-8')
|
||||
if country:
|
||||
country = country.decode('utf-8')
|
||||
|
||||
if not self._validate_input(searchtext, city, state_province, country):
|
||||
return []
|
||||
|
||||
address = []
|
||||
if searchtext and searchtext.strip():
|
||||
address.append(normalize(searchtext))
|
||||
if city:
|
||||
address.append(normalize(city))
|
||||
if state_province:
|
||||
address.append(normalize(state_province))
|
||||
|
||||
uri = self._uri(searchtext=', '.join(address), countries=country)
|
||||
|
||||
try:
|
||||
response = requests.get(uri)
|
||||
|
||||
if response.status_code == requests.codes.ok:
|
||||
return self._parse_geocoder_response(response.text)
|
||||
elif response.status_code == requests.codes.bad_request:
|
||||
return []
|
||||
elif response.status_code == requests.codes.unprocessable_entity:
|
||||
return []
|
||||
else:
|
||||
raise ServiceException(response.status_code, response)
|
||||
except requests.Timeout as te:
|
||||
# In case of timeout we want to stop the job because the server
|
||||
# could be down
|
||||
self._logger.error('Timeout connecting to TomTom geocoding server',
|
||||
te)
|
||||
raise ServiceException('Error geocoding {0} using TomTom'.format(
|
||||
searchtext), None)
|
||||
except requests.ConnectionError as ce:
|
||||
# Don't raise the exception to continue with the geocoding job
|
||||
self._logger.error('Error connecting to TomTom geocoding server',
|
||||
exception=ce)
|
||||
return []
|
||||
@@ -0,0 +1,140 @@
|
||||
'''
|
||||
Python implementation for TomTom services based isolines.
|
||||
'''
|
||||
|
||||
import json
|
||||
import requests
|
||||
from uritemplate import URITemplate
|
||||
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
from cartodb_services.tools.qps import qps_retry
|
||||
from cartodb_services.tools import Coordinate
|
||||
from types import (DEFAULT_PROFILE, VALID_PROFILES, DEFAULT_DEPARTAT,
|
||||
MAX_SPEEDS)
|
||||
|
||||
BASEURI = ('https://api.tomtom.com/routing/1/calculateReachableRange/'
|
||||
'{origin}'
|
||||
'/json'
|
||||
'?key={apikey}'
|
||||
'&timeBudgetInSec={time}'
|
||||
'&travelMode={travelmode}'
|
||||
'&departAt={departat}')
|
||||
|
||||
ENTRY_REACHABLERANGE = 'reachableRange'
|
||||
ENTRY_BOUNDARY = 'boundary'
|
||||
ENTRY_LATITUDE = 'latitude'
|
||||
ENTRY_LONGITUDE = 'longitude'
|
||||
|
||||
|
||||
class TomTomIsolines():
|
||||
'''
|
||||
Python wrapper for TomTom services based isolines.
|
||||
'''
|
||||
|
||||
def __init__(self, apikey, logger, service_params=None):
|
||||
service_params = service_params or {}
|
||||
self._apikey = apikey
|
||||
self._logger = logger
|
||||
|
||||
def _uri(self, origin, time_range, profile=DEFAULT_PROFILE,
|
||||
date_time=DEFAULT_DEPARTAT):
|
||||
uri = URITemplate(BASEURI).expand(apikey=self._apikey,
|
||||
origin=origin,
|
||||
time=time_range,
|
||||
travelmode=profile,
|
||||
departat=date_time)
|
||||
return uri
|
||||
|
||||
def _validate_profile(self, profile):
|
||||
if profile not in VALID_PROFILES:
|
||||
raise ValueError('{profile} is not a valid profile. '
|
||||
'Valid profiles are: {valid_profiles}'.format(
|
||||
profile=profile,
|
||||
valid_profiles=', '.join(
|
||||
[x for x in VALID_PROFILES])))
|
||||
|
||||
def _parse_coordinates(self, boundary):
|
||||
return [Coordinate(c[ENTRY_LONGITUDE], c[ENTRY_LATITUDE]) for c in boundary]
|
||||
|
||||
def _parse_reachablerange_response(self, response):
|
||||
json_response = json.loads(response)
|
||||
|
||||
if json_response:
|
||||
reachable_range = json_response[ENTRY_REACHABLERANGE]
|
||||
|
||||
return self._parse_coordinates(reachable_range[ENTRY_BOUNDARY])
|
||||
|
||||
@qps_retry(qps=5)
|
||||
def _calculate_isoline(self, origin, time_range,
|
||||
profile=DEFAULT_PROFILE,
|
||||
date_time=DEFAULT_DEPARTAT):
|
||||
origin = '{lat},{lon}'.format(lat=origin.latitude,
|
||||
lon=origin.longitude)
|
||||
|
||||
uri = self._uri(origin, time_range, profile, date_time)
|
||||
try:
|
||||
response = requests.get(uri)
|
||||
|
||||
if response.status_code == requests.codes.ok:
|
||||
return self._parse_reachablerange_response(response.text)
|
||||
elif response.status_code == requests.codes.bad_request:
|
||||
return []
|
||||
elif response.status_code == requests.codes.unprocessable_entity:
|
||||
return []
|
||||
else:
|
||||
raise ServiceException(response.status_code, response)
|
||||
except requests.Timeout as te:
|
||||
# In case of timeout we want to stop the job because the server
|
||||
# could be down
|
||||
self._logger.error('Timeout connecting to TomTom calculateReachableRange service',
|
||||
te)
|
||||
raise ServiceException('Error getting calculateReachableRange data from TomTom',
|
||||
None)
|
||||
except requests.ConnectionError as ce:
|
||||
# Don't raise the exception to continue with the geocoding job
|
||||
self._logger.error('Error connecting to TomTom calculateReachableRange service',
|
||||
exception=ce)
|
||||
return []
|
||||
|
||||
def calculate_isochrone(self, origin, time_ranges,
|
||||
profile=DEFAULT_PROFILE,
|
||||
date_time=DEFAULT_DEPARTAT):
|
||||
self._validate_profile(profile)
|
||||
|
||||
isochrones = []
|
||||
for time_range in time_ranges:
|
||||
coordinates = self._calculate_isoline(origin=origin,
|
||||
time_range=time_range,
|
||||
profile=profile,
|
||||
date_time=date_time)
|
||||
isochrones.append(TomTomIsochronesResponse(coordinates,
|
||||
time_range))
|
||||
return isochrones
|
||||
|
||||
def calculate_isodistance(self, origin, distance_range,
|
||||
profile=DEFAULT_PROFILE,
|
||||
date_time=DEFAULT_DEPARTAT):
|
||||
self._validate_profile(profile)
|
||||
|
||||
max_speed = MAX_SPEEDS[profile]
|
||||
time_range = distance_range / max_speed
|
||||
|
||||
return self._calculate_isoline(origin=origin,
|
||||
time_range=time_range,
|
||||
profile=profile,
|
||||
date_time=date_time)
|
||||
|
||||
|
||||
class TomTomIsochronesResponse:
|
||||
|
||||
def __init__(self, coordinates, duration):
|
||||
self._coordinates = coordinates
|
||||
self._duration = duration
|
||||
|
||||
@property
|
||||
def coordinates(self):
|
||||
return self._coordinates
|
||||
|
||||
@property
|
||||
def duration(self):
|
||||
return self._duration
|
||||
@@ -0,0 +1,144 @@
|
||||
'''
|
||||
Python client for the TomTom Routing service.
|
||||
'''
|
||||
|
||||
import json
|
||||
import requests
|
||||
from uritemplate import URITemplate
|
||||
from cartodb_services.metrics import Traceable
|
||||
from cartodb_services.tools import PolyLine
|
||||
from cartodb_services.tools.coordinates import (validate_coordinates,
|
||||
marshall_coordinates)
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
from cartodb_services.tools.qps import qps_retry
|
||||
from types import (DEFAULT_PROFILE, VALID_PROFILES, DEFAULT_DEPARTAT)
|
||||
|
||||
BASEURI = ('https://api.tomtom.com/routing/1/calculateRoute/'
|
||||
'{coordinates}'
|
||||
'/json'
|
||||
'?key={apikey}'
|
||||
'&travelMode={travelmode}'
|
||||
'&departAt={departat}'
|
||||
'&computeBestOrder=true')
|
||||
|
||||
NUM_WAYPOINTS_MIN = 2
|
||||
NUM_WAYPOINTS_MAX = 20
|
||||
|
||||
ENTRY_ROUTES = 'routes'
|
||||
ENTRY_SUMMARY = 'summary'
|
||||
ENTRY_LENGTH = 'lengthInMeters'
|
||||
ENTRY_TIME = 'travelTimeInSeconds'
|
||||
ENTRY_LEGS = 'legs'
|
||||
ENTRY_POINTS = 'points'
|
||||
ENTRY_LATITUDE = 'latitude'
|
||||
ENTRY_LONGITUDE = 'longitude'
|
||||
|
||||
|
||||
class TomTomRouting(Traceable):
|
||||
'''
|
||||
Python wrapper for the TomTom Routing service.
|
||||
'''
|
||||
|
||||
def __init__(self, apikey, logger, service_params=None):
|
||||
service_params = service_params or {}
|
||||
self._apikey = apikey
|
||||
self._logger = logger
|
||||
|
||||
def _uri(self, coordinates, profile=DEFAULT_PROFILE,
|
||||
date_time=DEFAULT_DEPARTAT):
|
||||
uri = URITemplate(BASEURI).expand(apikey=self._apikey,
|
||||
coordinates=coordinates,
|
||||
travelmode=profile,
|
||||
departat=date_time)
|
||||
return uri
|
||||
|
||||
def _validate_profile(self, profile):
|
||||
if profile not in VALID_PROFILES:
|
||||
raise ValueError('{profile} is not a valid profile. '
|
||||
'Valid profiles are: {valid_profiles}'.format(
|
||||
profile=profile,
|
||||
valid_profiles=', '.join(
|
||||
[x for x in VALID_PROFILES])))
|
||||
|
||||
def _marshall_coordinates(self, coordinates):
|
||||
return ':'.join(['{lat},{lon}'.format(lat=coordinate.latitude,
|
||||
lon=coordinate.longitude)
|
||||
for coordinate in coordinates])
|
||||
|
||||
def _parse_routing_response(self, response):
|
||||
json_response = json.loads(response)
|
||||
|
||||
if json_response:
|
||||
route = json_response[ENTRY_ROUTES][0] # Force the first route
|
||||
|
||||
geometry = self._parse_legs(route[ENTRY_LEGS])
|
||||
summary = route[ENTRY_SUMMARY]
|
||||
distance = summary[ENTRY_LENGTH]
|
||||
duration = summary[ENTRY_TIME]
|
||||
|
||||
return TomTomRoutingResponse(geometry, distance, duration)
|
||||
else:
|
||||
return TomTomRoutingResponse(None, None, None)
|
||||
|
||||
def _parse_legs(self, legs):
|
||||
geometry = []
|
||||
for leg in legs:
|
||||
points = leg[ENTRY_POINTS]
|
||||
for point in points:
|
||||
geometry.append((point[ENTRY_LATITUDE],
|
||||
point[ENTRY_LONGITUDE]))
|
||||
return geometry
|
||||
|
||||
@qps_retry(qps=5)
|
||||
def directions(self, waypoints, profile=DEFAULT_PROFILE,
|
||||
date_time=DEFAULT_DEPARTAT):
|
||||
self._validate_profile(profile)
|
||||
validate_coordinates(waypoints, NUM_WAYPOINTS_MIN, NUM_WAYPOINTS_MAX)
|
||||
|
||||
coordinates = self._marshall_coordinates(waypoints)
|
||||
|
||||
uri = self._uri(coordinates, profile, date_time)
|
||||
|
||||
try:
|
||||
response = requests.get(uri)
|
||||
|
||||
if response.status_code == requests.codes.ok:
|
||||
return self._parse_routing_response(response.text)
|
||||
elif response.status_code == requests.codes.bad_request:
|
||||
return TomTomRoutingResponse(None, None, None)
|
||||
elif response.status_code == requests.codes.unprocessable_entity:
|
||||
return TomTomRoutingResponse(None, None, None)
|
||||
else:
|
||||
raise ServiceException(response.status_code, response)
|
||||
except requests.Timeout as te:
|
||||
# In case of timeout we want to stop the job because the server
|
||||
# could be down
|
||||
self._logger.error('Timeout connecting to TomTom routing service',
|
||||
te)
|
||||
raise ServiceException('Error getting routing data from TomTom',
|
||||
None)
|
||||
except requests.ConnectionError as ce:
|
||||
# Don't raise the exception to continue with the geocoding job
|
||||
self._logger.error('Error connecting to TomTom routing service',
|
||||
exception=ce)
|
||||
return TomTomRoutingResponse(None, None, None)
|
||||
|
||||
|
||||
class TomTomRoutingResponse:
|
||||
|
||||
def __init__(self, shape, length, duration):
|
||||
self._shape = shape
|
||||
self._length = length
|
||||
self._duration = duration
|
||||
|
||||
@property
|
||||
def shape(self):
|
||||
return self._shape
|
||||
|
||||
@property
|
||||
def length(self):
|
||||
return self._length
|
||||
|
||||
@property
|
||||
def duration(self):
|
||||
return self._duration
|
||||
@@ -0,0 +1,26 @@
|
||||
TOMTOM_ROUTING_APIKEY_ROUNDROBIN = 'tomtom_routing_apikey_roundrobin'
|
||||
TOMTOM_GEOCODER_APIKEY_ROUNDROBIN = 'tomtom_geocoder_apikey_roundrobin'
|
||||
TOMTOM_ISOLINES_APIKEY_ROUNDROBIN = 'tomtom_isolines_apikey_roundrobin'
|
||||
|
||||
PROFILE_DRIVING = 'car'
|
||||
PROFILE_CYCLING = 'bicycle'
|
||||
PROFILE_WALKING = 'pedestrian'
|
||||
DEFAULT_PROFILE = PROFILE_DRIVING
|
||||
|
||||
DEFAULT_DEPARTAT = 'now'
|
||||
|
||||
VALID_PROFILES = [PROFILE_DRIVING,
|
||||
PROFILE_CYCLING,
|
||||
PROFILE_WALKING]
|
||||
|
||||
MAX_SPEEDS = {
|
||||
PROFILE_WALKING: 3.3333333, # In m/s, assuming 12km/h walking speed
|
||||
PROFILE_CYCLING: 16.67, # In m/s, assuming 60km/h max speed
|
||||
PROFILE_DRIVING: 41.67 # In m/s, assuming 140km/h max speed
|
||||
}
|
||||
|
||||
TRANSPORT_MODE_TO_TOMTOM = {
|
||||
'car': 'car',
|
||||
'walk': 'pedestrian',
|
||||
'bicycle': 'bicycle',
|
||||
}
|
||||
@@ -3,5 +3,7 @@ from coordinates import Coordinate
|
||||
from polyline import PolyLine
|
||||
from log import Logger, LoggerConfig
|
||||
from rate_limiter import RateLimiter
|
||||
from service_manager import ServiceManager, RateLimitExceeded
|
||||
from service_manager import ServiceManager
|
||||
from legacy_service_manager import LegacyServiceManager
|
||||
from exceptions import QuotaExceededException, RateLimitExceeded
|
||||
from country import country_to_iso3
|
||||
|
||||
@@ -45,6 +45,8 @@ def marshall_coordinates(coordinates):
|
||||
|
||||
def coordinates_to_polygon(coordinates):
|
||||
"""Convert a Coordinate array coordinates to a PostGIS polygon"""
|
||||
if not coordinates:
|
||||
return None
|
||||
coordinates.append(coordinates[0]) # Close the ring
|
||||
result_coordinates = []
|
||||
for coordinate in coordinates:
|
||||
@@ -53,7 +55,7 @@ def coordinates_to_polygon(coordinates):
|
||||
wkt_coordinates = ','.join(result_coordinates)
|
||||
|
||||
try:
|
||||
sql = "SELECT ST_CollectionExtract(ST_MakeValid(ST_MakePolygon(ST_GeomFromText('LINESTRING({0})', 4326))),3) as geom".format(wkt_coordinates)
|
||||
sql = "SELECT st_multi(ST_CollectionExtract(ST_MakeValid(ST_MakePolygon(ST_GeomFromText('LINESTRING({0})', 4326))),3)) as geom".format(wkt_coordinates)
|
||||
geometry = plpy.execute(sql, 1)[0]['geom']
|
||||
except BaseException as e:
|
||||
plpy.warning("Can't generate POLYGON from coordinates: {0}".format(e))
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import json
|
||||
|
||||
|
||||
class TimeoutException(Exception):
|
||||
def __str__(self):
|
||||
return repr('Timeout requesting to server')
|
||||
@@ -29,3 +28,11 @@ class WrongParams(Exception):
|
||||
class MalformedResult(Exception):
|
||||
def __str__(self):
|
||||
return repr('Result structure is malformed')
|
||||
|
||||
class RateLimitExceeded(Exception):
|
||||
def __str__(self):
|
||||
return repr('Rate limit exceeded')
|
||||
|
||||
class QuotaExceededException(Exception):
|
||||
def __str__(self):
|
||||
return repr('You have reached the limit of your quota')
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
def normalize(str_input):
|
||||
return str_input.replace('"', '"') \
|
||||
.replace(';', ',')
|
||||
@@ -51,9 +51,7 @@ def polyline_to_linestring(polyline):
|
||||
"""Convert a Mapzen polyline shape to a PostGIS linestring"""
|
||||
coordinates = []
|
||||
for point in polyline:
|
||||
# Divide by 10 because mapzen uses one more decimal than the
|
||||
# google standard (https://mapzen.com/documentation/turn-by-turn/decoding/)
|
||||
coordinates.append("%s %s" % (point[1]/10, point[0]/10))
|
||||
coordinates.append("%s %s" % (point[1], point[0]))
|
||||
wkt_coordinates = ','.join(coordinates)
|
||||
|
||||
try:
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
from cartodb_services.metrics import QuotaService
|
||||
from cartodb_services.tools import Logger
|
||||
from cartodb_services.tools import RateLimiter
|
||||
from cartodb_services.tools.log import Logger
|
||||
from cartodb_services.tools.rate_limiter import RateLimiter
|
||||
from cartodb_services.tools.exceptions import QuotaExceededException, RateLimitExceeded
|
||||
from cartodb_services.refactor.tools.logger import LoggerConfigBuilder
|
||||
from cartodb_services.refactor.backend.redis_metrics_connection import RedisMetricsConnectionFactory
|
||||
from cartodb_services.config import ServiceConfiguration, RateLimitsConfigBuilder
|
||||
|
||||
|
||||
class RateLimitExceeded(Exception):
|
||||
def __str__(self):
|
||||
return repr('Rate limit exceeded')
|
||||
|
||||
|
||||
class ServiceManagerBase:
|
||||
"""
|
||||
A Service manager collects the configuration needed to use a service,
|
||||
@@ -37,7 +33,7 @@ class ServiceManagerBase:
|
||||
if rate and not self.rate_limiter.check():
|
||||
raise RateLimitExceeded()
|
||||
if quota and not self.quota_service.check_user_quota():
|
||||
raise Exception('You have reached the limit of your quota')
|
||||
raise QuotaExceededException()
|
||||
|
||||
@property
|
||||
def config(self):
|
||||
|
||||
@@ -10,7 +10,7 @@ from setuptools import setup, find_packages
|
||||
setup(
|
||||
name='cartodb_services',
|
||||
|
||||
version='0.16.2',
|
||||
version='0.18.0',
|
||||
|
||||
description='CartoDB Services API Python Library',
|
||||
|
||||
|
||||
11
server/lib/python/cartodb_services/test/credentials.py
Normal file
11
server/lib/python/cartodb_services/test/credentials.py
Normal file
@@ -0,0 +1,11 @@
|
||||
import os
|
||||
|
||||
|
||||
def mapbox_api_key():
|
||||
"""Returns Mapbox API key. Requires setting MAPBOX_API_KEY environment variable."""
|
||||
return os.environ['MAPBOX_API_KEY']
|
||||
|
||||
|
||||
def tomtom_api_key():
|
||||
"""Returns TomTom API key. Requires setting TOMTOM_API_KEY environment variable."""
|
||||
return os.environ['TOMTOM_API_KEY']
|
||||
@@ -7,7 +7,7 @@ from cartodb_services.metrics.config import *
|
||||
|
||||
class TestGeocoderUserConfig(TestCase):
|
||||
|
||||
GEOCODER_PROVIDERS = ['heremaps', 'mapzen', 'mapbox', 'google']
|
||||
GEOCODER_PROVIDERS = ['heremaps', 'mapzen', 'mapbox', 'tomtom', 'google']
|
||||
|
||||
def setUp(self):
|
||||
self.redis_conn = MockRedis()
|
||||
@@ -28,6 +28,9 @@ class TestGeocoderUserConfig(TestCase):
|
||||
elif geocoder_provider == 'mapbox':
|
||||
assert geocoder_config.mapbox_geocoder is True
|
||||
assert geocoder_config.geocoding_quota == 100
|
||||
elif geocoder_provider == 'tomtom':
|
||||
assert geocoder_config.tomtom_geocoder is True
|
||||
assert geocoder_config.geocoding_quota == 100
|
||||
elif geocoder_provider == 'google':
|
||||
assert geocoder_config.google_geocoder is True
|
||||
assert geocoder_config.geocoding_quota is None
|
||||
@@ -81,7 +84,7 @@ class TestGeocoderUserConfig(TestCase):
|
||||
|
||||
class TestGeocoderOrgConfig(TestCase):
|
||||
|
||||
GEOCODER_PROVIDERS = ['heremaps', 'mapzen', 'mapbox', 'google']
|
||||
GEOCODER_PROVIDERS = ['heremaps', 'mapzen', 'mapbox', 'tomtom', 'google']
|
||||
|
||||
def setUp(self):
|
||||
self.redis_conn = MockRedis()
|
||||
@@ -107,6 +110,9 @@ class TestGeocoderOrgConfig(TestCase):
|
||||
elif geocoder_provider == 'mapbox':
|
||||
assert geocoder_config.mapbox_geocoder is True
|
||||
assert geocoder_config.geocoding_quota == 200
|
||||
elif geocoder_provider == 'tomtom':
|
||||
assert geocoder_config.tomtom_geocoder is True
|
||||
assert geocoder_config.geocoding_quota == 200
|
||||
elif geocoder_provider == 'google':
|
||||
assert geocoder_config.google_geocoder is True
|
||||
assert geocoder_config.geocoding_quota is None
|
||||
@@ -167,7 +173,7 @@ class TestGeocoderOrgConfig(TestCase):
|
||||
|
||||
|
||||
class TestIsolinesUserConfig(TestCase):
|
||||
ISOLINES_PROVIDERS = ['heremaps', 'mapzen', 'mapbox']
|
||||
ISOLINES_PROVIDERS = ['heremaps', 'mapzen', 'mapbox', 'tomtom']
|
||||
|
||||
def setUp(self):
|
||||
self.redis_conn = MockRedis()
|
||||
@@ -183,6 +189,8 @@ class TestIsolinesUserConfig(TestCase):
|
||||
assert isolines_config.service_type is 'mapzen_isolines'
|
||||
elif isolines_provider is 'mapbox':
|
||||
assert isolines_config.service_type is 'mapbox_isolines'
|
||||
elif isolines_provider is 'tomtom':
|
||||
assert isolines_config.service_type is 'tomtom_isolines'
|
||||
else:
|
||||
assert isolines_config.service_type is 'here_isolines'
|
||||
assert isolines_config.isolines_quota == 100
|
||||
@@ -226,7 +234,7 @@ class TestIsolinesUserConfig(TestCase):
|
||||
|
||||
class TestIsolinesOrgConfig(TestCase):
|
||||
|
||||
ISOLINES_PROVIDERS = ['heremaps', 'mapzen', 'mapbox']
|
||||
ISOLINES_PROVIDERS = ['heremaps', 'mapzen', 'mapbox', 'tomtom']
|
||||
|
||||
def setUp(self):
|
||||
self.redis_conn = MockRedis()
|
||||
@@ -301,7 +309,7 @@ class TestRoutingConfig(TestCase):
|
||||
self._redis_conn.hset(self._user_key, 'mapzen_routing_quota', 1000)
|
||||
orgname = None
|
||||
config = RoutingConfig(self._redis_conn, self._db_conn, self._username, orgname)
|
||||
assert config.monthly_quota == 1000
|
||||
assert config.routing_quota == 1000
|
||||
|
||||
def test_org_quota_overrides_user_quota(self):
|
||||
self._redis_conn.hset(self._user_key, 'mapzen_routing_quota', 1000)
|
||||
@@ -315,7 +323,7 @@ class TestRoutingConfig(TestCase):
|
||||
self._redis_conn.hset(orgname_key, 'here_isolines_quota', 0)
|
||||
|
||||
config = RoutingConfig(self._redis_conn, self._db_conn, self._username, orgname)
|
||||
assert config.monthly_quota == 5000
|
||||
assert config.routing_quota == 5000
|
||||
|
||||
def test_should_have_soft_limit_false_by_default(self):
|
||||
orgname = None
|
||||
|
||||
@@ -30,7 +30,7 @@ class TestQuotaChecker(TestCase):
|
||||
username = self.username,
|
||||
organization = None,
|
||||
service_type = self.service_type,
|
||||
monthly_quota = 1000,
|
||||
routing_quota = 1000,
|
||||
period_end_date = datetime.today(),
|
||||
soft_limit = False
|
||||
)
|
||||
@@ -43,7 +43,7 @@ class TestQuotaChecker(TestCase):
|
||||
username = self.username,
|
||||
organization = None,
|
||||
service_type = self.service_type,
|
||||
monthly_quota = 1000,
|
||||
routing_quota = 1000,
|
||||
period_end_date = datetime.today(),
|
||||
soft_limit = False
|
||||
)
|
||||
@@ -61,7 +61,7 @@ class TestQuotaChecker(TestCase):
|
||||
username = self.username,
|
||||
organization = None,
|
||||
service_type = self.service_type,
|
||||
monthly_quota = 1000,
|
||||
routing_quota = 1000,
|
||||
period_end_date = datetime.today(),
|
||||
soft_limit = False
|
||||
)
|
||||
@@ -75,7 +75,7 @@ class TestQuotaChecker(TestCase):
|
||||
username = self.username,
|
||||
organization = None,
|
||||
service_type = self.service_type,
|
||||
monthly_quota = 1000,
|
||||
routing_quota = 1000,
|
||||
period_end_date = datetime.today(),
|
||||
soft_limit = True
|
||||
)
|
||||
|
||||
@@ -18,10 +18,10 @@ class GoogleMapsClientFactoryTestCase(unittest.TestCase):
|
||||
GoogleMapsClientFactory.clients = {}
|
||||
|
||||
def test_consecutive_calls_with_same_params_return_same_client(self):
|
||||
id = 'any_id'
|
||||
client_id = 'any_id'
|
||||
key = base64.b64encode('any_key')
|
||||
client1 = GoogleMapsClientFactory.get(id, key)
|
||||
client2 = GoogleMapsClientFactory.get(id, key)
|
||||
client1 = GoogleMapsClientFactory.get(client_id, key)
|
||||
client2 = GoogleMapsClientFactory.get(client_id, key)
|
||||
self.assertEqual(client1, client2)
|
||||
|
||||
def test_consecutive_calls_with_different_key_return_different_clients(self):
|
||||
@@ -29,11 +29,11 @@ class GoogleMapsClientFactoryTestCase(unittest.TestCase):
|
||||
This requirement is important for security reasons as well as not to
|
||||
cache a wrong key accidentally.
|
||||
"""
|
||||
id = 'any_id'
|
||||
client_id = 'any_id'
|
||||
key1 = base64.b64encode('any_key')
|
||||
key2 = base64.b64encode('another_key')
|
||||
client1 = GoogleMapsClientFactory.get(id, key1)
|
||||
client2 = GoogleMapsClientFactory.get(id, key2)
|
||||
client1 = GoogleMapsClientFactory.get(client_id, key1)
|
||||
client2 = GoogleMapsClientFactory.get(client_id, key2)
|
||||
self.assertNotEqual(client1, client2)
|
||||
|
||||
def test_consecutive_calls_with_different_ids_return_different_clients(self):
|
||||
@@ -59,3 +59,11 @@ class GoogleMapsClientFactoryTestCase(unittest.TestCase):
|
||||
def test_credentials_with_underscores_can_be_valid(self):
|
||||
client = GoogleMapsClientFactory.get('yet_another_dummy_client_id', 'Ola_k_ase___')
|
||||
self.assertIsInstance(client, googlemaps.Client)
|
||||
|
||||
def test_invalid_credentials(self):
|
||||
with self.assertRaises(InvalidGoogleCredentials):
|
||||
GoogleMapsClientFactory.get('dummy_client_id', 'lalala')
|
||||
|
||||
def test_credentials_with_channel(self):
|
||||
client = GoogleMapsClientFactory.get('yet_another_dummy_client_id', 'Ola_k_ase___', 'channel')
|
||||
self.assertIsInstance(client, googlemaps.Client)
|
||||
|
||||
@@ -118,3 +118,18 @@ class GoogleGeocoderTestCase(unittest.TestCase):
|
||||
searchtext='Calle Eloy Gonzalo 27',
|
||||
city='Madrid',
|
||||
country='España')
|
||||
|
||||
def test_client_data_extraction(self, req_mock):
|
||||
client_id, channel = self.geocoder.parse_client_id('dummy_client_id')
|
||||
self.assertEqual(client_id, 'dummy_client_id')
|
||||
self.assertEqual(channel, None)
|
||||
|
||||
def test_client_data_extraction_with_client_parameter(self, req_mock):
|
||||
client_id, channel = self.geocoder.parse_client_id('client=gme-test')
|
||||
self.assertEqual(client_id, 'gme-test')
|
||||
self.assertEqual(channel, None)
|
||||
|
||||
def test_client_data_extraction_with_client_and_channel_parameter(self, req_mock):
|
||||
client_id, channel = self.geocoder.parse_client_id('client=gme-test&channel=testchannel')
|
||||
self.assertEqual(client_id, 'gme-test')
|
||||
self.assertEqual(channel, 'testchannel')
|
||||
|
||||
@@ -80,6 +80,7 @@ def plpy_mock_config():
|
||||
plpy_mock._define_result("CDB_Conf_GetConf\('heremaps_conf'\)", [{'conf': '{"geocoder": {"app_id": "app_id", "app_code": "code", "geocoder_cost_per_hit": 1}, "isolines": {"app_id": "app_id", "app_code": "code"}}'}])
|
||||
plpy_mock._define_result("CDB_Conf_GetConf\('mapzen_conf'\)", [{'conf': '{"routing": {"api_key": "api_key_rou", "monthly_quota": 1500000}, "geocoder": {"api_key": "api_key_geo", "monthly_quota": 1500000}, "matrix": {"api_key": "api_key_mat", "monthly_quota": 1500000}}'}])
|
||||
plpy_mock._define_result("CDB_Conf_GetConf\('mapbox_conf'\)", [{'conf': '{"routing": {"api_keys": ["api_key_rou"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["api_key_geo"], "monthly_quota": 1500000}, "matrix": {"api_keys": ["api_key_mat"], "monthly_quota": 1500000}}'}])
|
||||
plpy_mock._define_result("CDB_Conf_GetConf\('tomtom_conf'\)", [{'conf': '{"routing": {"api_keys": ["api_key_rou"], "monthly_quota": 1500000}, "geocoder": {"api_keys": ["api_key_geo"], "monthly_quota": 1500000}, "isolines": {"api_keys": ["api_key_mat"], "monthly_quota": 1500000}}'}])
|
||||
plpy_mock._define_result("CDB_Conf_GetConf\('logger_conf'\)", [{'conf': '{"geocoder_log_path": "/dev/null"}'}])
|
||||
plpy_mock._define_result("CDB_Conf_GetConf\('data_observatory_conf'\)", [{'conf': '{"connection": {"whitelist": ["ethervoid"], "production": "host=localhost port=5432 dbname=dataservices_db user=geocoder_api", "staging": "host=localhost port=5432 dbname=dataservices_db user=geocoder_api"}}'}])
|
||||
plpy_mock._define_result("CDB_Conf_GetConf\('server_conf'\)", [{'conf': '{"environment": "testing"}'}])
|
||||
|
||||
@@ -128,8 +128,14 @@ class HereMapsGeocoderTestCase(unittest.TestCase):
|
||||
def test_geocode_address_with_no_params(self, req_mock):
|
||||
req_mock.register_uri('GET', HereMapsGeocoder.PRODUCTION_GEOCODE_JSON_URL,
|
||||
text=self.GOOD_RESPONSE)
|
||||
with self.assertRaises(NoGeocodingParams):
|
||||
self.geocoder.geocode()
|
||||
result = self.geocoder.geocode()
|
||||
self.assertEqual(result, [])
|
||||
|
||||
def test_geocode_address_with_non_empty_string_params(self, req_mock):
|
||||
req_mock.register_uri('GET', HereMapsGeocoder.PRODUCTION_GEOCODE_JSON_URL,
|
||||
text=self.GOOD_RESPONSE)
|
||||
result = self.geocoder.geocode(searchtext=" ", city=None, state=" ", country=" ")
|
||||
self.assertEqual(result, [])
|
||||
|
||||
def test_geocode_address_empty_response(self, req_mock):
|
||||
req_mock.register_uri('GET', HereMapsGeocoder.PRODUCTION_GEOCODE_JSON_URL,
|
||||
|
||||
@@ -2,8 +2,8 @@ import unittest
|
||||
from mock import Mock
|
||||
from cartodb_services.mapbox import MapboxGeocoder
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
from credentials import mapbox_api_key
|
||||
|
||||
VALID_TOKEN = 'pk.eyJ1IjoiYWNhcmxvbiIsImEiOiJjamJuZjQ1Zjc0Ymt4Mnh0YmFrMmhtYnY4In0.gt9cw0VeKc3rM2mV5pcEmg'
|
||||
INVALID_TOKEN = 'invalid_token'
|
||||
VALID_ADDRESS = 'Calle Siempreviva 3, Valladolid'
|
||||
WELL_KNOWN_LONGITUDE = -4.730947
|
||||
@@ -12,7 +12,7 @@ WELL_KNOWN_LATITUDE = 41.668654
|
||||
|
||||
class MapboxGeocoderTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.geocoder = MapboxGeocoder(token=VALID_TOKEN, logger=Mock())
|
||||
self.geocoder = MapboxGeocoder(token=mapbox_api_key(), logger=Mock())
|
||||
|
||||
def test_invalid_token(self):
|
||||
invalid_geocoder = MapboxGeocoder(token=INVALID_TOKEN, logger=Mock())
|
||||
@@ -34,3 +34,23 @@ class MapboxGeocoderTestCase(unittest.TestCase):
|
||||
place = self.geocoder.geocode(searchtext='New York', country='us')
|
||||
|
||||
assert place
|
||||
|
||||
def test_odd_characters(self):
|
||||
place = self.geocoder.geocode(searchtext='Barcelona; "Spain"')
|
||||
|
||||
assert place
|
||||
|
||||
def test_empty_request(self):
|
||||
place = self.geocoder.geocode(searchtext='', country=None, city=None, state_province=None)
|
||||
|
||||
assert place == []
|
||||
|
||||
def test_empty_search_text_request(self):
|
||||
place = self.geocoder.geocode(searchtext=' ', country='us', city=None, state_province="")
|
||||
|
||||
assert place == []
|
||||
|
||||
def test_unknown_place_request(self):
|
||||
place = self.geocoder.geocode(searchtext='[unknown]', country='ch', state_province=None, city=None)
|
||||
|
||||
assert place == []
|
||||
|
||||
@@ -7,15 +7,15 @@ from cartodb_services.mapbox.routing import MapboxRouting
|
||||
from cartodb_services.tools import Coordinate
|
||||
from cartodb_services.tools.coordinates import (validate_coordinates,
|
||||
marshall_coordinates)
|
||||
from credentials import mapbox_api_key
|
||||
|
||||
VALID_TOKEN = 'pk.eyJ1IjoiYWNhcmxvbiIsImEiOiJjamJuZjQ1Zjc0Ymt4Mnh0YmFrMmhtYnY4In0.gt9cw0VeKc3rM2mV5pcEmg'
|
||||
VALID_ORIGIN = Coordinate(-73.989, 40.733)
|
||||
|
||||
|
||||
class MapboxIsolinesTestCase(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
matrix_client = MapboxMatrixClient(token=VALID_TOKEN, logger=Mock())
|
||||
matrix_client = MapboxMatrixClient(token=mapbox_api_key(), logger=Mock())
|
||||
self.mapbox_isolines = MapboxIsolines(matrix_client, logger=Mock())
|
||||
|
||||
def test_calculate_isochrone(self):
|
||||
|
||||
@@ -4,8 +4,8 @@ from cartodb_services.mapbox import MapboxMatrixClient
|
||||
from cartodb_services.mapbox.matrix_client import DEFAULT_PROFILE
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
from cartodb_services.tools import Coordinate
|
||||
from credentials import mapbox_api_key
|
||||
|
||||
VALID_TOKEN = 'pk.eyJ1IjoiYWNhcmxvbiIsImEiOiJjamJuZjQ1Zjc0Ymt4Mnh0YmFrMmhtYnY4In0.gt9cw0VeKc3rM2mV5pcEmg'
|
||||
INVALID_TOKEN = 'invalid_token'
|
||||
VALID_ORIGIN = Coordinate(-73.989, 40.733)
|
||||
VALID_TARGET = Coordinate(-74, 40.733)
|
||||
@@ -22,7 +22,7 @@ INVALID_PROFILE = 'invalid_profile'
|
||||
|
||||
class MapboxMatrixTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.matrix_client = MapboxMatrixClient(token=VALID_TOKEN,
|
||||
self.matrix_client = MapboxMatrixClient(token=mapbox_api_key(),
|
||||
logger=Mock())
|
||||
|
||||
def test_invalid_profile(self):
|
||||
|
||||
@@ -4,8 +4,8 @@ from cartodb_services.mapbox import MapboxRouting
|
||||
from cartodb_services.mapbox.routing import DEFAULT_PROFILE
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
from cartodb_services.tools import Coordinate
|
||||
from credentials import mapbox_api_key
|
||||
|
||||
VALID_TOKEN = 'pk.eyJ1IjoiYWNhcmxvbiIsImEiOiJjamJuZjQ1Zjc0Ymt4Mnh0YmFrMmhtYnY4In0.gt9cw0VeKc3rM2mV5pcEmg'
|
||||
INVALID_TOKEN = 'invalid_token'
|
||||
VALID_WAYPOINTS = [Coordinate(-73.989, 40.733), Coordinate(-74, 40.733)]
|
||||
NUM_WAYPOINTS_MAX = 25
|
||||
@@ -31,7 +31,7 @@ WELL_KNOWN_LENGTH = 1317.9
|
||||
|
||||
class MapboxRoutingTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.routing = MapboxRouting(token=VALID_TOKEN, logger=Mock())
|
||||
self.routing = MapboxRouting(token=mapbox_api_key(), logger=Mock())
|
||||
|
||||
def test_invalid_profile(self):
|
||||
with self.assertRaises(ValueError):
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import unittest
|
||||
from mock import Mock
|
||||
from cartodb_services.tomtom import TomTomGeocoder
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
from credentials import tomtom_api_key
|
||||
|
||||
INVALID_APIKEY = 'invalid_apikey'
|
||||
VALID_ADDRESS = u'Mantería 3, Valladolid'.encode('utf-8')
|
||||
|
||||
|
||||
class TomTomGeocoderTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.geocoder = TomTomGeocoder(apikey=tomtom_api_key(), logger=Mock())
|
||||
|
||||
def test_invalid_token(self):
|
||||
invalid_geocoder = TomTomGeocoder(apikey=INVALID_APIKEY, logger=Mock())
|
||||
with self.assertRaises(ServiceException):
|
||||
invalid_geocoder.geocode(VALID_ADDRESS)
|
||||
|
||||
def test_valid_request(self):
|
||||
place = self.geocoder.geocode(VALID_ADDRESS)
|
||||
|
||||
assert place
|
||||
|
||||
def test_valid_request_namedplace(self):
|
||||
place = self.geocoder.geocode(searchtext='Barcelona')
|
||||
|
||||
assert place
|
||||
|
||||
def test_valid_request_namedplace2(self):
|
||||
place = self.geocoder.geocode(searchtext='New York', country='us')
|
||||
|
||||
assert place
|
||||
|
||||
def test_odd_characters(self):
|
||||
place = self.geocoder.geocode(searchtext='Barcelona; "Spain"')
|
||||
|
||||
assert place
|
||||
|
||||
def test_empty_request(self):
|
||||
place = self.geocoder.geocode(searchtext='', country=None, city=None, state_province=None)
|
||||
|
||||
assert place == []
|
||||
|
||||
def test_empty_search_text_request(self):
|
||||
place = self.geocoder.geocode(searchtext=' ', country='us', city=None, state_province="")
|
||||
|
||||
assert place == []
|
||||
|
||||
def test_unknown_place_request(self):
|
||||
place = self.geocoder.geocode(searchtext='[unknown]', country='ch', state_province=None, city=None)
|
||||
|
||||
assert place == []
|
||||
@@ -0,0 +1,33 @@
|
||||
import unittest
|
||||
from mock import Mock
|
||||
from cartodb_services.tomtom.isolines import TomTomIsolines, DEFAULT_PROFILE
|
||||
from cartodb_services.tools import Coordinate
|
||||
|
||||
from credentials import tomtom_api_key
|
||||
|
||||
VALID_ORIGIN = Coordinate(-73.989, 40.733)
|
||||
|
||||
|
||||
class TomTomIsolinesTestCase(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.tomtom_isolines = TomTomIsolines(apikey=tomtom_api_key(),
|
||||
logger=Mock())
|
||||
|
||||
def test_calculate_isochrone(self):
|
||||
time_ranges = [300, 900]
|
||||
solution = self.tomtom_isolines.calculate_isochrone(
|
||||
origin=VALID_ORIGIN,
|
||||
profile=DEFAULT_PROFILE,
|
||||
time_ranges=time_ranges)
|
||||
|
||||
assert solution
|
||||
|
||||
def test_calculate_isodistance(self):
|
||||
distance_range = 10000
|
||||
solution = self.tomtom_isolines.calculate_isodistance(
|
||||
origin=VALID_ORIGIN,
|
||||
profile=DEFAULT_PROFILE,
|
||||
distance_range=distance_range)
|
||||
|
||||
assert solution
|
||||
@@ -0,0 +1,52 @@
|
||||
import unittest
|
||||
from mock import Mock
|
||||
from cartodb_services.tomtom import TomTomRouting
|
||||
from cartodb_services.tomtom.routing import DEFAULT_PROFILE
|
||||
from cartodb_services.tools.exceptions import ServiceException
|
||||
from cartodb_services.tools import Coordinate
|
||||
from credentials import tomtom_api_key
|
||||
|
||||
INVALID_APIKEY = 'invalid_apikey'
|
||||
VALID_WAYPOINTS = [Coordinate(13.42936, 52.50931),
|
||||
Coordinate(13.43872, 52.50274)]
|
||||
NUM_WAYPOINTS_MAX = 20
|
||||
INVALID_WAYPOINTS_EMPTY = []
|
||||
INVALID_WAYPOINTS_MIN = [Coordinate(13.42936, 52.50931)]
|
||||
INVALID_WAYPOINTS_MAX = [Coordinate(13.42936, 52.50931)
|
||||
for x in range(0, NUM_WAYPOINTS_MAX + 2)]
|
||||
VALID_PROFILE = DEFAULT_PROFILE
|
||||
INVALID_PROFILE = 'invalid_profile'
|
||||
|
||||
|
||||
class TomTomRoutingTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.routing = TomTomRouting(apikey=tomtom_api_key(), logger=Mock())
|
||||
|
||||
def test_invalid_profile(self):
|
||||
with self.assertRaises(ValueError):
|
||||
self.routing.directions(VALID_WAYPOINTS, INVALID_PROFILE)
|
||||
|
||||
def test_invalid_waypoints_empty(self):
|
||||
with self.assertRaises(ValueError):
|
||||
self.routing.directions(INVALID_WAYPOINTS_EMPTY, VALID_PROFILE)
|
||||
|
||||
def test_invalid_waypoints_min(self):
|
||||
with self.assertRaises(ValueError):
|
||||
self.routing.directions(INVALID_WAYPOINTS_MIN, VALID_PROFILE)
|
||||
|
||||
def test_invalid_waypoints_max(self):
|
||||
with self.assertRaises(ValueError):
|
||||
self.routing.directions(INVALID_WAYPOINTS_MAX, VALID_PROFILE)
|
||||
|
||||
def test_invalid_token(self):
|
||||
invalid_routing = TomTomRouting(apikey=INVALID_APIKEY, logger=Mock())
|
||||
with self.assertRaises(ServiceException):
|
||||
invalid_routing.directions(VALID_WAYPOINTS,
|
||||
VALID_PROFILE)
|
||||
|
||||
def test_valid_request(self):
|
||||
route = self.routing.directions(VALID_WAYPOINTS, VALID_PROFILE)
|
||||
|
||||
assert route.shape
|
||||
assert route.length
|
||||
assert route.duration
|
||||
@@ -23,14 +23,6 @@ class TestStreetFunctions(TestCase):
|
||||
geometry = IntegrationTestHelper.execute_query(self.sql_api_url, query)
|
||||
assert_not_equal(geometry['geometry'], None)
|
||||
|
||||
def test_if_select_with_mapzen_provider_street_point_is_ok(self):
|
||||
query = "SELECT cdb_mapzen_geocode_street_point(street) " \
|
||||
"as geometry FROM {0} LIMIT 1&api_key={1}".format(
|
||||
self.env_variables['table_name'],
|
||||
self.env_variables['api_key'])
|
||||
geometry = IntegrationTestHelper.execute_query(self.sql_api_url, query)
|
||||
assert_not_equal(geometry['geometry'], None)
|
||||
|
||||
def test_if_select_with_street_without_api_key_raise_error(self):
|
||||
query = "SELECT cdb_geocode_street_point(street) " \
|
||||
"as geometry FROM {0} LIMIT 1".format(
|
||||
|
||||
Reference in New Issue
Block a user