Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-h2 for openSUSE:Factory 
checked in at 2025-08-27 21:34:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-h2 (Old)
 and      /work/SRC/openSUSE:Factory/.python-h2.new.30751 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-h2"

Wed Aug 27 21:34:08 2025 rev:18 rq:1301436 version:4.3.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-h2/python-h2.changes      2025-02-11 
21:23:28.031380476 +0100
+++ /work/SRC/openSUSE:Factory/.python-h2.new.30751/python-h2.changes   
2025-08-27 21:34:50.439086804 +0200
@@ -1,0 +2,18 @@
+Tue Aug 26 11:28:51 UTC 2025 - Nico Krapp <nico.kr...@suse.com>
+
+- Update to 4.3.0 (fixes CVE-2025-57804, bsc#1248737)
+  * API Changes (Backward Incompatible)
+    - Reject header names and values containing illegal characters, based on
+      RFC 9113, section 8.2.1. The main Python API is compatible, but some
+      previously valid requests/response headers might now be blocked. Use the
+      `validate_inbound_headers` config option if needed. Thanks to Sebastiano
+      Sartor (sebsrt) for the report.
+  * API Changes (Backward Compatible)
+    - h2 events now have tighter type bounds, e.g. `stream_id` is guaranteed to
+      not be `None` for most events now. This simplifies downstream type
+      checking.
+    - Various typing-related improvements.
+  * Bugfixes
+    - Fix error value when opening a new stream on too many open streams.
+
+-------------------------------------------------------------------

Old:
----
  h2-4.2.0.tar.gz

New:
----
  h2-4.3.0.tar.gz

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

Other differences:
------------------
++++++ python-h2.spec ++++++
--- /var/tmp/diff_new_pack.Xg5YTj/_old  2025-08-27 21:34:50.987109683 +0200
+++ /var/tmp/diff_new_pack.Xg5YTj/_new  2025-08-27 21:34:50.987109683 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-h2
 #
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2025 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -16,11 +16,9 @@
 #
 
 
-%{?!python_module:%define python_module() python3-%{**}}
-%define skip_python2 1
 %{?sle15_python_module_pythons}
 Name:           python-h2
-Version:        4.2.0
+Version:        4.3.0
 Release:        0
 Summary:        HTTP/2 State-Machine based protocol implementation
 License:        MIT

++++++ h2-4.2.0.tar.gz -> h2-4.3.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-4.2.0/CHANGELOG.rst new/h2-4.3.0/CHANGELOG.rst
--- old/h2-4.2.0/CHANGELOG.rst  2025-02-02 08:41:04.000000000 +0100
+++ new/h2-4.3.0/CHANGELOG.rst  2025-08-23 20:05:56.000000000 +0200
@@ -1,6 +1,26 @@
 Release History
 ===============
 
+4.3.0 (2025-08-23)
+------------------
+
+**API Changes (Backward Incompatible)**
+
+- Reject header names and values containing illegal characters, based on RFC 
9113, section 8.2.1.
+  The main Python API is compatible, but some previously valid 
requests/response headers might now be blocked.
+  Use the `validate_inbound_headers` config option if needed.
+  Thanks to Sebastiano Sartor (sebsrt) for the report.
+
+**API Changes (Backward Compatible)**
+
+- h2 events now have tighter type bounds, e.g. `stream_id` is guaranteed to 
not be `None` for most events now.
+  This simplifies downstream type checking.
+- Various typing-related improvements.
+
+**Bugfixes**
+
+- Fix error value when opening a new stream on too many open streams.
+
 4.2.0 (2025-02-01)
 ------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-4.2.0/MANIFEST.in new/h2-4.3.0/MANIFEST.in
--- old/h2-4.2.0/MANIFEST.in    2025-01-22 22:47:11.000000000 +0100
+++ new/h2-4.3.0/MANIFEST.in    2025-04-30 23:04:28.000000000 +0200
@@ -11,3 +11,4 @@
 include README.rst LICENSE CHANGELOG.rst pyproject.toml
 
 global-exclude *.pyc *.pyo *.swo *.swp *.map *.yml *.DS_Store
+exclude .readthedocs.yaml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-4.2.0/PKG-INFO new/h2-4.3.0/PKG-INFO
--- old/h2-4.2.0/PKG-INFO       2025-02-02 08:41:38.774786700 +0100
+++ new/h2-4.3.0/PKG-INFO       2025-08-23 20:12:14.005698000 +0200
@@ -1,6 +1,6 @@
-Metadata-Version: 2.2
+Metadata-Version: 2.4
 Name: h2
-Version: 4.2.0
+Version: 4.3.0
 Summary: Pure-Python HTTP/2 protocol implementation
 Author-email: Cory Benfield <c...@lukasa.co.uk>
 Maintainer-email: Thomas Kriechbaumer <tho...@kriechbaumer.name>
@@ -48,6 +48,7 @@
 License-File: LICENSE
 Requires-Dist: hyperframe<7,>=6.1
 Requires-Dist: hpack<5,>=4.1
+Dynamic: license-file
 
 =========================
 h2: HTTP/2 Protocol Stack
@@ -113,7 +114,7 @@
 Before you contribute (either by opening an issue or filing a pull request),
 please `read the contribution guidelines`_.
 
-.. _read the contribution guidelines: 
http://python-hyper.org/en/latest/contributing.html
+.. _read the contribution guidelines: 
https://python-hyper.org/en/latest/contributing.html
 
 License
 =======
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-4.2.0/README.rst new/h2-4.3.0/README.rst
--- old/h2-4.2.0/README.rst     2021-06-06 17:01:49.000000000 +0200
+++ new/h2-4.3.0/README.rst     2025-04-30 23:04:28.000000000 +0200
@@ -62,7 +62,7 @@
 Before you contribute (either by opening an issue or filing a pull request),
 please `read the contribution guidelines`_.
 
-.. _read the contribution guidelines: 
http://python-hyper.org/en/latest/contributing.html
+.. _read the contribution guidelines: 
https://python-hyper.org/en/latest/contributing.html
 
 License
 =======
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-4.2.0/pyproject.toml new/h2-4.3.0/pyproject.toml
--- old/h2-4.2.0/pyproject.toml 2025-02-01 11:53:05.000000000 +0100
+++ new/h2-4.3.0/pyproject.toml 2025-04-30 23:14:23.000000000 +0200
@@ -73,7 +73,7 @@
   "check-manifest==0.50",
   "readme-renderer==44.0",
   "build>=1.2.2,<2",
-  "twine>=5.1.1,<6",
+  "twine>=6.1.0,<7",
   "wheel>=0.45.0,<1",
 ]
 
