Skip to content

Commit b4955cc

Browse files
edsutw4l
andauthored
Upgrade dependencies (#839)
- Update and pin dependencies to specific versions that support Python 3.7-3.11 - Replace deprecated werkzeug.pop_path_info with wsgiref.shift_path_info - Use the latest httpbin from psf/httpbin - Remove unused flask test dependency - Drop Python 2 and Python <3.7 support - Ensure greenlet 2 is used for now, as psf/httpbin doesn't yet work with greenlet 3 --------- Co-authored-by: Tessa Walsh <tessa@bitarchivist.net>
1 parent f40e7ef commit b4955cc

File tree

12 files changed

+49
-49
lines changed

12 files changed

+49
-49
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
strategy:
99
max-parallel: 3
1010
matrix:
11-
python-version: ['3.7', '3.8', '3.9', '3.10']
11+
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
1212

1313
steps:
1414
- name: checkout

pywb/apps/frontendapp.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from gevent.monkey import patch_all; patch_all()
22

33
from werkzeug.routing import Map, Rule, RequestRedirect, Submount
4-
from werkzeug.wsgi import pop_path_info
4+
from wsgiref.util import shift_path_info
55
from six.moves.urllib.parse import urljoin, parse_qsl
66
from six import iteritems
77
from warcio.utils import to_native_str
@@ -558,9 +558,9 @@ def setup_paths(self, environ, coll, record=False):
558558
return
559559

560560
if coll != '$root':
561-
pop_path_info(environ)
561+
shift_path_info(environ)
562562
if record:
563-
pop_path_info(environ)
563+
shift_path_info(environ)
564564

565565
paths = [self.warcserver.root_dir]
566566

@@ -669,7 +669,7 @@ def handle_request(self, environ, start_response):
669669

670670
lang = args.pop('lang', '')
671671
if lang:
672-
pop_path_info(environ)
672+
shift_path_info(environ)
673673

674674
if lang:
675675
environ['pywb_lang'] = lang

pywb/apps/rewriterapp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def __init__(self, framed_replay=False, jinja_env=None, config=None, paths=None)
6464

6565
if not jinja_env:
6666
jinja_env = JinjaEnv(globals={'static_path': 'static'},
67-
extensions=['jinja2.ext.i18n', 'jinja2.ext.with_'])
67+
extensions=['jinja2.ext.i18n'])
6868
jinja_env.jinja_env.install_null_translations()
6969

7070
self.jinja_env = jinja_env

pywb/rewrite/templateview.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from six.moves.urllib.parse import urlsplit, quote
77

8-
from jinja2 import Environment, TemplateNotFound, contextfunction, select_autoescape
8+
from jinja2 import Environment, TemplateNotFound, pass_context, select_autoescape
99
from jinja2 import FileSystemLoader, PackageLoader, ChoiceLoader
1010

1111
from webassets.ext.jinja2 import AssetsExtension
@@ -139,7 +139,7 @@ def get_translate(context):
139139
return loc_map.get(loc)
140140

141141
def override_func(jinja_env, name):
142-
@contextfunction
142+
@pass_context
143143
def get_override(context, text):
144144
translate = get_translate(context)
145145
if not translate:
@@ -158,7 +158,7 @@ def get_override(context, text):
158158

159159
# Special _Q() function to return %-encoded text, necessary for use
160160
# with text in banner
161-
@contextfunction
161+
@pass_context
162162
def quote_gettext(context, text):
163163
translate = get_translate(context)
164164
if not translate:
@@ -171,7 +171,7 @@ def quote_gettext(context, text):
171171
self.jinja_env.globals['_Q'] = quote_gettext
172172
self.jinja_env.globals['default_locale'] = default_locale
173173

174-
@contextfunction
174+
@pass_context
175175
def switch_locale(context, locale):
176176
environ = context.get('env')
177177
curr_loc = environ.get('pywb_lang', '')
@@ -188,7 +188,7 @@ def switch_locale(context, locale):
188188

