Skip to content

Commit 0dbfe56

Browse files
Merge pull request #56 from marblestation/python3
Migration to Python 3
2 parents bbc8eb9 + 034b904 commit 0dbfe56

11 files changed

+61
-51
lines changed

.github/workflows/python_actions.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ jobs:
1111
- uses: actions/checkout@v2
1212
- uses: actions/setup-python@v2
1313
with:
14-
python-version: 2.7
14+
python-version: 3.8
1515

1616
- name: Install dependencies
1717
run: |
18-
python -m pip install --upgrade wheel setuptools pip
18+
python -m pip install --upgrade setuptools pip
1919
pip install -U -r requirements.txt
2020
pip install -U -r dev-requirements.txt
2121

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
*pyc
22
.idea
33
python
4+
venv

alembic/env.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from __future__ import with_statement
2+
from __future__ import print_function
23
from alembic import context
34
from sqlalchemy import engine_from_config, pool
45
from logging.config import fileConfig
@@ -51,7 +52,7 @@ def get_app_config(key):
5152
app = application.create_app()
5253

5354
with app.app_context() as c:
54-
print 'Getting actual config for', key, app.config.get(key)
55+
print('Getting actual config for', key, app.config.get(key))
5556
return app.config.get(key)
5657

5758
def run_migrations_online():

dev-requirements.txt

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
flask-cors==2.0.0
2-
flask-testing==0.6.2
3-
httpretty==0.8.10
2+
Flask-Testing==0.8.1
3+
httpretty==0.9.5
44
pep257==0.5.0
5-
pytest==2.8.2
5+
pytest==6.2.4
66
pytest-cache==1.0
7-
pytest-cov==2.2.0
7+
pytest-cov==2.12.0
88
pytest-pep8==1.0.6
99
mock==2.0.0
1010
coverage==5.2.1

requirements.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
git+https://github.com/adsabs/ADSMicroserviceUtils.git@v1.1.9
1+
git+https://github.com/adsabs/ADSMicroserviceUtils.git@v1.2.0
22
alembic==0.8.1
3+
future==0.18.2

solr/__init__.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
import app
2-
from app import create_app
1+
from __future__ import absolute_import
2+
from . import app
3+
from .app import create_app

solr/app.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
from __future__ import absolute_import
2+
from past.builtins import basestring
13
from flask import Flask, make_response, jsonify
2-
from flask.ext.restful import Api
3-
from flask.ext.discoverer import Discoverer
4-
from flask.ext.sqlalchemy import SQLAlchemy
5-
from views import StatusView, Tvrh, Search, Qtree, BigQuery
4+
from flask_restful import Api
5+
from flask_discoverer import Discoverer
6+
from flask_sqlalchemy import SQLAlchemy
7+
from .views import StatusView, Tvrh, Search, Qtree, BigQuery
68
from adsmutils import ADSFlask
79

810
def create_app(**config):

solr/tests/unittests/test_solr.py

+17-18
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
import sys, os
22
PROJECT_HOME = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../'))
33
sys.path.append(PROJECT_HOME)
4-
from flask.ext.testing import TestCase
4+
from flask_testing import TestCase
55
from flask import url_for
66
import unittest
77
import httpretty
88
import json
9-
import app
9+
from solr import app
1010
from werkzeug.security import gen_salt
1111
from werkzeug.datastructures import MultiDict
12-
from StringIO import StringIO
12+
from io import BytesIO
1313
from solr.tests.mocks import MockSolrResponse
14-
from views import SolrInterface
1514
from solr import views
15+
from solr.views import SolrInterface
1616
from models import Limits, Base
1717
import mock
18-
from StringIO import StringIO
1918

2019
class TestSolrInterface(TestCase):
2120

@@ -248,11 +247,11 @@ def request_callback(request, uri, headers):
248247
r = c.get(url_for('search'), query_string={'q': 'star'})
249248

250249
# Two cookies (session and sroute)
251-
self.assertEqual(len(r.data.split(';')), len(self.app.config.get("SOLR_SERVICE_FORWARDED_COOKIES")))
250+
self.assertEqual(len(r.data.decode('utf-8').split(';')), len(self.app.config.get("SOLR_SERVICE_FORWARDED_COOKIES")))
252251

