osm_poi_matchmaker.dao.poi_base.POIBase.pool()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
0 ignored issues
show
introduced by
Missing module docstring
Loading history...
2
try:
3
    import logging
4
    import sys
5
    import geopandas as gpd
6
    import pandas as pd
7
    import sqlalchemy
8
    import time
9
    import math
10
    from math import isnan
0 ignored issues
show
Unused Code introduced by
Unused isnan imported from math
Loading history...
11
    from osm_poi_matchmaker.utils import config, poitypes
12
    from osm_poi_matchmaker.dao.data_structure import Base
13
    import psycopg2
14
except ImportError as err:
15
    logging.error('Error %s import module: %s', __name__, err)
16
    logging.exception('Exception occurred')
17
18
    sys.exit(128)
19
20
21
class POIBase:
22
    """Represents the full database.
23
24
    :param db_conection: Either a sqlalchemy database url or a filename to be used with sqlite.
25
26
    """
27
28
    def __init__(self, db_connection, retry_counter=100, retry_sleep=30):
29
        reco = 0  # Actual retry counter
30
        self.db_retry_counter = retry_counter
31
        self.db_retry_sleep = retry_sleep
32
        self.db_connection = db_connection
33
        self.db_filename = None
34
        if '://' not in db_connection:
35
            self.db_connection = 'sqlite:///{}'.format(self.db_connection)
36
        if self.db_connection.startswith('sqlite'):
37
            self.db_filename = self.db_connection
38
        try:
