diff --git a/collections_abc.patch b/collections_abc.patch new file mode 100644 index 0000000..7d247ba --- /dev/null +++ b/collections_abc.patch @@ -0,0 +1,22 @@ +diff -ru dnspython-1.16.0-orig/dns/namedict.py dnspython-1.16.0/dns/namedict.py +--- dnspython-1.16.0-orig/dns/namedict.py 2018-12-01 10:25:27.000000000 -0500 ++++ dnspython-1.16.0/dns/namedict.py 2020-01-21 19:48:57.266576401 -0500 +@@ -27,12 +27,16 @@ + + """DNS name dictionary""" + +-import collections + import dns.name + from ._compat import xrange + ++try: ++ from collections.abc import MutableMapping ++except ImportError: ++ from collections import MutableMapping + +-class NameDict(collections.MutableMapping): ++ ++class NameDict(MutableMapping): + """A dictionary whose keys are dns.name.Name objects. + + In addition to being like a regular Python dictionary, this diff --git a/python-dns.spec b/python-dns.spec index a0c0ca6..a346d41 100644 --- a/python-dns.spec +++ b/python-dns.spec @@ -25,7 +25,7 @@ manipulation of DNS zones, messages, names, and records. \ Name: python-%{py_package_name} Version: 1.16.0 -Release: 5%{?dist} +Release: 6%{?dist} Summary: %{summary} License: MIT @@ -34,7 +34,8 @@ URL: http://www.dnspython.org Source0: http://www.dnspython.org/kits/%{version}/%{pypi_name}-%{version}.tar.gz BuildArch: noarch -#Patch0: unicode_label_escapify.patch +Patch0: unicode_label_escapify.patch +Patch1: collections_abc.patch %if %{with python2} BuildRequires: python2-devel @@ -178,7 +179,11 @@ find examples -type f | xargs chmod a-x %changelog -* Tue Nov 5 2019 Paul Howarth - 1.16.0-5 +* Tue Jan 21 2020 Avram Lubkin - 1.16.0-6 +- Enable unicode patch (rhbz#1731100) +- Fix collections.abc import for Python 3.9 (rhbz#1792919) + +* Tue Nov 05 2019 Paul Howarth - 1.16.0-5 - Use pycryptodomex instead of pycrypto - Also use python-ecdsa (except with Python 2) diff --git a/unicode_label_escapify.patch b/unicode_label_escapify.patch index 7ad866f..58e5aa8 100644 --- a/unicode_label_escapify.patch +++ b/unicode_label_escapify.patch @@ -1,35 +1,7 @@ diff -ru dnspython-1.16.0-orig/dns/name.py dnspython-1.16.0/dns/name.py --- dnspython-1.16.0-orig/dns/name.py 2018-12-05 08:35:40.000000000 -0500 -+++ dnspython-1.16.0/dns/name.py 2019-07-28 08:48:37.893331388 -0400 -@@ -110,15 +110,23 @@ - def __init__(self): - pass - -+ def is_idna(self, label): -+ return label.lower().startswith(b'xn--') -+ -+ def is_all_ascii(self, label): -+ for c in label: -+ if ord(c) > 0x7f: -+ return False -+ return True -+ - def encode(self, label): - raise NotImplementedError - - def decode(self, label): -- # We do not apply any IDNA policy on decode; we just -- downcased = label.lower() -- if downcased.startswith(b'xn--'): -+ # We do not apply any IDNA policy on decode. -+ if self.is_idna(label): - try: -- label = downcased[4:].decode('punycode') -+ label = label[4:].decode('punycode') - except Exception as e: - raise IDNAException(idna_exception=e) - else: -@@ -195,12 +203,6 @@ ++++ dnspython-1.16.0/dns/name.py 2020-01-22 01:07:53.319289996 -0500 +@@ -195,16 +195,10 @@ self.allow_pure_ascii = allow_pure_ascii self.strict_decode = strict_decode @@ -42,7 +14,12 @@ diff -ru dnspython-1.16.0-orig/dns/name.py dnspython-1.16.0/dns/name.py def encode(self, label): if label == '': return b'' -@@ -230,6 +232,7 @@ +- if self.allow_pure_ascii and self.is_all_ascii(label): ++ if self.allow_pure_ascii and is_all_ascii(label): + return label.encode('ascii') + if not have_idna_2008: + raise NoIDNA2008 +@@ -230,6 +224,7 @@ raise IDNAException(idna_exception=e) _escaped = bytearray(b'"().;\\@$') @@ -50,27 +27,64 @@ diff -ru dnspython-1.16.0-orig/dns/name.py dnspython-1.16.0/dns/name.py IDNA_2003_Practical = IDNA2003Codec(False) IDNA_2003_Strict = IDNA2003Codec(True) -@@ -265,11 +268,12 @@ +@@ -263,7 +258,9 @@ + if isinstance(label, binary_type): + label = label.decode() for c in label: - if c > u'\x20' and c < u'\x7f': - text += c +- if c > u'\x20' and c < u'\x7f': + if c in _escaped_text: -+ text += '\\' + c -+ elif c <= '\x20': -+ text += '\\%03d' % ord(c) ++ text += u'\\' + c ++ elif c > u'\x20' and c < u'\x7f': + text += c else: -- if c >= u'\x7f': -- text += c -- else: -- text += u'\\%03d' % ord(c) -+ tect += c - return text + if c >= u'\x7f': +@@ -827,7 +824,7 @@ + if text == u'@': + text = u'' + if text: +- if text == u'.': ++ if text in [u'.', u'\u3002', u'\uff0e', u'\uff61']: + return Name([b'']) # no Unicode "u" on this constant! + for c in text: + if escaping: +@@ -870,6 +867,13 @@ + return Name(labels) - def _validate_labels(labels): + ++def is_all_ascii(text): ++ for c in text: ++ if ord(c) > 0x7f: ++ return False ++ return True ++ ++ + def from_text(text, origin=root, idna_codec=None): + """Convert text into a Name object. + +@@ -886,7 +890,18 @@ + """ + + if isinstance(text, text_type): +- return from_unicode(text, origin, idna_codec) ++ if not is_all_ascii(text): ++ # Some codepoint in the input text is > 127, so IDNA applies. ++ return from_unicode(text, origin, idna_codec) ++ # The input is all ASCII, so treat this like an ordinary non-IDNA ++ # domain name. Note that "all ASCII" is about the input text, ++ # not the codepoints in the domain name. E.g. if text has value ++ # ++ # r'\150\151\152\153\154\155\156\157\158\159' ++ # ++ # then it's still "all ASCII" even though the domain name has ++ # codepoints > 127. ++ text = text.encode('ascii') + if not isinstance(text, binary_type): + raise ValueError("input to from_text() must be a string") + if not (origin is None or isinstance(origin, Name)): diff -ru dnspython-1.16.0-orig/tests/test_name.py dnspython-1.16.0/tests/test_name.py --- dnspython-1.16.0-orig/tests/test_name.py 2018-12-01 10:48:40.000000000 -0500 -+++ dnspython-1.16.0/tests/test_name.py 2019-07-28 08:52:46.831657776 -0400 -@@ -255,6 +255,11 @@ ++++ dnspython-1.16.0/tests/test_name.py 2020-01-21 23:19:07.998492185 -0500 +@@ -255,6 +255,23 @@ t = dns.name.root.to_unicode() self.assertEqual(t, '.') @@ -78,6 +92,18 @@ diff -ru dnspython-1.16.0-orig/tests/test_name.py dnspython-1.16.0/tests/test_na + n = dns.name.from_text(r'a\.b.c') + t = n.to_unicode() + self.assertEqual(t, r'a\.b.c.') ++ ++ def testToText13(self): ++ n = dns.name.from_text(r'\150\151\152\153\154\155\156\157\158\159.') ++ t = n.to_text() ++ self.assertEqual(t, r'\150\151\152\153\154\155\156\157\158\159.') ++ ++ def testToText14(self): ++ # You can't send this to_unicode() as it wasn't unicode to begin with. ++ def bad(): ++ n = dns.name.from_text(r'\150\151\152\153\154\155\156\157\158\159.') ++ t = n.to_unicode() ++ self.failUnlessRaises(UnicodeDecodeError, bad) + def testSlice1(self): n = dns.name.from_text(r'a.b.c.', origin=None)