@@ -183,9 +183,6 @@
 """
 
 [tool.tox.env_run_base]
-pass_env = [
-  "GITHUB_*",
-]
 dependency_groups = ["testing"]
 commands = [
   ["python", "-bb", "-m", "pytest", "--cov-report=xml", "--cov-report=term", 
"--cov=h2", { replace = "posargs", extend = true }]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-4.2.0/src/h2/__init__.py 
new/h2-4.3.0/src/h2/__init__.py
--- old/h2-4.2.0/src/h2/__init__.py     2025-02-02 08:41:04.000000000 +0100
+++ new/h2-4.3.0/src/h2/__init__.py     2025-08-23 20:05:56.000000000 +0200
@@ -3,4 +3,4 @@
 """
 from __future__ import annotations
 
-__version__ = "4.2.0"
+__version__ = "4.3.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-4.2.0/src/h2/connection.py 
new/h2-4.3.0/src/h2/connection.py
--- old/h2-4.2.0/src/h2/connection.py   2025-01-22 22:59:24.000000000 +0100
+++ new/h2-4.3.0/src/h2/connection.py   2025-02-22 17:40:39.000000000 +0100
@@ -793,8 +793,9 @@
         # Check we can open the stream.
         if stream_id not in self.streams:
             max_open_streams = self.remote_settings.max_concurrent_streams
-            if (self.open_outbound_streams + 1) > max_open_streams:
-                msg = f"Max outbound streams is {max_open_streams}, 
{self.open_outbound_streams} open"
+            value = self.open_outbound_streams # take a copy due to the 
property accessor having side affects
+            if (value + 1) > max_open_streams:
+                msg = f"Max outbound streams is {max_open_streams}, {value} 
open"
                 raise TooManyStreamsError(msg)
 
         self.state_machine.process_input(ConnectionInputs.SEND_HEADERS)
@@ -1593,8 +1594,9 @@
         # stream ID is valid.
         if frame.stream_id not in self.streams:
             max_open_streams = self.local_settings.max_concurrent_streams
-            if (self.open_inbound_streams + 1) > max_open_streams:
-                msg = f"Max outbound streams is {max_open_streams}, 
{self.open_outbound_streams} open"
+            value = self.open_inbound_streams # take a copy due to the 
property accessor having side affects
+            if (value + 1) > max_open_streams:
+                msg = f"Max inbound streams is {max_open_streams}, {value} 
open"
                 raise TooManyStreamsError(msg)
 
         # Let's decode the headers. We handle headers as bytes internally up
@@ -1806,9 +1808,7 @@
             )
 
             # FIXME: Should we split this into one event per active stream?
-            window_updated_event = WindowUpdated()
-            window_updated_event.stream_id = 0
-            window_updated_event.delta = frame.window_increment
+            window_updated_event = WindowUpdated(stream_id=0, 
delta=frame.window_increment)
             stream_events = [window_updated_event]
             frames = []
 
@@ -1825,9 +1825,9 @@
 
         evt: PingReceived | PingAckReceived
         if "ACK" in frame.flags:
-            evt = PingAckReceived()
+            evt = PingAckReceived(ping_data=frame.opaque_data)
         else:
-            evt = PingReceived()
+            evt = PingReceived(ping_data=frame.opaque_data)
 
             # automatically ACK the PING with the same 'opaque data'
             f = PingFrame(0)
@@ -1835,7 +1835,6 @@
             f.opaque_data = frame.opaque_data
             frames.append(f)
 
-        evt.ping_data = frame.opaque_data
         events.append(evt)
 
         return frames, events
@@ -1974,8 +1973,7 @@
         self.config.logger.debug(
             "Received unknown extension frame (ID %d)", frame.stream_id,
         )
-        event = UnknownFrameReceived()
-        event.frame = frame
+        event = UnknownFrameReceived(frame=frame)
         return [], [event]
 
     def _local_settings_acked(self) -> dict[SettingCodes | int, 
ChangedSetting]:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-4.2.0/src/h2/events.py 
new/h2-4.3.0/src/h2/events.py
--- old/h2-4.2.0/src/h2/events.py       2025-01-22 22:59:24.000000000 +0100
+++ new/h2-4.3.0/src/h2/events.py       2025-02-10 21:12:26.000000000 +0100
@@ -11,24 +11,41 @@
 from __future__ import annotations
 
 import binascii
-from typing import TYPE_CHECKING
+import sys
+from dataclasses import dataclass
+from typing import TYPE_CHECKING, Any
 
 from .settings import ChangedSetting, SettingCodes, Settings, 
_setting_code_from_int
 
 if TYPE_CHECKING:  # pragma: no cover
-    from hpack import HeaderTuple
+    from hpack.struct import Header
     from hyperframe.frame import Frame
 
     from .errors import ErrorCodes
 
 
+if sys.version_info < (3, 10):  # pragma: no cover
+    kw_only: dict[str, bool] = {}
+else:  # pragma: no cover
+    kw_only = {"kw_only": True}
+
+
+_LAZY_INIT: Any = object()
+"""
+Some h2 events are instantiated by the state machine, but its attributes are
+subsequently populated by H2Stream. To make this work with strict type 
annotations
+on the events, they are temporarily set to this placeholder value.
+This value should never be exposed to users.
+"""
+
+
 class Event:
     """
     Base class for h2 events.
     """
 
 
-
+@dataclass(**kw_only)
 class RequestReceived(Event):
     """
     The RequestReceived event is fired whenever all of a request's headers
@@ -47,31 +64,35 @@
        Added ``stream_ended`` and ``priority_updated`` properties.
     """
 
-    def __init__(self) -> None:
-        #: The Stream ID for the stream this request was made on.
-        self.stream_id: int | None = None
+    stream_id: int
+    """The Stream ID for the stream this request was made on."""
 
-        #: The request headers.
-        self.headers: list[HeaderTuple] | None = None
+    headers: list[Header] = _LAZY_INIT
+    """The request headers."""
 
-        #: If this request also ended the stream, the associated
-        #: :class:`StreamEnded <h2.events.StreamEnded>` event will be available
-        #: here.
-        #:
-        #: .. versionadded:: 2.4.0
-        self.stream_ended: StreamEnded | None = None
-
-        #: If this request also had associated priority information, the
-        #: associated :class:`PriorityUpdated <h2.events.PriorityUpdated>`
-        #: event will be available here.
-        #:
-        #: .. versionadded:: 2.4.0
-        self.priority_updated: PriorityUpdated | None = None
+    stream_ended: StreamEnded | None = None
+    """
+    If this request also ended the stream, the associated
+    :class:`StreamEnded <h2.events.StreamEnded>` event will be available
+    here.
+
+    .. versionadded:: 2.4.0
+    """
+
+    priority_updated: PriorityUpdated | None = None
+    """
+    If this request also had associated priority information, the
+    associated :class:`PriorityUpdated <h2.events.PriorityUpdated>`
+    event will be available here.
+
+    .. versionadded:: 2.4.0
+    """
 
     def __repr__(self) -> str:
         return f"<RequestReceived stream_id:{self.stream_id}, 