189189
return app_prefix + '/' + locale + request_uri
190190

191-
@contextfunction
191+
@pass_context
192192
def get_locale_prefixes(context):
193193
environ = context.get('env')
194194
locale_prefixes = {}

pywb/warcserver/test/test_inputreq.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def __call__(self, environ, start_response):
3939

4040
#=============================================================================
4141
class TestInputReq(object):
42-
def setup(self):
42+
def setup_method(self):
4343
self.app = InputReqApp()
4444
self.testapp = webtest.TestApp(self.app)
4545

pywb/warcserver/test/test_upstream.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919

2020
class TestUpstream(LiveServerTests, HttpBinLiveTests, BaseTestClass):
21-
def setup(self):
21+
def setup_method(self):
2222
app = BaseWarcServer()
2323

2424
base_url = 'http://localhost:{0}'.format(self.server.port)

requirements.txt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
six
22
warcio>=1.7.1
33
requests
4-
redis<3.0
5-
jinja2<3.0.0
4+
redis
5+
jinja2>=3.1.2
66
surt>=0.3.1
77
brotlipy
88
pyyaml
9-
werkzeug
9+
werkzeug==2.2.3
1010
webencodings
11-
gevent==21.12.0
11+
gevent==22.10.2
12+
greenlet>=2.0.2,<3.0
1213
webassets==2.0
1314
portalocker
1415
wsgiprox>=1.5.1
1516
fakeredis<1.0
1617
tldextract
1718
python-dateutil
18-
markupsafe<2.1.0
19+
markupsafe>=2.1.1
1920
ua_parser

setup.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ def get_package_data():
113113
"translate_toolkit"
114114
],
115115
},
116+
python_requires='>=3.7,<3.12',
116117
tests_require=load_requirements("test_requirements.txt"),
117118
cmdclass={'test': PyTest},
118119
test_suite='',
@@ -131,16 +132,12 @@ def get_package_data():
131132
'Environment :: Web Environment',
132133
'License :: OSI Approved :: GNU General Public License (GPL)',
133134
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
134-
'Programming Language :: Python :: 2',
135-
'Programming Language :: Python :: 2.7',
136135
'Programming Language :: Python :: 3',
137-
'Programming Language :: Python :: 3.3',
138-
'Programming Language :: Python :: 3.4',
139-
'Programming Language :: Python :: 3.5',
140-
'Programming Language :: Python :: 3.6',
141136
'Programming Language :: Python :: 3.7',
142137
'Programming Language :: Python :: 3.8',
143138
'Programming Language :: Python :: 3.9',
139+
'Programming Language :: Python :: 3.10',
140+
'Programming Language :: Python :: 3.11',
144141
'Topic :: Internet :: Proxy Servers',
145142
'Topic :: Internet :: WWW/HTTP',
146143
'Topic :: Internet :: WWW/HTTP :: WSGI',

test_requirements.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ WebTest
33
pytest-cov
44
mock
55
urllib3
6-
httpbin==0.5.0
7-
flask<2.0
86
ujson
97
lxml
8+
httpbin>=0.10.2

tests/test_force_https.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@ def test_force_https_root_replay_1(self, fmod):
5656
resp = self.get('/20140128051539{0}/http://www.iana.org/domains/example', fmod,
5757
headers={'X-Forwarded-Proto': 'https'})
5858

59-
assert resp.headers['Location'] == 'https://localhost:80/20140128051539{0}/http://www.iana.org/domains/reserved'.format(fmod)
59+
assert resp.headers['Location'] == 'https://localhost:80/20140128051539{0}/http://www.iana.org/help/example-domains'.format(fmod)
6060

6161

tests/test_live_rewriter.py

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -91,25 +91,28 @@ def test_live_head(self, fmod_sl):
9191
resp = self.head('/live/{0}httpbin.org/get?foo=bar', fmod_sl)
9292
assert resp.status_int == 200
9393

