Skip to content

Commit ba57421

Browse files
committed
Updates for Python 3.x compatibility
* Use `future` aliases for renamed packages * Use `dict.items()` instead of `dict.iteritems()` * Compare parsed URL in tests due to changed dict ordering * Use `unicode_literals` from `__future__`
1 parent cdb9892 commit ba57421

File tree

2 files changed

+43
-23
lines changed

2 files changed

+43
-23
lines changed

swiftype/swiftype.py

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
1+
from __future__ import unicode_literals
2+
3+
from future.standard_library import install_aliases
4+
install_aliases()
5+
16
import anyjson
2-
import httplib
3-
import urllib
4-
import urlparse
57
import base64
68
import time
79
import hashlib
10+
from urllib.parse import urlparse, urlunparse, urlencode
11+
12+
try:
13+
# VCRpy only works when `httplib` is imported directly on Python 2.x
14+
import httplib
15+
except ImportError:
16+
import http.client as httplib
817

9-
from version import VERSION
18+
from .version import VERSION
1019

1120
USER_AGENT = 'Swiftype-Python/' + VERSION
1221
DEFAULT_API_HOST = 'api.swiftype.com'
@@ -80,41 +89,41 @@ def destroy_documents(self, engine_id, document_type_id, document_ids=[]):
8089

8190
def search(self, engine_id, query, options={}):
8291
query_string = {'q': query}
83-
full_query = dict(query_string.items() + options.items())
92+
full_query = dict(list(query_string.items()) + list(options.items()))
8493
return self.conn._get(self.__search_path(engine_id), data=full_query)
8594

8695
def search_document_type(self, engine_id, document_type_id, query, options={}):
8796
query_string = {'q': query}
88-
full_query = dict(query_string.items() + options.items())
97+
full_query = dict(list(query_string.items()) + list(options.items()))
8998
return self.conn._get(self.__document_type_search_path(engine_id, document_type_id), data=full_query)
9099

91100
def suggest(self, engine_id, query, options={}):
92101
query_string = {'q': query}
93-
full_query = dict(query_string.items() + options.items())
102+
full_query = dict(list(query_string.items()) + list(options.items()))
94103
return self.conn._get(self.__suggest_path(engine_id), data=full_query)
95104

96105
def suggest_document_type(self, engine_id, document_type_id, query, options={}):
97106
query_string = {'q': query}
98-
full_query = dict(query_string.items() + options.items())
107+
full_query = dict(list(query_string.items()) + list(options.items()))
99108
return self.conn._get(self.__document_type_suggest_path(engine_id, document_type_id), data=full_query)
100109

101110
def analytics_searches(self, engine_id, start_date=None, end_date=None):
102-
params = dict((k,v) for k,v in {'start_date': start_date, 'end_date': end_date}.iteritems() if v is not None)
111+
params = dict((k,v) for k,v in {'start_date': start_date, 'end_date': end_date}.items() if v is not None)
103112
return self.conn._get(self.__analytics_path(engine_id) + '/searches', params)
104113

105114
def analytics_autoselects(self, engine_id, start_date=None, end_date=None):
106-
params = dict((k,v) for k,v in {'start_date': start_date, 'end_date': end_date}.iteritems() if v is not None)
115+
params = dict((k,v) for k,v in {'start_date': start_date, 'end_date': end_date}.items() if v is not None)
107116
return self.conn._get(self.__analytics_path(engine_id) + '/autoselects', params)
108117

109118
def analytics_top_queries(self, engine_id, page=None, per_page=None):
110119
return self.conn._get(self.__analytics_path(engine_id) + '/top_queries', self.__pagination_params(page, per_page))
111120

112121
def analytics_top_queries_in_range(self, engine_id, start_date=None, end_date=None):
113-
params = dict((k,v) for k,v in {'start_date': start_date, 'end_date': end_date}.iteritems() if v is not None)
122+
params = dict((k,v) for k,v in {'start_date': start_date, 'end_date': end_date}.items() if v is not None)
114123
return self.conn._get(self.__analytics_path(engine_id) + '/top_queries_in_range', params)
115124

116125
def analytics_top_no_result_queries(self, engine_id, start_date=None, end_date=None):
117-
params = dict((k,v) for k,v in {'start_date': start_date, 'end_date': end_date}.iteritems() if v is not None)
126+
params = dict((k,v) for k,v in {'start_date': start_date, 'end_date': end_date}.items() if v is not None)
118127
return self.conn._get(self.__analytics_path(engine_id) + '/top_no_result_queries_in_range', params)
119128

120129
def domains(self, engine_id):
@@ -137,7 +146,7 @@ def crawl_url(self, engine_id, domain_id, url):
137146

138147
def users(self, page=None, per_page=None):
139148
params = {'client_id': self.client_id, 'client_secret': self.client_secret}
140-
return self.conn._get(self.__users_path(), dict(params.items() + self.__pagination_params(page, per_page).items()))
149+
return self.conn._get(self.__users_path(), dict(list(params.items()) + list(self.__pagination_params(page, per_page).items())))
141150