headers:{self.headers}>"
 
 
+@dataclass(**kw_only)
 class ResponseReceived(Event):
     """
     The ResponseReceived event is fired whenever response headers are received.
@@ -86,31 +107,35 @@
       Added ``stream_ended`` and ``priority_updated`` properties.
     """
 
-    def __init__(self) -> None:
-        #: The Stream ID for the stream this response was made on.
-        self.stream_id: int | None = None
+    stream_id: int
+    """The Stream ID for the stream this response was made on."""
 
-        #: The response headers.
-        self.headers: list[HeaderTuple] | None = None
+    headers: list[Header] = _LAZY_INIT
+    """The response headers."""
 
-        #: If this response also ended the stream, the associated
-        #: :class:`StreamEnded <h2.events.StreamEnded>` event will be available
-        #: here.
-        #:
-        #: .. versionadded:: 2.4.0
-        self.stream_ended: StreamEnded | None = None
-
-        #: If this response also had associated priority information, the
-        #: associated :class:`PriorityUpdated <h2.events.PriorityUpdated>`
-        #: event will be available here.
-        #:
-        #: .. versionadded:: 2.4.0
-        self.priority_updated: PriorityUpdated | None = None
+    stream_ended: StreamEnded | None = None
+    """
+    If this response also ended the stream, the associated
+    :class:`StreamEnded <h2.events.StreamEnded>` event will be available
+    here.
+
+    .. versionadded:: 2.4.0
+    """
+
+    priority_updated: PriorityUpdated | None = None
+    """
+    If this response also had associated priority information, the
+    associated :class:`PriorityUpdated <h2.events.PriorityUpdated>`
+    event will be available here.
+
+    .. versionadded:: 2.4.0
+    """
 
     def __repr__(self) -> str:
         return f"<ResponseReceived stream_id:{self.stream_id}, 
headers:{self.headers}>"
 
 
+@dataclass(**kw_only)
 class TrailersReceived(Event):
     """
     The TrailersReceived event is fired whenever trailers are received on a
@@ -128,25 +153,28 @@
        Added ``stream_ended`` and ``priority_updated`` properties.
     """
 
-    def __init__(self) -> None:
-        #: The Stream ID for the stream on which these trailers were received.
-        self.stream_id: int | None = None
+    stream_id: int
+    """The Stream ID for the stream on which these trailers were received."""
 
-        #: The trailers themselves.
-        self.headers: list[HeaderTuple] | None = None
+    headers: list[Header] = _LAZY_INIT
+    """The trailers themselves."""
 
-        #: Trailers always end streams. This property has the associated
-        #: :class:`StreamEnded <h2.events.StreamEnded>` in it.
-        #:
-        #: .. versionadded:: 2.4.0
-        self.stream_ended: StreamEnded | None = None
-
-        #: If the trailers also set associated priority information, the
-        #: associated :class:`PriorityUpdated <h2.events.PriorityUpdated>`
-        #: event will be available here.
-        #:
-        #: .. versionadded:: 2.4.0
-        self.priority_updated: PriorityUpdated | None = None
+    stream_ended: StreamEnded | None = None
+    """
+    Trailers always end streams. This property has the associated
+    :class:`StreamEnded <h2.events.StreamEnded>` in it.
+
+    .. versionadded:: 2.4.0
+    """
+
+    priority_updated: PriorityUpdated | None = None
+    """
+    If the trailers also set associated priority information, the
+    associated :class:`PriorityUpdated <h2.events.PriorityUpdated>`
+    event will be available here.
+
+    .. versionadded:: 2.4.0
+    """
 
     def __repr__(self) -> str:
         return f"<TrailersReceived stream_id:{self.stream_id}, 
headers:{self.headers}>"
@@ -207,7 +235,7 @@
     """
 
 
-
+@dataclass(**kw_only)
 class InformationalResponseReceived(Event):
     """
     The InformationalResponseReceived event is fired when an informational
@@ -231,25 +259,26 @@
        Added ``priority_updated`` property.
     """
 
-    def __init__(self) -> None:
-        #: The Stream ID for the stream this informational response was made
-        #: on.
-        self.stream_id: int | None = None
+    stream_id: int
+    """The Stream ID for the stream this informational response was made on."""
 
-        #: The headers for this informational response.
-        self.headers: list[HeaderTuple] | None = None
+    headers: list[Header] = _LAZY_INIT
+    """The headers for this informational response."""
+
+    priority_updated: PriorityUpdated | None = None
+    """
+    If this response also had associated priority information, the
+    associated :class:`PriorityUpdated <h2.events.PriorityUpdated>`
+    event will be available here.
 
-        #: If this response also had associated priority information, the
-        #: associated :class:`PriorityUpdated <h2.events.PriorityUpdated>`
-        #: event will be available here.
-        #:
-        #: .. versionadded:: 2.4.0
-        self.priority_updated: PriorityUpdated | None = None
+    .. versionadded:: 2.4.0
+    """
 
     def __repr__(self) -> str:
         return f"<InformationalResponseReceived stream_id:{self.stream_id}, 
headers:{self.headers}>"
 
 
+@dataclass(**kw_only)
 class DataReceived(Event):
     """
     The DataReceived event is fired whenever data is received on a stream from
@@ -260,25 +289,28 @@
        Added ``stream_ended`` property.
     """
 
-    def __init__(self) -> None:
-        #: The Stream ID for the stream this data was received on.
-        self.stream_id: int | None = None
+    stream_id: int
+    """The Stream ID for the stream this data was received on."""
+
+    data: bytes = _LAZY_INIT
+    """The data itself."""
 
-        #: The data itself.
-        self.data: bytes | None = None
+    flow_controlled_length: int = _LAZY_INIT
+    """
+    The amount of data received that counts against the flow control
+    window. Note that padding counts against the flow control window, so
+    when adjusting flow control you should always use this field rather
+    than ``len(data)``.
+    """
+
+    stream_ended: StreamEnded | None = None
+    """
+    If this data chunk also completed the stream, the associated
+    :class:`StreamEnded <h2.events.StreamEnded>` event will be available
+    here.
 
-        #: The amount of data received that counts against the flow control
-        #: window. Note that padding counts against the flow control window, so
-        #: when adjusting flow control you should always use this field rather
-        #: than ``len(data)``.
-        self.flow_controlled_length: int | None = None
-
-        #: If this data chunk also completed the stream, the associated
-        #: :class:`StreamEnded <h2.events.StreamEnded>` event will be available
-        #: here.
-        #:
-        #: .. versionadded:: 2.4.0
-        self.stream_ended: StreamEnded | None = None
+    .. versionadded:: 2.4.0
+    """
 
     def __repr__(self) -> str:
         return (
@@ -292,6 +324,7 @@
         )
 
 
+@dataclass(**kw_only)
 class WindowUpdated(Event):
     """
     The WindowUpdated event is fired whenever a flow control window changes
