Skip to content

Commit cb82997

Browse files
authored
geocoding with components and fix tag_line (#160)
* geocoding with components and fix tag_line * tests for geocoding without country * fix tests * use region biasing * location search with other branch
1 parent 367bac4 commit cb82997

File tree

7 files changed

+57
-19
lines changed

7 files changed

+57
-19
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ sandbox/
99
nginx/prod/keys/
1010
activate.prod.*
1111
activate.beta.*
12+
.pytest_cache/

tcsocket/app/geo.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
ONE_HOUR = 3_600
99
NINETY_DAYS = ONE_HOUR * 24 * 90
1010
IP_HEADER = 'X-Forwarded-For'
11+
COUNTRY_HEADER = 'CF-IPCountry'
1112
logger = logging.getLogger('socket.geo')
1213

1314

@@ -22,7 +23,12 @@ async def geocode(request):
2223
return
2324

2425
location_str = location_str.strip(' \t\n\r,.')
25-
loc_key = 'loc:' + hashlib.md5(location_str.lower().encode()).hexdigest()
26+
region = request.headers[COUNTRY_HEADER].lower()
27+
if region == 'gb':
28+
# https://en.wikipedia.org/wiki/Country_code_top-level_domain#ASCII_ccTLDs_not_in_ISO_3166-1
29+
region = 'uk'
30+
31+
loc_key = 'loc:' + hashlib.md5(f'{location_str.lower()}|{region}'.encode()).hexdigest()
2632
redis_pool = request.app['redis']
2733
settings: Settings = request.app['settings']
2834

@@ -32,7 +38,7 @@ async def geocode(request):
3238
loc_data = await redis.get(loc_key)
3339
if loc_data:
3440
result = json.loads(loc_data.decode())
35-
logger.info('cached geocode result "%s" > "%s"', location_str, result and result['pretty'])
41+
logger.info('cached geocode result "%s|%s" > "%s"', location_str, region, result and result['pretty'])
3642
return result
3743

3844
ip_key = 'geoip:' + ip_address
@@ -48,6 +54,7 @@ async def geocode(request):
4854
)
4955
params = {
5056
'address': location_str,
57+
'region': region,
5158
'key': settings.geocoding_key,
5259
}
5360
data = None
@@ -70,6 +77,6 @@ async def geocode(request):
7077
else:
7178
result = None
7279
await redis.setex(loc_key, NINETY_DAYS, json.dumps(result).encode())
73-
logger.info('new geocode result "%s" > "%s" (%d from "%s")',
74-
location_str, result and result['pretty'], geo_attempts, ip_address)
80+
logger.info('new geocode result "%s|%s" > "%s" (%d from "%s")',
81+
location_str, region, result and result['pretty'], geo_attempts, ip_address)
7582
return result

tcsocket/app/management.py

