Use pp.common.downcaseTokens for pyparsing v3#209
Conversation
|
env) busunkim@busunkim:~/github/httplib2$ pytest -sv tests/test_auth.py
================================================================================== test session starts ===================================================================================
platform linux -- Python 3.9.7, pytest-3.2.1, py-1.10.0, pluggy-0.4.0 -- /usr/local/google/home/busunkim/github/httplib2/env/bin/python3
cachedir: .cache
Using --randomly-seed=1635290136
rootdir: /usr/local/google/home/busunkim/github/httplib2, inifile: setup.cfg
plugins: xdist-1.20.0, timeout-1.2.0, randomly-1.2.1, forked-0.2, cov-2.5.1
timeout: 17.0s method: signal
collected 50 items
tests/test_auth.py::test_basic debug: auth_parsed {'basic': {'token': 'am9lOk4lJjc7HhgzbSR9DGJ5WRozAjlaASBNVhVnJxoYdHNkLiw/E0xpXhg4N2YmTCJ/fwF5GnVNY2t7Vlxsdj09'}}
debug: first auth scheme='basic'
PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[relax-{'www-authenticate': 'Digest realm="myrealm", nonce="KBAA=3", algorithm=MD5, qop="auth", stale=true'}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[relax-{'www-authenticate': 'T*!%#st realm=to*!%#en, to*!%#en="quoted string"'}] PASSED
tests/test_auth.py::test_digest_next_nonce_nc debug: auth_parsed {'digest': {'username': 'joe', 'realm': 'httplib2 test', 'nonce': 'FrG3typ19gA6PhiqaBhlMq8sqqvSxj4mhLKQ8Ag=', 'uri': '/', 'algorithm': 'MD5', 'response': '0d58f218ebd6fff7042a9a83178fb1a3', 'qop': 'auth', 'nc': '00000001', 'cnonce': '740729028247c47e', 'opaque': 'FrG3typ2WgA6akJXtj+U+XKv37llfGNai2CiuC8='}}
debug: first auth scheme='digest'
debug: response1 authentication-info: qop=auth, rspauth="f8ee112a52d75e096dbcb9fdd1dea7f9", cnonce="740729028247c47e", nc=00000001
parsed: {'qop': 'auth', 'rspauth': 'f8ee112a52d75e096dbcb9fdd1dea7f9', 'cnonce': '740729028247c47e', 'nc': '00000001'}
debug: auth_parsed {'digest': {'username': 'joe', 'realm': 'httplib2 test', 'nonce': 'FrG3typ19gA6PhiqaBhlMq8sqqvSxj4mhLKQ8Ag=', 'uri': '/', 'algorithm': 'MD5', 'response': '72f42a98029cdad45f295e936517de64', 'qop': 'auth', 'nc': '00000002', 'cnonce': 'e85682e9b130b5ec', 'opaque': 'FrG3typ2WgA6akJXtj+U+XKv37llfGNai2CiuC8='}}
debug: first auth scheme='digest'
debug: auth_parsed {'digest': {'username': 'joe', 'realm': 'httplib2 test', 'nonce': 'FrG3typ19gA6PhiqaBhlMq8sqqvSxj4mhLKQ8Ag=', 'uri': '/', 'algorithm': 'MD5', 'response': 'b25e81c3c3688d09cf3cd3249a96bb4f', 'qop': 'auth', 'nc': '00000003', 'cnonce': 'd97b2c5ed08f6e43', 'opaque': 'FrG3typ2WgA6akJXtj+U+XKv37llfGNai2CiuC8='}}
debug: first auth scheme='digest'
debug: auth_parsed {'digest': {'username': 'joe', 'realm': 'httplib2 test', 'nonce': 'FrG3tysCWAA63mc7WdHy0vGoTh3PW71x8GL6dlE=', 'uri': '/', 'algorithm': 'MD5', 'response': '49c8f3bb3a0209272697bf966bc70455', 'qop': 'auth', 'nc': '00000001', 'cnonce': '5119827dfea3bc46', 'opaque': 'FrG3typ2WgA6akJXtj+U+XKv37llfGNai2CiuC8='}}
debug: first auth scheme='digest'
PASSED
tests/test_auth.py::test_digest_object_auth_info PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[strict-{'www-authenticate': ''}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[relax-{'www-authenticate': 'Basic realm="me", algorithm=MD5'}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[strict-{'www-authenticate': 'Basic realm="me",other="fred" '}] PASSED
tests/test_auth.py::test_parse_www_authenticate_malformed[{'www-authenticate': 'OAuth "Facebook Platform" "invalid_token" "Invalid OAuth access token."'}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[strict-{'www-authenticate': 'Digest realm="myrealm", nonce="KBAA=3", algorithm=MD5, qop="auth", stale=true'}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[relax-{'www-authenticate': 'Digest realm="com3d", Basic realm="com3b", WSSE realm="com3w", profile="token"'}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[relax-{'www-authenticate': 'Basic realm="me", algorithm="MD5"'}] PASSED
tests/test_auth.py::test_benchmark_parse_www_authenticate[Basic realm="me", algorithm="MD5"] SKIPPED
tests/test_auth.py::test_parse_www_authenticate_correct[relax-{'www-authenticate': "Basic param='single quote'"}] PASSED
tests/test_auth.py::test_digest_object_with_opaque PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[strict-{'www-authenticate': 'Basic REAlm="me" '}] PASSED
tests/test_auth.py::test_parse_www_authenticate_complexity x50: time=455.0us speed=9.1 us/op
x100: time=624.0us speed=6.2 us/op expected=18.2 us/op error=0.3
PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[relax-{'www-authenticate': 'Test realm="a \\\\"test\\\\" realm"'}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[relax-{'www-authenticate': 'Digest realm="2-comma-d", qop="auth-int", nonce="c0c8ff1", Basic realm="2-comma-b"'}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[strict-{'www-authenticate': 'Digest realm="digest1", qop="auth,auth-int", nonce="7102dd2", opaque="e9517f"'}] PASSED
tests/test_auth.py::test_basic_for_domain debug: auth_parsed {'basic': {'token': 'am9lOk4lJjc7HhgzbSR9DGJ5WRozAjlaASBNVhVnJxoYdHNkLiw/E0xpXhg4N2YmTCJ/fwF5GnVNY2t7Vlxsdj09'}}
debug: first auth scheme='basic'
PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[strict-{'www-authenticate': 'T*!%#st realm=to*!%#en, to*!%#en="quoted string"'}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[relax-{'www-authenticate': ''}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[strict-{'www-authenticate': "Basic param='single quote'"}] PASSED
tests/test_auth.py::test_benchmark_parse_www_authenticate[Digest realm="digest1", qop="auth,auth-int", nonce="7102dd2", opaque="e9517f"] SKIPPED
tests/test_auth.py::test_wsse_ok debug: auth_parsed {'wsse': {'profile': 'UsernameToken'}}
debug: first auth scheme='wsse'
debug: wsse_params {'username': 'user314', 'passworddigest': 'fTKaWNdTKU/vzNTR6mB0sbnvlis=', 'nonce': '740729028247c47e', 'created': '2021-10-26T23:15:37Z'}
debug: check client=fTKaWNdTKU/vzNTR6mB0sbnvlis= == real=fTKaWNdTKU/vzNTR6mB0sbnvlis=
PASSED
tests/test_auth.py::test_digest debug: auth_parsed {'digest': {'username': 'joe', 'realm': 'httplib2 test', 'nonce': 'FrG3ty6VTAA6siOK9sUYgyCnaeOf7HUn9L4dUow=', 'uri': '/', 'algorithm': 'MD5', 'response': '2a859767761bef586f493a350dd1c193', 'qop': 'auth', 'nc': '00000001', 'cnonce': '740729028247c47e', 'opaque': 'FrG3ty6VhwA6KpBa6903oAOLEQSnAuEIHfKDUnk='}}
debug: first auth scheme='digest'
PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[relax-{'www-authenticate': 'Digest realm="digest1", qop="auth,auth-int", nonce="7102dd2", opaque="e9517f"'}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[strict-{'www-authenticate': 'Test realm="a \\\\"test\\\\" realm"'}] PASSED
tests/test_auth.py::test_benchmark_parse_www_authenticate[Digest realm="2-comma-d", qop="auth-int", nonce="c0c8ff1", Basic realm="2-comma-b"] SKIPPED
tests/test_auth.py::test_parse_www_authenticate_correct[strict-{'www-authenticate': 'Digest realm="2-comma-d", qop="auth-int", nonce="c0c8ff1", Basic realm="2-comma-b"'}] PASSED
tests/test_auth.py::test_digest_object_stale PASSED
tests/test_auth.py::test_credentials PASSED
tests/test_auth.py::test_benchmark_parse_www_authenticate[Bearer 0b79bab50daca910b000d4f1a2b675d604257e42] SKIPPED
tests/test_auth.py::test_digest_object PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[relax-{}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[relax-{'www-authenticate': 'Basic realm="me",other="fred" '}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[relax-{'www-authenticate': 'Test realm="test realm" , foo=foo ,bar="bar", baz=baz,qux=qux'}] PASSED
tests/test_auth.py::test_basic_two_credentials debug: auth_parsed {'basic': {'token': 'ZnJlZDpMExAgExx1B0R+L1doQXd4ewYOfVFzOkxuXitRXzdvUGkdXhhqPVp7GWtiCAN1Hjogchc8YQ=='}}
debug: first auth scheme='basic'
debug: auth_parsed {'basic': {'token': 'ZnJlZDpMExAgExx1B0R+L1doQXd4ewYOfVFzOkxuXitRXzdvUGkdXhhqPVp7GWtiCAN1Hjogchc8YQ=='}}
debug: first auth scheme='basic'
debug: auth_parsed {'basic': {'token': 'am9lOk4lJjc7HhgzbSR9DGJ5WRozAjlaASBNVhVnJxoYdHNkLiw/E0xpXhg4N2YmTCJ/fwF5GnVNY2t7Vlxsdj09'}}
debug: first auth scheme='basic'
debug: auth_parsed {'basic': {'token': 'am9lOk4lJjc7HhgzbSR9DGJ5WRozAjlaASBNVhVnJxoYdHNkLiw/E0xpXhg4N2YmTCJ/fwF5GnVNY2t7Vlxsdj09'}}
debug: first auth scheme='basic'
debug: auth_parsed {'basic': {'token': 'ZnJlZDpMExAgExx1B0R+L1doQXd4ewYOfVFzOkxuXitRXzdvUGkdXhhqPVp7GWtiCAN1Hjogchc8YQ=='}}
debug: first auth scheme='basic'
PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[relax-{'www-authenticate': 'Basic REAlm="me" '}] PASSED
tests/test_auth.py::test_wsse_algorithm PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[relax-{'www-authenticate': 'Basic realm="me"'}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[strict-{'www-authenticate': 'Basic realm="me"'}] PASSED
tests/test_auth.py::test_digest_auth_stale debug: auth_parsed {'digest': {'username': 'joe', 'realm': 'httplib2 test', 'nonce': 'FrG3tzEBUwA68ZaqTFeAsiQvOqkBsibN2Ul4HB8=', 'uri': '/', 'algorithm': 'MD5', 'response': '8aa1f326b974ab6b32b700f45b197646', 'qop': 'auth', 'nc': '00000001', 'cnonce': '740729028247c47e', 'opaque': 'FrG3tzEBnAA6BjpWtDY6+87W7oOHgq9h879zeV0='}}
debug: first auth scheme='digest'
debug: auth_parsed {'digest': {'username': 'joe', 'realm': 'httplib2 test', 'nonce': 'FrG3tzEBUwA68ZaqTFeAsiQvOqkBsibN2Ul4HB8=', 'uri': '/', 'algorithm': 'MD5', 'response': 'adef6fff2ecb7035f82752a33b857dc4', 'qop': 'auth', 'nc': '00000002', 'cnonce': 'e85682e9b130b5ec', 'opaque': 'FrG3tzEBnAA6BjpWtDY6+87W7oOHgq9h879zeV0='}}
debug: first auth scheme='digest'
debug: auth_parsed {'digest': {'username': 'joe', 'realm': 'httplib2 test', 'nonce': 'FrG3tzFdpgA6owqS12s8MOqE91Xj7bXx38ElSG8=', 'uri': '/', 'algorithm': 'MD5', 'response': '67b3e0d5bbd4f01a226e71094f6eeb82', 'qop': 'auth', 'nc': '00000001', 'cnonce': 'd97b2c5ed08f6e43', 'opaque': 'FrG3tzEBnAA6BjpWtDY6+87W7oOHgq9h879zeV0='}}
debug: first auth scheme='digest'
PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[strict-{}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[strict-{'www-authenticate': 'Basic realm="me", algorithm=MD5'}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[strict-{'www-authenticate': 'Basic realm="me", algorithm="MD5"'}] PASSED
tests/test_auth.py::test_wsse_invalid debug: auth_parsed {'wsse': {'profile': 'UsernameToken'}}
debug: first auth scheme='wsse'
debug: wsse_params {'username': 'user294', 'passworddigest': '3Mri76zy1ilTPFonE/TJR5K79J8=', 'nonce': '740729028247c47e', 'created': '2021-10-26T23:15:37Z'}
debug: check client=3Mri76zy1ilTPFonE/TJR5K79J8= == real=fTKaWNdTKU/vzNTR6mB0sbnvlis=
PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[strict-{'www-authenticate': 'Test realm="test realm" , foo=foo ,bar="bar", baz=baz,qux=qux'}] PASSED
tests/test_auth.py::test_parse_www_authenticate_correct[strict-{'www-authenticate': 'Digest realm="com3d", Basic realm="com3b", WSSE realm="com3w", profile="token"'}] PASSED
----------- coverage: platform linux, python 3.9.7-final-0 -----------
Name Stmts Miss Cover
--------------------------------------------------
python3/httplib2/__init__.py 923 540 41%
python3/httplib2/auth.py 40 3 92%
python3/httplib2/certs.py 29 8 72%
python3/httplib2/error.py 25 3 88%
python3/httplib2/iri2uri.py 41 18 56%
python3/httplib2/socks.py 244 201 18%
--------------------------------------------------
TOTAL 1302 773 41%
================================================================================ short test summary info =================================================================================
SKIP [4] tests/test_auth.py:249: benchmark disabled by default, set env httplib2_test_bench=1
========================================================================== 46 passed, 4 skipped in 0.34 seconds ========================================================================== |
|
Did you check Sorry IDK how you do that, this patch fails for me on two very different machines. Please wait until I restore CI. it looks like lost captures. |
Co-authored-by: Sergey Shepelev <temotor@gmail.com>
|
It looks like I had an older |
|
I will circle back to this tomorrow to try to figure out why the parsing behavior has changed. It looks like there have been a number of patch releases of pyparsing the past few days (https://pypi.org/project/pyparsing/#history) so it might also be an unintentional behavior changes. |
|
Cool, glad to see consistent result. Problem was greedy challenges. # test code
header = "basic realm=\"well\", sign n1234"
print([
c.asDict()
for c in auth.www_authenticate.parseString(header)
])# pyparsing<3
[{'scheme': 'basic', 'params': {'realm': 'well'}}, {'scheme': 'sign', 'token': 'n1234'}]
# pyparsing>=3
[{'scheme': 'basic', 'realm': 'well', 'params': [['realm', 'well']]}, {'scheme': 'sign', 'token': 'n1234'}]@ptmcg would you be so kind to help with updating this seemingly simple parser to pyparsing 3? |
|
I stepped through each of the 3.0.0 pre-releases and found the unit tests start to fail on 3.0.0b1. The commit where the httplib2 unit tests begin to fail is pyparsing/pyparsing@3c495db. It looks like the different output comes from changes on lines 4547 - 4550 in In |
|
Excellent! Thanks so much for chasing this down. I think this addresses at least one other issue as well. |
|
Opened pyparsing/pyparsing#324. Thank you @ptmcg for maintaining pyparsing, and @temoto for maintaining httplib2! |
|
Unit tests all pass for me locally with |
|
For pyparsing v3 support use @busunkim96 thank you very much |

For #207.
Applies the patch @temoto shared in #207 (comment) and adjusts
requirements.txtto install a compatible version ofpyparsingbased on the Python version.