@@ -301,13 +334,16 @@
     the connection), and the delta in the window size.
     """
 
-    def __init__(self) -> None:
-        #: The Stream ID of the stream whose flow control window was changed.
-        #: May be ``0`` if the connection window was changed.
-        self.stream_id: int | None = None
+    stream_id: int
+    """
+    The Stream ID of the stream whose flow control window was changed.
+    May be ``0`` if the connection window was changed.
+    """
 
-        #: The window delta.
-        self.delta: int | None = None
+    delta: int = _LAZY_INIT
+    """
+    The window delta.
+    """
 
     def __repr__(self) -> str:
         return f"<WindowUpdated stream_id:{self.stream_id}, 
delta:{self.delta}>"
@@ -367,6 +403,7 @@
         )
 
 
+@dataclass(**kw_only)
 class PingReceived(Event):
     """
     The PingReceived event is fired whenever a PING is received. It contains
@@ -376,14 +413,14 @@
     .. versionadded:: 3.1.0
     """
 
-    def __init__(self) -> None:
-        #: The data included on the ping.
-        self.ping_data: bytes | None = None
+    ping_data: bytes
+    """The data included on the ping."""
 
     def __repr__(self) -> str:
         return f"<PingReceived 
ping_data:{_bytes_representation(self.ping_data)}>"
 
 
+@dataclass(**kw_only)
 class PingAckReceived(Event):
     """
     The PingAckReceived event is fired whenever a PING acknowledgment is
@@ -396,14 +433,14 @@
        Removed deprecated but equivalent ``PingAcknowledged``.
     """
 
-    def __init__(self) -> None:
-        #: The data included on the ping.
-        self.ping_data: bytes | None = None
+    ping_data: bytes
+    """The data included on the ping."""
 
     def __repr__(self) -> str:
         return f"<PingAckReceived 
ping_data:{_bytes_representation(self.ping_data)}>"
 
 
+@dataclass(**kw_only)
 class StreamEnded(Event):
     """
     The StreamEnded event is fired whenever a stream is ended by a remote
@@ -411,14 +448,14 @@
     locally, but no further data or headers should be expected on that stream.
     """
 
-    def __init__(self) -> None:
-        #: The Stream ID of the stream that was closed.
-        self.stream_id: int | None = None
+    stream_id: int
+    """The Stream ID of the stream that was closed."""
 
     def __repr__(self) -> str:
         return f"<StreamEnded stream_id:{self.stream_id}>"
 
 
+@dataclass(**kw_only)
 class StreamReset(Event):
     """
     The StreamReset event is fired in two situations. The first is when the
@@ -430,16 +467,20 @@
        This event is now fired when h2 automatically resets a stream.
     """
 
-    def __init__(self) -> None:
-        #: The Stream ID of the stream that was reset.
-        self.stream_id: int | None = None
+    stream_id: int
+    """
+    The Stream ID of the stream that was reset.
+    """
 
-        #: The error code given. Either one of :class:`ErrorCodes
-        #: <h2.errors.ErrorCodes>` or ``int``
-        self.error_code: ErrorCodes | None = None
+    error_code: ErrorCodes | int = _LAZY_INIT
+    """
+    The error code given.
+    """
 
-        #: Whether the remote peer sent a RST_STREAM or we did.
-        self.remote_reset = True
+    remote_reset: bool = True
+    """
+    Whether the remote peer sent a RST_STREAM or we did.
+    """
 
     def __repr__(self) -> str:
         return f"<StreamReset stream_id:{self.stream_id}, 
error_code:{self.error_code!s}, remote_reset:{self.remote_reset}>"
@@ -460,7 +501,7 @@
         self.parent_stream_id: int | None = None
 
         #: The request headers, sent by the remote party in the push.
-        self.headers: list[HeaderTuple] | None = None
+        self.headers: list[Header] | None = None
 
     def __repr__(self) -> str:
         return (
@@ -601,6 +642,7 @@
         )
 
 
+@dataclass(**kw_only)
 class UnknownFrameReceived(Event):
     """
     The UnknownFrameReceived event is fired when the remote peer sends a frame
@@ -616,9 +658,7 @@
     .. versionadded:: 2.7.0
     """
 
-    def __init__(self) -> None:
-        #: The hyperframe Frame object that encapsulates the received frame.
-        self.frame: Frame | None = None
+    frame: Frame
 
     def __repr__(self) -> str:
         return "<UnknownFrameReceived>"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-4.2.0/src/h2/frame_buffer.py 
new/h2-4.3.0/src/h2/frame_buffer.py
--- old/h2-4.2.0/src/h2/frame_buffer.py 2025-01-22 22:59:24.000000000 +0100
+++ new/h2-4.3.0/src/h2/frame_buffer.py 2025-04-30 23:02:48.000000000 +0200
@@ -30,7 +30,7 @@
     """
 
     def __init__(self, server: bool = False) -> None:
-        self.data = b""
+        self._data = bytearray()
         self.max_frame_size = 0
         self._preamble = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" if server else b""
         self._preamble_len = len(self._preamble)
@@ -54,7 +54,7 @@
             self._preamble_len -= of_which_preamble
             self._preamble = self._preamble[of_which_preamble:]
 