+8
Original file line numberDiff line numberDiff line change
@@ -321,3 +321,11 @@ def add_review_fields(conn):
321321
"""
322322
conn.execute('ALTER TABLE contractors ADD review_rating DOUBLE PRECISION')
323323
conn.execute('ALTER TABLE contractors ADD review_duration INTEGER NOT NULL DEFAULT 0')
324+
325+
326+
@patch
327+
def resize_tag_line(conn):
328+
"""
329+
resize the tag_line field on contractors to 255 chars
330+
"""
331+
conn.execute('ALTER TABLE contractors ALTER COLUMN tag_line TYPE VARCHAR(255)')

tcsocket/app/models.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class Contractor(Base):
5454
latitude = Column(Float)
5555
longitude = Column(Float)
5656

57-
tag_line = Column(String(63))
57+
tag_line = Column(String(255))
5858
primary_description = Column(Text())
5959

6060
extra_attributes = Column(JSONB)

tests/conftest.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,8 @@ async def grecaptcha_post_view(request):
249249

250250
async def geocoding_view(request):
251251
address = request.GET.get('address')
252-
request.app['request_log'].append(('geocode', address))
252+
region = request.GET.get('region')
253+
request.app['request_log'].append(('geocode', f'{address}|{region}'))
253254
status = 200
254255
if address == 'SW1W 0EN':
255256
loc = {

tests/requirements.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ flake8==3.5.0
33
isort==4.3.3
44
pycodestyle==2.3.1
55
pyflakes==1.6.0
6-
pytest==3.3.2
6+
pytest==3.4.0
77
pytest-aiohttp==0.3.0
88
pytest-cov==2.5.1
99
pytest-isort==0.1.0
1010
pytest-mock==1.6.3
11-
pytest-sugar==0.9.0
11+
pytest-sugar==0.9.1
1212
pytest-toolbox==0.2

tests/test_public_filtering_views.py

+32-11
Original file line numberDiff line numberDiff line change
@@ -187,51 +187,72 @@ async def test_distance_filter(cli, db_conn, company, params, con_distances):
187187
)
188188

189189
url = str(cli.server.app.router['contractor-list'].url_for(company=company.public_key))
190-
r = await cli.get(url, params=params, headers={'X-Forwarded-For': '1.1.1.1'})
190+
r = await cli.get(url, params=params, headers={'X-Forwarded-For': '1.1.1.1', 'CF-IPCountry': 'GB'})
191191
assert r.status == 200, await r.text()
192192
obj = await r.json()
193193
assert list(map(itemgetter('link', 'distance'), obj['results'])) == con_distances
194194

195195

196196
async def test_geocode_cache(cli, other_server, company):
197197
url = str(cli.server.app.router['contractor-list'].url_for(company=company.public_key))
198-
r = await cli.get(url, params={'location': 'SW1W 0EN'}, headers={'X-Forwarded-For': '1.1.1.1'})
198+
country = {'CF-IPCountry': 'GB'}
199+
r = await cli.get(url, params={'location': 'SW1W 0EN'}, headers={'X-Forwarded-For': '1.1.1.1', **country})
199200
assert r.status == 200, await r.text()
200-
assert other_server.app['request_log'] == [('geocode', 'SW1W 0EN')]
201+
assert other_server.app['request_log'] == [('geocode', 'SW1W 0EN|uk')]
201202
obj = await r.json()
202203
assert {
203204
'pretty': 'Lower Grosvenor Pl, Westminster, London SW1W 0EN, UK',
204205
'lat': 51.4980603,
205206
'lng': -0.14505
206207
} == obj['location']
207208

208-
r = await cli.get(url, params={'location': 'SW1W 0EN'}, headers={'X-Forwarded-For': '1.1.1.2'})
209+
r = await cli.get(url, params={'location': 'SW1W 0EN'}, headers={'X-Forwarded-For': '1.1.1.2', **country})
209210
assert r.status == 200, await r.text()
210-
r = await cli.get(url, params={'location': 'SW1W 0EN'}, headers={'X-Forwarded-For': '1.1.1.3'})
211+
r = await cli.get(url, params={'location': 'SW1W 0EN'}, headers={'X-Forwarded-For': '1.1.1.3', **country})
211212
assert r.status == 200, await r.text()
212-
assert other_server.app['request_log'] == [('geocode', 'SW1W 0EN')]
213+
assert other_server.app['request_log'] == [('geocode', 'SW1W 0EN|uk')]
213214

214215

215216
async def test_geocode_rate_limit(cli, other_server, company):
216217
url = str(cli.server.app.router['contractor-list'].url_for(company=company.public_key))
218+
country = {'CF-IPCountry': 'GB'}
217219
for i in range(10):
218-
r = await cli.get(url, params={'location': f'SW1W {i}EN'}, headers={'X-Forwarded-For': '1.1.1.1'})
220+
r = await cli.get(url, params={'location': f'SW1W {i}EN'}, headers={'X-Forwarded-For': '1.1.1.1', **country})
219221
assert r.status == 200, await r.text()
220-
r = await cli.get(url, params={'location': 'SW1W 1ENx'}, headers={'X-Forwarded-For': '1.1.1.1'})
222+
assert len(other_server.app['request_log']) == 10
223+
r = await cli.get(url, params={'location': 'SW1W 1ENx'}, headers={'X-Forwarded-For': '1.1.1.1', **country})
221224
assert r.status == 429, await r.text()
222-
r = await cli.get(url, params={'location': 'SW1W 1ENx'}, headers={'X-Forwarded-For': '1.1.1.1'})
225+
assert len(other_server.app['request_log']) == 10
226+
r = await cli.get(url, params={'location': 'SW1W 1ENx'}, headers={'X-Forwarded-For': '1.1.1.1', **country})
223227
assert r.status == 429, await r.text()
224-
r = await cli.get(url, params={'location': 'SW1W 1ENx'}, headers={'X-Forwarded-For': '1.1.1.2'})
228+
assert len(other_server.app['request_log']) == 10
229+
r = await cli.get(url, params={'location': 'SW1W 1ENx'}, headers={'X-Forwarded-For': '1.1.1.2', **country})
225230
assert r.status == 200, await r.text()
226231
assert len(other_server.app['request_log']) == 11
227232

228233

229234
async def test_geocode_error(cli, other_server, company):
230235
url = str(cli.server.app.router['contractor-list'].url_for(company=company.public_key))
231-
r = await cli.get(url, params={'location': '500'}, headers={'X-Forwarded-For': '1.1.1.1'})
236+
r = await cli.get(url, params={'location': '500'}, headers={'X-Forwarded-For': '1.1.1.1', 'CF-IPCountry': 'GB'})
232237
assert r.status == 500, await r.text()
233238

234239

240+
async def test_geocode_other_country(cli, other_server, company):
241+
r = await cli.get(
242+
cli.server.app.router['contractor-list'].url_for(company=company.public_key),
243+
params={'location': 'SW1W 0EN'},
244+
headers={'X-Forwarded-For': '1.1.1.1', 'CF-IPCountry': 'US'}
245+
)
246+
assert r.status == 200, await r.text()
247+
obj = await r.json()
248+
assert {
249+
'pretty': 'Lower Grosvenor Pl, Westminster, London SW1W 0EN, UK',
250+
'lat': 51.4980603,
251+
'lng': -0.14505,
252+
} == obj['location']
253+
assert other_server.app['request_log'] == [('geocode', 'SW1W 0EN|us')]
254+
255+
235256
async def create_labels(db_conn, company):
236257
await db_conn.execute(
237258
sa_labels

0 commit comments

Comments
 (0)