253252
# This forwarded cookie should match the one we gave originally
254253
n_found_cookies_with_good_value = 0
255-
for cookie in r.data.split(';'):
254+
for cookie in r.data.decode('utf-8').split(';'):
256255
key, value = cookie.split('=')
257256
if key in self.app.config.get("SOLR_SERVICE_FORWARDED_COOKIES"):
258257
self.assertEqual(value.strip(), cookie_value)
@@ -417,7 +416,7 @@ def test_docs_subquery(self):
417416
data={
418417
'q': '*:*',
419418
'fq': 'docs(hHGU1Ef-TpacAhicI3J8kQ)',
420-
'big': (StringIO('foo\nbar'), 'bigname', 'big-query/csv')
419+
'big': (BytesIO('foo\nbar'.encode('utf-8')), 'bigname', 'big-query/csv')
421420
},
422421
headers={'Authorization': 'Bearer foo'})
423422
# it made a request to retrieve library
@@ -568,7 +567,7 @@ def request_callback(request, uri, headers):
568567
'q': '*:*',
569568
'fl': 'bibcode',
570569
'fq': '{!bitset}',
571-
'file_field': (StringIO(bibcodes), 'file', 'big-query/csv')
570+
'file_field': (BytesIO(bibcodes.encode('utf-8')), 'file', 'big-query/csv')
572571
}
573572
)
574573

@@ -581,13 +580,13 @@ def request_callback(request, uri, headers):
581580
data={
582581
'q': '*:*',
583582
'fl': 'bibcode',
584-
'file_field': (StringIO(bibcodes), 'filename', 'big-query/csv'),
583+
'file_field': (BytesIO(bibcodes.encode('utf-8')), 'filename', 'big-query/csv'),
585584
}
586585
)
587586

588587
self.assertEqual(resp.status_code, 200)
589-
self.assertTrue('bitset' not in resp.data)
590-
self.assertTrue("Content-Disposition: form-data; name=\"file_field\"; filename=\"file_field\"\r\nContent-Type: big-query/csv" in resp.data)
588+
self.assertTrue('bitset' not in resp.data.decode('utf-8'))
589+
self.assertTrue("Content-Disposition: form-data; name=\"file_field\"; filename=\"file_field\"\\r\\nContent-Type: big-query/csv" in resp.data.decode('utf-8'))
591590

592591

593592
# Missing 'fq' parameter is filled in - but only when data (request.post(data=...)
@@ -599,8 +598,8 @@ def request_callback(request, uri, headers):
599598
)
600599

601600
self.assertEqual(resp.status_code, 200)
602-
self.assertTrue('fq=%7B%21bitset%7D' in resp.data)
603-
self.assertTrue("Content-Disposition: form-data; name=\"old-bad-behaviour\"; filename=\"old-bad-behaviour\"\r\nContent-Type: big-query/csv" in resp.data)
601+
self.assertTrue('fq=%7B%21bitset%7D' in resp.data.decode('utf-8'))
602+
self.assertTrue("Content-Disposition: form-data; name=\"old-bad-behaviour\"; filename=\"old-bad-behaviour\"\\r\\nContent-Type: big-query/csv" in resp.data.decode('utf-8'))
604603

605604

606605

@@ -612,20 +611,20 @@ def request_callback(request, uri, headers):
612611
'q': '*:*',
613612
'fl': 'bibcode',
614613
'fq': '{!bitset compression = true}',
615-
'file_field': (StringIO(bibcodes), 'filename', 'big-query/csv'),
614+
'file_field': (BytesIO(bibcodes.encode('utf-8')), 'filename', 'big-query/csv'),
616615
}
617616
)
618617

619618
self.assertEqual(resp.status_code, 200)
620-
self.assertTrue('fq=%7B%21bitset+compression+%3D+true%7D' in resp.data)
619+
self.assertTrue('fq=%7B%21bitset+compression+%3D+true%7D' in resp.data.decode('utf-8'))
621620

622621
# We now allow more content streams to be sent
623622
data = MultiDict([
624623
('q', '*:*'),
625624
('fl', 'bibcode'),
626625
('fq', '{!bitset}'),
627-
('file_field', (StringIO(bibcodes), 'filename', 'big-query/csv')),
628-
('file_field', (StringIO(bibcodes), 'filename', 'big-query/csv')),
626+
('file_field', (BytesIO(bibcodes.encode('utf-8')), 'filename', 'big-query/csv')),
627+
('file_field', (BytesIO(bibcodes.encode('utf-8')), 'filename', 'big-query/csv')),
629628
])
630629

631630
resp = self.client.post(

solr/tests/unittests/test_webservices.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from flask.ext.testing import TestCase
1+
from flask_testing import TestCase
2+
from past.builtins import basestring
23
import unittest
3-
import app
4+
from solr import app
45

56

67
class TestWebservices(TestCase):
@@ -23,7 +24,7 @@ def test_ResourcesRoute(self):
2324
'methods': list,
2425
'description': basestring,
2526
'rate_limit': list,
26-
}.iteritems():
27+
}.items():
2728
# Assert each resource is described has the expected_field
2829
[self.assertIn(expected_field, v) for v in r.json.values()]
2930