-        self.data += data
+        self._data += data
 
     def _validate_frame_length(self, length: int) -> None:
         """
@@ -119,18 +119,18 @@
     def __next__(self) -> Frame:
         # First, check that we have enough data to successfully parse the
         # next frame header. If not, bail. Otherwise, parse it.
-        if len(self.data) < 9:
+        if len(self._data) < 9:
             raise StopIteration
 
         try:
-            f, length = Frame.parse_frame_header(memoryview(self.data[:9]))
+            f, length = Frame.parse_frame_header(memoryview(self._data[:9]))
         except (InvalidDataError, InvalidFrameError) as err:  # pragma: no 
cover
             msg = f"Received frame with invalid header: {err!s}"
             raise ProtocolError(msg) from err
 
         # Next, check that we have enough length to parse the frame body. If
         # not, bail, leaving the frame header data in the buffer for next time.
-        if len(self.data) < length + 9:
+        if len(self._data) < length + 9:
             raise StopIteration
 
         # Confirm the frame has an appropriate length.
@@ -138,7 +138,7 @@
 
         # Try to parse the frame body
         try:
-            f.parse_body(memoryview(self.data[9:9+length]))
+            f.parse_body(memoryview(self._data[9:9+length]))
         except InvalidDataError as err:
             msg = "Received frame with non-compliant data"
             raise ProtocolError(msg) from err
@@ -148,7 +148,7 @@
 
         # At this point, as we know we'll use or discard the entire frame, we
         # can update the data.
-        self.data = self.data[9+length:]
+        self._data = self._data[9+length:]
 
         # Pass the frame through the header buffer.
         new_frame = self._update_header_buffer(f)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-4.2.0/src/h2/stream.py 
new/h2-4.3.0/src/h2/stream.py
--- old/h2-4.2.0/src/h2/stream.py       2025-01-22 22:59:24.000000000 +0100
+++ new/h2-4.3.0/src/h2/stream.py       2025-04-30 23:14:23.000000000 +0200
@@ -7,7 +7,7 @@
 from __future__ import annotations
 
 from enum import Enum, IntEnum
-from typing import TYPE_CHECKING, Any
+from typing import TYPE_CHECKING, Any, Union, cast
 
 from hpack import HeaderTuple
 from hyperframe.frame import AltSvcFrame, ContinuationFrame, DataFrame, Frame, 
HeadersFrame, PushPromiseFrame, RstStreamFrame, WindowUpdateFrame
@@ -46,7 +46,7 @@
 from .windows import WindowManager
 
 if TYPE_CHECKING:  # pragma: no cover
-    from collections.abc import Generator, Iterable
+    from collections.abc import Callable, Generator, Iterable
 
     from hpack.hpack import Encoder
     from hpack.struct import Header, HeaderWeaklyTyped
@@ -131,7 +131,7 @@
         # How the stream was closed. One of StreamClosedBy.
         self.stream_closed_by: StreamClosedBy | None = None
 
-    def process_input(self, input_: StreamInputs) -> Any:
+    def process_input(self, input_: StreamInputs) -> list[Event]:
         """
         Process a specific input in the state machine.
         """
@@ -195,8 +195,7 @@
 
         self.client = False
         self.headers_received = True
-        event = RequestReceived()
-        event.stream_id = self.stream_id
+        event = RequestReceived(stream_id=self.stream_id)
         return [event]
 
     def response_received(self, previous_state: StreamState) -> list[Event]:
@@ -208,11 +207,11 @@
         if not self.headers_received:
             assert self.client is True
             self.headers_received = True
-            event = ResponseReceived()
+            event = ResponseReceived(stream_id=self.stream_id)
         else:
             assert not self.trailers_received
             self.trailers_received = True
-            event = TrailersReceived()
+            event = TrailersReceived(stream_id=self.stream_id)
 
         event.stream_id = self.stream_id
         return [event]
@@ -224,25 +223,21 @@
         if not self.headers_received:
             msg = "cannot receive data before headers"
             raise ProtocolError(msg)
-        event = DataReceived()
-        event.stream_id = self.stream_id
+        event = DataReceived(stream_id=self.stream_id)
         return [event]
 
     def window_updated(self, previous_state: StreamState) -> list[Event]:
         """
         Fires when a window update frame is received.
         """
-        event = WindowUpdated()
-        event.stream_id = self.stream_id
-        return [event]
+        return [WindowUpdated(stream_id=self.stream_id)]
 
     def stream_half_closed(self, previous_state: StreamState) -> list[Event]:
         """
         Fires when an END_STREAM flag is received in the OPEN state,
         transitioning this stream to a HALF_CLOSED_REMOTE state.
         """
-        event = StreamEnded()
-        event.stream_id = self.stream_id
+        event = StreamEnded(stream_id=self.stream_id)
         return [event]
 
     def stream_ended(self, previous_state: StreamState) -> list[Event]:
@@ -250,8 +245,7 @@
         Fires when a stream is cleanly ended.
         """
         self.stream_closed_by = StreamClosedBy.RECV_END_STREAM
-        event = StreamEnded()
-        event.stream_id = self.stream_id
+        event = StreamEnded(stream_id=self.stream_id)
         return [event]
 
     def stream_reset(self, previous_state: StreamState) -> list[Event]:
@@ -259,9 +253,7 @@
         Fired when a stream is forcefully reset.
         """
         self.stream_closed_by = StreamClosedBy.RECV_RST_STREAM
-        event = StreamReset()
-        event.stream_id = self.stream_id
-        return [event]
+        return [StreamReset(stream_id=self.stream_id)]
 
     def send_new_pushed_stream(self, previous_state: StreamState) -> 
list[Event]:
         """
@@ -315,21 +307,23 @@
         event.parent_stream_id = self.stream_id
         return [event]
 
-    def send_end_stream(self, previous_state: StreamState) -> None:
+    def send_end_stream(self, previous_state: StreamState) -> list[Event]:
         """
         Called when an attempt is made to send END_STREAM in the
         HALF_CLOSED_REMOTE state.
         """
         self.stream_closed_by = StreamClosedBy.SEND_END_STREAM
+        return []
 
-    def send_reset_stream(self, previous_state: StreamState) -> None:
+    def send_reset_stream(self, previous_state: StreamState) -> list[Event]:
         """
         Called when an attempt is made to send RST_STREAM in a non-closed
         stream state.
         """
         self.stream_closed_by = StreamClosedBy.SEND_RST_STREAM
+        return []
 
-    def reset_stream_on_error(self, previous_state: StreamState) -> None:
+    def reset_stream_on_error(self, previous_state: StreamState) -> 
list[Event]:
         """
         Called when we need to forcefully emit another RST_STREAM frame on
         behalf of the state machine.
@@ -342,15 +336,16 @@
         self.stream_closed_by = StreamClosedBy.SEND_RST_STREAM
 
         error = StreamClosedError(self.stream_id)
-
-        event = StreamReset()
-        event.stream_id = self.stream_id
-        event.error_code = ErrorCodes.STREAM_CLOSED
-        event.remote_reset = False
-        error._events = [event]
+        error._events = [
+            StreamReset(
+                stream_id=self.stream_id,
+                error_code=ErrorCodes.STREAM_CLOSED,
+                remote_reset=False,
+            ),
+        ]
         raise error
 
-    def recv_on_closed_stream(self, previous_state: StreamState) -> None:
+    def recv_on_closed_stream(self, previous_state: StreamState) -> 
list[Event]:
         """
         Called when an unexpected frame is received on an already-closed
         stream.
@@ -362,7 +357,7 @@
         """
         raise StreamClosedError(self.stream_id)
 
-    def send_on_closed_stream(self, previous_state: StreamState) -> None:
+    def send_on_closed_stream(self, previous_state: StreamState) -> 
list[Event]:
         """
         Called when an attempt is made to send data on an already-closed
         stream.
@@ -374,7 +369,7 @@
         """
         raise StreamClosedError(self.stream_id)
 
-    def recv_push_on_closed_stream(self, previous_state: StreamState) -> None:
+    def recv_push_on_closed_stream(self, previous_state: StreamState) -> 
list[Event]:
         """
         Called when a PUSH_PROMISE frame is received on a full stop
         stream.
@@ -393,7 +388,7 @@
         msg = "Attempted to push on closed stream."
         raise ProtocolError(msg)
 
-    def send_push_on_closed_stream(self, previous_state: StreamState) -> None:
+    def send_push_on_closed_stream(self, previous_state: StreamState) -> 
list[Event]:
         """
         Called when an attempt is made to push on an already-closed stream.
 
@@ -429,9 +424,7 @@
             msg = "Informational response after final response"
             raise ProtocolError(msg)
 
-        event = InformationalResponseReceived()
-        event.stream_id = self.stream_id
-        return [event]
+        return [InformationalResponseReceived(stream_id=self.stream_id)]
 
     def recv_alt_svc(self, previous_state: StreamState) -> list[Event]:
         """
