Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-Twisted for openSUSE:Factory 
checked in at 2026-11-01 22:21:11
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-Twisted (Old)
 and      /work/SRC/openSUSE:Factory/.python-Twisted.new.1255 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-Twisted"

Sun Nov  1 22:21:11 2026 rev:82 rq:1393922 version:26.10.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-Twisted/python-Twisted.changes    
2026-10-14 18:34:41.694793324 +0200
+++ /work/SRC/openSUSE:Factory/.python-Twisted.new.1255/python-Twisted.changes  
2026-11-01 22:21:15.827641372 +0100
@@ -1,0 +2,31 @@
+Fri Oct 30 12:47:48 UTC 2026 - Markéta Machová <[email protected]>
+
+- Update to 26.10.0 (CVE-2026-83813, bsc#1287833,
+  CVE-2026-115778, bsc#1287678, CVE-2026-115775, bsc#1287675,
+  CVE-2026-115877, bsc#1287848, CVE-2026-115774, bsc#1287671,
+  CVE-2026-115776, bsc#1287676)
+  * It is now possible to set the SO_REUSEPORT and SO_REUSEADDR TCP
+    socket flags from user code.
+  * Python 3.14 is now supported.
+  * twisted.internet.defer.Deferred.__iter__, used when awaiting a
+    Deferred, is now about 2-3% faster.
+  * twisted.internet.tcp.Connection no longer supports returning a
+    non-None value from a protocol's dataReceived method
+  * Implementations of twisted.internet.interfaces.IProcessProtocol
+    are now required to provide a processExited method
+  * twisted.internet.tcp.Port.startListening() now closes the socket
+    when raising CannotListenError
+  * twisted.logger.LoggingFile.fileno now raises io.UnsupportedOperation
+    instead of returning -1. This fixes an interoperability issue with
+    multiprocessing.
+  * twistd now exits with a non-zero status given an unknown subcommand.
+  * twisted.protocols.ftp.FTPClient now uses ip address of the original
+    ftp server to open passive data connections by default, instead of
+    trusting PASV responses.
+  * _makeGetterFactory method in twisted.web.client has been removed.
+  * twisted.trial.runner.samefile is deprecated and replaced by
+    os.path.samefile.
+- Drop merged pycryptography-use-csr.patch and CVE-2026-106454.patch
+- Add upstream py315.patch to fix tests with python 3.15
+
+-------------------------------------------------------------------

Old:
----
  CVE-2026-106454.patch
  pycryptography-use-csr.patch
  twisted-26.4.0.tar.gz

New:
----
  py315.patch
  twisted-26.10.0.tar.gz

----------(Old B)----------
  Old:    os.path.samefile.
- Drop merged pycryptography-use-csr.patch and CVE-2026-106454.patch
- Add upstream py315.patch to fix tests with python 3.15
  Old:    os.path.samefile.
- Drop merged pycryptography-use-csr.patch and CVE-2026-106454.patch
- Add upstream py315.patch to fix tests with python 3.15
----------(Old E)----------

----------(New B)----------
  New:- Drop merged pycryptography-use-csr.patch and CVE-2026-106454.patch
- Add upstream py315.patch to fix tests with python 3.15
----------(New E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-Twisted.spec ++++++
--- /var/tmp/diff_new_pack.V7sxHF/_old  2026-11-01 22:21:17.219698983 +0100
+++ /var/tmp/diff_new_pack.V7sxHF/_new  2026-11-01 22:21:17.221699066 +0100
@@ -31,7 +31,7 @@
 %endif
 %{?sle15_python_module_pythons}
 Name:           python-Twisted%{psuffix}
-Version:        26.4.0
+Version:        26.10.0
 Release:        0
 Summary:        An asynchronous networking framework written in Python
 License:        MIT
@@ -46,10 +46,8 @@
 Patch2:         no-cython_test_exception_raiser.patch
 # PATCH-FIX-OPENSUSE remove-dependency-version-upper-bounds.patch boo#1190036 
-- run with h2 >= 4.0.0 and priority >= 2.0
 Patch3:         remove-dependency-version-upper-bounds.patch
-# PATCH-FIX-UPSTREAM: https://github.com/twisted/twisted/pull/12661
-Patch4:         pycryptography-use-csr.patch
-# PATCH-FIX-UPSTREAM CVE-2026-106454.patch bsc#1284420 
gh#twisted/twisted@f570190
-Patch5:         CVE-2026-106454.patch
+# PATCH-FIX-UPSTREAM py315.patch https://github.com/twisted/twisted/pull/12602 
Fix Python 3.15 compatibility issues in trial - #12602
+Patch4:         py315.patch
 BuildRequires:  %{python_module base >= 3.9}
 BuildRequires:  %{python_module hatch-fancy-pypi-readme}
 BuildRequires:  %{python_module hatchling}
@@ -62,13 +60,13 @@
 Requires:       python-Twisted-tls = %{version}
 BuildArch:      noarch
 # SECTION install requires
-Requires:       python-Automat >= 24.8.0
+Requires:       python-Automat >= 24.8.1
 Requires:       python-attrs >= 22.2
 Requires:       python-constantly >= 15.1
-Requires:       python-hyperlink >= 17.1.1
+Requires:       python-hyperlink >= 18.0.0
 Requires:       python-incremental >= 24.7.0
-Requires:       python-typing_extensions >= 4.2
-Requires:       python-zope.interface >= 5
+Requires:       python-typing_extensions >= 4.13.2
+Requires:       python-zope.interface >= 8
 # /SECTION
 %if %{with libalternatives}
 BuildRequires:  alts
@@ -84,6 +82,8 @@
 BuildRequires:  %{python_module hypothesis}
 # declared nowhere but required to pass 8 tests with timezone checks
 BuildRequires:  %{python_module pytz}
+# needs the ssh command for conch tests
+BuildRequires:  openssh
 %endif
 %python_subpackages
 
@@ -105,9 +105,9 @@
 %package tls
 Summary:        TLS support for Twisted
 Requires:       python-Twisted = %{version}
-Requires:       python-idna >= 2.4
-Requires:       python-pyOpenSSL >= 25.2
-Requires:       python-service_identity >= 18.1.0
+Requires:       python-idna >= 2.5
+Requires:       python-pyOpenSSL >= 25.3
+Requires:       python-service_identity >= 21.1.0
 
 %description tls
 Twisted is an extensible framework for Python programming, with special focus
@@ -120,7 +120,7 @@
 Requires:       python-Twisted = %{version}
 Requires:       python-appdirs >= 1.4.0
 Requires:       python-bcrypt >= 3.2.1
-Requires:       python-cryptography >= 38
+Requires:       python-cryptography >= 46
 
 %description conch
 Twisted is an extensible framework for Python programming, with special focus

++++++ no-cython_test_exception_raiser.patch ++++++
--- /var/tmp/diff_new_pack.V7sxHF/_old  2026-11-01 22:21:17.272701177 +0100
+++ /var/tmp/diff_new_pack.V7sxHF/_new  2026-11-01 22:21:17.275701301 +0100
@@ -1,9 +1,9 @@
-Index: twisted-26.4.0/src/twisted/test/test_failure.py
+Index: twisted-26.10.0/src/twisted/test/test_failure.py
 ===================================================================
---- twisted-26.4.0.orig/src/twisted/test/test_failure.py
-+++ twisted-26.4.0/src/twisted/test/test_failure.py
+--- twisted-26.10.0.orig/src/twisted/test/test_failure.py
++++ twisted-26.10.0/src/twisted/test/test_failure.py
 @@ -20,7 +20,8 @@ from types import TracebackType
- from typing import Any, cast
+ from typing import Any
  from unittest import skipIf
  
 -from cython_test_exception_raiser import raiser

++++++ pycryptography-use-csr.patch -> py315.patch ++++++
--- /work/SRC/openSUSE:Factory/python-Twisted/pycryptography-use-csr.patch      
2026-06-16 18:29:24.473542490 +0200
+++ /work/SRC/openSUSE:Factory/.python-Twisted.new.1255/py315.patch     
2026-11-01 22:21:15.585631356 +0100
@@ -1,456 +1,114 @@
-From 5b4601c9965ffc92d6aa952b8c05127d5ac37307 Mon Sep 17 00:00:00 2001
-From: Alex Gaynor <[email protected]>
-Date: Mon, 8 Jun 2026 08:51:19 -0700
-Subject: [PATCH 1/5] #12660 Replace OpenSSL.crypto.X509Req with
- pyca/cryptography CSR
-
-Replace usage of pyOpenSSL's X509Req with pyca/cryptography's
-CertificateSigningRequest in twisted.internet._sslverify and the
-test_ssl certificate generation helpers.
-
-Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
+From 3962d15a2c593d2e47d240ab6f0c5352caca3464 Mon Sep 17 00:00:00 2001
+From: Lumir Balhar <[email protected]>
+Date: Wed, 1 Apr 2026 12:56:27 +0200
+Subject: [PATCH] Fix Python 3.15 compatibility issues
+
+- Replace deprecated SourceFileLoader.load_module() with exec_module()
+- Add addSubTest() method to _AdaptedReporter for Python 3.15 doctest support
+- Update test expectations for Python 3.15 doctest changes:
+  - Different success/failure counts
+  - Changed error output format
 ---
- src/twisted/internet/_sslverify.py   | 103 ++++++++++++++++++++++-----
- src/twisted/newsfragments/12660.misc |   0
- src/twisted/test/test_ssl.py         |  42 +++++++----
- 3 files changed, 114 insertions(+), 31 deletions(-)
- create mode 100644 src/twisted/newsfragments/12660.misc
-
-diff --git a/src/twisted/internet/_sslverify.py 
b/src/twisted/internet/_sslverify.py
-index c6dabf6c4c4..f1cec9c2d87 100644
---- a/src/twisted/internet/_sslverify.py
-+++ b/src/twisted/internet/_sslverify.py
-@@ -20,6 +20,9 @@
- 
- import attr
- from constantly import FlagConstant, Flags, NamedConstant, Names
-+from cryptography import x509
-+from cryptography.hazmat.primitives import hashes, serialization
-+from cryptography.x509.oid import NameOID
- from incremental import Version
- 
- from twisted.internet.abstract import isIPAddress, isIPv6Address
-@@ -169,6 +172,29 @@ def protocolNegotiationMechanisms() -> FlagConstant:
-     "emailAddress": "emailAddress",
- }
- 
-+_x509NameOIDs = {
-+    "commonName": NameOID.COMMON_NAME,
-+    "organizationName": NameOID.ORGANIZATION_NAME,
-+    "organizationalUnitName": NameOID.ORGANIZATIONAL_UNIT_NAME,
-+    "localityName": NameOID.LOCALITY_NAME,
-+    "stateOrProvinceName": NameOID.STATE_OR_PROVINCE_NAME,
-+    "countryName": NameOID.COUNTRY_NAME,
-+    "emailAddress": NameOID.EMAIL_ADDRESS,
-+}
-+
-+# Reverse of _x509NameOIDs, for translating a parsed subject back into a
-+# DistinguishedName.
-+_x509OIDNames = {oid: name for name, oid in _x509NameOIDs.items()}
-+
-+_digestAlgorithms = {
-+    "md5": hashes.MD5,
-+    "sha1": hashes.SHA1,
-+    "sha224": hashes.SHA224,
-+    "sha256": hashes.SHA256,
-+    "sha384": hashes.SHA384,
-+    "sha512": hashes.SHA512,
-+}
-+
- 
- class DistinguishedName(dict[str, bytes]):
-     """
-@@ -490,19 +516,51 @@ class CertificateRequest(CertBase):
- 
-     Certificate requests are given to certificate authorities to be signed and
-     returned resulting in an actual certificate.
-+
-+    @ivar original: The underlying CSR object.
-+    @type original: L{cryptography.x509.CertificateSigningRequest}
-     """
+ src/twisted/trial/reporter.py           | 13 +++++++++++++
+ src/twisted/trial/runner.py             |  6 +++++-
+ src/twisted/trial/test/test_doctest.py  |  9 +++++++--
+ src/twisted/trial/test/test_reporter.py | 17 ++++++++++++-----
+ 4 files changed, 37 insertions(+), 8 deletions(-)
+
+diff --git a/src/twisted/trial/reporter.py b/src/twisted/trial/reporter.py
+index 98ad7eb1aa6..bfdaca5e907 100644
+--- a/src/twisted/trial/reporter.py
++++ b/src/twisted/trial/reporter.py
+@@ -390,6 +390,19 @@ def stopTest(self, test):
+         """
+         return self._originalReporter.stopTest(self.testAdapter(test))
  
-     @classmethod
--    def load(Class, requestData, requestFormat=crypto.FILETYPE_ASN1):
--        req = crypto.load_certificate_request(requestFormat, requestData)
-+    def load(
-+        cls, requestData: bytes, requestFormat=crypto.FILETYPE_ASN1
-+    ) -> CertificateRequest:
-+        if requestFormat == crypto.FILETYPE_ASN1:
-+            req = x509.load_der_x509_csr(requestData)
-+        elif requestFormat == crypto.FILETYPE_PEM:
-+            req = x509.load_pem_x509_csr(requestData)
-+        else:
-+            raise ValueError(f"Unsupported format: {requestFormat!r}")
-+        if not req.is_signature_valid:
-+            subject = req.subject
-+            raise VerifyError(
-+                f"Can't verify that request for {subject!r} is self-signed."
-+            )
-+        return cls(req)
-+
-+    def _subjectToDistinguishedName(self) -> DistinguishedName:
++    def addSubTest(self, test, subtest, outcome):
 +        """
-+        Retrieve the subject of this certificate request.
++        See L{unittest.TestResult.addSubTest}.
 +
-+        @return: A copy of the subject of this certificate request.
-+        @rtype: L{DistinguishedName}
++        Called by the doctest runner in Python 3.15+ when reporting sub-test 
results.
 +        """
-         dn = DistinguishedName()
--        dn._copyFrom(req.get_subject())
--        if not req.verify(req.get_pubkey()):
--            raise VerifyError(f"Can't verify that request for {dn!r} is 
self-signed.")
--        return Class(req)
-+        for attribute in self.original.subject:
-+            try:
-+                name = _x509OIDNames[attribute.oid]
-+            except KeyError:
-+                raise ValueError(f"Unknown X509 name attribute: 
{attribute.oid!r}")
-+            setattr(dn, name, attribute.value)
-+        return dn
- 
--    def dump(self, format=crypto.FILETYPE_ASN1):
--        return crypto.dump_certificate_request(format, self.original)
-+    def dump(self, format=crypto.FILETYPE_ASN1) -> bytes:
-+        if format == crypto.FILETYPE_ASN1:
-+            return self.original.public_bytes(serialization.Encoding.DER)
-+        elif format == crypto.FILETYPE_PEM:
-+            return self.original.public_bytes(serialization.Encoding.PEM)
-+        else:
-+            raise ValueError(f"Unsupported format: {format!r}")
- 
- 
- class PrivateCertificate(Certificate):
-@@ -714,10 +772,21 @@ def newCertificate(self, newCertData, 
format=crypto.FILETYPE_ASN1):
-         return PrivateCertificate.load(newCertData, self, format)
- 
-     def requestObject(self, distinguishedName, digestAlgorithm="sha256"):
--        req = crypto.X509Req()
--        req.set_pubkey(self.original)
--        distinguishedName._copyInto(req.get_subject())
--        req.sign(self.original, digestAlgorithm)
-+        req = (
-+            x509.CertificateSigningRequestBuilder()
-+            .subject_name(
-+                x509.Name(
-+                    [
-+                        x509.NameAttribute(_x509NameOIDs[k], nativeString(v))
-+                        for k, v in distinguishedName.items()
-+                    ]
-+                )
-+            )
-+            .sign(
-+                self.original.to_cryptography_key(),
-+                _digestAlgorithms[digestAlgorithm](),
-+            )
-+        )
-         return CertificateRequest(req)
- 
-     def certificateRequest(
-@@ -750,7 +819,7 @@ def signCertificateRequest(
-         """
-         hlreq = CertificateRequest.load(requestData, requestFormat)
- 
--        dn = hlreq.getSubject()
-+        dn = hlreq._subjectToDistinguishedName()
-         vval = verifyDNCallback(dn)
- 
-         def verified(value):
-@@ -787,8 +856,8 @@ def signRequestObject(
-         req = requestObject.original
-         cert = crypto.X509()
-         issuerDistinguishedName._copyInto(cert.get_issuer())
--        cert.set_subject(req.get_subject())
--        cert.set_pubkey(req.get_pubkey())
-+        
requestObject._subjectToDistinguishedName()._copyInto(cert.get_subject())
-+        cert.set_pubkey(crypto.PKey.from_cryptography_key(req.public_key()))
-         cert.gmtime_adj_notBefore(0)
-         cert.gmtime_adj_notAfter(secondsToExpiry)
-         cert.set_serial_number(serialNumber)
-@@ -1656,10 +1725,10 @@ def contextSelectionCallback(connection: 
SSL.Connection) -> None:
-         return ctx
- 
- 
--OpenSSLCertificateOptions.__getstate__ = deprecated(  # 
type:ignore[method-assign]
-+OpenSSLCertificateOptions.__getstate__ = deprecated(  # type: 
ignore[method-assign]
-     Version("Twisted", 15, 0, 0), "a real persistence system"
- )(OpenSSLCertificateOptions.__getstate__)
--OpenSSLCertificateOptions.__setstate__ = deprecated(  # 
type:ignore[method-assign]
-+OpenSSLCertificateOptions.__setstate__ = deprecated(  # type: 
ignore[method-assign]
-     Version("Twisted", 15, 0, 0), "a real persistence system"
- )(OpenSSLCertificateOptions.__setstate__)
- 
-diff --git a/src/twisted/newsfragments/12660.misc 
b/src/twisted/newsfragments/12660.misc
-new file mode 100644
-index 00000000000..e69de29bb2d
-diff --git a/src/twisted/test/test_ssl.py b/src/twisted/test/test_ssl.py
-index cb5d6925af7..8e2eb423949 100644
---- a/src/twisted/test/test_ssl.py
-+++ b/src/twisted/test/test_ssl.py
-@@ -21,6 +21,10 @@
- try:
-     from OpenSSL import SSL, crypto
- 
-+    from cryptography import x509
-+    from cryptography.hazmat.primitives import hashes, serialization
-+    from cryptography.x509.oid import NameOID
++        test = self.testAdapter(test)
++        if hasattr(self._originalReporter, "addSubTest"):
++            return self._originalReporter.addSubTest(test, subtest, outcome)
++        # If the underlying reporter doesn't support subtests, treat as 
error/success
++        if outcome is not None:
++            return self._originalReporter.addError(test, outcome)
 +
-     from twisted.internet import ssl
-     from twisted.test.ssl_helpers import ClientTLSContext, certPath
- except ImportError:
-@@ -164,21 +168,31 @@ def generateCertificateObjects(organization, 
organizationalUnit):
-     """
-     pkey = crypto.PKey()
-     pkey.generate_key(crypto.TYPE_RSA, 2048)
--    req = crypto.X509Req()
--    subject = req.get_subject()
--    subject.O = organization
--    subject.OU = organizationalUnit
--    req.set_pubkey(pkey)
--    req.sign(pkey, "md5")
-+    req = (
-+        x509.CertificateSigningRequestBuilder()
-+        .subject_name(
-+            x509.Name(
-+                [
-+                    x509.NameAttribute(NameOID.ORGANIZATION_NAME, 
organization),
-+                    x509.NameAttribute(
-+                        NameOID.ORGANIZATIONAL_UNIT_NAME, organizationalUnit
-+                    ),
-+                ]
-+            )
-+        )
-+        .sign(pkey.to_cryptography_key(), hashes.SHA256())
-+    )
- 
-     # Here comes the actual certificate
-     cert = crypto.X509()
-     cert.set_serial_number(1)
-     cert.gmtime_adj_notBefore(0)
-     cert.gmtime_adj_notAfter(60)  # Testing certificates need not be long 
lived
--    cert.set_issuer(req.get_subject())
--    cert.set_subject(req.get_subject())
--    cert.set_pubkey(req.get_pubkey())
-+    subject = cert.get_subject()
-+    subject.O = organization
-+    subject.OU = organizationalUnit
-+    cert.set_issuer(cert.get_subject())
-+    cert.set_pubkey(pkey)
-     cert.sign(pkey, "md5")
- 
-     return pkey, req, cert
-@@ -191,13 +205,13 @@ def generateCertificateFiles(basename, organization, 
organizationalUnit):
-     """
-     pkey, req, cert = generateCertificateObjects(organization, 
organizationalUnit)
- 
--    for ext, obj, dumpFunc in [
--        ("key", pkey, crypto.dump_privatekey),
--        ("req", req, crypto.dump_certificate_request),
--        ("cert", cert, crypto.dump_certificate),
-+    for ext, data in [
-+        ("key", crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey)),
-+        ("req", req.public_bytes(serialization.Encoding.PEM)),
-+        ("cert", crypto.dump_certificate(crypto.FILETYPE_PEM, cert)),
-     ]:
-         fName = os.extsep.join((basename, ext)).encode("utf-8")
--        FilePath(fName).setContent(dumpFunc(crypto.FILETYPE_PEM, obj))
-+        FilePath(fName).setContent(data)
- 
- 
- class ContextGeneratingMixin:
-
-From 3fc8db4e7e3924eb3e6b93bb67380bcdb273e17e Mon Sep 17 00:00:00 2001
-From: Alex Gaynor <[email protected]>
-Date: Mon, 8 Jun 2026 09:00:00 -0700
-Subject: [PATCH 2/5] Fix mypy errors in CertificateRequest
-
-Annotate the format parameters and type the original CSR attribute so
-public_bytes is no longer inferred as Any.
-
-Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
----
- src/twisted/internet/_sslverify.py | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/src/twisted/internet/_sslverify.py 
b/src/twisted/internet/_sslverify.py
-index f1cec9c2d87..fdfa37adeef 100644
---- a/src/twisted/internet/_sslverify.py
-+++ b/src/twisted/internet/_sslverify.py
-@@ -521,9 +521,11 @@ class CertificateRequest(CertBase):
-     @type original: L{cryptography.x509.CertificateSigningRequest}
-     """
  
-+    original: x509.CertificateSigningRequest
-+
-     @classmethod
-     def load(
--        cls, requestData: bytes, requestFormat=crypto.FILETYPE_ASN1
-+        cls, requestData: bytes, requestFormat: int = crypto.FILETYPE_ASN1
-     ) -> CertificateRequest:
-         if requestFormat == crypto.FILETYPE_ASN1:
-             req = x509.load_der_x509_csr(requestData)
-@@ -554,7 +556,7 @@ def _subjectToDistinguishedName(self) -> DistinguishedName:
-             setattr(dn, name, attribute.value)
-         return dn
+ @implementer(itrial.IReporter)
+ class Reporter(TestResult):
+diff --git a/src/twisted/trial/runner.py b/src/twisted/trial/runner.py
+index 6d4fdb96d18..6d780bb3545 100644
+--- a/src/twisted/trial/runner.py
++++ b/src/twisted/trial/runner.py
+@@ -760,7 +760,11 @@ def loadFile(self, fileName, recurse=False):
+         """
+         name = reflect.filenameToModuleName(fileName)
+         try:
+-            module = SourceFileLoader(name, fileName).load_module()
++            loader = SourceFileLoader(name, fileName)
++            spec = importlib.util.spec_from_loader(name, loader)
++            module = importlib.util.module_from_spec(spec)
++            sys.modules[name] = module
++            spec.loader.exec_module(module)
+             return self.loadAnything(module, recurse=recurse)
+         except OSError:
+             raise ValueError(f"{fileName} is not a Python file.")
+diff --git a/src/twisted/trial/test/test_doctest.py 
b/src/twisted/trial/test/test_doctest.py
+index 05d57d44e06..5f6a1c17fe8 100644
+--- a/src/twisted/trial/test/test_doctest.py
++++ b/src/twisted/trial/test/test_doctest.py
+@@ -4,6 +4,7 @@
+ """
+ Test Twisted's doctest support.
+ """
++import sys
+ import unittest as pyunit
  
--    def dump(self, format=crypto.FILETYPE_ASN1) -> bytes:
-+    def dump(self, format: int = crypto.FILETYPE_ASN1) -> bytes:
-         if format == crypto.FILETYPE_ASN1:
-             return self.original.public_bytes(serialization.Encoding.DER)
-         elif format == crypto.FILETYPE_PEM:
-
-From 7cb81ce013455a0adfee8e439c309593bd9d192d Mon Sep 17 00:00:00 2001
-From: Alex Gaynor <[email protected]>
-Date: Mon, 8 Jun 2026 09:17:26 -0700
-Subject: [PATCH 3/5] Add CertificateRequest test coverage
-
-Cover the PEM/DER load and dump branches, unsupported-format and
-unverifiable-signature errors, and the unknown subject attribute path.
-
-Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
----
- src/twisted/test/test_sslverify.py | 81 ++++++++++++++++++++++++++++++
- 1 file changed, 81 insertions(+)
-
-diff --git a/src/twisted/test/test_sslverify.py 
b/src/twisted/test/test_sslverify.py
-index c50fb8b1055..579ae1d03f6 100644
---- a/src/twisted/test/test_sslverify.py
-+++ b/src/twisted/test/test_sslverify.py
-@@ -51,6 +51,7 @@
-     from cryptography import x509
-     from cryptography.hazmat.backends import default_backend
-     from cryptography.hazmat.primitives import hashes
-+    from cryptography.hazmat.primitives.asymmetric import ec
-     from cryptography.hazmat.primitives.asymmetric.rsa import (
-         RSAPrivateKey,
-         generate_private_key,
-@@ -3472,3 +3473,83 @@ def test_noTrailingNewlinePemCert(self):
+ from twisted.trial import itrial, reporter, runner, unittest
+@@ -40,8 +41,12 @@ def _testRun(self, suite: pyunit.TestSuite) -> None:
+         """
+         result = reporter.TestResult()
+         suite.run(result)
+-        self.assertEqual(5, result.successes)
+-        self.assertEqual(2, len(result.failures))
++        # Python 3.15+ counts doctest examples differently, resulting in more 
successes
++        # and also consolidates some failures
++        expected_successes = 7 if sys.version_info >= (3, 15) else 5
++        expected_failures = 1 if sys.version_info >= (3, 15) else 2
++        self.assertEqual(expected_successes, result.successes)
++        self.assertEqual(expected_failures, len(result.failures))
  
-         certPEM = noTrailingNewlineKeyPemPath.getContent()
-         ssl.Certificate.loadPEM(certPEM)
-+
-+
-+class CertificateRequestTests(SynchronousTestCase):
-+    """
-+    Tests for L{sslverify.CertificateRequest}.
-+    """
-+
-+    if skipSSL:
-+        skip = skipSSL
-+
-+    def _makeRequest(self):
-+        """
-+        Create a self-signed L{sslverify.CertificateRequest}.
-+
-+        @return: a fresh certificate request.
-+        @rtype: L{sslverify.CertificateRequest}
-+        """
-+        dn = 
sslverify.DistinguishedName(commonName="example.twistedmatrix.com")
-+        return sslverify.KeyPair.generate().requestObject(dn)
-+
-+    def test_pemRoundTrip(self):
-+        """
-+        A L{sslverify.CertificateRequest} dumped to PEM format and loaded back
-+        again preserves its subject.
-+        """
-+        request = self._makeRequest()
-+        pem = request.dump(FILETYPE_PEM)
-+        self.assertIn(b"BEGIN CERTIFICATE REQUEST", pem)
-+        loaded = sslverify.CertificateRequest.load(pem, FILETYPE_PEM)
-+        self.assertEqual(
-+            loaded._subjectToDistinguishedName(),
-+            request._subjectToDistinguishedName(),
-+        )
-+
-+    def test_loadUnsupportedFormat(self):
-+        """
-+        L{sslverify.CertificateRequest.load} raises L{ValueError} when given 
an
-+        unrecognized format.
-+        """
-+        request = self._makeRequest()
-+        with self.assertRaises(ValueError):
-+            sslverify.CertificateRequest.load(request.dump(), object())
-+
-+    def test_loadUnverifiableSignature(self):
-+        """
-+        L{sslverify.CertificateRequest.load} raises L{sslverify.VerifyError}
-+        when the request's self-signature does not verify.
-+        """
-+        data = bytearray(self._makeRequest().dump())
-+        # Corrupt the trailing signature bytes so the self-signature no longer
-+        # verifies while the structure still parses.
-+        data[-1] ^= 0xFF
-+        with self.assertRaises(sslverify.VerifyError):
-+            sslverify.CertificateRequest.load(bytes(data))
-+
-+    def test_dumpUnsupportedFormat(self):
-+        """
-+        L{sslverify.CertificateRequest.dump} raises L{ValueError} when given 
an
-+        unrecognized format.
-+        """
-+        with self.assertRaises(ValueError):
-+            self._makeRequest().dump(object())
-+
-+    def test_subjectUnknownAttribute(self):
-+        """
-+        L{sslverify.CertificateRequest._subjectToDistinguishedName} raises
-+        L{ValueError} when the subject contains a name attribute that does not
-+        correspond to a known L{sslverify.DistinguishedName} field.
-+        """
-+        key = ec.generate_private_key(ec.SECP256R1(), 
backend=default_backend())
-+        csr = (
-+            x509.CertificateSigningRequestBuilder()
-+            .subject_name(
-+                x509.Name([x509.NameAttribute(NameOID.GIVEN_NAME, "Alice")])
+     def test_expectedResults(self, count: int = 1) -> None:
+         """
+diff --git a/src/twisted/trial/test/test_reporter.py 
b/src/twisted/trial/test/test_reporter.py
+index 76172e7a6de..441704c7662 100644
+--- a/src/twisted/trial/test/test_reporter.py
++++ b/src/twisted/trial/test/test_reporter.py
+@@ -205,12 +205,19 @@ def test_doctestError(self):
+         suite = unittest.decorate(self.loader.loadDoctests(erroneous), 
itrial.ITestCase)
+         output = self.getOutput(suite)
+         path = "twisted.trial.test.erroneous.unexpectedException"
+-        for substring in ["1/0", "ZeroDivisionError", "Exception raised:", 
path]:
++        # Python 3.15+ changed doctest error output format
++        if sys.version_info >= (3, 15):
++            substrings = ["1/0", "ZeroDivisionError", path]
++        else:
++            substrings = ["1/0", "ZeroDivisionError", "Exception raised:", 
path]
++        for substring in substrings:
+             self.assertSubstring(substring, output)
+-        self.assertTrue(
+-            re.search("Fail(ed|ure in) example:", output),
+-            "Couldn't match 'Failure in example: ' " "or 'Failed example: '",
+-        )
++        # Python 3.15+ no longer uses "Failed example:" format
++        if sys.version_info < (3, 15):
++            self.assertTrue(
++                re.search("Fail(ed|ure in) example:", output),
++                "Couldn't match 'Failure in example: ' " "or 'Failed example: 
'",
 +            )
-+            .sign(key, hashes.SHA256())
-+        )
-+        request = sslverify.CertificateRequest(csr)
-+        with self.assertRaises(ValueError):
-+            request._subjectToDistinguishedName()
-
-From 7f5219d25e9eabed51f20f707ac10b1533c7a8c3 Mon Sep 17 00:00:00 2001
-From: Alex Gaynor <[email protected]>
-Date: Wed, 10 Jun 2026 06:14:45 -0700
-Subject: [PATCH 4/5] remove comment that's no longer required
-
----
- src/twisted/internet/_sslverify.py | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/src/twisted/internet/_sslverify.py 
b/src/twisted/internet/_sslverify.py
-index fdfa37adeef..bd71a401636 100644
---- a/src/twisted/internet/_sslverify.py
-+++ b/src/twisted/internet/_sslverify.py
-@@ -518,7 +518,6 @@ class CertificateRequest(CertBase):
-     returned resulting in an actual certificate.
+         expect = [self.doubleSeparator, re.compile(r"\[(ERROR|FAIL)\]")]
+         self.stringComparison(expect, output.splitlines())
  
-     @ivar original: The underlying CSR object.
--    @type original: L{cryptography.x509.CertificateSigningRequest}
-     """
- 
-     original: x509.CertificateSigningRequest
-
-From b2201db3e08760d4d0ae6563b44109d5c5f555df Mon Sep 17 00:00:00 2001
-From: Alex Gaynor <[email protected]>
-Date: Wed, 10 Jun 2026 06:15:39 -0700
-Subject: [PATCH 5/5] fmt
-
----
- src/twisted/test/test_sslverify.py | 4 +---
- 1 file changed, 1 insertion(+), 3 deletions(-)
-
-diff --git a/src/twisted/test/test_sslverify.py 
b/src/twisted/test/test_sslverify.py
-index 579ae1d03f6..282121bc023 100644
---- a/src/twisted/test/test_sslverify.py
-+++ b/src/twisted/test/test_sslverify.py
-@@ -3545,9 +3545,7 @@ def test_subjectUnknownAttribute(self):
-         key = ec.generate_private_key(ec.SECP256R1(), 
backend=default_backend())
-         csr = (
-             x509.CertificateSigningRequestBuilder()
--            .subject_name(
--                x509.Name([x509.NameAttribute(NameOID.GIVEN_NAME, "Alice")])
--            )
-+            .subject_name(x509.Name([x509.NameAttribute(NameOID.GIVEN_NAME, 
"Alice")]))
-             .sign(key, hashes.SHA256())
-         )
-         request = sslverify.CertificateRequest(csr)

++++++ twisted-26.4.0.tar.gz -> twisted-26.10.0.tar.gz ++++++
++++ 13455 lines of diff (skipped)

Reply via email to