142151
def user(self, user_id):
143152
params = {'client_id': self.client_id, 'client_secret': self.client_secret}
@@ -150,10 +159,12 @@ def create_user(self):
150159
def sso_url(self, user_id):
151160
timestamp = self._get_timestamp()
152161
params = {'user_id': user_id, 'client_id': self.client_id, 'timestamp': timestamp, 'token': self._sso_token(user_id, timestamp)}
153-
return urlparse.urlunparse(('https', 'swiftype.com', '/sso', '', urllib.urlencode(params), ''))
162+
return urlunparse(('https', 'swiftype.com', '/sso', '', urlencode(params), ''))
154163

155164
def _sso_token(self, user_id, timestamp):
156-
return hashlib.sha1('%s:%s:%s' % (user_id, self.client_secret, timestamp)).hexdigest()
165+
return hashlib.sha1((
166+
'%s:%s:%s' % (user_id, self.client_secret, timestamp)
167+
).encode('utf-8')).hexdigest()
157168

158169
def _get_timestamp(self):
159170
return int(time.time())
@@ -175,7 +186,7 @@ def __users_path(self): return 'users'
175186
def __user_path(self, user_id): return 'users/%s' % (user_id)
176187

177188
def __pagination_params(self, page, per_page):
178-
return dict((k,v) for k,v in {'page': page, 'per_page': per_page}.iteritems() if v is not None)
189+
return dict((k,v) for k,v in {'page': page, 'per_page': per_page}.items() if v is not None)
179190

180191
class HttpException(Exception):
181192
def __init__(self, status, msg):
@@ -224,7 +235,7 @@ def _request(self, method, path, params={}, data={}):
224235
raise Unauthorized('Authorization required.')
225236

226237
full_path = self.__base_path + path + '.json'
227-
query = urllib.urlencode(params, True)
238+
query = urlencode(params, True)
228239
if query:
229240
full_path += '?' + query
230241

@@ -235,11 +246,11 @@ def _request(self, method, path, params={}, data={}):
235246

236247
response = connection.getresponse()
237248
response.body = response.read()
238-
if (response.status / 100 == 2):
249+
if (response.status // 100 == 2):
239250
if response.body:
240251
try:
241-
response.body = anyjson.deserialize(response.body)
242-
except ValueError, e:
252+
response.body = anyjson.deserialize(response.body.decode('utf-8'))
253+
except ValueError as e:
243254
raise InvalidResponseFromServer('The JSON response could not be parsed: %s.\n%s' % (e, response.body))
244255
ret = {'status': response.status, 'body':response.body }
245256
else:

tests/test_swiftype.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import os
33
import time
44
import unittest2 as unittest
5+
from urllib.parse import urlparse, parse_qs
56
import vcr
67
from mock import Mock
78

@@ -269,14 +270,14 @@ def __is_expected_search_result(self, request, document_type_count, args=[]):
269270
def __is_expected_result(self, request, status_code, expected_values, *args):
270271
response = request(*args)
271272
self.assertEqual(response['status'], status_code)
272-
for k,v in expected_values.iteritems():
273+
for k,v in expected_values.items():
273274
self.assertEqual(response['body'][k], v)
274275

275276
def __is_expected_collection(self, request, status_code, collection_length, expected_values, *args):
276277
response = request(*args)
277278
self.assertEqual(response['status'], status_code)
278279
self.assertEqual(len(response['body']), collection_length)
279-
for k,v in expected_values.iteritems():
280+
for k,v in expected_values.items():
280281
self.assertEqual(len([item for item in response['body'] if item[k] == v]), 1)
281282

282283
def __time_name(self):
@@ -331,7 +332,15 @@ def test_sso_url(self):
331332
self.client._get_timestamp = Mock(return_value=1379382520)
332333
user_id = '5064a7de2ed960e715000276'
333334
url = self.client.sso_url(user_id)
334-
self.assertEqual(url, 'https://swiftype.com/sso?timestamp=1379382520&token=81033d182ad51f231cc9cda9fb24f2298a411437&user_id=5064a7de2ed960e715000276&client_id=3e4fd842fc99aecb4dc50e5b88a186c1e206ddd516cdd336da3622c4afd7e2e9')
335+
self.assertEqual(
336+
parse_qs(urlparse(url).query),
337+
{
338+
'user_id': ['5064a7de2ed960e715000276'],
339+
'client_id': ['3e4fd842fc99aecb4dc50e5b88a186c1e206ddd516cdd336da3622c4afd7e2e9'],
340+
'token': ['81033d182ad51f231cc9cda9fb24f2298a411437'],
341+
'timestamp': ['1379382520'],
342+
},
343+
)
335344

336345
class TestPlatformResources(unittest.TestCase):
337346

0 commit comments

Comments
 (0)