@@ -473,7 +466,7 @@
         # the event and let it get populated.
         return [AlternativeServiceAvailable()]
 
-    def send_alt_svc(self, previous_state: StreamState) -> None:
+    def send_alt_svc(self, previous_state: StreamState) -> list[Event]:
         """
         Called when sending an ALTSVC frame on this stream.
 
@@ -489,6 +482,7 @@
         if self.headers_sent:
             msg = "Cannot send ALTSVC after sending response headers."
             raise ProtocolError(msg)
+        return []
 
 
 
@@ -561,7 +555,10 @@
 # (state, input) to tuples of (side_effect_function, end_state). This
 # map contains all allowed transitions: anything not in this map is
 # invalid and immediately causes a transition to ``closed``.
-_transitions = {
+_transitions: dict[
+    tuple[StreamState, StreamInputs],
+    tuple[Callable[[H2StreamStateMachine, StreamState], list[Event]] | None, 
StreamState],
+] = {
     # State: idle
     (StreamState.IDLE, StreamInputs.SEND_HEADERS):
         (H2StreamStateMachine.request_sent, StreamState.OPEN),
@@ -1040,10 +1037,11 @@
         events = self.state_machine.process_input(
             StreamInputs.RECV_PUSH_PROMISE,
         )
-        events[0].pushed_stream_id = promised_stream_id
+        push_event = cast("PushedStreamReceived", events[0])
+        push_event.pushed_stream_id = promised_stream_id
 
         hdr_validation_flags = self._build_hdr_validation_flags(events)
-        events[0].headers = self._process_received_headers(
+        push_event.headers = self._process_received_headers(
             headers, hdr_validation_flags, header_encoding,
         )
         return [], events
@@ -1077,22 +1075,30 @@
             input_ = StreamInputs.RECV_HEADERS
 
         events = self.state_machine.process_input(input_)
+        headers_event = cast(
+            "Union[RequestReceived, ResponseReceived, TrailersReceived, 
InformationalResponseReceived]",
+            events[0],
+        )
 
         if end_stream:
             es_events = self.state_machine.process_input(
                 StreamInputs.RECV_END_STREAM,
             )
-            events[0].stream_ended = es_events[0]
+            # We ensured it's not an information response at the beginning of 
the method.
+            cast(
+                "Union[RequestReceived, ResponseReceived, TrailersReceived]",
+                headers_event,
+            ).stream_ended = cast("StreamEnded", es_events[0])
             events += es_events
 
         self._initialize_content_length(headers)
 
-        if isinstance(events[0], TrailersReceived) and not end_stream:
+        if isinstance(headers_event, TrailersReceived) and not end_stream:
             msg = "Trailers must have END_STREAM set"
             raise ProtocolError(msg)
 
         hdr_validation_flags = self._build_hdr_validation_flags(events)
-        events[0].headers = self._process_received_headers(
+        headers_event.headers = self._process_received_headers(
             headers, hdr_validation_flags, header_encoding,
         )
         return [], events
@@ -1106,6 +1112,7 @@
             "set to %d", self, end_stream, flow_control_len,
         )
         events = self.state_machine.process_input(StreamInputs.RECV_DATA)
+        data_event = cast("DataReceived", events[0])
         self._inbound_window_manager.window_consumed(flow_control_len)
         self._track_content_length(len(data), end_stream)
 
@@ -1113,11 +1120,11 @@
             es_events = self.state_machine.process_input(
                 StreamInputs.RECV_END_STREAM,
             )
-            events[0].stream_ended = es_events[0]
+            data_event.stream_ended = cast("StreamEnded", es_events[0])
             events.extend(es_events)
 
-        events[0].data = data
-        events[0].flow_controlled_length = flow_control_len
+        data_event.data = data
+        data_event.flow_controlled_length = flow_control_len
         return [], events
 
     def receive_window_update(self, increment: int) -> tuple[list[Frame], 
list[Event]]:
@@ -1137,7 +1144,7 @@
         # this should be treated as a *stream* error, not a *connection* error.
         # That means we need to catch the error and forcibly close the stream.
         if events:
-            events[0].delta = increment
+            cast("WindowUpdated", events[0]).delta = increment
             try:
                 self.outbound_flow_control_window = guard_increment_window(
                     self.outbound_flow_control_window,
@@ -1146,13 +1153,14 @@
             except FlowControlError:
                 # Ok, this is bad. We're going to need to perform a local
                 # reset.
-                event = StreamReset()
-                event.stream_id = self.stream_id
-                event.error_code = ErrorCodes.FLOW_CONTROL_ERROR
-                event.remote_reset = False
-
-                events = [event]
-                frames = self.reset_stream(event.error_code)
+                events = [
+                    StreamReset(
+                        stream_id=self.stream_id,
+                        error_code=ErrorCodes.FLOW_CONTROL_ERROR,
+                        remote_reset=False,
+                    ),
+                ]
+                frames = self.reset_stream(ErrorCodes.FLOW_CONTROL_ERROR)
 
         return frames, events
 
@@ -1220,7 +1228,7 @@
 
         if events:
             # We don't fire an event if this stream is already closed.
-            events[0].error_code = _error_code_from_int(frame.error_code)
+            cast("StreamReset", events[0]).error_code = 
_error_code_from_int(frame.error_code)
 
         return [], events
 
@@ -1322,7 +1330,7 @@
     def _process_received_headers(self,
                                   headers: Iterable[Header],
                                   header_validation_flags: 
HeaderValidationFlags,
-                                  header_encoding: bool | str | None) -> 
Iterable[Header]:
+                                  header_encoding: bool | str | None) -> 
list[Header]:
         """
         When headers have been received from the remote peer, run a processing
         pipeline on them to transform them into the appropriate form for
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-4.2.0/src/h2/utilities.py 
new/h2-4.3.0/src/h2/utilities.py
--- old/h2-4.2.0/src/h2/utilities.py    2025-01-22 22:59:24.000000000 +0100
+++ new/h2-4.3.0/src/h2/utilities.py    2025-08-23 19:56:57.000000000 +0200
@@ -7,8 +7,6 @@
 from __future__ import annotations
 
 import collections
-import re
-from string import whitespace
 from typing import TYPE_CHECKING, Any, NamedTuple
 
 from hpack.struct import HeaderTuple, NeverIndexedHeaderTuple
@@ -20,7 +18,6 @@
 
     from hpack.struct import Header, HeaderWeaklyTyped
 
-UPPER_RE = re.compile(b"[A-Z]")
 SIGIL = ord(b":")
 INFORMATIONAL_START = ord(b"1")
 
@@ -70,9 +67,6 @@
 _CONNECT_REQUEST_ONLY_HEADERS = frozenset([b":protocol"])
 
 