94-
@pytest.mark.skipif(sys.version_info < (3,0), reason='does not respond in 2.7')
95-
def test_live_bad_content_length(self, fmod_sl):
96-
resp = self.get('/live/{0}httpbin.org/response-headers?content-length=149,149', fmod_sl, status=200)
97-
assert resp.headers['Content-Length'] == '149'
98-
99-
resp = self.get('/live/{0}httpbin.org/response-headers?Content-Length=xyz', fmod_sl, status=200)
100-
assert resp.headers['Content-Length'] == '90'
101-
102-
@pytest.mark.skipif(sys.version_info < (3,0), reason='does not respond in 2.7')
103-
def test_live_bad_content_length_with_range(self, fmod_sl):
104-
resp = self.get('/live/{0}httpbin.org/response-headers?content-length=149,149', fmod_sl,
105-
headers={'Range': 'bytes=0-'}, status=206)
106-
assert resp.headers['Content-Length'] == '149'
107-
assert resp.headers['Content-Range'] == 'bytes 0-148/149'
108-
109-
resp = self.get('/live/{0}httpbin.org/response-headers?Content-Length=xyz', fmod_sl,
110-
headers={'Range': 'bytes=0-'}, status=206)
111-
assert resp.headers['Content-Length'] == '90'
112-
assert resp.headers['Content-Range'] == 'bytes 0-89/90'
94+
# Following tests are temporarily commented out because latest version of PSF httpbin
95+
# now returns 400 if content-length header isn't parsable as an int
96+
97+
# @pytest.mark.skipif(sys.version_info < (3,0), reason='does not respond in 2.7')
98+
# def test_live_bad_content_length(self, fmod_sl):
99+
# resp = self.get('/live/{0}httpbin.org/response-headers?content-length=149,149', fmod_sl, status=200)
100+
# assert resp.headers['Content-Length'] == '149'
101+
102+
# resp = self.get('/live/{0}httpbin.org/response-headers?Content-Length=xyz', fmod_sl, status=200)
103+
# assert resp.headers['Content-Length'] == '90'
104+
105+
# @pytest.mark.skipif(sys.version_info < (3,0), reason='does not respond in 2.7')
106+
# def test_live_bad_content_length_with_range(self, fmod_sl):
107+
# resp = self.get('/live/{0}httpbin.org/response-headers?content-length=149,149', fmod_sl,
108+
# headers={'Range': 'bytes=0-'}, status=206)
109+
# assert resp.headers['Content-Length'] == '149'
110+
# assert resp.headers['Content-Range'] == 'bytes 0-148/149'
111+
112+
# resp = self.get('/live/{0}httpbin.org/response-headers?Content-Length=xyz', fmod_sl,
113+
# headers={'Range': 'bytes=0-'}, status=206)
114+
# assert resp.headers['Content-Length'] == '90'
115+
# assert resp.headers['Content-Range'] == 'bytes 0-89/90'
113116

114117
def test_custom_unicode_header(self, fmod_sl):
115118
value = u'⛄'

tox.ini

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ testpaths =
44
tests
55

66
[tox]
7-
envlist = py36, py37, py38, py39, py310
7+
envlist = py37, py38, py39, py310, py311
88

99
[gh-actions]
1010
python =
11-
3.6: py36
1211
3.7: py37
1312
3.8: py38
1413
3.9: py39
1514
3.10: py310
15+
3.11: py311
1616

1717
[testenv]
1818
setenv = PYWB_NO_VERIFY_SSL = 1
@@ -22,6 +22,6 @@ deps =
2222
-rrequirements.txt
2323
-rextra_requirements.txt
2424
commands =
25-
py.test --cov-config .coveragerc --cov pywb -v --doctest-modules ./pywb/ tests/
25+
pytest --cov-config .coveragerc --cov pywb -v --doctest-modules ./pywb/ tests/
2626

2727

0 commit comments

Comments
 (0)