Hello community,
here is the log from the commit of package python-Twisted for
openSUSE:Leap:15.2 checked in at 2020-04-08 12:47:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Leap:15.2/python-Twisted (Old)
and /work/SRC/openSUSE:Leap:15.2/.python-Twisted.new.3248 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-Twisted"
Wed Apr 8 12:47:56 2020 rev:19 rq:788619 version:19.10.0
Changes:
--------
--- /work/SRC/openSUSE:Leap:15.2/python-Twisted/python-Twisted.changes
2020-01-15 15:46:25.723357127 +0100
+++
/work/SRC/openSUSE:Leap:15.2/.python-Twisted.new.3248/python-Twisted.changes
2020-04-08 12:47:57.326329510 +0200
@@ -1,0 +2,36 @@
+Wed Dec 4 05:01:47 UTC 2019 - Steve Kowalik <[email protected]>
+
+- Update to 19.10.0 bsc#1162424:
+ * twisted.trial.successResultOf, twisted.trial.failureResultOf, and
twisted.trial.assertNoResult accept coroutines as well as Deferreds. (#9006)
+ * Fixed circular import in twisted.trial.reporter, introduced in Twisted
16.0.0. (#8267)
+ * The POP3 server implemented by twisted.mail.pop3 now accepts passwords
that contain spaces. (#9100)
+ * Incoming HTTP/2 connections will now not time out if they persist for
longer than one minute. (#9653)
+ * twisted.conch.ssh.keys now correctly writes the "iqmp" parameter in
serialized RSA private keys as q^-1 mod p rather than p^-1 mod q. (#9681)
+ * twisted.web.server.Request will now use
twisted.web.server.Site.getContentFile, if it exists, to get a file into which
to write request content. If getContentFile is not provided by the site, it
will fall back to the previous behavior of using io.BytesIO for small requests
and tempfile.TemporaryFile for large ones. (#9655)
+ * twisted.web.client.FileBodyProducer will now stop producing when the
Deferred returned by FileBodyProducer.startProducing is cancelled. (#9547)
+ * The HTTP/2 server implementation now enforces TCP flow control on control
frame messages and times out clients that send invalid data without reading
responses. This closes CVE-2019-9512 (Ping Flood), CVE-2019-9514 (Reset Flood),
and CVE-2019-9515 (Settings Flood). Thanks to Jonathan Looney and Piotr Sikora.
(#9694)
+- Add python-38-xml-namespace.patch to fix dictionary mutation under Python 3.8
+- Add python-38-hmac-digestmod.patch to add digestmod parameter where required
+- Add python-38-no-cgi-parseqs.patch to no longer import parse_qs from cgi
+
+-------------------------------------------------------------------
+Sat Sep 14 15:29:06 UTC 2019 - John Vandenberg <[email protected]>
+
+- Remove mailmail when only building Python 3 flavour
+
+-------------------------------------------------------------------
+Fri Sep 13 13:09:16 UTC 2019 - Tomáš Chvátal <[email protected]>
+
+- Update to 19.7.0:
+ * The callable argument to twisted.internet.task.deferLater() is no longer
required. (#9577)
+ * twisted.internet.utils.getProcessOutputAndValue now accepts stdinBytes to
write to the child process's standard input. (#9607)
+ * Add new twisted.logger.capturedLogs context manager for capturing observed
log events in tests. (#9617)
+ * twisted.internet.base.PluggableResolverMixin, which implements the
pluggable resolver interfaces for easier re-use in other reactors, has been
factored out of ReactorBase. (#9632)
+ * The PyPI page for Twisted has been enhanced to include more information
and useful links. (#9648)
+- Refresh patch:
+ * skip_MultiCast.patch
+- Remove merged patch hyperlink.patch
+- Remove patch 0001-Prevent-CRLF-injections-described-in-CVE-2019-12387.patch
+- Remove patch PR-1147.patch
+
+-------------------------------------------------------------------
@@ -14,0 +51,96 @@
+
+-------------------------------------------------------------------
+Wed Jun 12 05:55:44 UTC 2019 - Thomas Bechtold <[email protected]>
+
+- update to 19.2.1 (bsc#1137825, CVE-2019-12387):
+ * Prevent CRLF injections described in CVE-2019-12387
+
+-------------------------------------------------------------------
+Wed May 22 09:59:19 UTC 2019 - Tomáš Chvátal <[email protected]>
+
+- Update to 19.2.0:
+ * twisted.internet.ssl.CertificateOptions now uses 32 random bytes instead
of an MD5 hash for the ssl session identifier context. (#9463)
+ * DeferredLock and DeferredSemaphore can be used as asynchronous context
managers on Python 3.5+. (#9546)
+ * t.i.b.BaseConnector has custom __repr__ (#9548)
+ * twisted.internet.ssl.optionsForClientTLS now supports validating IP
addresses from the certificate subjectAltName (#9585)
+ * Twisted's minimum Cryptography requirement is now 2.5. (#9592)
+ * twisted.conch.ssh.keys can now read private keys in the new
"openssh-key-v1" format, introduced in OpenSSH 6.5 and made the default in
OpenSSH 7.8. (#9515)
+ * twisted.web.client.HostnameCachingHTTPSPolicy was added as a new
contextFactory option. The policy caches a specified number of
twisted.internet.interfaces.IOpenSSLClientConnectionCreator instances to to
avoid the cost of instantiating a connection creator for multiple requests to
the same host. (#9138)
+- Remove merged patches:
+ * openssl-errormsg.aptch
+ * openssl111.patch
+- Add patch to tests for new hyperlink:
+ * hyperlink.patch
+
+-------------------------------------------------------------------
+Mon Feb 18 11:24:53 UTC 2019 - Tomáš Chvátal <[email protected]>
+
+- Add another patch for openssl 1.1.1 (from upstream git):
+ * openssl-errormsg.aptch
+
+-------------------------------------------------------------------
+Thu Jan 24 16:09:14 UTC 2019 - [email protected]
+
+- test-mktime-invalid-tm_isdst.patch: don't pass invalid tm_isdst value to
+ mktime (see also bpo-15750)
+
+-------------------------------------------------------------------
+Thu Nov 8 10:28:09 CET 2018 - [email protected]
+
+- Add no-pygtkcompat.patch to avoid dependency on Gtk (boo#1110669)
+
+-------------------------------------------------------------------
+Thu Nov 1 09:21:03 UTC 2018 - Tomáš Chvátal <[email protected]>
+
+- Version update to 18.9.0:
+ * Fixes for the 3.7 python
+- Remove merged python37.patch
+- Add patch openssl111.patch which fixes tests with new pyOpenssl
+ * Asserts changed behaviour
+
+-------------------------------------------------------------------
+Mon Oct 22 08:48:37 UTC 2018 - Tomáš Chvátal <[email protected]>
+
+- Do not write bytecode stuff when running the tests
+
+-------------------------------------------------------------------
+Fri Oct 19 13:27:25 UTC 2018 - Matěj Cepl <[email protected]>
+
+- Add BuildRequires python-tz, which seems to be required to test suite
+ to pass.
+- Also, add skip_MultiCast.patch to skip tests requiring full
+ netrworking stack.
+
+-------------------------------------------------------------------
+Fri Oct 12 09:06:36 UTC 2018 - [email protected]
+
+- Add missing Requires.
+
+-------------------------------------------------------------------
+Thu Oct 11 08:32:44 UTC 2018 - Tomáš Chvátal <[email protected]>
+
+- Fix the dependencies to match up upstream setup.py
+- Run the tests
+- Add patch to build with python3.7:
+ * python37.patch
+- Add missing dependency on pyamcrest
+- Remove unused patch lp1102685.diff
+
+-------------------------------------------------------------------
+Tue Jul 17 19:42:41 UTC 2018 - [email protected]
+
+- update to 18.7.0:
+ for full list of changes please see
+ https://github.com/twisted/twisted/blob/twisted-18.7.0/NEWS.rst
+
+-------------------------------------------------------------------
+Tue May 29 19:22:32 UTC 2018 - [email protected]
+
+- Add python-service_identity Recommends.
+
+-------------------------------------------------------------------
+Fri May 18 16:59:15 UTC 2018 - [email protected]
+
+- update to 18.4.0
+ For full list of changes please see:
+ https://github.com/twisted/twisted/blob/twisted-18.4.0/NEWS.rst
Old:
----
0001-Prevent-CRLF-injections-described-in-CVE-2019-12387.patch
PR-1147.patch
Twisted-17.9.0.tar.bz2
lp1102685.diff
New:
----
Twisted-19.10.0.tar.bz2
no-pygtkcompat.patch
python-38-hmac-digestmod.patch
python-38-no-cgi-parseqs.patch
python-38-xml-namespace.patch
skip_MultiCast.patch
test-mktime-invalid-tm_isdst.patch
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-Twisted.spec ++++++
--- /var/tmp/diff_new_pack.CfHHCU/_old 2020-04-08 12:47:57.994329847 +0200
+++ /var/tmp/diff_new_pack.CfHHCU/_new 2020-04-08 12:47:57.994329847 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-Twisted
#
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -12,7 +12,7 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
@@ -20,40 +20,59 @@
%define oldpython python
%define modname Twisted
Name: python-Twisted
-Version: 17.9.0
+Version: 19.10.0
Release: 0
Summary: An asynchronous networking framework written in Python
License: MIT
Group: Development/Languages/Python
-Url: http://twistedmatrix.com/
+URL: http://twistedmatrix.com/
Source:
https://files.pythonhosted.org/packages/source/T/Twisted/%{modname}-%{version}.tar.bz2
-# PATCH-FIX-UPSTREAM -- https://twistedmatrix.com/trac/ticket/6280
-Patch0: lp1102685.diff
-# PATCH-FIX-UPSTREAM
0001-Prevent-CRLF-injections-described-in-CVE-2019-12387.patch --
https://github.com/twisted/twisted/commit/6c61fc4503ae39ab8ecee52d10f10ee2c371d7e2
-Patch1: 0001-Prevent-CRLF-injections-described-in-CVE-2019-12387.patch
-# PATCH-FIX-UPSTREAM PR-1147.patch --
https://github.com/twisted/twisted/pull/1147
-Patch2: PR-1147.patch
-BuildRequires: %{python_module constantly}
+Patch1: skip_MultiCast.patch
+Patch2: no-pygtkcompat.patch
+Patch3: test-mktime-invalid-tm_isdst.patch
+Patch4: python-38-xml-namespace.patch
+Patch5: python-38-hmac-digestmod.patch
+Patch6: python-38-no-cgi-parseqs.patch
+BuildRequires: %{python_module Automat >= 0.3.0}
+BuildRequires: %{python_module PyHamcrest >= 1.9.0}
+BuildRequires: %{python_module appdirs >= 1.4.0}
+BuildRequires: %{python_module attrs >= 17.4.0}
+BuildRequires: %{python_module bcrypt >= 3.0.0}
+BuildRequires: %{python_module constantly >= 15.1}
+BuildRequires: %{python_module cryptography >= 2.5}
BuildRequires: %{python_module devel}
-BuildRequires: %{python_module hyperlink}
-BuildRequires: %{python_module incremental}
-BuildRequires: %{python_module pyOpenSSL}
+BuildRequires: %{python_module h2 >= 3.0}
+BuildRequires: %{python_module hyperlink >= 17.1.1}
+BuildRequires: %{python_module idna >= 0.6}
+BuildRequires: %{python_module incremental >= 16.10.1}
+BuildRequires: %{python_module pyOpenSSL >= 16.0.0}
+BuildRequires: %{python_module pyasn1}
+BuildRequires: %{python_module pyserial >= 3.0}
BuildRequires: %{python_module pyserial}
BuildRequires: %{python_module pytest}
+BuildRequires: %{python_module python-subunit}
+BuildRequires: %{python_module pytz}
+BuildRequires: %{python_module service_identity >= 18.1.0}
BuildRequires: %{python_module setuptools}
-BuildRequires: %{python_module zope.interface}
+BuildRequires: %{python_module zope.interface >= 4.4.2}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
-Requires: python-Automat
-Requires: python-constantly
-Requires: python-hyperlink
-Requires: python-incremental
-Requires: python-pyOpenSSL
+Requires: python-Automat >= 0.3.0
+Requires: python-PyHamcrest >= 1.9.0
+Requires: python-appdirs >= 1.4.0
+Requires: python-attrs >= 17.4.0
+Requires: python-bcrypt >= 3.0.0
+Requires: python-constantly >= 15.1
+Requires: python-cryptography >= 2.5
+Requires: python-h2 >= 3.0
+Requires: python-hyperlink >= 17.1.1
+Requires: python-idna >= 0.6
+Requires: python-incremental >= 16.10.1
+Requires: python-pyOpenSSL >= 16.0.0
Requires: python-pyasn1
-Requires: python-pycrypto
-Requires: python-pyserial
-Requires: python-zope.interface
-BuildRoot: %{_tmppath}/%{name}-%{version}-build
+Requires: python-pyserial >= 3.0
+Requires: python-service_identity >= 18.1.0
+Requires: python-zope.interface >= 4.4.2
%ifpython2
Provides: %{oldpython}-twisted = %{version}
Obsoletes: %{oldpython}-twisted < %{version}
@@ -96,10 +115,7 @@
%prep
%setup -q -n %{modname}-%{version}
-#%%patch0 -p1
-%patch1 -p1
-%patch2 -p1
-#sed -i "1d" twisted/{mail/test/pop3testserver,trial/test/scripttest}.py
+%autopatch -p1
%build
%python_build
@@ -111,7 +127,7 @@
install -m0644 docs/*/man/*.1 %{buildroot}%{_mandir}/man1/ # Install man pages
find docs -type f -print0 | xargs -0 chmod a-x # Fix doc-file dependency by
removing x flags
#sed -i "s/\r//"
docs/core/howto/listings/udp/{MulticastClient,MulticastServer}.py
-%fdupes %{buildroot}%{_prefix}
+%python_expand %fdupes %{buildroot}%{$python_sitearch}
# Prepare for update-alternatives usage
for p in twistd cftp ckeygen conch pyhtmlizer tkconch trial ; do
@@ -124,16 +140,25 @@
%python_clone %{buildroot}%{_bindir}/mailmail
%python_clone %{buildroot}%{_mandir}/man1/mailmail.1
%endif
+%if ! 0%{?have_python2} || 0%{?skip_python2}
+rm %{buildroot}%{_bindir}/mailmail %{buildroot}%{_mandir}/man1/mailmail.1
+%endif
+
# no manpage for twist yet:
%python_clone %{buildroot}%{_bindir}/twist
+%check
+export LANG=en_US.UTF-8
+export PATH=%{buildroot}%{_bindir}:$PATH
+export PYTHONDONTWRITEBYTECODE=1
+%python_expand PYTHONPATH=%{buildroot}%{$python_sitearch} $python -m
twisted.trial twisted
+
%files -n %{name}-doc
-%defattr(-,root,root,-)
%doc docs/*
%files %{python_files}
-%defattr(-,root,root,-)
-%doc LICENSE NEWS.rst README.rst
+%license LICENSE
+%doc NEWS.rst README.rst
%{_bindir}/*-%{python_bin_suffix}
%{_mandir}/man1/*-%{python_bin_suffix}.1%{?ext_man}
%python3_only %{_bindir}/twistd
@@ -150,7 +175,7 @@
%python3_only %{_mandir}/man1/cftp.1%{?ext_man}
%python3_only %{_mandir}/man1/ckeygen.1%{?ext_man}
%python3_only %{_mandir}/man1/conch.1%{?ext_man}
-%python3_only %{_mandir}/man1/mailmail.1%{?ext_man}
+%python2_only %{_mandir}/man1/mailmail.1%{?ext_man}
%python3_only %{_mandir}/man1/pyhtmlizer.1%{?ext_man}
%python3_only %{_mandir}/man1/tkconch.1%{?ext_man}
%python3_only %{_mandir}/man1/trial.1%{?ext_man}
++++++ Twisted-17.9.0.tar.bz2 -> Twisted-19.10.0.tar.bz2 ++++++
++++ 57844 lines of diff (skipped)
++++++ no-pygtkcompat.patch ++++++
diff -ur Twisted-18.7.0.orig/src/twisted/internet/gireactor.py
Twisted-18.7.0/src/twisted/internet/gireactor.py
--- Twisted-18.7.0.orig/src/twisted/internet/gireactor.py 2018-03-26
10:19:31.000000000 +0200
+++ Twisted-18.7.0/src/twisted/internet/gireactor.py 2018-10-04
01:41:32.547220235 +0200
@@ -75,8 +75,12 @@
# Newer version of gi, so we can try to initialize compatibility layer; if
# real pygtk was already imported we'll get ImportError at this point
# rather than segfault, so unconditional import is fine.
- import gi.pygtkcompat
- gi.pygtkcompat.enable()
+ try:
+ import gi.pygtkcompat
+ except ImportError:
+ pass # This is probably Python 3, with pygtkcompat removed
+ else:
+ gi.pygtkcompat.enable()
# At this point importing gobject will get you gi version, and importing
# e.g. gtk will either fail in non-segfaulty way or use gi version if user
# does gi.pygtkcompat.enable_gtk(). So, no need to prevent imports of
++++++ python-38-hmac-digestmod.patch ++++++
Index: Twisted-19.10.0/src/twisted/cred/credentials.py
===================================================================
--- Twisted-19.10.0.orig/src/twisted/cred/credentials.py
+++ Twisted-19.10.0/src/twisted/cred/credentials.py
@@ -439,7 +439,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
Index: Twisted-19.10.0/src/twisted/cred/test/test_cramauth.py
===================================================================
--- Twisted-19.10.0.orig/src/twisted/cred/test/test_cramauth.py
+++ Twisted-19.10.0/src/twisted/cred/test/test_cramauth.py
@@ -7,6 +7,7 @@ Tests for L{twisted.cred}'s implementati
from __future__ import division, absolute_import
+from hashlib import md5
from hmac import HMAC
from binascii import hexlify
@@ -39,7 +40,7 @@ class CramMD5CredentialsTests(TestCase):
"""
c = CramMD5Credentials()
chal = c.getChallenge()
- c.response = hexlify(HMAC(b'secret', chal).digest())
+ c.response = hexlify(HMAC(b'secret', chal, digestmod=md5).digest())
self.assertTrue(c.checkPassword(b'secret'))
@@ -61,7 +62,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=md5).digest())
self.assertFalse(c.checkPassword(b'secret'))
@@ -75,7 +77,7 @@ class CramMD5CredentialsTests(TestCase):
chal = c.getChallenge()
c.setResponse(b" ".join(
(b"squirrel",
- hexlify(HMAC(b'supersecret', chal).digest()))))
+ hexlify(HMAC(b'supersecret', chal, digestmod=md5).digest()))))
self.assertTrue(c.checkPassword(b'supersecret'))
self.assertEqual(c.username, b"squirrel")
Index: Twisted-19.10.0/src/twisted/mail/_cred.py
===================================================================
--- Twisted-19.10.0.orig/src/twisted/mail/_cred.py
+++ Twisted-19.10.0/src/twisted/mail/_cred.py
@@ -7,6 +7,7 @@ Credential managers for L{twisted.mail}.
from __future__ import absolute_import, division
+from hashlib import md5
import hmac
from zope.interface import implementer
@@ -28,7 +29,8 @@ class CramMD5ClientAuthenticator:
def challengeResponse(self, secret, chal):
- response = hmac.HMAC(secret, chal).hexdigest().encode('ascii')
+ response = hmac.HMAC(
+ secret, chal, digestmod=md5).hexdigest().encode('ascii')
return self.user + b' ' + response
Index: Twisted-19.10.0/src/twisted/mail/test/test_pop3.py
===================================================================
--- Twisted-19.10.0.orig/src/twisted/mail/test/test_pop3.py
+++ Twisted-19.10.0/src/twisted/mail/test/test_pop3.py
@@ -12,6 +12,7 @@ import base64
import itertools
from collections import OrderedDict
+from hashlib import md5
from io import BytesIO
from zope.interface import implementer
@@ -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'))
++++++ python-38-no-cgi-parseqs.patch ++++++
Index: Twisted-19.10.0/src/twisted/web/test/test_http.py
===================================================================
--- Twisted-19.10.0.orig/src/twisted/web/test/test_http.py
+++ Twisted-19.10.0/src/twisted/web/test/test_http.py
@@ -9,15 +9,14 @@ from __future__ import absolute_import,
import base64
import calendar
-import cgi
import random
import hamcrest
try:
- from urlparse import urlparse, urlunsplit, clear_cache
+ from urlparse import urlparse, urlunsplit, clear_cache, parse_qs
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
@@ -2156,15 +2155,15 @@ Hello,
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"))
++++++ python-38-xml-namespace.patch ++++++
>From e42ba68b39f0ae98f1ea89a38a9317f2966c7d0e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Poisson?= <[email protected]>
Date: Sun, 17 Nov 2019 19:48:53 +0100
Subject: [PATCH] Fix parsing of namespaced attributes with Python 3.8 in
twisted.words.xish.domish.ExpatElementStream
---
src/twisted/words/newsfragments/9730.bugfix | 1 +
src/twisted/words/test/test_domish.py | 16 ++++++++++++++++
src/twisted/words/xish/domish.py | 11 +++++++++--
3 files changed, 26 insertions(+), 2 deletions(-)
create mode 100644 src/twisted/words/newsfragments/9730.bugfix
diff --git a/src/twisted/words/newsfragments/9730.bugfix
b/src/twisted/words/newsfragments/9730.bugfix
new file mode 100644
index 00000000000..5c91305c8f7
--- /dev/null
+++ b/src/twisted/words/newsfragments/9730.bugfix
@@ -0,0 +1 @@
+Fixed parsing of streams with Python 3.8 when there are spaces in namespaces
or namespaced attributes in twisted.words.xish.domish.ExpatElementStream
diff --git a/src/twisted/words/test/test_domish.py
b/src/twisted/words/test/test_domish.py
index a8f8fa76b63..5a691270443 100644
--- a/src/twisted/words/test/test_domish.py
+++ b/src/twisted/words/test/test_domish.py
@@ -350,6 +350,22 @@ def test_namespaceWithWhitespace(self):
self.elements[0].attributes, {(" bar baz ", "baz"): "quux"})
+ def test_attributesWithNamespaces(self):
+ """
+ Attributes with namespace are parsed correctly (#9730 regression test).
+ """
+
+ xml = b"""<root xmlns:test='http://example.org' xml:lang='en'>
+ <test:test>test</test:test>
+ </root>"""
+
+ # with Python 3.8 and without #9730 fix, the following error would
+ # happen at next line:
+ # ``RuntimeError: dictionary keys changed during iteration``
+ self.stream.parse(xml)
+ self.assertEqual(self.elements[0].uri, "http://example.org")
+
+
def testChildPrefix(self):
xml = b"<root xmlns='testns' xmlns:foo='testns2'><foo:child/></root>"
diff --git a/src/twisted/words/xish/domish.py b/src/twisted/words/xish/domish.py
index 2063c410a3c..30e47458f82 100644
--- a/src/twisted/words/xish/domish.py
+++ b/src/twisted/words/xish/domish.py
@@ -807,11 +807,18 @@ def _onStartElement(self, name, attrs):
qname = ('', name)
# Process attributes
+ new_attrs = {}
+ to_delete = []
for k, v in attrs.items():
if " " in k:
aqname = k.rsplit(" ", 1)
- attrs[(aqname[0], aqname[1])] = v
- del attrs[k]
+ new_attrs[(aqname[0], aqname[1])] = v
+ to_delete.append(k)
+
+ attrs.update(new_attrs)
+
+ for k in to_delete:
+ del attrs[k]
# Construct the new element
e = Element(qname, self.defaultNsStack[-1], attrs, self.localPrefixes)
++++++ skip_MultiCast.patch ++++++
Index: Twisted-19.7.0/src/twisted/test/test_udp.py
===================================================================
--- Twisted-19.7.0.orig/src/twisted/test/test_udp.py
+++ Twisted-19.7.0/src/twisted/test/test_udp.py
@@ -514,6 +514,7 @@ class MulticastTests(unittest.TestCase):
skip = "Does not work on Azure Pipelines"
def setUp(self):
+ raise unittest.SkipTest("Multicast networking doesn't work with OBS")
self.server = Server()
self.client = Client()
# multicast won't work if we listen over loopback, apparently
++++++ test-mktime-invalid-tm_isdst.patch ++++++
Index: Twisted-18.9.0/src/twisted/test/test_log.py
===================================================================
--- Twisted-18.9.0.orig/src/twisted/test/test_log.py
+++ Twisted-18.9.0/src/twisted/test/test_log.py
@@ -456,13 +456,13 @@ class FileObserverTests(LogPublisherTest
# Compute a POSIX timestamp for a certain date and time that is
# known to occur at a time when daylight saving time is in effect.
- localDaylightTuple = (2006, 6, 30, 0, 0, 0, 4, 181, 1)
+ localDaylightTuple = (2006, 6, 30, 0, 0, 0, 4, 181, -1)
daylight = time.mktime(localDaylightTuple)
# Compute a POSIX timestamp for a certain date and time that is
# known to occur at a time when daylight saving time is not in
# effect.
- localStandardTuple = (2007, 1, 31, 0, 0, 0, 2, 31, 0)
+ localStandardTuple = (2007, 1, 31, 0, 0, 0, 2, 31, -1)
standard = time.mktime(localStandardTuple)
self.assertEqual(