-_WHITESPACE = frozenset(map(ord, whitespace))
-
-
 def _secure_headers(headers: Iterable[Header],
                     hdr_validation_flags: HeaderValidationFlags | None) -> 
Generator[Header, None, None]:
     """
@@ -201,13 +195,10 @@
     # For example, we avoid tuple unpacking in loops because it represents a
     # fixed cost that we don't want to spend, instead indexing into the header
     # tuples.
-    headers = _reject_empty_header_names(
+    headers = _reject_illegal_characters(
         headers, hdr_validation_flags,
     )
-    headers = _reject_uppercase_header_fields(
-        headers, hdr_validation_flags,
-    )
-    headers = _reject_surrounding_whitespace(
+    headers = _reject_empty_header_names(
         headers, hdr_validation_flags,
     )
     headers = _reject_te(
@@ -225,53 +216,66 @@
     return _check_path_header(headers, hdr_validation_flags)
 
 
-
-def _reject_empty_header_names(headers: Iterable[Header],
+def _reject_illegal_characters(headers: Iterable[Header],
                                hdr_validation_flags: HeaderValidationFlags) -> 
Generator[Header, None, None]:
     """
-    Raises a ProtocolError if any header names are empty (length 0).
-    While hpack decodes such headers without errors, they are semantically
-    forbidden in HTTP, see RFC 7230, stating that they must be at least one
-    character long.
+    Raises a ProtocolError if any header names or values contain illegal 
characters.
+    See <https://www.rfc-editor.org/rfc/rfc9113.html#section-8.2.1>.
     """
     for header in headers:
-        if len(header[0]) == 0:
-            msg = "Received header name with zero length."
+        # > A field name MUST NOT contain characters in the ranges 0x00-0x20, 
0x41-0x5a,
+        # > or 0x7f-0xff (all ranges inclusive).
+        for c in header[0]:
+            if 0x41 <= c <= 0x5a:
+                msg = f"Received uppercase header name {header[0]!r}."
+                raise ProtocolError(msg)
+            if c <= 0x20 or c >= 0x7f:
+                msg = f"Illegal character '{chr(c)}' in header name: 
{header[0]!r}"
+                raise ProtocolError(msg)
+
+        # > With the exception of pseudo-header fields (Section 8.3), which 
have a name
+        # > that starts with a single colon, field names MUST NOT include a 
colon (ASCII
+        # > COLON, 0x3a).
+        if header[0].find(b":", 1) != -1:
+            msg = f"Illegal character ':' in header name: {header[0]!r}"
             raise ProtocolError(msg)
-        yield header
 
+        # For compatibility with RFC 7230 header fields, we need to allow the 
field
+        # value to be an empty string. This is ludicrous, but technically 
allowed.
+        if field_value := header[1]:
+
+            # > A field value MUST NOT contain the zero value (ASCII NUL, 
0x00), line feed
+            # > (ASCII LF, 0x0a), or carriage return (ASCII CR, 0x0d) at any 
position.
+            for c in field_value:
+                if c == 0 or c == 0x0a or c == 0x0d:  # noqa: PLR1714
+                    msg = f"Illegal character '{chr(c)}' in header value: 
{field_value!r}"
+                    raise ProtocolError(msg)
+
+            # > A field value MUST NOT start or end with an ASCII whitespace 
character
+            # > (ASCII SP or HTAB, 0x20 or 0x09).
+            if (
+                field_value[0] == 0x20 or
+                field_value[0] == 0x09 or
+                field_value[-1] == 0x20 or
+                field_value[-1] == 0x09
+            ):
+                msg = f"Received header value surrounded by whitespace 
{field_value!r}"
+                raise ProtocolError(msg)
 
-def _reject_uppercase_header_fields(headers: Iterable[Header],
-                                    hdr_validation_flags: 
HeaderValidationFlags) -> Generator[Header, None, None]:
-    """
-    Raises a ProtocolError if any uppercase character is found in a header
-    block.
-    """
-    for header in headers:
-        if UPPER_RE.search(header[0]):
-            msg = f"Received uppercase header name {header[0]!r}."
-            raise ProtocolError(msg)
         yield header
 
 
-def _reject_surrounding_whitespace(headers: Iterable[Header],
-                                   hdr_validation_flags: 
HeaderValidationFlags) -> Generator[Header, None, None]:
+def _reject_empty_header_names(headers: Iterable[Header],
+                               hdr_validation_flags: HeaderValidationFlags) -> 
Generator[Header, None, None]:
     """