39
            self.engine = sqlalchemy.create_engine(self.db_connection, client_encoding='utf8', echo=False)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (106/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
40
        except psycopg2.OperationalError as e:
0 ignored issues
show
Coding Style Naming introduced by
Variable name "e" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
41
            logging.error('Database error: %s', e)
42
            if self.retry_counter >= reco:
0 ignored issues
show
Bug introduced by
The Instance of POIBase does not seem to have a member named retry_counter.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
43
                logging.error('Cannot connect to database with %s connection string', self.db_connection)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (105/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
44
            else:
45
                logging.error('Cannot connect to the database. It will retry within %s seconds. [%s/%s]',
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (105/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
46
                              self.db_retry_sleep, reco, self.db_retry_counter)
47
                time.sleep(self.db_retry_sleep)
48
                self.engine = sqlalchemy.create_engine(self.db_connection, echo=False)
49
                self.db_retry_counter += 1
50
        self.Session = sqlalchemy.orm.sessionmaker(bind=self.engine)
0 ignored issues
show
Coding Style Naming introduced by
Attribute name "Session" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
51
        Base.metadata.create_all(self.engine)
52
53
    @property
54
    def pool(self):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
55
        return self.engine
56
57
    @property
58
    def session(self):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
59
        return self.Session()
60
61
    def __del__(self):
62
        self.session.close()
63
        self.engine.dispose()
64
65
    def query_all_pd(self, table):
66
67
        '''
68
        Load all POI data from SQL
69
        :param table: Name of table where POI data is stored
70
        :return: Full table read from SQL database table
71
        '''
72
        return pd.read_sql_table(table, self.engine)
73
74
    def query_all_gpd(self, table):
75
        '''
76
        Load all POI data from SQL that contains gometry
77
        :param table: Name of table where POI data is stored
78
        :return: Full table with poi_lat and poi_long fileds read from SQL database table
79
        '''
80
        query = sqlalchemy.text('select * from {} where poi_geom is not NULL'.format(table))
81
        data = gpd.GeoDataFrame.from_postgis(query, self.engine, geom_col='poi_geom')
82
        data['poi_lat'] = data['poi_geom'].x
83
        data['poi_lon'] = data['poi_geom'].y
84
        return data
85
86
    def query_all_gpd_in_order(self, table):
87
        '''
88
        Load all POI data from SQL that contains gometry and ordered by poi_common_id and postcode
89
        :param table: Name of table where POI data is stored
90
        :return: Full table with poi_lat and poi_long fileds read from SQL database table
91
        '''
92
        query = sqlalchemy.text('''SELECT * FROM {}
93
                                     WHERE poi_geom is not NULL
94
                                     ORDER BY poi_common_id ASC, poi_postcode ASC, poi_addr_street ASC,
95
                                       poi_addr_housenumber ASC'''.format(table))
96
        data = gpd.GeoDataFrame.from_postgis(query, self.engine, geom_col='poi_geom')
97
        data['poi_lat'] = data['poi_geom'].x
98
        data['poi_lon'] = data['poi_geom'].y
99
        return data
100
101
    def count_all_gpd(self, table):
102
        '''
103
        Load all POI data from SQL that contains geometry
104
        :param table: Name of table where POI data is stored
105
        :return: Full table with poi_lat and poi_long fields read from SQL database table
106
        '''
107
        query = sqlalchemy.text('select count(*) from {} where poi_geom is not NULL'.format(table))
108
        data = gpd.GeoDataFrame.from_postgis(query, self.engine, geom_col='poi_geom')
109
        return data
110
111
    def query_from_cache(self, node_id, object_type):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
112
        if node_id > 0:
113
            query = sqlalchemy.text(
114
                'select * from poi_osm_cache where osm_id = :node_id and osm_object_type = :object_type limit 1')
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (113/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
115
            data = pd.read_sql(query, self.engine, params={'node_id': int(node_id), 'object_type': object_type.name})
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (117/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
116
            if not data.values.tolist():
0 ignored issues
show
unused-code introduced by
Unnecessary "else" after "return"
Loading history...
117
                return None
118
            else:
119
                return data.to_dict('records')[0]
120
        else:
121
            return None
122
123
    def query_ways_nodes(self, way_id):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
124
        if way_id > 0:
0 ignored issues
show
unused-code introduced by
Unnecessary "else" after "return"
Loading history...
125
            query = sqlalchemy.text('select nodes from planet_osm_ways where id = :way_id limit 1')
126
            data = pd.read_sql(query, self.engine, params={'way_id': int(way_id)})
127
            return data.values.tolist()[0][0]
128
        else:
129
            return None
130
131
    def query_relation_nodes(self, relation_id):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
132
        query = sqlalchemy.text('select members from planet_osm_rels where id = :relation_id limit 1')
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (102/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
133
        data = pd.read_sql(query, self.engine, params={'relation_id': int(abs(relation_id))})
134
        return data.values.tolist()[0][0]
135
136
    def query_osm_shop_poi_gpd(self, lon: float, lat: float, ptype: str = 'shop', name: str = '', avoid_name: str = '', street_name: str = '',
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (142/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
best-practice introduced by
Too many arguments (14/5)
Loading history...
Comprehensibility introduced by
This function exceeds the maximum number of variables (29/15).
Loading history...
137
                               housenumber: str = '', conscriptionnumber: str = '', city: str = '',
138
                               distance_perfect: int = None, distance_safe: int = None, distance_unsafe: int = None,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (116/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
139
                               with_metadata: bool = True):
140
        '''
141
        Search for POI in OpenStreetMap database based on POI type and geom within preconfigured distance
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (105/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
142
        :param lon:
143
        :param lat:
144
        :param ptype:
145
        :param name:
146
        :param avoid_name:
147
        :param street_name:
148
        :param housenumber:
149
        :param conscriptionnumber:
150
        :param city:
151
        :param distance_perfect:
152
        :param distance_safe:
153
        :param distance_unsafe:
154
        :parm with_metadata:
155
        :return:
156
        '''
157
        buffer = 10
158
        query_arr = []
159
        query_params = {}
160
        query_type, distance = poitypes.getPOITypes(ptype)
0 ignored issues
show
Unused Code introduced by
The variable distance seems to be unused.
Loading history...
161
        # If we have PO common defined unsafe search radius distance, then use it (or use defaults specified above)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (115/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
162
        if distance_unsafe is None or distance_unsafe == '' or math.isnan(distance_unsafe):
163
            distance_unsafe = config.get_geo_default_poi_unsafe_distance()
164
        query_params.update({'distance_unsafe': distance_unsafe})
165
        if distance_safe is None or distance_safe == '' or math.isnan(distance_safe):
166
            distance_safe = config.get_geo_default_poi_distance()
167
        query_params.update({'distance_safe': distance_safe})
168
        if lon is not None and lon != '':
169
            query_params.update({'lon': lon})
170
        if lat is not None and lat != '':
171
            query_params.update({'lat': lat})
172
        query_params.update({'buffer': buffer})
173
        # Do not match with other specified names and brands
174
        if name is not None and name != '':
175
            query_name = ' AND (LOWER(TEXT(name)) ~* LOWER(TEXT(:name)) OR LOWER(TEXT(brand)) ~* LOWER(TEXT(:name)))'
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (117/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
176
            query_params.update({'name': '.*{}.*'.format(name)})
177
            # If we have PO common defined safe search radius distance, then use it (or use defaults specified above)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (117/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
178
            if distance_perfect is None or distance_perfect != '' or math.isnan(distance_perfect):
179
                distance_perfect = config.get_geo_default_poi_perfect_distance()
180
            query_params.update({'distance_perfect': distance_perfect})
181
        else:
182
            query_name = '' 
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
183
        # Do not match with other specified names and brands
184
        if avoid_name is not None and avoid_name != '':
185
            query_avoid_name = ' AND (LOWER(TEXT(name)) !~* LOWER(TEXT(:avoid_name)) AND LOWER(TEXT(brand)) !~* LOWER(TEXT(:avoid_name)))'
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (138/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
186
            query_params.update({'avoid_name': '.*{}.*'.format(avoid_name)})
187
        else:
188
            query_avoid_name = '' 
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
189
        if with_metadata is True:
190
            metadata_fields = ' osm_user, osm_uid, osm_version, osm_changeset, osm_timestamp, '
191
        else:
192
            metadata_fields = ''
193
        if street_name is not None and street_name != '':
194
            street_query = ' AND LOWER(TEXT("addr:street")) = LOWER(TEXT(:street_name))'
195
            query_params.update({'street_name': street_name})
196
        else:
197
            street_query = ''
198
        if housenumber is not None and housenumber != '':
199
            housenumber_query = ' AND LOWER(TEXT("addr:housenumber")) = LOWER(TEXT(:housenumber))'
200
            query_params.update({'housenumber': housenumber})
201
        else:
202
            housenumber_query = ''
203
        if conscriptionnumber is not None and conscriptionnumber != '':
204
            conscriptionnumber_query = ' AND LOWER(TEXT("addr:conscriptionnumber")) = LOWER(TEXT(:conscriptionnumber))'
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (119/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
205
            query_params.update({'conscriptionnaumber': conscriptionnaumber})
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable conscriptionnaumber does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
Undefined variable 'conscriptionnaumber'
Loading history...
206
        else:
207
            conscriptionnumber_query = ''
208
        if city is not None and city != '':
209
            city_query = ' AND LOWER(TEXT("addr:city")) = LOWER(TEXT(:city))'
210
            query_params.update({'city': city})
211
        else:
212
            city_query = ''
213
        logging.debug('%s %s: %s, %s (NOT %s), %s %s %s (%s) [%s, %s, %s]', lon, lat, ptype, name, avoid_name, city,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (116/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
214
                      street_name, housenumber, conscriptionnumber, distance_perfect, distance_safe, distance_unsafe)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (117/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
215
        # Looking for way (building)
216
        if query_name is not None and query_name != '' and city_query is not None and city_query != '' and \
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (108/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
best-practice introduced by
Too many boolean expressions in if statement (6/5)
Loading history...
217
                conscriptionnumber_query is not None and conscriptionnumber_query != '':
218
            query_text = '''
219
            --- WITH NAME, WITH CONSCRIPTINNUMBER, WITH CITY
220
            --- The way selector with conscriptionnumber and city
221
            SELECT name, osm_id, {metadata_fields} 965 AS priority, 'way' AS node, shop, amenity, "addr:housename",
222
                   "addr:housenumber", "addr:postcode", "addr:city", "addr:street", "addr:conscriptionnumber",
223
                   '0' as distance, way, ST_AsEWKT(way) as way_ewkt,
224
                   ST_X(ST_PointOnSurface(planet_osm_polygon.way)) as lon,
225
                   ST_Y(ST_PointOnSurface(planet_osm_polygon.way)) as lat
226
            FROM planet_osm_polygon
227
            WHERE ({query_type}) AND osm_id > 0 {query_name} {conscriptionnumber_query} {city_query}
228
            UNION ALL
229
            --- The node selector with conscriptionnumber and city
230
            SELECT name, osm_id, {metadata_fields} 965 AS priority, 'node' AS node, shop, amenity, "addr:housename",
231
                   "addr:housenumber", "addr:postcode", "addr:city", "addr:street", "addr:conscriptionnumber",
232
                   '0' as distance, way, ST_AsEWKT(way) as way_ewkt,
233
                   ST_X(planet_osm_point.way) as lon,
234
                   ST_Y(planet_osm_point.way) as lat
235
            FROM planet_osm_point
236
            WHERE ({query_type}) AND osm_id > 0 {query_name} {conscriptionnumber_query} {city_query}
237
            UNION ALL
238
            --- The relation selector with conscriptionnumber and city
239
            SELECT name, osm_id, {metadata_fields} 965 AS priority, 'relation' AS node, shop, amenity,
240
                   "addr:housename", "addr:housenumber", "addr:postcode", "addr:city", "addr:street",
241
                   "addr:conscriptionnumber", '0' as distance, way, ST_AsEWKT(way) as way_ewkt,
242
                   ST_X(ST_PointOnSurface(planet_osm_polygon.way)) as lon,
243
                   ST_Y(ST_PointOnSurface(planet_osm_polygon.way)) as lat
244
            FROM planet_osm_polygon
245
            WHERE ({query_type}) AND osm_id < 0 {query_name} {conscriptionnumber_query} {city_query}
246
            '''
247
            query = sqlalchemy.text(query_text.format(query_type=query_type, query_name=query_name,
248
                                                      metadata_fields=metadata_fields,
249
                                                      conscriptionnumber_query=conscriptionnumber_query,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (104/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
250
                                                      city_query=city_query))
251
            logging.debug(str(query))
252
            data = gpd.GeoDataFrame.from_postgis(query, self.engine, geom_col='way', params=query_params)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (105/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
253
            '''perf_query = sqlalchemy.text('EXPLAIN ' + query_text.format(query_type=query_type, query_name=query_name,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (120/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
254
                                                      metadata_fields=metadata_fields,
255
                                                      conscriptionnumber_query=conscriptionnumber_query,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (104/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
256
                                                      city_query=city_query))
257
            perf = gpd.GeoDataFrame.from_postgis(perf_query, self.engine, geom_col='way', params=query_params)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (110/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
258
            logging.debug(perf)
259
            '''
0 ignored issues
show
Unused Code introduced by
This string statement has no effect and could be removed.
Loading history...
260
            if not data.empty:
261
                logging.debug(data.to_string())
262
                return data.iloc[[0]]
263
        if query_name is not None and query_name != '' and city_query is not None and city_query != '' and \
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (108/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
best-practice introduced by
Too many boolean expressions in if statement (8/5)
Loading history...
264
                street_query is not None and street_query != '' and \
265
                housenumber_query is not None and housenumber_query != '':
266
            query_text = '''
267
            --- WITH NAME, WITH CITY, WITH STREETNAME, WITH HOUSENUMBER
268
            --- The way selector with city, street name and housenumber
269
            SELECT name, osm_id, {metadata_fields} 940 AS priority, 'way' AS node, shop, amenity, "addr:housename",
270
                   "addr:housenumber", "addr:postcode", "addr:city", "addr:street", "addr:conscriptionnumber",
271
                   '0' as distance, way, ST_AsEWKT(way) as way_ewkt,
272
                   ST_X(ST_PointOnSurface(planet_osm_polygon.way)) as lon,
273
                   ST_Y(ST_PointOnSurface(planet_osm_polygon.way)) as lat
274
            FROM planet_osm_polygon
275
            WHERE ({query_type}) AND osm_id > 0 {query_name} {city_query} {street_query} {housenumber_query}
276
            UNION ALL
277
            --- The node selector with street name and housenumber
278
            SELECT name, osm_id, {metadata_fields} 940 AS priority, 'node' AS node, shop, amenity, "addr:housename",
279
                   "addr:housenumber", "addr:postcode", "addr:city", "addr:street", "addr:conscriptionnumber",
280
                   '0' as distance, way, ST_AsEWKT(way) as way_ewkt,
281
                   ST_X(planet_osm_point.way) as lon,
282
                   ST_Y(planet_osm_point.way) as lat
283
            FROM planet_osm_point
284
            WHERE ({query_type}) AND osm_id > 0 {query_name} {city_query} {street_query} {housenumber_query}
285
            UNION ALL
286
            --- The relation selector with street name and housenumber
287
            SELECT name, osm_id, {metadata_fields} 940 AS priority, 'relation' AS node, shop, amenity,
288
                   "addr:housename", "addr:housenumber", "addr:postcode", "addr:city", "addr:street",
289
                   "addr:conscriptionnumber", '0' as distance, way, ST_AsEWKT(way) as way_ewkt,
290
                   ST_X(ST_PointOnSurface(planet_osm_polygon.way)) as lon,
291
                   ST_Y(ST_PointOnSurface(planet_osm_polygon.way)) as lat
292
            FROM planet_osm_polygon
293
            WHERE ({query_type}) AND osm_id < 0 {query_name} {city_query} {street_query} {housenumber_query}
294
            '''
295
            query = sqlalchemy.text(query_text.format(query_type=query_type, query_name=query_name,
296
                                                      metadata_fields=metadata_fields,
297
                                                      street_query=street_query,
298
                                                      city_query=city_query,
299
                                                      housenumber_query=housenumber_query))
300
            logging.debug(str(query))
301
            data = gpd.GeoDataFrame.from_postgis(query, self.engine, geom_col='way', params=query_params)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (105/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
302
            '''
303
            perf_query = sqlalchemy.text('EXPLAIN ' + query_text.format(query_type=query_type, query_name=query_name,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (117/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
304
                                                      metadata_fields=metadata_fields,
305
                                                      street_query=street_query,
306
                                                      city_query=city_query,
307
                                                      housenumber_query=housenumber_query))
308
            perf = gpd.GeoDataFrame.from_postgis(perf_query, self.engine, geom_col='way', params=query_params)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (110/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
309
            logging.debug(perf)
310
            '''
0 ignored issues
show
Unused Code introduced by
This string statement has no effect and could be removed.
Loading history...
311
            if not data.empty:
312
                logging.debug(data.to_string())
313
                return data.iloc[[0]]
314
        if street_query is not None and street_query != '':
315
            # Using street name for query
316
            if housenumber_query is not None and housenumber_query != '':
317
                query_arr.append('''
318
                --- WITH NAME, WITH STREETNAME, WITH HOUSENUMBER
319
                --- The way selector with street name and with housenumber
320
                SELECT name, osm_id, {metadata_fields} 950 AS priority, 'way' AS node, shop, amenity, "addr:housename",
321
                       "addr:housenumber", "addr:postcode", "addr:city", "addr:street", "addr:conscriptionnumber",
322
                       ST_DistanceSphere(way, point.geom) as distance, way,
323
                       ST_AsEWKT(way) as way_ewkt,
324
                       ST_X(ST_PointOnSurface(planet_osm_polygon.way)) as lon,
325
                       ST_Y(ST_PointOnSurface(planet_osm_polygon.way)) as lat
326
                FROM planet_osm_polygon, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
327
                WHERE ({query_type}) AND osm_id > 0 {query_name} {street_query} {housenumber_query}
328
                    AND ST_DistanceSphere(way, point.geom) < :distance_perfect
329
                UNION ALL
330
                --- The node selector with street name and with housenumber
331
                SELECT name, osm_id, {metadata_fields} 950 AS priority, 'node' AS node, shop, amenity, "addr:housename",
332
                       "addr:housenumber", "addr:postcode", "addr:city", "addr:street", "addr:conscriptionnumber",
333
                       ST_DistanceSphere(way, point.geom) as distance, way,
334
                       ST_AsEWKT(way) as way_ewkt,
335
                       ST_X(planet_osm_point.way) as lon,
336
                       ST_Y(planet_osm_point.way) as lat
337
                FROM planet_osm_point, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
338
                WHERE ({query_type}) AND osm_id > 0 {query_name} {street_query} {housenumber_query}
339
                    AND ST_DistanceSphere(way, point.geom) < :distance_perfect
340
                UNION ALL
341
                --- The relation selector with street name and with housenumber
342
                SELECT name, osm_id, {metadata_fields} 950 AS priority, 'relation' AS node, shop, amenity,
343
                       "addr:housename", "addr:housenumber", "addr:postcode", "addr:city", "addr:street",
344
                       "addr:conscriptionnumber", ST_DistanceSphere(way, point.geom) as distance, way,
345
                       ST_AsEWKT(way) as way_ewkt,
346
                       ST_X(ST_PointOnSurface(planet_osm_polygon.way)) as lon,
347
                       ST_Y(ST_PointOnSurface(planet_osm_polygon.way)) as lat
348
                FROM planet_osm_polygon, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
349
                WHERE ({query_type}) AND osm_id < 0 {query_name} {street_query} {housenumber_query}
350
                    AND ST_DistanceSphere(way, point.geom) < :distance_perfect
351
                ''')
352
            query_arr.append('''
353
            --- WITH NAME, WITH STREETNAME, NO HOUSENUMBER
354
            --- The way selector with street name and without housenumber
355
            SELECT name, osm_id, {metadata_fields} 970 AS priority, 'way' AS node, shop, amenity, "addr:housename",
356
                   "addr:housenumber", "addr:postcode", "addr:city", "addr:street", "addr:conscriptionnumber",
357
                   ST_DistanceSphere(way, point.geom) as distance, way,
358
                   ST_AsEWKT(way) as way_ewkt,
359
                   ST_X(ST_PointOnSurface(planet_osm_polygon.way)) as lon,
360
                   ST_Y(ST_PointOnSurface(planet_osm_polygon.way)) as lat
361
            FROM planet_osm_polygon, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
362
            WHERE (({query_type}) AND osm_id > 0 {query_name} {street_query})
363
                AND ST_DistanceSphere(way, point.geom) < :distance_safe
364
            UNION ALL
365
            --- The node selector with street name and without housenumber
366
            SELECT name, osm_id, {metadata_fields} 970 AS priority, 'node' AS node, shop, amenity, "addr:housename",
367
                   "addr:housenumber", "addr:postcode", "addr:city", "addr:street", "addr:conscriptionnumber",
368
                   ST_DistanceSphere(way, point.geom) as distance, way,
369
                   ST_AsEWKT(way) as way_ewkt,
370
                   ST_X(planet_osm_point.way) as lon,
371
                   ST_Y(planet_osm_point.way) as lat
372
            FROM planet_osm_point, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
373
            WHERE (({query_type}) AND osm_id > 0 {query_name} {street_query})
374
                AND ST_DistanceSphere(way, point.geom) < :distance_safe
375
            UNION ALL
376
            --- The relation selector with street name and without housenumber
377
            SELECT name, osm_id, {metadata_fields} 970 AS priority, 'relation' AS node, shop, amenity,
378
                   "addr:housename", "addr:housenumber", "addr:postcode", "addr:city", "addr:street",
379
                   "addr:conscriptionnumber", ST_DistanceSphere(way, point.geom) as distance, way,
380
                   ST_AsEWKT(way) as way_ewkt,
381
                   ST_X(ST_PointOnSurface(planet_osm_polygon.way)) as lon,
382
                   ST_Y(ST_PointOnSurface(planet_osm_polygon.way)) as lat
383
            FROM planet_osm_polygon, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
384
            WHERE (({query_type}) AND osm_id < 0 {query_name} {street_query})
385
                AND ST_DistanceSphere(way, point.geom) < :distance_safe
386
            ''')
387
        else:
388
            if housenumber_query is not None and housenumber_query != '':
389
                query_arr.append('''
390
                --- WITH NAME, NO STREETNAME, WITH HOUSENUMBER
391
                --- The way selector without street name and with housenumber
392
                SELECT name, osm_id, {metadata_fields} 970 AS priority, 'way' AS node, shop, amenity, "addr:housename",
393
                       "addr:housenumber", "addr:postcode", "addr:city", "addr:street", "addr:conscriptionnumber",
394
                       ST_DistanceSphere(way, point.geom) as distance, way,
395
                       ST_AsEWKT(way) as way_ewkt,
396
                       ST_X(ST_PointOnSurface(planet_osm_polygon.way)) as lon,
397
                       ST_Y(ST_PointOnSurface(planet_osm_polygon.way)) as lat
398
                FROM planet_osm_polygon, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
399
                WHERE (({query_type}) AND osm_id > 0 {query_name} {housenumber_query})
400
                    AND ST_DistanceSphere(way, point.geom) < :distance_safe
401
                UNION ALL
402
                --- The node selector without street name and with housenumber
403
                SELECT name, osm_id, {metadata_fields} 970 AS priority, 'node' AS node, shop, amenity, "addr:housename",
404
                       "addr:housenumber", "addr:postcode", "addr:city", "addr:street", "addr:conscriptionnumber",
405
                       ST_DistanceSphere(way, point.geom) as distance, way,
406
                       ST_AsEWKT(way) as way_ewkt,
407
                       ST_X(planet_osm_point.way) as lon,
408
                       ST_Y(planet_osm_point.way) as lat
409
                FROM planet_osm_point, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
410
                WHERE (({query_type}) AND osm_id > 0 {query_name} {housenumber_query})
411
                    AND ST_DistanceSphere(way, point.geom) < :distance_safe
412
                UNION ALL
413
                --- The relation selector without street name and with housenumber
414
                SELECT name, osm_id, {metadata_fields} 970 AS priority, 'relation' AS node, shop, amenity,
415
                       "addr:housename", "addr:housenumber", "addr:postcode", "addr:city", "addr:street",
416
                       "addr:conscriptionnumber",
417
                       ST_DistanceSphere(way, point.geom) as distance, way,
418
                       ST_AsEWKT(way) as way_ewkt,
419
                       ST_X(ST_PointOnSurface(planet_osm_polygon.way)) as lon,
420
                       ST_Y(ST_PointOnSurface(planet_osm_polygon.way)) as lat
421
                FROM planet_osm_polygon, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
422
                WHERE ({query_type}) AND osm_id < 0 {query_name} {housenumber_query}
423
                    AND ST_DistanceSphere(way, point.geom) < :distance_safe
424
                ''')
425
        # Trying without street name and house number in case when the street name and/or the house not matching at all
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (119/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
426
        query_arr.append('''
427
        --- WITH NAME, NO STREETNAME, NO HOUSENUMBER
428
        --- The way selector without street name and without housenumber
429
        SELECT name, osm_id, {metadata_fields} 980 AS priority, 'way' AS node, shop, amenity, "addr:housename",
430
               "addr:housenumber", "addr:postcode", "addr:city", "addr:street", "addr:conscriptionnumber",
431
               ST_DistanceSphere(way, point.geom) as distance, way,
432
               ST_AsEWKT(way) as way_ewkt,
433
               ST_X(ST_PointOnSurface(planet_osm_polygon.way)) as lon,
434
               ST_Y(ST_PointOnSurface(planet_osm_polygon.way)) as lat
435
        FROM planet_osm_polygon, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
436
        WHERE (({query_type}) AND osm_id > 0 {query_name} )
437
            AND ST_DistanceSphere(way, point.geom) < :distance_safe
438
        UNION ALL
439
        --- The node selector without street name and without housenumber
440
        SELECT name, osm_id, {metadata_fields} 980 AS priority, 'node' AS node, shop, amenity, "addr:housename",
441
               "addr:housenumber", "addr:postcode", "addr:city", "addr:street", "addr:conscriptionnumber",
442
               ST_DistanceSphere(way, point.geom) as distance, way,
443
               ST_AsEWKT(way) as way_ewkt,
444
               ST_X(planet_osm_point.way) as lon,
445
               ST_Y(planet_osm_point.way) as lat
446
        FROM planet_osm_point, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
447
        WHERE (({query_type}) AND osm_id > 0 {query_name} )
448
            AND ST_DistanceSphere(way, point.geom) < :distance_safe
449
        UNION ALL
450
        --- The relation selector without street name and without housenumber
451
        SELECT name, osm_id, {metadata_fields} 980 AS priority, 'relation' AS node, shop, amenity,
452
               "addr:housename", "addr:housenumber", "addr:postcode", "addr:city", "addr:street",
453
               "addr:conscriptionnumber",
454
               ST_DistanceSphere(way, point.geom) as distance, way,
455
               ST_AsEWKT(way) as way_ewkt,
456
               ST_X(ST_PointOnSurface(planet_osm_polygon.way)) as lon,
457
               ST_Y(ST_PointOnSurface(planet_osm_polygon.way)) as lat
458
        FROM planet_osm_polygon, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
459
        WHERE (({query_type}) AND osm_id < 0 {query_name} )
460
            AND ST_DistanceSphere(way, point.geom) < :distance_safe
461
        ''')
462
        query_arr.append('''
463
            --- NO NAME, NO STREETNAME, NO HOUSENUMBER
464
            --- The way selector without name and street name
465
            SELECT name, osm_id, {metadata_fields} 990 AS priority, 'way' AS node, shop, amenity, "addr:housename",
466
                   "addr:housenumber", "addr:postcode", "addr:city", "addr:street", "addr:conscriptionnumber",
467
                   ST_DistanceSphere(way, point.geom) as distance, way,
468
                   ST_AsEWKT(way) as way_ewkt,
469
                   ST_X(ST_PointOnSurface(planet_osm_polygon.way)) as lon,
470
                   ST_Y(ST_PointOnSurface(planet_osm_polygon.way)) as lat
471
            FROM planet_osm_polygon, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
472
            WHERE (({query_type}) AND osm_id > 0 {query_avoid_name} )
473
                AND ST_DistanceSphere(way, point.geom) < :distance_unsafe
474
            UNION ALL
475
            --- The node selector without name and street name
476
            SELECT name, osm_id, {metadata_fields} 990 AS priority, 'node' AS node, shop, amenity, "addr:housename",
477
                   "addr:housenumber", "addr:postcode", "addr:city", "addr:street", "addr:conscriptionnumber",
478
                   ST_DistanceSphere(way, point.geom) as distance, way,
479
                   ST_AsEWKT(way) as way_ewkt,
480
                   ST_X(planet_osm_point.way) as lon,
481
                   ST_Y(planet_osm_point.way) as lat
482
            FROM planet_osm_point, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
483
            WHERE (({query_type}) AND osm_id > 0 {query_avoid_name} )
484
                AND ST_DistanceSphere(way, point.geom) < :distance_unsafe
485
            UNION ALL
486
            --- The relation selector without name street name
487
            SELECT name, osm_id, {metadata_fields} 990 AS priority, 'relation' AS node, shop, amenity,
488
                   "addr:housename", "addr:housenumber", "addr:postcode", "addr:city", "addr:street",
489
                   "addr:conscriptionnumber",
490
                   ST_DistanceSphere(way, point.geom) as distance, way,
491
                   ST_AsEWKT(way) as way_ewkt,
492
                   ST_X(ST_PointOnSurface(planet_osm_polygon.way)) as lon,
493
                   ST_Y(ST_PointOnSurface(planet_osm_polygon.way)) as lat
494
            FROM planet_osm_polygon, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
495
            WHERE (({query_type}) AND osm_id < 0 {query_avoid_name} )
496
                AND ST_DistanceSphere(way, point.geom) < :distance_unsafe
497
        ''')
498
        query_text = 'UNION ALL'.join(query_arr) + 'ORDER BY priority ASC, distance ASC;'
499
        query = sqlalchemy.text(query_text.format(query_type=query_type, query_name=query_name,
500
                                                  query_avoid_name=query_avoid_name,
501
                                                  metadata_fields=metadata_fields,
502
                                                  street_query=street_query,
503
                                                  city_query=city_query,
504
                                                  housenumber_query=housenumber_query))
505
        logging.debug(str(query))
506
        data = gpd.GeoDataFrame.from_postgis(query, self.engine, geom_col='way', params=query_params)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (101/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
507
        '''
508
        perf_query = sqlalchemy.text('EXPLAIN ' + query_text.format(query_type=query_type, query_name=query_name,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (113/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
509
                                                  metadata_fields=metadata_fields,
510
                                                  street_query=street_query,
511
                                                  city_query=city_query,
512
                                                  housenumber_query=housenumber_query))
513
        perf = gpd.GeoDataFrame.from_postgis(perf_query, self.engine, geom_col='way', params=query_params)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (106/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
514
        logging.debug(perf)
515
        '''
0 ignored issues
show
Unused Code introduced by
This string statement has no effect and could be removed.
Loading history...
516
        if not data.empty:
0 ignored issues
show
unused-code introduced by
Unnecessary "else" after "return"
Loading history...
517
            logging.debug(data.to_string())
518
            return data.iloc[[0]]
519
        else:
520
            return None
521
522
    def query_osm_building_poi_gpd(self, lon, lat, city, postcode, street_name='', housenumber='',
0 ignored issues
show
best-practice introduced by
Too many arguments (9/5)
Loading history...
Unused Code introduced by
The argument city seems to be unused.
Loading history...
Unused Code introduced by
The argument postcode seems to be unused.
Loading history...
523
                                   in_building_percentage=0.50, distance=60):
524
        '''
525
        Looking for a building (actually a way) around the POI node with same address with within a preconfigured distance.
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (123/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
526
        Actually this method helps to find a building for a single node.
527
        :param lon: Longitude of POI node type coordinate.
528
        :param lat: Latitude of POI node type coordinate.
529
        :param: city: Name of city where the POI node is.
530
        :param: postcode: Postcode of area where the POI node is.
531
        :param: street_name: Name of street where the POI node is.
532
        :param: housenumber: House number of street where the POI node is.
533
        :param: in_building_percentage: In building line argument is a float8 between 0 and 1 representing fraction of
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (118/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
534
          total linestring length the point has to be located.
535
          Documentation: https://postgis.net/docs/ST_LineInterpolatePoint.html
536
        :param: distance: Look buildings around the POI node within this radius (specified in meter).
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (101/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
537
        :return: A new node within the building with same address.
538
        '''
539
        buffer = 10
540
        # When we got all address parts, then we should try to fetch only one coordinate pair of building geometry
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (114/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
541
        if street_name is not None and street_name != '' and housenumber is not None and housenumber != '':
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (107/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
542
            street_query = ' AND LOWER(TEXT("addr:street")) = LOWER(TEXT(:street_name))'
543
            housenumber_query = ' AND LOWER(TEXT("addr:housenumber")) = LOWER(TEXT(:housenumber))'
544
        else:
545
            return None
546
        query = sqlalchemy.text('''
547
            --- The building selector based on POI node distance and
548
            --- city, postcode, street name and housenumber of building
549
            --- Make a line that connects the building and POI coords, using one point from union
550
            SELECT name, building, osm_id, 'way' AS node, "addr:housename",
551
                "addr:housenumber", "addr:postcode", "addr:city", "addr:street", "addr:conscriptionnumber",
552
                 ST_Y(ST_PointOnSurface(way)) as lat_in_b,
553
                 ST_X(ST_PointOnSurface(way)) as lon_in_b,
554
                 ST_Y(ST_LineInterpolatePoint(ST_GeometryN(ST_Intersection(way,
555
                 ST_MakeLine(ST_PointOnSurface(way), point.geom)), 1), :ibp)) as lat,
556
                 ST_X(ST_LineInterpolatePoint(ST_GeometryN(ST_Intersection(way,
557
                 ST_MakeLine(ST_PointOnSurface(way), point.geom)), 1), :ibp)) as lon,
558
                ST_DistanceSphere(way, point.geom) as distance, way,
559
                ST_PointOnSurface(way) in_building, ST_AsEWKT(way) as way_ewkt,
560
                ST_AsEWKT(ST_PointOnSurface(way)) in_building_ewkt
561
            FROM planet_osm_polygon, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
562
            WHERE building <> '' AND osm_id > 0 AND ST_DistanceSphere(way, point.geom) < :distance
563
                {street_query} {housenumber_query}
564
            ORDER BY distance ASC LIMIT 1'''.format(street_query=street_query, housenumber_query=housenumber_query))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (116/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
565
        data = gpd.GeoDataFrame.from_postgis(query, self.engine, geom_col='way', params={'lon': lon, 'lat': lat,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (112/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
566
                                                                                         'distance': distance,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (110/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
567
                                                                                         'buffer': buffer,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (106/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
568
                                                                                         'street_name': street_name,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (116/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
569
                                                                                         'housenumber': housenumber,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (116/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
570
                                                                                         'ibp': in_building_percentage})
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (120/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
571
        if data.empty:
0 ignored issues
show
unused-code introduced by
Unnecessary "else" after "return"
Loading history...
572
            return None
573
        else:
574
            return data
575
576
    def query_poi_in_water(self, lon, lat):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
577
        distance = 1
578
        try:
579
            query = sqlalchemy.text('''
580
            SELECT * FROM
581
              (SELECT osm_id, way, ST_DistanceSphere(way, point.geom) as distance
582
              FROM planet_osm_polygon, (SELECT ST_SetSRID(ST_MakePoint(:lon, :lat), 4326) as geom) point
583
              WHERE (water IS NOT NULL OR waterway IS NOT NULL)
584
              ORDER BY distance ASC LIMIT 1) AS geo
585
            WHERE geo.distance < :distance
586
              ''')
587
            data = gpd.GeoDataFrame.from_postgis(query, self.engine, geom_col='way', params={'lon': lon, 'lat': lat,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (116/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
588
                                                                                             'distance': distance})
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (115/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
589
            return data
590
        except Exception as err:
0 ignored issues
show
Best Practice introduced by
Catching very general exceptions such as Exception is usually not recommended.

Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.

So, unless you specifically plan to handle any error, consider adding a more specific exception.

Loading history...
591
            logging.error(err)
592
            logging.exception('Exception occurred')
593
594
    def query_name_road_around(self, lon, lat, name='', with_metadata=True, mode='both'):
0 ignored issues
show
best-practice introduced by
Too many arguments (6/5)
Loading history...
595
        '''
596
        Search for road with name specified around the lon, lat point location in OpenStreetMap database based on
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (113/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
597
        within preconfigured distance
598
        :param lon: Longitude parameter. Looking for roads around this geom.
599
        :param lat: Latitude parameter. Looking for roads around this geom.
600
        :param name: Name of the road. Search OpenStreetMap "highway" tagged ways with this name tag.
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (101/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
601
        :param with_metadata: Query OpenStreetMap metadata information
602
        :param mode: Looking for name, metaphone or both
603
        :return: GeoDataFrame of distance ordered result.
604
        '''
605
        try:
606
            distance = config.get_geo_default_poi_road_distance()
607
            if with_metadata is True:
608
                metadata_fields = ' osm_user, osm_uid, osm_version, osm_changeset, osm_timestamp, '
609
            else:
610
                metadata_fields = ''
611
            # Looking for way (road)
612
            if mode == 'both':
613
                name_query = '("name" = :name OR dmetaphone(name) = dmetaphone(:name))'
614
            elif mode == 'name':
615
                name_query = '("name" = :name)'
616
            elif mode == 'metaphone':
617
                name_query = 'dmetaphone(name) = dmetaphone(:name)'
618
            else:
619
                name_query = '("name" = :name OR dmetaphone(name) = dmetaphone(:name))'
620
            query = sqlalchemy.text('''
621
                SELECT * FROM
622
                  (SELECT name, osm_id, highway, {metadata_fields}
623
                    ST_DistanceSphere(way, point.geom) as distance, way, ST_AsEWKT(way) as way_ewkt
624
                  FROM planet_osm_line, (SELECT ST_SetSRID(ST_MakePoint(:lon,:lat), 4326) as geom) point
625
                  WHERE "highway" is not NULL
626
                    AND {name_query}
627
                  ORDER BY distance ASC LIMIT 1) AS geo
628
                WHERE geo.distance < :distance
629
                '''.format(metadata_fields=metadata_fields, name_query=name_query))
630
            data = gpd.GeoDataFrame.from_postgis(query, self.engine, geom_col='way', params={'lon': lon, 'lat': lat,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (116/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
631
                                                                                             'distance': distance,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (114/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
632
                                                                                             'name': '{}'.format(name)})
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (120/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
633
            data.sort_values(by=['distance'])
634
            return data
635
        except Exception as err:
0 ignored issues
show
Best Practice introduced by
Catching very general exceptions such as Exception is usually not recommended.

Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.

So, unless you specifically plan to handle any error, consider adding a more specific exception.

Loading history...
636
            logging.error(err)
637
            logging.exception('Exception occurred')
638