mirror of
https://github.com/gentoo-mirror/gentoo.git
synced 2026-08-24 06:48:18 -07:00
dev-python/twisted: Backport py3.8 fixes to 20.3.0
Signed-off-by: Michał Górny <mgorny@gentoo.org>
This commit is contained in:
259
dev-python/twisted/files/twisted-20.3.0-py38-cgi.patch
Normal file
259
dev-python/twisted/files/twisted-20.3.0-py38-cgi.patch
Normal file
@@ -0,0 +1,259 @@
|
||||
From 62ab0203c59c1f9788c53dfad4a212774094d05c Mon Sep 17 00:00:00 2001
|
||||
From: Craig Rodrigues <rodrigc@FreeBSD.org>
|
||||
Date: Mon, 13 Apr 2020 01:22:23 -0700
|
||||
Subject: [PATCH 2/2] Merge 9801-rodrigc-cgi: Change import of cgi.parse_qs to
|
||||
urllib.parse.parse_qs
|
||||
|
||||
Author: rodrigc
|
||||
Reviewer: hawkowl
|
||||
Fixes: ticket:9801
|
||||
---
|
||||
src/twisted/web/client.py | 17 ++++-----
|
||||
src/twisted/web/http.py | 49 ++++++++++++-------------
|
||||
src/twisted/web/newsfragments/9801.misc | 0
|
||||
src/twisted/web/test/test_http.py | 41 +++------------------
|
||||
src/twisted/web/test/test_webclient.py | 5 +--
|
||||
5 files changed, 38 insertions(+), 74 deletions(-)
|
||||
create mode 100644 src/twisted/web/newsfragments/9801.misc
|
||||
|
||||
diff --git a/src/twisted/web/client.py b/src/twisted/web/client.py
|
||||
index 7e4642ef3..8209f5a5e 100644
|
||||
--- a/src/twisted/web/client.py
|
||||
+++ b/src/twisted/web/client.py
|
||||
@@ -12,15 +12,8 @@ import os
|
||||
import collections
|
||||
import warnings
|
||||
|
||||
-try:
|
||||
- from urlparse import urlunparse, urljoin, urldefrag
|
||||
-except ImportError:
|
||||
- from urllib.parse import urljoin, urldefrag
|
||||
- from urllib.parse import urlunparse as _urlunparse
|
||||
-
|
||||
- def urlunparse(parts):
|
||||
- result = _urlunparse(tuple([p.decode("charmap") for p in parts]))
|
||||
- return result.encode("charmap")
|
||||
+from urllib.parse import urljoin, urldefrag
|
||||
+from urllib.parse import urlunparse as _urlunparse
|
||||
|
||||
import zlib
|
||||
from functools import wraps
|
||||
@@ -51,6 +44,12 @@ from twisted.web._newclient import _ensureValidURI, _ensureValidMethod
|
||||
|
||||
|
||||
|
||||
+def urlunparse(parts):
|
||||
+ result = _urlunparse(tuple([p.decode("charmap") for p in parts]))
|
||||
+ return result.encode("charmap")
|
||||
+
|
||||
+
|
||||
+
|
||||
class PartialDownloadError(error.Error):
|
||||
"""
|
||||
Page was only partially downloaded, we got disconnected in middle.
|
||||
diff --git a/src/twisted/web/http.py b/src/twisted/web/http.py
|
||||
index b7afa8b0d..94d0ae81f 100644
|
||||
--- a/src/twisted/web/http.py
|
||||
+++ b/src/twisted/web/http.py
|
||||
@@ -66,27 +66,10 @@ import time
|
||||
import calendar
|
||||
import warnings
|
||||
import os
|
||||
-from io import BytesIO as StringIO
|
||||
-
|
||||
-try:
|
||||
- from urlparse import (
|
||||
- ParseResult as ParseResultBytes, urlparse as _urlparse)
|
||||
- from urllib import unquote
|
||||
- from cgi import parse_header as _parseHeader
|
||||
-except ImportError:
|
||||
- from urllib.parse import (
|
||||
- ParseResultBytes, urlparse as _urlparse, unquote_to_bytes as unquote)
|
||||
-
|
||||
- def _parseHeader(line):
|
||||
- # cgi.parse_header requires a str
|
||||
- key, pdict = cgi.parse_header(line.decode('charmap'))
|
||||
-
|
||||
- # We want the key as bytes, and cgi.parse_multipart (which consumes
|
||||
- # pdict) expects a dict of str keys but bytes values
|
||||
- key = key.encode('charmap')
|
||||
- pdict = {x:y.encode('charmap') for x, y in pdict.items()}
|
||||
- return (key, pdict)
|
||||
+from io import BytesIO
|
||||
|
||||
+from urllib.parse import (
|
||||
+ ParseResultBytes, urlparse as _urlparse, unquote_to_bytes as unquote)
|
||||
|
||||
from zope.interface import Attribute, Interface, implementer, provider
|
||||
|
||||
@@ -163,6 +146,20 @@ monthname = [None,
|
||||
weekdayname_lower = [name.lower() for name in weekdayname]
|
||||
monthname_lower = [name and name.lower() for name in monthname]
|
||||
|
||||
+
|
||||
+
|
||||
+def _parseHeader(line):
|
||||
+ # cgi.parse_header requires a str
|
||||
+ key, pdict = cgi.parse_header(line.decode('charmap'))
|
||||
+
|
||||
+ # We want the key as bytes, and cgi.parse_multipart (which consumes
|
||||
+ # pdict) expects a dict of str keys but bytes values
|
||||
+ key = key.encode('charmap')
|
||||
+ pdict = {x: y.encode('charmap') for x, y in pdict.items()}
|
||||
+ return (key, pdict)
|
||||
+
|
||||
+
|
||||
+
|
||||
def urlparse(url):
|
||||
"""
|
||||
Parse an URL into six components.
|
||||
@@ -486,13 +483,15 @@ class _IDeprecatedHTTPChannelToRequestInterface(Interface):
|
||||
|
||||
class StringTransport:
|
||||
"""
|
||||
- I am a StringIO wrapper that conforms for the transport API. I support
|
||||
+ I am a BytesIO wrapper that conforms for the transport API. I support
|
||||
the `writeSequence' method.
|
||||
"""
|
||||
def __init__(self):
|
||||
- self.s = StringIO()
|
||||
+ self.s = BytesIO()
|
||||
+
|
||||
def writeSequence(self, seq):
|
||||
self.s.write(b''.join(seq))
|
||||
+
|
||||
def __getattr__(self, attr):
|
||||
return getattr(self.__dict__['s'], attr)
|
||||
|
||||
@@ -513,7 +512,7 @@ class HTTPClient(basic.LineReceiver):
|
||||
@type firstLine: C{bool}
|
||||
|
||||
@ivar __buffer: The buffer that stores the response to the HTTP request.
|
||||
- @type __buffer: A C{StringIO} object.
|
||||
+ @type __buffer: A C{BytesIO} object.
|
||||
|
||||
@ivar _header: Part or all of an HTTP request header.
|
||||
@type _header: C{bytes}
|
||||
@@ -579,7 +578,7 @@ class HTTPClient(basic.LineReceiver):
|
||||
if self._header != b"":
|
||||
# Only extract headers if there are any
|
||||
self.extractHeader(self._header)
|
||||
- self.__buffer = StringIO()
|
||||
+ self.__buffer = BytesIO()
|
||||
self.handleEndHeaders()
|
||||
self.setRawMode()
|
||||
return
|
||||
@@ -665,7 +664,7 @@ def _getContentFile(length):
|
||||
Get a writeable file-like object to which request content can be written.
|
||||
"""
|
||||
if length is not None and length < 100000:
|
||||
- return StringIO()
|
||||
+ return BytesIO()
|
||||
return tempfile.TemporaryFile()
|
||||
|
||||
|
||||
diff --git a/src/twisted/web/newsfragments/9801.misc b/src/twisted/web/newsfragments/9801.misc
|
||||
new file mode 100644
|
||||
index 000000000..e69de29bb
|
||||
diff --git a/src/twisted/web/test/test_http.py b/src/twisted/web/test/test_http.py
|
||||
index a3067f732..4189b307c 100644
|
||||
--- a/src/twisted/web/test/test_http.py
|
||||
+++ b/src/twisted/web/test/test_http.py
|
||||
@@ -9,15 +9,11 @@ from __future__ import absolute_import, division
|
||||
|
||||
import base64
|
||||
import calendar
|
||||
-import cgi
|
||||
import random
|
||||
|
||||
import hamcrest
|
||||
|
||||
-try:
|
||||
- from urlparse import urlparse, urlunsplit, clear_cache
|
||||
-except ImportError:
|
||||
- from urllib.parse import urlparse, urlunsplit, clear_cache
|
||||
+from urllib.parse import urlparse, urlunsplit, clear_cache, parse_qs
|
||||
|
||||
from io import BytesIO
|
||||
from itertools import cycle
|
||||
@@ -28,7 +24,7 @@ from zope.interface import (
|
||||
)
|
||||
from zope.interface.verify import verifyObject
|
||||
|
||||
-from twisted.python.compat import (_PY3, iterbytes, long, networkString,
|
||||
+from twisted.python.compat import (iterbytes, long, networkString,
|
||||
unicode, intToBytes)
|
||||
from twisted.python.components import proxyForInterface
|
||||
from twisted.python.failure import Failure
|
||||
@@ -2019,33 +2015,6 @@ Content-Type: application/x-www-form-urlencoded
|
||||
self.assertEqual(content, [networkString(query)])
|
||||
|
||||
|
||||
- def test_missingContentDisposition(self):
|
||||
- """
|
||||
- If the C{Content-Disposition} header is missing, the request is denied
|
||||
- as a bad request.
|
||||
- """
|
||||
- req = b'''\
|
||||
-POST / HTTP/1.0
|
||||
-Content-Type: multipart/form-data; boundary=AaB03x
|
||||
-Content-Length: 103
|
||||
-
|
||||
---AaB03x
|
||||
-Content-Type: text/plain
|
||||
-Content-Transfer-Encoding: quoted-printable
|
||||
-
|
||||
-abasdfg
|
||||
---AaB03x--
|
||||
-'''
|
||||
- channel = self.runRequest(req, http.Request, success=False)
|
||||
- self.assertEqual(
|
||||
- channel.transport.value(),
|
||||
- b"HTTP/1.1 400 Bad Request\r\n\r\n")
|
||||
-
|
||||
- if _PY3:
|
||||
- test_missingContentDisposition.skip = (
|
||||
- "cgi.parse_multipart is much more error-tolerant on Python 3.")
|
||||
-
|
||||
-
|
||||
def test_multipartProcessingFailure(self):
|
||||
"""
|
||||
When the multipart processing fails the client gets a 400 Bad Request.
|
||||
@@ -2373,15 +2342,15 @@ ok
|
||||
class QueryArgumentsTests(unittest.TestCase):
|
||||
def testParseqs(self):
|
||||
self.assertEqual(
|
||||
- cgi.parse_qs(b"a=b&d=c;+=f"),
|
||||
+ parse_qs(b"a=b&d=c;+=f"),
|
||||
http.parse_qs(b"a=b&d=c;+=f"))
|
||||
self.assertRaises(
|
||||
ValueError, http.parse_qs, b"blah", strict_parsing=True)
|
||||
self.assertEqual(
|
||||
- cgi.parse_qs(b"a=&b=c", keep_blank_values=1),
|
||||
+ parse_qs(b"a=&b=c", keep_blank_values=1),
|
||||
http.parse_qs(b"a=&b=c", keep_blank_values=1))
|
||||
self.assertEqual(
|
||||
- cgi.parse_qs(b"a=&b=c"),
|
||||
+ parse_qs(b"a=&b=c"),
|
||||
http.parse_qs(b"a=&b=c"))
|
||||
|
||||
|
||||
diff --git a/src/twisted/web/test/test_webclient.py b/src/twisted/web/test/test_webclient.py
|
||||
index 680e02780..672594993 100644
|
||||
--- a/src/twisted/web/test/test_webclient.py
|
||||
+++ b/src/twisted/web/test/test_webclient.py
|
||||
@@ -11,10 +11,7 @@ import io
|
||||
import os
|
||||
from errno import ENOSPC
|
||||
|
||||
-try:
|
||||
- from urlparse import urlparse, urljoin
|
||||
-except ImportError:
|
||||
- from urllib.parse import urlparse, urljoin
|
||||
+from urllib.parse import urlparse, urljoin
|
||||
|
||||
from twisted.python.compat import networkString, nativeString, intToBytes
|
||||
from twisted.trial import unittest, util
|
||||
--
|
||||
2.26.2
|
||||
|
||||
94
dev-python/twisted/files/twisted-20.3.0-py38-hmac.patch
Normal file
94
dev-python/twisted/files/twisted-20.3.0-py38-hmac.patch
Normal file
@@ -0,0 +1,94 @@
|
||||
From 653fb2aea0ca1f60558917d52f4ff0c33cd7b067 Mon Sep 17 00:00:00 2001
|
||||
From: Craig Rodrigues <rodrigc@crodrigues.org>
|
||||
Date: Sun, 12 Apr 2020 14:28:23 -0700
|
||||
Subject: [PATCH 1/2] Add digestmod parameter to HMAC.__init__() invocations
|
||||
|
||||
This parameter is now required on Python 3.8+
|
||||
---
|
||||
src/twisted/cred/credentials.py | 3 ++-
|
||||
src/twisted/cred/test/test_cramauth.py | 11 ++++++++---
|
||||
src/twisted/mail/test/test_pop3.py | 4 +++-
|
||||
3 files changed, 13 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/twisted/cred/credentials.py b/src/twisted/cred/credentials.py
|
||||
index 5469e5158..67c24cb01 100644
|
||||
--- a/src/twisted/cred/credentials.py
|
||||
+++ b/src/twisted/cred/credentials.py
|
||||
@@ -441,7 +441,8 @@ class CramMD5Credentials(object):
|
||||
|
||||
|
||||
def checkPassword(self, password):
|
||||
- verify = hexlify(hmac.HMAC(password, self.challenge).digest())
|
||||
+ verify = hexlify(hmac.HMAC(password, self.challenge,
|
||||
+ digestmod=md5).digest())
|
||||
return verify == self.response
|
||||
|
||||
|
||||
diff --git a/src/twisted/cred/test/test_cramauth.py b/src/twisted/cred/test/test_cramauth.py
|
||||
index 1ee08712b..d21f2f68c 100644
|
||||
--- a/src/twisted/cred/test/test_cramauth.py
|
||||
+++ b/src/twisted/cred/test/test_cramauth.py
|
||||
@@ -7,6 +7,8 @@ Tests for L{twisted.cred}'s implementation of CRAM-MD5.
|
||||
|
||||
from __future__ import division, absolute_import
|
||||
|
||||
+import hashlib
|
||||
+
|
||||
from hmac import HMAC
|
||||
from binascii import hexlify
|
||||
|
||||
@@ -39,7 +41,8 @@ class CramMD5CredentialsTests(TestCase):
|
||||
"""
|
||||
c = CramMD5Credentials()
|
||||
chal = c.getChallenge()
|
||||
- c.response = hexlify(HMAC(b'secret', chal).digest())
|
||||
+ c.response = hexlify(HMAC(b'secret', chal,
|
||||
+ digestmod=hashlib.md5).digest())
|
||||
self.assertTrue(c.checkPassword(b'secret'))
|
||||
|
||||
|
||||
@@ -61,7 +64,8 @@ class CramMD5CredentialsTests(TestCase):
|
||||
"""
|
||||
c = CramMD5Credentials()
|
||||
chal = c.getChallenge()
|
||||
- c.response = hexlify(HMAC(b'thewrongsecret', chal).digest())
|
||||
+ c.response = hexlify(HMAC(b'thewrongsecret', chal,
|
||||
+ digestmod=hashlib.md5).digest())
|
||||
self.assertFalse(c.checkPassword(b'secret'))
|
||||
|
||||
|
||||
@@ -75,7 +79,8 @@ class CramMD5CredentialsTests(TestCase):
|
||||
chal = c.getChallenge()
|
||||
c.setResponse(b" ".join(
|
||||
(b"squirrel",
|
||||
- hexlify(HMAC(b'supersecret', chal).digest()))))
|
||||
+ hexlify(HMAC(b'supersecret', chal,
|
||||
+ digestmod=hashlib.md5).digest()))))
|
||||
self.assertTrue(c.checkPassword(b'supersecret'))
|
||||
self.assertEqual(c.username, b"squirrel")
|
||||
|
||||
diff --git a/src/twisted/mail/test/test_pop3.py b/src/twisted/mail/test/test_pop3.py
|
||||
index 4a59c3b49..ea513487c 100644
|
||||
--- a/src/twisted/mail/test/test_pop3.py
|
||||
+++ b/src/twisted/mail/test/test_pop3.py
|
||||
@@ -11,6 +11,7 @@ import hmac
|
||||
import base64
|
||||
import itertools
|
||||
|
||||
+from hashlib import md5
|
||||
from collections import OrderedDict
|
||||
from io import BytesIO
|
||||
|
||||
@@ -1097,7 +1098,8 @@ class SASLTests(unittest.TestCase):
|
||||
p.lineReceived(b"AUTH CRAM-MD5")
|
||||
chal = s.getvalue().splitlines()[-1][2:]
|
||||
chal = base64.decodestring(chal)
|
||||
- response = hmac.HMAC(b'testpassword', chal).hexdigest().encode("ascii")
|
||||
+ response = hmac.HMAC(b'testpassword', chal,
|
||||
+ digestmod=md5).hexdigest().encode("ascii")
|
||||
|
||||
p.lineReceived(
|
||||
base64.encodestring(b'testuser ' + response).rstrip(b'\n'))
|
||||
--
|
||||
2.26.2
|
||||
|
||||
@@ -81,6 +81,11 @@ DEPEND="
|
||||
S=${WORKDIR}/${TWISTED_P}
|
||||
|
||||
python_prepare_all() {
|
||||
local PATCHES=(
|
||||
"${FILESDIR}"/twisted-20.3.0-py38-cgi.patch
|
||||
"${FILESDIR}"/twisted-20.3.0-py38-hmac.patch
|
||||
)
|
||||
|
||||
# upstream test for making releases; not very useful and requires
|
||||
# sphinx (including on py2)
|
||||
rm src/twisted/python/test/test_release.py || die
|
||||
|
||||
Reference in New Issue
Block a user