-    Raises a ProtocolError if any header name or value is surrounded by
-    whitespace characters.
+    Raises a ProtocolError if any header names are empty (length 0).
+    While hpack decodes such headers without errors, they are semantically
+    forbidden in HTTP, see RFC 7230, stating that they must be at least one
+    character long.
     """
-    # For compatibility with RFC 7230 header fields, we need to allow the field
-    # value to be an empty string. This is ludicrous, but technically allowed.
-    # The field name may not be empty, though, so we can safely assume that it
-    # must have at least one character in it and throw exceptions if it
-    # doesn't.
     for header in headers:
-        if header[0][0] in _WHITESPACE or header[0][-1] in _WHITESPACE:
-            msg = f"Received header name surrounded by whitespace 
{header[0]!r}"
-            raise ProtocolError(msg)
-        if header[1] and ((header[1][0] in _WHITESPACE) or
-           (header[1][-1] in _WHITESPACE)):
-            msg = f"Received header value surrounded by whitespace 
{header[1]!r}"
+        if len(header[0]) == 0:
+            msg = "Received header name with zero length."
             raise ProtocolError(msg)
         yield header
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-4.2.0/src/h2.egg-info/PKG-INFO 
new/h2-4.3.0/src/h2.egg-info/PKG-INFO
--- old/h2-4.2.0/src/h2.egg-info/PKG-INFO       2025-02-02 08:41:38.000000000 
+0100
+++ new/h2-4.3.0/src/h2.egg-info/PKG-INFO       2025-08-23 20:12:13.000000000 
+0200
@@ -1,6 +1,6 @@
-Metadata-Version: 2.2
+Metadata-Version: 2.4
 Name: h2
-Version: 4.2.0
+Version: 4.3.0
 Summary: Pure-Python HTTP/2 protocol implementation
 Author-email: Cory Benfield <c...@lukasa.co.uk>
 Maintainer-email: Thomas Kriechbaumer <tho...@kriechbaumer.name>
@@ -48,6 +48,7 @@
 License-File: LICENSE
 Requires-Dist: hyperframe<7,>=6.1
 Requires-Dist: hpack<5,>=4.1
+Dynamic: license-file
 
 =========================
 h2: HTTP/2 Protocol Stack
@@ -113,7 +114,7 @@
 Before you contribute (either by opening an issue or filing a pull request),
 please `read the contribution guidelines`_.
 
-.. _read the contribution guidelines: 
http://python-hyper.org/en/latest/contributing.html
+.. _read the contribution guidelines: 
https://python-hyper.org/en/latest/contributing.html
 
 License
 =======
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-4.2.0/tests/test_events.py 
new/h2-4.3.0/tests/test_events.py
--- old/h2-4.2.0/tests/test_events.py   2025-01-22 22:59:24.000000000 +0100
+++ new/h2-4.3.0/tests/test_events.py   2025-02-10 20:54:58.000000000 +0100
@@ -7,6 +7,7 @@
 import inspect
 import sys
 
+import hyperframe.frame
 import pytest
 from hypothesis import given
 from hypothesis.strategies import integers, lists, tuples
@@ -114,9 +115,10 @@
         """
         RequestReceived has a useful debug representation.
         """
-        e = h2.events.RequestReceived()
-        e.stream_id = 5
-        e.headers = self.example_request_headers
+        e = h2.events.RequestReceived(
+            stream_id=5,
+            headers=self.example_request_headers
+        )
 
         assert repr(e) == (
             "<RequestReceived stream_id:5, headers:["
@@ -130,9 +132,10 @@
         """
         ResponseReceived has a useful debug representation.
         """
-        e = h2.events.ResponseReceived()
-        e.stream_id = 500
-        e.headers = self.example_response_headers
+        e = h2.events.ResponseReceived(
+            stream_id=500,
+            headers=self.example_response_headers,
+        )
 
         assert repr(e) == (
             "<ResponseReceived stream_id:500, headers:["
@@ -144,9 +147,7 @@
         """
         TrailersReceived has a useful debug representation.
         """
-        e = h2.events.TrailersReceived()
-        e.stream_id = 62
-        e.headers = self.example_response_headers
+        e = h2.events.TrailersReceived(stream_id=62, 
headers=self.example_response_headers)
 
         assert repr(e) == (
             "<TrailersReceived stream_id:62, headers:["
@@ -158,9 +159,10 @@
         """
         InformationalResponseReceived has a useful debug representation.
         """
-        e = h2.events.InformationalResponseReceived()
-        e.stream_id = 62
-        e.headers = self.example_informational_headers
+        e = h2.events.InformationalResponseReceived(
+            stream_id=62,
+            headers=self.example_informational_headers,
+        )
 
         assert repr(e) == (
             "<InformationalResponseReceived stream_id:62, headers:["
@@ -172,10 +174,11 @@
         """
         DataReceived has a useful debug representation.
         """
-        e = h2.events.DataReceived()
-        e.stream_id = 888
-        e.data = b"abcdefghijklmnopqrstuvwxyz"
-        e.flow_controlled_length = 88
+        e = h2.events.DataReceived(
+            stream_id=888,
+            data=b"abcdefghijklmnopqrstuvwxyz",
+            flow_controlled_length=88,
+        )
 
         assert repr(e) == (
             "<DataReceived stream_id:888, flow_controlled_length:88, "
@@ -186,9 +189,7 @@
         """
         WindowUpdated has a useful debug representation.
         """
-        e = h2.events.WindowUpdated()
-        e.stream_id = 0
-        e.delta = 2**16
+        e = h2.events.WindowUpdated(stream_id=0, delta=2**16)
 
         assert repr(e) == "<WindowUpdated stream_id:0, delta:65536>"
 
@@ -221,8 +222,7 @@
         """
         PingReceived has a useful debug representation.
         """
-        e = h2.events.PingReceived()
-        e.ping_data = b"abcdefgh"
+        e = h2.events.PingReceived(ping_data=b"abcdefgh")
 
         assert repr(e) == "<PingReceived ping_data:6162636465666768>"
 
@@ -230,8 +230,7 @@
         """
         PingAckReceived has a useful debug representation.
         """
-        e = h2.events.PingAckReceived()
-        e.ping_data = b"abcdefgh"
+        e = h2.events.PingAckReceived(ping_data=b"abcdefgh")
 
         assert repr(e) == "<PingAckReceived ping_data:6162636465666768>"
 
@@ -239,8 +238,7 @@
         """
         StreamEnded has a useful debug representation.
         """
-        e = h2.events.StreamEnded()
-        e.stream_id = 99
+        e = h2.events.StreamEnded(stream_id=99)
 
         assert repr(e) == "<StreamEnded stream_id:99>"
 
@@ -248,10 +246,11 @@
         """
         StreamEnded has a useful debug representation.
         """
-        e = h2.events.StreamReset()
-        e.stream_id = 919
-        e.error_code = h2.errors.ErrorCodes.ENHANCE_YOUR_CALM
-        e.remote_reset = False
+        e = h2.events.StreamReset(
+            stream_id=919,
+            error_code=h2.errors.ErrorCodes.ENHANCE_YOUR_CALM,
+            remote_reset=False,
+        )
 
         if sys.version_info >= (3, 11):
             assert repr(e) == (
@@ -363,7 +362,7 @@
         """
         UnknownFrameReceived has a useful debug representation.
         """
-        e = h2.events.UnknownFrameReceived()
+        e = h2.events.UnknownFrameReceived(frame=hyperframe.frame.Frame(1))
         assert repr(e) == "<UnknownFrameReceived>"
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/h2-4.2.0/tests/test_invalid_headers.py 
new/h2-4.3.0/tests/test_invalid_headers.py
--- old/h2-4.2.0/tests/test_invalid_headers.py  2025-01-22 22:59:24.000000000 
+0100
+++ new/h2-4.3.0/tests/test_invalid_headers.py  2025-08-23 18:49:56.000000000 
+0200
@@ -48,6 +48,14 @@
         [*base_request_headers, ("name ", "name with trailing space")],
         [*base_request_headers, ("name", " value with leading space")],
         [*base_request_headers, ("name", "value with trailing space ")],
+        [*base_request_headers, ("illegal:characters", "value")],
+        [*base_request_headers, ("illegal-\r-characters", "value")],
+        [*base_request_headers, ("illegal-\n-characters", "value")],
+        [*base_request_headers, ("illegal-\x00-characters", "value")],
+        [*base_request_headers, ("illegal-\x01-characters", "value")],
+        [*base_request_headers, ("illegal-characters", "some \r value")],
+        [*base_request_headers, ("illegal-characters", "some \n value")],
+        [*base_request_headers, ("illegal-characters", "some \x00 value")],
         [header for header in base_request_headers
          if header[0] != ":authority"],
         [(":protocol", "websocket"), *base_request_headers],
@@ -665,7 +673,7 @@
 
     def test_inbound_header_name_length_full_frame_decode(self, frame_factory) 
-> None:
         f = frame_factory.build_headers_frame([])
-        f.data = b"\x00\x00\x05\x00\x00\x00\x00\x04"
+        f.data = b"\x00\x00\x01\x04"
         data = f.serialize()
 
         c = 
h2.connection.H2Connection(config=h2.config.H2Configuration(client_side=False))

Reply via email to