solr/views.py

+19-15
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
1+
from __future__ import absolute_import
2+
from future import standard_library
3+
standard_library.install_aliases()
4+
from builtins import str
5+
from past.builtins import basestring
16
from flask import current_app, request
2-
from flask.ext.restful import Resource
3-
from flask.ext.discoverer import advertise
7+
from flask_restful import Resource
8+
from flask_discoverer import advertise
49
try:
510
from flask_login import current_user
611
except:
712
# If solr service is not shipped with adsws, this will fail and it is ok
813
pass
914
import json
10-
from models import Limits
15+
from .models import Limits
1116
from sqlalchemy import or_
1217
from werkzeug.datastructures import MultiDict
13-
try:
14-
from cStringIO import StringIO
15-
except:
16-
from StringIO import StringIO
18+
from io import StringIO
1719
from io import BytesIO
18-
from urlparse import parse_qs
20+
from urllib.parse import parse_qs
1921

2022
import requests # Do not use current_app.client but requests, to avoid re-using
2123
# connections from a pool which would make solr ingress nginx
@@ -145,7 +147,7 @@ def apply_protective_filters(self, payload, user_id, protected_fields, key):
145147
for f in session.query(Limits).filter(Limits.uid==user_id, or_(Limits.field==x for x in protected_fields)).all():
146148
if f.filter:
147149
fl = u'{0},{1}'.format(fl, f.field)
148-
fq.append(unicode(f.filter))
150+
fq.append(str(f.filter))
149151
payload['fl'] = fl
150152
session.commit()
151153

@@ -173,7 +175,7 @@ def cleanup_solr_request(self, payload, user_id=None, handler_class="default"):
173175
handler = self.handler.get(handler_class, self.handler.get("default", "-"))
174176
headers['Host'] = self.get_host(current_app.config.get(handler))
175177
internal_logging = []
176-
for internal_param, default in self.internal_logging_params.iteritems():
178+
for internal_param, default in self.internal_logging_params.items():
177179
if internal_param in request.headers:
178180
internal_logging.append("{}={}".format(internal_param, request.headers[internal_param]))
179181
headers[internal_param] = request.headers[internal_param]
@@ -208,7 +210,7 @@ def cleanup_solr_request(self, payload, user_id=None, handler_class="default"):
208210

209211
max_hl = current_app.config.get('SOLR_SERVICE_MAX_SNIPPETS', 4)
210212
max_frag = current_app.config.get('SOLR_SERVICE_MAX_FRAGSIZE', 100)
211-
for k,v in payload.items():
213+
for k,v in list(payload.items()):
212214
if 'hl.' in k:
213215
if '.snippets' in k:
214216
payload[k] = max(0, min(_safe_int(v, default=max_hl), max_hl))
@@ -242,7 +244,7 @@ def _cleanup_fields(self, payload, key, allowed_fields):
242244
fields.extend([i.strip().lower() for i in y.split(',')])
243245

244246
if allowed_fields:
245-
fields = filter(lambda x: x in allowed_fields, fields)
247+
fields = [x for x in fields if x in allowed_fields]
246248

247249
payload[key] = ','.join(fields)
248250

@@ -271,8 +273,8 @@ def _cleanup_fl(self, payload, user_id, key):
271273

272274
protected_fields = []
273275
if disallowed:
274-
protected_fields = filter(lambda x: x in disallowed, fields)
275-
fields = filter(lambda x: x not in disallowed, fields)
276+
protected_fields = [x for x in fields if x in disallowed]
277+
fields = [x for x in fields if x not in disallowed]
276278

277279
if len(fields) == 0:
278280
fields.append('id')
@@ -340,7 +342,9 @@ def check_for_embedded_bigquery(self, params, request, headers, handler_class="d
340342
if request.data and isinstance(request.data, basestring) and len(request.data) > 0:
341343
if 'fq' not in params:
342344
params['fq'] = [u'{!bitset}']
343-
elif len(filter(lambda x: '!bitset' in x, params['fq'])) == 0:
345+
elif isinstance(params['fq'], str) and '{!bitset}' not in params['fq']:
346+
params['fq'] += u' {!bitset}'
347+
elif isinstance(params['fq'], list) and len([x for x in params['fq'] if '!bitset' in x]) == 0:
344348
params['fq'].append(u'{!bitset}')
345349

346350
# we'll package request.data into files

wsgi.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from werkzeug.serving import run_simple
2-
from werkzeug.wsgi import DispatcherMiddleware
2+
from werkzeug.middleware.dispatcher import DispatcherMiddleware
33
from solr import app
44

55
application = app.create_app()

0 commit comments

Comments
 (0)